• 0 Votes
    2 Posts
    23 Views
    ferdinandF
    Hey @Dunhou, our c4d_string.str files use standard ASCII escaping (of unicode). There is the relatively new py-cmd_gui_resources_2024 example which documents this (of particular interest would be unicode_encode_strings.py for you). But when I wrote unicode_encode_strings.py, I think it was a deliberate decision of mine to exclude the so called control characters in ASCII/Unicode (i.e., \x00 to \x1F as Python Unicode escape sequences). Which includes the whitespace characters like \t, \n, \r, etc. So, the script will not encode them for you. If you take the code example from above and wanted to add a line break in its help string, you cannot use \n in the string, because it would be escaped as \\n in the output, which is not what you want. Instead, you would have to use \x0A (i.e., the value 10 which is the code point for a line break in ASCII). But since this is not Python, but our C++ code which follows the Unicode standard to the letter, we do not use the \x prefix but \u and also pad it to 4 digits, so it would actually be \u000A for a line break. STRINGTABLE { IDS_PLUGIN_NAME "Py - Resource Gui"; IDS_PLUGIN_HELP "Opens a dialog window that is populated\u000a using resource files."; } [image: 1777885216433-d48918e5-eca2-4b9d-90f5-36101de3f0bc-image.png] If you wanted a more generic solution than writing such strings by hand, you would have to update EscapeUnicode in unicode_encode_strings.py to something like this: def EscapeUnicode(item: str) -> str: """Escapes both non-ASCII and control characters in a string to their unicode code point representation, e.g., \u000A for a line break. """ return re.sub(r"([^\x00-\x7f]|\x00-\x1F)", lambda m: "\\u{:04x}".format(ord(m.group(1))), item ) You could also just escape everything, but that would make the strings less readable in the resource files. I am personally also not sure it is a good idea to allow users putting control characters into strings, primarily due to whitespace. I would for example say that it is not wanted that strings in general and tooltips in particular contain line breaks, and that it is up to Cinema 4D to handle wrapping strings. When I look at our Move tool, I see no line breaks in the help string? The help string is just 'Move Tool', the other things (the name and the shortcut) are added by Cinema 4D dynamically (and therefore put onto a new line). [image: 1777885575797-2d99ee72-e853-415c-a4a6-448796c526b7-image.png] Cheers, Ferdinand
  • 0 Votes
    6 Posts
    102 Views
    ferdinandF
    The second ID is the sub ID. You can have a command (FOO = 100) which supports the sub-commands (BAR=1, and BAZ=2). So, you can then call CallCommand(100, 1) or CallCommand(100, 2) to invoke the two different things FOO can do. But as you said yourself, this is a rather unusual thing, and it is even more unusual that I manged to randomly click five things in a row that all have sub IDs What should also be said is that my little "extrude" log there does not really reproduce the modelling operations I carried out. It just runs the tools in the order they are invoked. And because when you run this right after your created the log, the extrude tool will for example still have set the same extrude depth from the last operation. But when you manually extrude something, and then run the script again, it will use these new current extrude tool settings, i.e., and not the ones from when your 'recorded' the log. The script log can be useful, but it is not the auto-script-recording feature users often whish it was.
  • Executing a Redshift texture bake from Python

    Cinema 4D SDK python 2026
    2
    0 Votes
    2 Posts
    47 Views
    ferdinandF
    Hello @mplec1, Welcome to the Maxon developers forum and its community, it is great to have you with us! Getting Started Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules. Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment. Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support. Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads. It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions. About your First Question The bake tag and by extension cinema::BakeTexture (and its Python equivalent c4d.utils.BakeTexture) unfortunately do not support Redshift, even for the older Xpresso based materials. Redshift uses the tools found in Redshift/Tools/Texture Baking for baking. And while you can programmatically create a bake set and then programmatically click the 'Bake' button in it (which both would also work in a headless version of Cinema 4D, such as c4dpy), the following dialog which opens to set baking details and actually start the rendering is sealed, i.e., you cannot interact with it from the public API. And opening such dialog would also fail in a headless Cinema 4D instance. So, I am afraid there is currently no solution for your problem. You can technically export the whole scene to a format such FBX or USD, and use the builtin baking output (which would also work in a headless environment, as long as you do NOT pass SAVEDOCUMENTFLAGS_DIALOGSALLOWED to the save/export operation). But the output of that automated baking is often of poor quality compared to manually baking object(s) via bake sets. Cheers, Ferdinand
  • Using the Bridge Tool

    Cinema 4D SDK python
    9
    0 Votes
    9 Posts
    276 Views
    ferdinandF
    Hello @Dimitris_Derm. No, with islands I do not mean different objects. With islands are polygon (selection) islands meant. And that is just the term that is used for these things. The "Plane" object below has two polygon islands, the left and right rectangle shown in the viewport, each composed out of 4 * 5 polygons. They are islands because they are topological disjunct from each other - you cannot 'get' from one island to another without jumping over a gap. [image: 1777019034509-a88ac530-c105-430c-bd11-f922f5688881-image.png] The same can be applied to selections, as shown below. Now the left polygon island in the mesh has two polygonal selection islands. You cannot get from one selection island to another without jumping over a gap (they are topologically disjunct). [image: 1777019065284-bf41be6a-3993-4eb1-b603-438df9aa1bb3-image.png] This is a requirement because as my code example demonstrates, when bridging in island mode, you just specify a polygon and a point (and set the flags), and the tool then 'grows out' the to be bridged patch from the given polygon, based on the active polygon selection. And this growing will stop at topological boundaries. So, when you would bridge from the selection in the lower left corner of the left rectangle (to some unspecified target in another mesh), it would only grow into these four polygons. The selection in the top right corner would never be part of the operation. Cheers, Ferdinand
  • 0 Votes
    2 Posts
    269 Views
    W
    新的py我不知道,但是旧的 我觉得能达到你的要求,虽然我没这样尝试。一般子工具重命名有两种方式: 一种 通过设置 FileNameSetNext 导出空文件 的方式,利用程序导出时自动改名来重命名。还有一个是 调用ZFileUtils64.dll中的 重命名函数,修改: ··· // 设置要使用的名称,而不是询问用户 // @str:将替换为用户输入的文本/字符串 [RoutineDef, ZFU_RenameSetNext, [FileExecute, [Var, dllPath], RenameSetNext, str] , str] // 通过为请求重命名框的按钮提供路径来重命名 “something” // @buttonPath:要求用户重命名“某物”的按钮的路径 // @str:将替换为用户输入的文本/字符串 [RoutineDef, ZFU_RenameFromButtonPath, [If, (([IExists, buttonPath]) && ([IsEnabled, buttonPath])), [FileExecute, [Var, dllPath], RenameSetNext, str] [IPress, buttonPath] ] , buttonPath, str] // 重命名当前 SubTool // @str:新的 SubTool 名称 [RoutineDef, ZFU_RenameCurrentSubTool, [RoutineCall, ZFU_RenameFromButtonPath, "Tool:SubTool:Rename", str] , str] ··· 个人建议 :批量重命名还是在外部处理好 再导入最佳。而且ZB支持bat 等外部执行方式。
  • 0 Votes
    1 Posts
    42 Views
    No one has replied
  • 2 Votes
    1 Posts
    3k Views
    No one has replied
  • Load *.py scripts on startup.

    ZBrush SDK windows
    2
    0 Votes
    2 Posts
    104 Views
    D
    Hi @diegoev2026 Welcome to the Maxon developers forum and its community, it is great to have you with us! Getting Started Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules. Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment. Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support. Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads. It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions. About your Question Good question, and indeed we wouldn’t recommend modifying the init.py file in the installation directory. Instead, ZBrush provides a dedicated folder for this type of user customization, you can quickly navigate to it from the ZBrush menu: Preferences > Asset Directory > Open Directory. You can find more details about that here, if you are looking for further detail : https://help.maxon.net/zbr/en-us/Content/html/user-guide/customizing-zbrush/user-content/user-content.html In order to execute your own script at startup, it should be sufficient to replicate the setup you see in the ZBrush directory by creating a Python directory inside your asset directory with an init.py in it. If you are using the default location for the asset directory, the path would look something like C:\Users\[UserName]\AppData\Roaming\Maxon\ZBrush_[HashValue]\Python\init.py. On top of the init.py scripts, ZBrush also allows running Python scripts as plugins from a directory you can configure through the environment variable in ZBRUSH_PLUGIN_PATH. You can find more details on how to set those up here: https://developers.maxon.net/docs/zbrush/py/2026_1_0/manuals/python_environment.html#zbrush-plugin-path The user asset directory I mentioned above is also part of the ZBRUSH_PLUGIN_PATH by default, meaning you can just drop your plugins in there. Let us know if you need any further clarification! Regards, Davide
  • Tile rendering with Cinema 4D

    Cinema 4D SDK python 2026
    7
    0 Votes
    7 Posts
    516 Views
    ferdinandF
    Hey, just as an FYI, I added this as an example to the 2026.2 rendering examples. You will be able to find it under \scripts\04_3d_concepts\rendering\render_document_tiles_2026_2.py. Since the script will use some 2026.2 features, it does not make much sense to post a preview here, as you will not be able to run it right now. The example also does the kernel border thing we discussed here. Cheers, Ferdinand
  • Reading Immutable Selection Tags

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    140 Views
    D
    Ah ! They are called Proxy Tags and I can see the actual tag with the MSG_GETREALTAGDATA ! Thank you ️
  • 0 Votes
    6 Posts
    198 Views
    ferdinandF
    Your approach is not necessarily worse, one could even argue that it is better. I personally would always avoid manually binding to an OS DLL via ctypes, but that is more a personal preference.
  • 0 Votes
    3 Posts
    140 Views
    AnlvA
    @ferdinand Thanks for the encouragement, much appreciated!
  • Effector Objects written in Python

    Cinema 4D SDK python
    3
    0 Votes
    3 Posts
    139 Views
    ferdinandF
    Hey @Dimitris_Derm. , no there is currently no dedicated plugin class for MoGraph effectors and fields in Python, only the scripting objects exist at the moment. Cheers, Ferdinand
  • 0 Votes
    5 Posts
    209 Views
    ferdinandF
    Hey, well, "intended" would be the wrong word, but I am aware. The whole resource parsing situation is a bit of a mess at the moment, both in C++ and the Python API. Why is it like this? A description is defined by a res file (more or less its GUI declaration) and an h file which declares symbols for parameter IDs. The resource for the loop tool looks like this: CONTAINER ToolLoopSelection { NAME ToolLoopSelection; INCLUDE ToolBase; GROUP MDATA_MAINGROUP { BOOL MDATA_LOOP_SEL_STOP_AT_SELECTIONS { } BOOL MDATA_LOOP_SEL_STOP_AT_NON_QUADS { } BOOL MDATA_LOOP_SEL_STOP_AT_POLES { } } HIDE MDATA_COMMANDGROUP; } I.e., it indeed only defines three parameters. But the header file looks like this: #ifndef TOOLLOOPSELECTION_H__ #define TOOLLOOPSELECTION_H__ enum { MDATA_LOOP_SEL_STOP_AT_SELECTIONS = 1100, // BOOL MDATA_LOOP_SEL_STOP_AT_NON_QUADS = 1110, // BOOL MDATA_LOOP_SEL_STOP_AT_POLES = 1120, // BOOL MDATA_LOOP_FIRST_VERTEX = 1130, // LONG MDATA_LOOP_SECOND_VERTEX = 1131, // LONG MDATA_LOOP_POLYGON_INDEX = 1132, // LONG MDATA_LOOP_BOTH_SIDES = 1133, // BOOL MDATA_LOOP_SWAP_SIDES = 1134, // BOOL MDATA_LOOP_SELECTION_TYPE = 1140, // LONG (must be SELECTION_NEW, SELECTION_ADD or SELECTION_SUB) MDATA_LOOP_SEL_POLYGON_OBJECT = 1150, // LINK }; #endif // TOOLLOOPSELECTION_H__ I.e., it not only defines these three parameters, but also all the others. Because there are all these "hidden" parameters which are written into the data container of the tool, but never show up in the GUI. What collides here is (a) the a bit irregular (but not illegal) behavior of a resource to define more parameters in its header file than are used in the resource and (b) the questionable decision of our resource parser to ignore hidden parameters. Our resource parsing is automated, i.e., I cannot just go into a file and just add these parameters for a docs build. I could touch the resource parsers for Python and C++, but I do not have the time for that right now as they has been written in a very opaque manner. My advice is simply what the docs suggest: Search in the header files directly. Go to your Cinema folder, make sure that the resource.zip is either unpacked to the local folder (the folder existing does not mean necessarily that it has been fully unpacked) or an external folder of your choice. And then simply search in that folder with an editor of your choice. [image: 1775557617243-c122abc5-8cfc-40da-90be-534532600b4a-image-resized.png] At some point I will replace the resource and symbols parsing for Python and C++, because we made there quite a mess in the past with questionable parsers and manually curated lists. But for now this cannot be changed and using the files directly is the way to go when you want to look at descriptions. Cheers, Ferdinand PS: The C++ docs are NOT inherently better in that regard. The parser shares there the same flaws. The reason why you find some symbols there is because developers have duplicated them from the resources into the frameworks.
  • 0 Votes
    2 Posts
    192 Views
    ferdinandF
    Hello @vaishhg, Thank you for reaching out to us and your comprehensive yet sparse problem description, this really makes things easier for us. The problem is a bit that you somewhat forgot a crucial part: The scene data :). You provided this: Create a Cinema 4D scene with a Main take (frame range 0-6) Create child takes (V, E, R, A) and override the render data's frame range on each (e.g., V: 0-9, E: 0-23, R: 0-13, A: 0-17) But I cannot recreate a scene with these instructions, unless you meant the second step in a rather metaphorical way (switching the render data itself via takes). I also talked with some of our support specialists, and the consensus seems to be that what you claim to be the case - a scene with take overwritten FROM/TO values - is not possible. What you can do, is create multiple render settings and then activate them via takes. But Takes are a tricky subject, and I would not rule out that you somehow found a way to create take overrides for parameters of a render data instance. If so, please share the scene. Find also a scene attached which demonstrates what I discussed above: A scene that switches the active render data based on takes. It will print this with your script: Take 'Main': FRAMEFROM=0, FRAMETO=90 Take '0_45': FRAMEFROM=0, FRAMETO=45 Take '0_90': FRAMEFROM=0, FRAMETO=90 take_renderdata.c4d So, to formally answer your main question: When my assumptions above are true, your scene is printing the same values because each take does have the same values, as these two parameters are not directly overridable. Cheers, Ferdinand
  • NETWORK_CONNECTTIMEOUT with SSL

    Cinema 4D SDK 2024 c++ 2025 2026
    5
    0 Votes
    5 Posts
    265 Views
    R
    For now I am good. If I need further help, I will send the endpoint and function by email.
  • Create Motion Clip Source with Python API

    Cinema 4D SDK python windows 2026
    3
    0 Votes
    3 Posts
    187 Views
    J
    Hi @ferdinand, and thank you! Your proof-of-concept and pointing me toward mxutils.GetSceneGraphString() was exactly what I needed to solve this. By using the scene graph dumper on a native UI-generated Motion Source from a rigged character, I realized it's just a standard Ojoint hierarchy with normal CTrack objects. I used GetClone(c4d.COPYFLAGS_NO_HIERARCHY) to perfectly replicate the Ojoint skeleton and injected the time variables into the container, and it maps and plays back perfectly. Thanks again.
  • Command to create a Nodes Modifier

    General Talk programming
    3
    0 Votes
    3 Posts
    170 Views
    I
    @ferdinand Thanks for the reply. This will help immensely thank you.
  • 0 Votes
    7 Posts
    364 Views
    T
    Here's my prototype, if you are interested in my goal Right now, everything works as expected, but only with these lines of code. profile = GetCloneSpline(profile_orig) path = GetCloneSpline(path_orig) I'm happy with the current result. So, I'd love to get some additional advice on correctness and optimization. I think your previous answer was comprehensive enough, so I'll try to integrate some of it. But I'd also be very grateful if you could take a look at my plugin and perhaps give me some more specific optimization tips. If that's not too much trouble, of course! @ferdinand @ThomasB Anyway, thanks for your replies and advices!
  • Batching Slider messages

    Cinema 4D SDK c++ 2026
    5
    0 Votes
    5 Posts
    310 Views
    SteveHill3DS
    Thank you. MSG_DESCRIPTION_USERINTERACTION_END is just what was needed.