• 0 Votes
    2 Posts
    298 Views
    M
    Hey you need to react to MSG_GETCUSTOM_NAME_ADDITION and return a dict with the expected string with the "res" key. You need to register your object with c4d.OBJECT_CUSTOM_NAME_ADDITION to have the additional name displayed in the Object Manager. Cheers, Maxime.
  • exporting usd with python

    Cinema 4D SDK 2025 python windows
    2
    0 Votes
    2 Posts
    441 Views
    ferdinandF
    Hey @lionlion44, Thank you for reaching out to us. I doubt that this will not work in Python, it is just that we have not documented the symbols there yet. But you can find them in the C++ docs: [image: 1757607809636-6e23eada-2198-4c34-84bf-a576bbdd0ef9-image.png] I.e., it will be c4d.FORMAT_USDIMPORT and c4d.FORMAT_USDEXPORT. Cheers, Ferdinand
  • GetRad() / GetMp() update issue

    Cinema 4D SDK windows python 2025
    2
    0 Votes
    2 Posts
    304 Views
    ferdinandF
    Hey @datamilch, Thank you for reaching out to us. GetRad and GetMp express the locally aligned bounding box of an object. I.e., the bounding box in the coordinate system of the object. For a world space aligned bounding box we once had this thread, the Cinema API does not offer this out of the box. So, transforming an object will never change its bounding box. What will change the bounding box of an object, is changing its size or changing the parameters of a generator object. When you change the parameters of a generator or when your instantiate a new object, you will have to execute the passes (BaseDocument.ExecutePasses) on a document that contains the object to see the correct bounding box - or wait for the next scene update. PS: Your script is also running illegal code. You cannot modify the active document off-main-thread. I assume the is a script for a Python generator object. Its main function runs off-main-thread and you call there your csto which in turn calls SendModelingCommand on the active document. This will all sooner or later crash. https://developers.maxon.net/docs/py/2025_3_1/manuals/manual_threading.html#threading-information Cheers, Ferdinand
  • 0 Votes
    11 Posts
    1k Views
    A
    @ferdinand Thank you for your in-depth analysis. It would have taken me way too long to figure this out lol, especially finding "CUSTOMDATA_BLEND_LIST". The first example seems to work for me, but like you said, it may not be reliable. The Python node example also works great. Again, thank you for your time.
  • Can I get keyboard input mode?

    Cinema 4D SDK windows python c++ 2025
    4
    1
    0 Votes
    4 Posts
    508 Views
    ferdinandF
    Hey @Dunhou, I have edited your posting. It is fine to mention the beta forum, but we would rather not see its name written here. When you are talking about 'C++', I assume you are talking here about the Windows SDK/API, as for example GetGUIThreadInfo. I would doubt that you get very far with that here. Cinema 4D is very OS agnostic and we have our whole GUI decoupled from the OS. The little rename window in our tree view control is not an OS rename dialog. I am not even sure if this is something with an HWND handle which you could address so that you could intercept keyboard events to it, or if this is just a virtual window within our API. For this IMM thing to work, we would have to use the IME API in Cinema 4D, so that our text edit gadgets support it. I also do not quite understand what you are trying to do. The missing piece is here probably that our text edit gadget does not send its current content to the IME API (at a glance, via ImmSetCompositionStringW as shown here). And as a third party, you cannot really fix that. Because you (a) do not own the implementation and you (b) are not informed about an edit event, so you cannot just write a plugin which sends the object name to the IME API. Cheers, Ferdinand
  • 0 Votes
    4 Posts
    405 Views
    ferdinandF
    Hey, thanks for the extended code, but I still cannot run this, as it is only a fragment So, I only have a very rough understanding of what is going wrong. A likely issue apart from you just having a bug in your hit logic, is that you use the wrong coordinate system. if msg[c4d.BFM_INPUT_DEVICE] == c4d.BFM_INPUT_MOUSE \ and msg[c4d.BFM_INPUT_CHANNEL] == c4d.BFM_INPUT_MOUSELEFT \ and msg[c4d.BFM_INPUT_VALUE]: local_x = msg[c4d.BFM_INPUT_X] local_y = msg[c4d.BFM_INPUT_Y] scroll_y = self.dialog.get_scroll_offset() I would have to check myself, but there is some inconsistency with which dialogs send mouse input messages regarding the used coordinate system. Sometimes they send messages in the coordinate system of the dialog and sometimes messages in the coordinate system of the gadget. Just print out your (local_x and local_y) and check if the values make sense as local coordinates as you seem to treat them. On GeUserArea are multiple coordinate conversion methods. I think BFM_INPUT in this context is in local user area coordinates but I am not sure, it could also be that you have to convert them. The other thing is of course that you add this self.dialog.get_scroll_offset() on top of things. I assume this is sourced by something like GeDialog.GetVisibleArea? There you could also unintentionally mix coordinate systems. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    547 Views
    d_keithD
    Thanks for the response! I appreciate the ASSETDATA_FLAG_MULTIPLEUSE tip. My hope was that there was some sort of existing RenameAsset SDK method that would also update all references to that asset without implementing custom handling for various element types (Redshift Nodal Material, Cinema 4D Classic Material, Arnold Dome Light, XRef, etc). Evidently such a public python SDK method doesn't exist. My example code was texture specific as that's the part of the problem that's most pressing to me and I was able to implement with custom per-type handling - if I manage to get other types working, I'll attempt to update over time.
  • Motion Blur, ExecutePasses in VideoPostData

    Cinema 4D SDK c++ 2025
    2
    0 Votes
    2 Posts
    324 Views
    ferdinandF
    Hello @Aaron, Thank you for reaching out to us. Please follow our support procedures. You should consolidate your postings until we answer, i.e., update your last posting instead of creating new ones. I have consolidated your postings for you. You should also spend more time on making your problems reproducible for us. I know it can be easy to overlook in the heat of the battle but your question(s) are not as obvious to me as you probably think they are. As lined out in our support procedures, example code and/or scene data is usually required. I cannot answer every possible angle and interpretation this topic of yours could take, but I can state three things which come to mind when reading your two postings. What's the way to get several steps of motion blur transformation matrices for BaseObjects of the BaseDocument. That is simply not possible. A document has no notion of motion blur as it is a render effects implemented by a render engine, not something documents implement. Cinema's time system BaseTime allows for sub-frame accuracy, e.g., you could set a 10fps document to BaseTime(i, 30) and with that step with three sub-frames through the document. Simple things like position animations or other interpolated values will also work doing this. But simulations might yield different results than stepping with the natural frame rate through the document. And the most important thing is that there is absolutely no guarantee that this approach will result in 'matrices', i.e., transforms, that will match with what a render engine produces when you add some kind of sub-frame-based motion blur. Using this BaseTime approach is one way how the render engine could do it, but since render engines always have their own scene format, they could also do the calculation there, yielding different results than what Cinema's animation system would yield. When we want to add Motion Blur and call document->ExecutePasses(...) for some time then this POC is flushed and has no polygons or vertices, so it's not collected and can't be rendered It is too opaque for me what you are doing there to give a real answer, but: There is no guarantee that the caches of an object are built at any point except for when a render engine gets a scene state to render or inside GetVirtualsObjects when you manually build your dependent objcts. Usually, caches are built but depending on where you are, the cache of another object might not have been built or updated yet, resulting in either an empty cache or you looking at the cache output from the previous scene update. ExecutePasses has become a bit too popular tool recently. I guess that is partially my fault, because I have shown its usage in some examples. But executing the passes on a document is a very expensive operation and should only be carried out when absolutely necessary. I would absolutely not be surprised if something like liquids do not support stepping through a document with a frame rate lower than the documents frame rate. But without concrete data and example code I am just guessing. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    395 Views
    A
    okay the docs you gave were great for insight working code to change parameter of roughness for x given mat selections import c4d import maxon from maxon import GraphDescription doc = c4d.documents.GetActiveDocument() # Get selected materials directly selected_materials = doc.GetActiveMaterials() # Modify roughness for each selected material for material in selected_materials: graph = GraphDescription.GetGraph(material, nodeSpaceId=maxon.NodeSpaceIdentifiers.RedshiftMaterial) GraphDescription.ApplyDescription(graph, { "$query": { "$type": "Standard Material" }, "Reflection/Roughness": 1 }) c4d.EventAdd()
  • How to get explicit import node space?

    Cinema 4D SDK windows python 2025
    3
    1
    0 Votes
    3 Posts
    321 Views
    DunhouD
    Thanks @ferdinand for your great solution! Cheers~ DunHou
  • 0 Votes
    5 Posts
    527 Views
    DunhouD
    Hey @ferdinand , thanks for details. Cheers~ DunHou About forum, I can get notification about my own topic, And I clear all the cache, but nothing changed. After I tried to reset my account settings manually, then it worked as expected.
  • Knowing if a font exists

    Cinema 4D SDK windows python 2025
    4
    0 Votes
    4 Posts
    421 Views
    D
    for my use case i will probably have a fallback solution with web-save or system fonts like this: import platform system_name = platform.system() if system_name == "Windows": font_name = "Consolas" elif system_name == "Darwin": font_name = "Menlo" elif system_name == "Linux": font_name = "DejaVu Sans Mono"
  • 0 Votes
    8 Posts
    664 Views
    A
    @ferdinand said in BaseBitmap.Init("somefile.exr") crashes with multiple std::thread: omp #parallel Sorry for late reply, I am not advocating for std::threads, I understand your design explanation. The omp #parallel thing is OpenMP directive to launch parallel threads. It's an old but simple method. Actually I have made a solution by exploiting Cinema way of launching threads and it works fine. However, I hope it would be good to make BaseBitmap->Init a thread safe and independent call from other C4D threads and resources. I will collect an example for you with exr images soon. Cheers, Aaron
  • Bundle fonts with Cinema 4D submissions

    Cinema 4D SDK python 2025 2024
    7
    0 Votes
    7 Posts
    943 Views
    K
    Hey @ferdinand , Sorry for the late replies. You can only answer these with end user support and the beta community. I will do that. Although I haven't used the beta community yet, I'll post the same question there to better understand what the recommended workflows are right now. you would either have to limit the feature to 2024+ clients That's good enough for us. Our plugin officially supports only the latest versions of 2024 and 2025.
  • How to Encrypt Python Plugins without a License?

    Cinema 4D SDK python 2025
    2
    0 Votes
    2 Posts
    355 Views
    ferdinandF
    Hey @kbar, thank you for reaching out to us. Please remember creating new topics instead of posting in older one's, so that our forum remains a searchable database. I have forked your question. I understand the necessity and use case for this, but in the proposed form, this is not possible. At least not without more work than it makes sense to invest here. Because the license validation is one of the first steps in the boot sequence of Cinema 4D, and trying to evaluate a command line argument and use all the components of our API necessary to encrypt a file could easily lead to problems (as these modules might not have been loaded yet). What we could think about is offering this as a standalone tool. The issue is here that we cannot just ship the source for that tool (for third parties to compile it themself) as the source would then also be known to bad actors. And shipping it as a binary would be extra work. An alternative could be a REST service, but that is also extra work (but less than the former route). I currently have no time for either of this. At the end of the year I will probably do some website work, then we could think about the REST route. But it is likely that I then also do not have time for this. As an MRD, you also have the option to ask in our beta forums or make a source code sharing request. In the end, this is very simple code and could probably easily emulated with a couple of lines of Python code. That is probably the most sensible route, but we would have to involve PMs etc. here, if we are willing to do that. I myself am even not sure if I would greenlight such request due to the sensitive nature of the topic. So, unfortunately, there is no clear cut route here, although I definitely can see the use case. Cheers, Ferdinand
  • 0 Votes
    2 Posts
    457 Views
    ferdinandF
    Hey @Amazing_iKe, Thank you for reaching out to us. That RenderDocument does not support animations is only partially true. Effectively it does not for users, but that is more a regression than the lack of an actual feature. When you look into its documentation, you will see that many symbols and arguments are animation related. And when you send it a document which holds an animation, you are paying the price for rendering the full animation. The regressed state is however that you effectively only have access to the bitmap of the last frame of that animation. There is also the issue that the OCIO workflow with RenderDocument is a bit clunky at the moment. We have these issues in our backlog by I unfortunately cannot make any guarantees as to when we will fix them. You have two options: Render the document frame by frame yourself with RenderDocument and then assemble the animation yourself. Use the BatchRender, i.e., what is shown to the user as the render queue. You can use this in a fully programmatic manner, but you are restricted to rendering documents that have been saved to disk, and the output will also be put to disk. I.e., you do not have the 'memory only'-aspect of RenderDocument. There are many topics about this subject on this forum, for example here where I showed how you abstract some of the disc-only limitations aways. Maxime also recently added some features to the batch render like switching cameras and takes, which makes it less likely that you have to modify the file. I cannot write examples for all possible routes here. You have to decide yourself which route you want to go, and when you are then stuck there, I will help you. What to pick depends on your goals. When you expect the renderings to be quick, doing it manually with RenderDocument could be a solution. For more complex animations, the batch renderer is probably the better route. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    479 Views
    ferdinandF
    Hey @Amazing_iKe, Thank you for reaching out to us. You do the same thing you did incorrectly in your other thread. You create an async dialog and you do not keep it alive. We would prefer it to keep things G-rated here. I.e., no nudity, no violence, and no weapons. I removed the image in your posting. With that being said, and when I try out your script (with the dlg thing fixed). I end up with this: [image: 1752854682502-fc83d223-abc0-4568-98fc-deb82596b059-image.png] I.e., it just works. But you docked your dialog (and so did I imitating what you did). I now cannot reproduce this anymore, but when I did something in my layout, I think I dragged a palette, I got a similar result as yours. That is not too surprising though as you implement here an async dialog in a hacky manner. You have no CommandData.RestoreLayout which would handle layout events for your dialog. Something getting out of whack with scroll areas is not out of question for such irregular cases. Please follow the patterns shown in our GUI examples I would recommend to follow py-cmd_gui_simple_2024, it also contains code for handling layout events. I.e., this: def RestoreLayout(self, secret: any) -> bool: """Restores the dialog on layout changes. Implementing this is absolutely necessary, as otherwise the dialog will not be restored when the user changes the layout of Cinema 4D. """ return self.Dialog.Restore(self.ID_PLUGIN, secret) And to be clear, it is absolutely fine to share plugins with us here. It does not have to be a script manager script. Things should just not get too long. Feel free to anonymize your plugin IDs when you feel skittish about sharing them in public. Cheers, Ferdinand edit: Okay, there it is again. Not exactly the same as yours but close. But I would still have to ask you to provide an example where this happens inside a valid async dialog implementation (with a command or a similar owner). It is not out of question that there is a bug but we still need a non-hacky example. [image: 1752856082257-df89038f-124d-434f-8cde-3442bd9aebba-image.png]
  • 0 Votes
    3 Posts
    417 Views
    ferdinandF
    And just to be clear, using a modal dialog, e.g., DLG_TYPE_MODAL, is absolutely fine in a script manager script. Because then the GeDialog.Open call will only return when the dialog is closed (and you therefore do not have to keep the dialog alive). The hack I showed above is only needed when you need one of the async dialog types in a script manager script for testing purposes.
  • 0 Votes
    3 Posts
    533 Views
    Amazing_iKeA
    @ferdinand Thank you very much for your response and suggestions. I’ll make sure to follow best practices and provide a minimal, testable code sample when posting questions in the future. I’ll also give embedding a group a try. Thanks again for your support!
  • 0 Votes
    13 Posts
    2k Views
    ferdinandF
    Hey, your second code snippet never sets self._result. Regarding loading vs. cloning documents: That I did it how I did it was no accident, but that does not necessarily mean that cloning things is bad. C4DAtom::GetClone is implemented in the different scene elements independently; i.e., BaseObject::GetClone, BaseDocument::GetClone, BaseTag::GetClone, etc. and C4DAtom::GetClone is just the empty implementation. The different implementations then rely on C4DAtom::CopyTo to copy data from the reference into a new instance of that scene element type. On top of that comes that Cinema 4D is largely Copy-on-Write these days, with data actually only being copied when you try to modify it. This all explains why BaseDocument::GetClone is so inexplicably performant, it just copies the metadata and only copies the real payload of the scene when it has to. On top of that comes that cloning from the same document from multiple threads in parallel could entail read-access violations (although somewhat unlikely). On the other hand, our rendering pipeline does exactly the same, it clones documents for rendering (the cloning is however done on the main thread). I personally would say what you are doing is probably okay, but I would not write such code as example code. I would have to spend more time on this to figure out if this is absolutely safe. Doing the actual cloning off-main-thread seems risky though (but is probably also fine in 99,9% of the cases). Cheers, Ferdinand