• 0 Votes
    3 Posts
    784 Views
    M
    Hi @FSS first of all happy new year ! And I'm glad that you found a solution however even if this is in the documentation we don't explicitly support PyCharm and only provide a dummy package to have autocompletion working with any Python instance. But C4dpy is not supported by all IDE and we can't provide any support there. If you want to have a better IDE workflow we released a plugin for Visual Studio Code, requiring a Cinema 4D plugin and a VS Code plugin. Finally I moved this topic to general talk as it this is nothing related to Cinema 4D API. Cheers, Maxime.
  • 0 Votes
    5 Posts
    841 Views
    ManuelM
    @kng_ito said in How to get weights from a Vertex Map tag on an uneditable object: Sorry for asking a question that has already been resolved in another thread. Don't worry, we are glad to help. Cheers, Manuel
  • 0 Votes
    6 Posts
    709 Views
    ferdinandF
    Hey @thomasb, Thank you for the clarification. Yeah, this setup requires you modifying the cache. So, the slow performance version with disabling the optimization is the best you can do when approaching things in such brutish manner. FYI: I do not have much time this week, so this is all the help you will get this week from me, but I am happy to help you next week if you still need help then. Things you can do: Turning off the optimization will calculate the cache every time Cinema 4D asks for it. Depending on how your blinking works, you might not have to calculate the cache every frame. Just determine when a new cache is needed and when not, as demonstrated in my first posting. When in 99% of the cases 99% of your old invalid cache is still good, nothing prevents you from either caching expensive to compute parts yourself or modifying the existing cache and return that as the new one. Changing a selection state is such an example of where 99.9% of the expensive work is still valid. It would be quite easy to do, when selection tags could reach into caches, but they cannot. So, you cannot have a selection tag on a generator (in Python) which indexes elements of the cache. But you can have a selection tag inside the cache which is referenced by for example a material on the generator holding the cache. With this knowledge, you can: Write a solution following (2.) where everything happens in the object, but in most cases, you just modify an existing cache instead of creating a new one. Do the same, but here you use a tag to modify the cache. This is a little bit dicey, as you should not mess with caches. But in this specific form, where we only change the selection state of a selection tag inside the cache, it should be okay. All other external cache modifications are off limits and can lead to crashes when you do not know what you are doing. In a nicer variant, you would implement the tag as a TagData plugin, but I provided a simple Python programming tag version below. The shader solution is not viable in Python; it will be too slow. You will also need quite some math knowledge and reverse engineering skills, as you would have to sort of reimplement texture mapping. PS: In your more complex setup, this could mean that you just change the materials on things. Although consolidating things inside caches is always advantageous. The more generators your cache contains, the more expensive it will be to evaluate the cache of your object. When possible, it is always better to return a single polygon object as your cache result, or at least a tree which contains only null objects and polygon objects, and no generator objects as the Sphere object, instance-objects, cloners, etc., i.e., things which must be cached themselves. When the cache for an object is being built, all that stuff is converted to polygons anyway. But when you return one hundred instance objects which reference a sphere generator each, cinema will have to build 102 caches in total: one for your object, one for the sphere object, and one hundred for the instance objects. When you just return one polygon object which contains all the geometry, Cinema 4D must build only one cache. In Python this fact is a little bit mitigated by the slowness of Python, and it can be advantageous to push things to C++, but your cache is too complicated IMHO. Just construct your LED once, then build the cache for it, copy the cache thirty-five times, modify the position and material of each copy, and return these thirty-five copies under a null object as your object cache. Cheers, Ferdinand File: led.c4d Result:[image: 1674038759398-led_ani.gif] Python Generator object: import c4d op: c4d.BaseObject # The Python Generator object containing this code. def main() -> c4d.BaseObject: """Returns a clone of the polygon object linked in its first user data field. """ source: c4d.PolygonObject = op[c4d.ID_USERDATA, 1] if not isinstance(source, c4d.PolygonObject): return c4d.BaseObject(c4d.Onull) clone: c4d.PolygonObject = source.GetClone(c4d.COPYFLAGS_NO_HIERARCHY | c4d.COPYFLAGS_NO_BITS) clone.SetMg(c4d.Matrix()) return clone Python Programming tag: import c4d doc: c4d.documents.BaseDocument # The document evaluating this tag. op: c4d.BaseTag # They Python Programming tag containing this code. def main(): """Reaches into the cache of its host object and modifies it. """ # Get the host object, its cache, and find the polygon selection tag on it. obj: c4d.BaseObject = op.GetMain() if not isinstance(obj, c4d.BaseObject): return cache: c4d.BaseObject = obj.GetCache() if not isinstance(cache, c4d.PolygonObject): return tag: c4d.SelectionTag = cache.GetTag(c4d.Tpolygonselection) if not isinstance(tag, c4d.SelectionTag): return # Get the current document frame and the selection of the tag and flush it. In practice you could # also make this parameter driven, but for expressions, tags, it is also fine to make things # automatic as such. frame: int = doc.GetTime().GetFrame(doc.GetFps()) bs: c4d.BaseSelect = tag.GetBaseSelect() bs.DeselectAll() # Define the indices of 100 cap polygons, and pick the polygon which matches the current time. states: list[int] = [n for n in range(4, 599, 6)] i: int = states[frame % 100] # Set the new selected element. bs.Select(i)
  • Can REAL MIN / MAX value be changed on Init?

    Moved Bugs 2023 python s26 sdk
    20
    0 Votes
    20 Posts
    4k Views
    mocolocoM
    Hi there, Was the issue fixed on R2023 or R2024? Thanks, Christophe
  • Make Description Parameter Uneditable

    Cinema 4D SDK r23 2023 python windows
    3
    1
    0 Votes
    3 Posts
    515 Views
    ThomasBT
    @ferdinand As always thank you very much Ferdinand, it works as expected
  • RS Proxy Export Parameters?

    Cinema 4D SDK 2023 python
    2
    1
    0 Votes
    2 Posts
    284 Views
    B
    False Alarm. Found it under C:\Program Files\Maxon Cinema 4D 2023\Redshift\res\description instead. Hehe. Closing this thread now.
  • RenderDocument produces different color

    Moved Bugs python 2023
    11
    1
    0 Votes
    11 Posts
    3k Views
    ferdinandF
    Hey @moghurt, no, there is unfortunately not a permanent solution yet, we have talked about it, but nothing concrete has yet happened. But your verbatim statement that RenderDocument does not respect OCIO, is not true. It does, it just a bit complicated to serialize the linear render result into non-linear files on disk or to send them to the picture viewer. Check the Python SDK OCIO Examples for details. Cheers, Ferdinand
  • 0 Votes
    8 Posts
    1k Views
    P
    Thanks for the good explanation.
  • 0 Votes
    6 Posts
    1k Views
    M
    @ferdinand said in A few items that should get fixed on the Python side: Hey @mikegold10, ..., the word "of" does not in any way indicate ownership, [...] It does, of is a possessive preposition, in is a relative preposition, specifically one that denotes a place. See here for an overview of the subject. I would not even challenge the fact that for you and your peers of might sound more natural (or maybe even all native speakers as you claim). But language in general, and especially things like prepositions, pronouns, and flexions, is subject to language change which is often highly regional, so what people consider correct can vary regionally. As indicated in my first answer, prepositions are quite interchangeable, and if the text would have said of instead of in, I would not waste any time on changing that. But in the same notion, I cannot change the preposition on what you subjectively consider better. The grammatical situation from a Standard English point of view seems obvious here and personal preference cannot be grounds for a change. I am more than happy to change the preposition when you can demonstrate with a respectable English style guide like Oxford English that it would be more common to use here of. But that seems unlikely to me. Cheers, Ferdinand As additional supportive evidence for my proposed change, I am providing a link to a respected source for the definitions of American English words, including many sample phrases that provide context for the often huge set of alternative definitions that are provided for commonly used words like "of" (and "in"): Meriam-Webster Dictionary: of - Definition / preposition Specifically, under the definitions of the word "of," when used as a preposition (i.e., Section 1 of 3 on the page, as linked above), please examine the following alternative definitions and examples of proper English usage that I believe are of relevance to my proposed change to the original Python comment: a, c, and e a and b b Here is a copy of the original comment to provide context: The index of the first and last selected elements in the given segment. ..., and the revised version that replaces the preposition in with of:: The index of the first and last selected elements of the given segment. Of course the decision is yours to make. I am simply trying to "open your mind" to, as well as provide objective evidence for, an alternative phrasing which I perceive to be a better fit for the technical subject matter that is being documented, within the framework of modern American English usage patterns. I have to concede on the fact that this is ultimately subjective and may (or may not - not sure) be specific to the en_US locale. Michael
  • Set the Preview of an Asset using an Image file.

    Cinema 4D SDK 2023 python
    8
    0 Votes
    8 Posts
    1k Views
    ferdinandF
    Hello @tdapper, I still do not fully understand what you want to do, but in general, my answer does not change much. I do not want to be rude here, but in C++ you have everything you need. And what you want to do here, is fundamentally interfere with how the Asset API works. Such low-level access is traditionally the domain of the C++ API and not the Python API. Bottom line is that it's cool that the asset browser automatically creates thumbnails [...] That was less me showing off the features of the asset API and more pointing out its general approach. Therefore we are basically trying to replicate the functionality you get when you right-click on the thumbnail in the Asset Browser and Click "Update Thumbnail from File...". 'Update Thumbnail from File...' will not prevent thumbnails from being overwritten either. So the only way to do so, would be to make the metadata entry read-only as pointed out in my first posting. Perhaps there is a way to just immediately kill the job that creates the thumbnail from being generated in the background or prevent that job from starting in the first place. If that is not possible, maybe there is a message we could intercept to know the thumbnail has been updated so we can run our workaround right after the thumbnail creation job is finished instead of waiting a hardcoded amount of time. Maybe there is another option that we're not clearly seeing right now? Neither your first nor second option are possible. The preview thumbnail job queue is non-public and there is no such thing as messages in the maxon API. There are Observables which realize the idea of events, but they are not exposed in Python nor are you able to stop a preview rendering with them. Again, I do not want to be rude here, but as pointed out in my first posting, what you want to do is not intended. You could get hacky from the Python API, but that is more or less up to you. [image: 1674145517216-982bbbbf-ca43-4f16-a85c-b9b5cb836a6f-image.png] Fig. 1: The physical location of thumbnails for local assets is always the same, net.maxon.asset.previewimageurl.meta.png. With that knowledge one can infer the future pyhsical location of a thumbnail for a local asset. # Create a new object asset. asset: maxon.AssetDescription = maxon.AssetCreationInterface.CreateObjectAsset( obj, doc, storeAssetStruct, assetId, assetName, assetVersion, assetMetadata, True) # Get the physical location of the asset #asset, normally one should not touch # AssetDescriptionInterface.GetUrl(). Then get the directory of that path and infer the # preview thumbnail location from it. assetUrl: maxon.Url = asset.GetUrl() assetPath: maxon.Url = maxon.Url(assetUrl.GetSystemPath()) previewFile: maxon.Url = assetPath + maxon.Url("net.maxon.asset.previewimageurl.meta.png") # Print out the paths, #previewFile won't yet exist at this point, because the thumbnailing is # parallelized. print (f"{assetUrl = }") print (f"{assetPath = }") print (f"{previewFile = }") print (f"{os.path.exists(previewFile.GetUrl()) = }") Example output: assetUrl = file:///C:/Users/f_hoppe/AppData/Roaming/Maxon/2023.1.3_97ABE84B/userrepository/object_a2c9ff14d748481fb9a8ae03d7bfa9b7/1/asset.c4d assetPath = file:///C:/Users/f_hoppe/AppData/Roaming/Maxon/2023.1.3_97ABE84B/userrepository/object_a2c9ff14d748481fb9a8ae03d7bfa9b7/1/ previewFile = file:///C:/Users/f_hoppe/AppData/Roaming/Maxon/2023.1.3_97ABE84B/userrepository/object_a2c9ff14d748481fb9a8ae03d7bfa9b7/1/net.maxon.asset.previewimageurl.meta.png os.path.exists(previewFile.GetUrl()) = False With that knowledge you could start messing with that file. But that is obviously out of scope of support and a hack. Otherwise you will have to use the C++ API or file a bug report for your thumbnails being black in the first place. Cheers, Ferdinand
  • 0 Votes
    6 Posts
    935 Views
    M
    @baca said in Cinema 4D R2023 - c4d.plugins.RegisterObjectPlugin issue: Any suggestion how to properly handle that kind of issues -- just catch exception and warn user using message box somehow? Correct you can catch the OsError and check if there is the word 50 in the exception message. Would it be reasonable to switch to NodeData from ObjectData -- It depends of your plugin if this is at the end an ObjectData then it's irrelevant, if this is just an object that you store in a list in memory or in a custom GeListHead then NodeData is perfectly relevant. does RegisterNodePlugin has separate 50 plugins registrations? Yes each type have 50 plugins. What's the logic behind plugin initialization order -- alphabetical, date-based, random? Folders from g_additionalModulePath are iterated by alphabetical order and each files are then iterated by alphabetical order too. Cheers, Maxime.
  • 0 Votes
    4 Posts
    636 Views
    T
    Hi @m_adam, this works perfectly. Thank you for your fast response.
  • How to use RemoveConnections?

    Cinema 4D SDK 2023 python
    3
    0 Votes
    3 Posts
    284 Views
    B
    @Manuel Gotcha. Thanks for the clarification. Works as expected.
  • Simple Organisational Structure Generation Script

    Cinema 4D SDK 2023 python
    6
    0 Votes
    6 Posts
    979 Views
    ManuelM
    @nealhulme you can have a look at our forum guidelines we have a section that explains how to mark your thread as a question. Then you can select a post as the answer or mark the thread solved. I forgot, welcome to the forum, i did not saw it was your first post. Cheers, Manuel
  • Skin Weights File Parser?

    Cinema 4D SDK python 2023
    3
    0 Votes
    3 Posts
    324 Views
    ManuelM
    hi, this is out of scope of the support and i never used configparser. Maybe maxime or Ferdinand will have some nice tips out of their head without having to investigate. I am happy you found a solution by pre-processing the file first. Cheers, Manuel
  • Timeline playing - MSG or method to get it?

    Cinema 4D SDK 2023 python s26
    3
    0 Votes
    3 Posts
    528 Views
    mocolocoM
    Hello @m_adam, Thanks a lot, it works like a charm! Have a good day, Christophe
  • 0 Votes
    7 Posts
    1k Views
    ferdinandF
    Hey @mocoloco, Should, that's why I asked. Yeah, that is not the style of the classic API, there are only little error messages and things like that. What you can also do, is use the return value of SetParameter, a boolean. It will be False when setting the parameter failed. I used 'Ge' to design all [...] Eh, I understand, you mean from GeDialog, or what? I think it just stands for GenericDialog, it also pops up in thing like GeListNode or GeClipMap. There are some really old entities in the classic API and naming conventions were different then Ge is at least not a name for interface gadgets in our APIs. Cheers, Ferdinand
  • Volume Object Example

    Cinema 4D SDK 2023 c++
    5
    0 Votes
    5 Posts
    759 Views
    D
    Thanks! That worked for me! Dan
  • How to read Field driven VertexMapTag's

    Cinema 4D SDK 2023 c++
    4
    0 Votes
    4 Posts
    1k Views
    K
    Yes that's what afraid to hear:) I did iteration over tags of Cache/Deform Cache and compare with GetOrigin() thingy to find related tag. I believe there should be some functionality in the SDK. Thanks for answers!
  • Info for ITEMTREE/customgui_itemtree

    Cinema 4D SDK
    8
    1
    0 Votes
    8 Posts
    2k Views
    M
    Hi @khor unfortunately Fritz is in holiday, but from what I see this is not possible since few types are not public. I will confirm with him when he will be back, in the meantime I wish you a nice Christmas. Cheers, Maxime.