• API for Adding a Port on a Group Node?

    Cinema 4D SDK 2023 python
    5
    1
    0 Votes
    5 Posts
    780 Views
    B
    @manuel Thanks for the illustration. Works as expected. When you have this statement: maxon.GraphModelHelper.FindNodesByAssetId(graph,"net.maxon.node.type", True, value) valueNode = value[0] inputNode = valueNode.GetInputs().FindChild("in") I'm guessing this part of my previous code is no longer working and so we need to reestablish the variable again. value = selectedNodes[0] Anyhow, thanks again. Closing this thread now
  • Set PYP file syntax highlighting in VS Code?

    General Talk r25 python
    4
    0 Votes
    4 Posts
    869 Views
    M
    Btw if you install the Cinema 4D Vs Code extension, pyp extension should be added as Python.
  • 0 Votes
    3 Posts
    788 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
    849 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
    710 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.
  • [SOLVED] ARROWBUTTON resource not accessible for Python?

    Cinema 4D SDK
    5
    0 Votes
    5 Posts
    724 Views
    ferdinandF
    Great to hear! One thing I forgot to mention: For ICONID1 XXX and ICONID2 YYY you can use any of the built-in icon IDs as listed here. When you want to use your own icons, you must make sure the icon IDs are registered before the node which is using them in its description. Simply put the c4d.gui.RegisterIcon call before the RegisterXXXPlugin call of the plugin using them. Cheers, Ferdinand
  • 0 Votes
    17 Posts
    3k Views
    ferdinandF
    Hey @vannipo, GUI builder is inside C4D, isn't it? I am not sure, atm. There is no WYSIWYG GUI builder for dialogs in Cinema 4D anymore. A long time ago existed the classic API Resource Editor, but it is not published anymore by us. The Resource Editor you can find via CTRL + C in a modern Cinema 4D instance is an editor for maxon API resources, a different and newer GUI paradigm in Cinema 4D. When you want to implement a dialog, you will have to either write a resource file manually or use the methods of GeDialog to add elements at runtime, you could have a look at this posting where I recently lined out some basics. The Python GUI Manual is quite superficial at the moment, but we have some simple examples on GitHub. For learning dialog resource markup, I would recommend the Dialog Resource Manual. The most important point for an animator is to key the desired channel as fast as possible. [...] But, the pop-up idea is very interesting, and I will have a look [...] Yeah, I understood that you were after a very streamlined setup. When you want to make zero compromises, nine shortcuts are probably the best solution. The solution I proposed with the popup menu is a compromise of the number of shortcut keys to allocate and the speed with which keys can be generated. The advantage is here that the popup menu will always open under your mouse cursor no matter where it is, which will minimize mouse travel distances. But when you overpopulate the menu with all nine entries (you can also add separators if you want to), selecting the right item will probably become slow. So, if you want a good compromise, you could use three scripts (translate/rotate/scale) which each provide a popup for x, y, or z. Btw, is it possible to set a "real name" for a script? atm, everywhere it just shows the filename. You can supply a different name from its filename by adding file docstring containing Name-en-US: XXXX where XXX is the name of the plugin. This can also be done for description that will be displayed when you hover the command with Description-en-US: XXX. If you need to support other language please refer to Plugin Structure Manual which specify the different language code. Finally you can find an example within GitHub - script_custom_name_description.py Cheers, Ferdinand
  • Implement A Usage Counter?

    General Talk python r25
    3
    0 Votes
    3 Posts
    597 Views
    B
    @ferdinand Thanks for the pointers. I'll try to look up those options. Will close this thread now.
  • 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
  • Switch render engine to Redshift (In memory)

    Cinema 4D SDK python
    4
    0 Votes
    4 Posts
    727 Views
    ferdinandF
    Hi @everyone, just as an FYI, the example is slightly outdated. With 2023.0.0 or newer, there is no need to manually define a symbol for the Redshift renderer, as one can use the newly exposed VPrsrenderer symbol (c4d.VPrsrenderer in Python). I have updated the C++ example. Cheers, Ferdinand
  • 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
    942 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
    639 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
    285 Views
    B
    @Manuel Gotcha. Thanks for the clarification. Works as expected.
  • Editing RS Nodes with Python

    Cinema 4D SDK python
    5
    0 Votes
    5 Posts
    936 Views
    M
    Hello @cgweasel, without further questions or postings, we will consider this topic as solved by Friday 02/06/2023 and flag it accordingly. Thank you for your understanding, Maxime.