Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Recent
    • Tags
    • Users
    • Register
    • Login
    1. Maxon Developers Forum
    2. ferdinand
    3. Posts
    Offline
    • Profile
    • Following 0
    • Followers 16
    • Topics 56
    • Posts 3,211
    • Groups 2

    Posts

    Recent Best Controversial
    • RE: How do I retrieve a command call from it's index number ?

      Hey @Dimitris_Derm. ,

      what do you mean by 'method'? CallCommand just invokes the CommandData plugin which has been registered under the plugin ID you passed to the call.

      What you can do, is resolve the numeric plugin ID integer value to a symbol. But unlike for message IDs, the docs currently do not resolve symbols to their integer values. You can do two things:

      1. Just search in the main symbol definition file with a text editor, i.e., {c4d}/resource/modules/python/libs/python311/c4d/__init__.py
      2. Or use mxutils.SymbolTranslationCache which exists for the very purpose of resolving such integer values to symbols.

      But in your case, 14046 , you will draw a blank in both cases, which simply means developers never defined a public symbol for that command.
      1b4e6537-4fad-48a1-b4ec-c6edd4103083-image.png

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Using the Bridge Tool

      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.

      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).

      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

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Using the Bridge Tool

      Hey @Dimitris_Derm. ,

      you should be able to upload things, it is at least working for me and other users. But we have a file size limit of 32 megabytes and only allow the file types: png jpg bmp c4d gif txt py pyp vdb zip mp4 webm cpp h pdf mov.

      NodeBB sometimes also rejects GIFs and JPEGs when it thinks they contain a malicious payload but that should not happen for images sourced from an OS or reputable apps such as Photoshop, Gimp, InfraView, XnView, etc.

      Your code contains some mistakes, and the question what you want to bridge (islands or elements) is still not clear to me, as you yourself do not seem to be quite sure. Since the case of bridging islands is not entirely trivial, and because SMC in general tends to be a hurdle for users, I decided to add a dedicated bridge tool SMC example to the SDK.

      You can find the example here, it should cover you use case, since I go over both bridging distinct elements and bridging selection islands.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Using the Bridge Tool

      Hey @Dimitris_Derm. ,

      please share complete code and a scene of what you are doing, otherwise I am guessing what you are trying to do. I assume you are trying to bridge to polygon islands, i.e., instead of distinct mesh elements in the destination and target, you have a group of polygons selected in both and then want to bridge by specifying a point index in the destination and target (which are an element of said polygon selections)?

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Using the Bridge Tool

      Hey @Dimitris_Derm. ,

      Thank you for reaching out to us. The bridge tool in Cinema supports (in point mode) up to four objects as inputs. MDATA_BRIDGE_OBJINDEX1 to MDATA_BRIDGE_OBJINDEX4 are BaseLink parameters where you must link the PolygonObject instances you want to bridge. When you want the common case of bridging within one object, you set the same object for all four slots.

      MDATA_BRIDGE_ELEMENT1 to MDATA_BRIDGE_ELEMENT4 are then the element (e.g. point) indices to bridge (which can be scattered over multiple objects). They will be evaluated in relation to what you have set for the object indices.

      MDATA_BRIDGE_DELETE is "Delete Original Polygons" when you are bridging polygons in polygon mode. MDATA_BRIDGE_ISO seems to be related to SDS isoparms in the viewport, you can probably ignore it.

      // Only use case of MDATA_BRIDGE_ISO in our code base, very likely a dormant parameter.
      Bool BridgeTool::MouseInput(...)
      {
        // ...
        if (bd->GetEditState()& DISPLAYEDITSTATE::SDS)
          data.SetBool(MDATA_BRIDGE_ISO, true);
        else
          data.SetBool(MDATA_BRIDGE_ISO, false);
        // ...
      

      When bridging in edge mode, you likely will have to operate with half-edge indices, as for example described under GetEdgeS. I would personally either go for point or polygon mode bridging, as edges are a virtual construct which can be a pain in the *** to deal with in code.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • Maxon One 2026.2 SDK Release

      Dear development community,

      On April the 15th, 2026, Maxon Computer released Maxon One 2026.2. For an overview of the new features please refer to the end user release notes.

      Alongside this release, existing APIs have been updated. For a detailed overview, please see the Cinema 4D C++ SDK and the Cinema 4D Python SDK change notes.

      Cinema 4D

      C++ API

      • Updated RenderDocument workflow to offer a more streamlined experience when rendering OCIO documents.
      • Also added two new rendering related code examples and updated older examples.

      Python API

      • Updated c4d.documents.RenderDocument workflow to offer a more streamlined experience when rendering modern OCIO documents which is explained in a suite of new rendering examples.
      • Added the ability to read and write SDS weighting data through the new c4d.HNWeightTag class.
      • Added the ability to do efficient nearest neighbor searches through the new c4d.utils.KDTree and c4d.utils.KDTreeQuery classes.
      • Added multiple new code examples, mostly revolving around rendering.

      ZBrush

      The ZBrush Python SDK has not been updated for this release.

      Head to our download section to grab the newest SDK downloads.

      Happy rendering and coding,
      the Maxon SDK Team

      ℹ We are aware that the notifications are currently malfunctioning on the forum.
      ℹ Cloudflare unfortunately still does interfere with our server cache. You might have to refresh your cache manually to see new data when you read this posting within 24 hours of its release.

      posted in News & Information cinema 4d zbrush c++ python sdk information
      ferdinandF
      ferdinand
    • RE: Tile rendering with Cinema 4D

      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

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: How to select multiple files using "c4d.storage.LoadDialog()"?

      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.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Is it okay to release a free plugin that overlaps with paid alternatives?

      Hey @Anlv,

      to make it short: You can release whatever you want, there is no etiquette that prevents you from releasing your software because it rains on the parade of someone else. That is just part of software development that you always outshine someone else in some shape or form.

      But the Cinema community is very polite, I would be surprised if someone would take offsense in any shape or form.

      Cheers,
      Ferdinand

      posted in General Talk
      ferdinandF
      ferdinand
    • RE: How to select multiple files using "c4d.storage.LoadDialog()"?

      Yes, that is a very low level way to do it, I assume you had help from an AI in writing it?

      I personally meant more to use a GUI kit such as tkinter or QT. We deliberately do not ship our Python with tkinter (the builtin GUI lib of Python), but you could just install it yourself. The advantage of tkinter or a similar lib is that things like filedialog.askopenfilenames will work on multiple OS's and versions of it, the disadvantge is that you have to install the dependency. Doing it manually yourself means that you have to support each OS yourself and also have to track versions of the API. But at least GetOpenFileNameW is probably so stable that you never have to care about the latter on WIndows.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Effector Objects written in Python

      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

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Reading Immutable Selection Tags

      Hello @Dimitris_Derm. ,

      Thank you for reaching out to us. Please follow our Support Procedures, especially regarding providing code and scene data alongside your questions. Because otherwise things can become a guessing game for us. It also often the case that things are more complicated than it seems, as the case here.

      About your Question

      When you talk about 'selection tags', I assume from the context that you actually mean selection proxy tags (denoted by the little link overlay icon). E.g., as here generated by the extrude object.
      13749476-8f97-400c-af06-411186aaad78-image.png

      Proxy selection tags exist because selection tags need a point object to work, when a selection tag sits on a generator, it becomes ambiguous to which point object inside the cache of the generator they belong. Proxies solve this by pointing to one or many actual selection tags in a cache (it is often the case that a proxy tag does not resolve to a singular discrete tag in the cache but to multiple tags).

      The proxy tag type class/interface is private as declared in the C++ API, i.e., one cannot interact directly with them (as a third party). But one can send MSG_GETREALTAGDATA to find the discrete tag(s) it points to.

      ⚠ The data returned by MSG_GETREALTAGDATA is by design data in caches. You can read data in caches, but you should never attempt to write data in caches, as caches are static by design, and violating this rule can lead to crashes.

      ⚠ What makes this more complicated in this case is that you use Neutron (Scene Nodes) which adds another layer of complexity. We would need here your existing code and a concrete scene to give an answer, as the approach shown below will likely not work there.

      Cheers,
      Ferdinand

      Result

      An extrude object which holds a proxy selection tag. In the console we can see the partial scene graph for the object. I have highlighted the line which is the actual selection tag inside the cache of the extrude object the proxy points to.

      ec1e1feb-d525-49c5-a800-4668aeb9abd4-image.png

      My scene: extrude.c4d

      Code

      """Demonstrates how to find the discrete selection tags which are pointed to by a selection proxy tag 
      on a generator.
      """
      
      import c4d
      import mxutils
      
      doc: c4d.documents.BaseDocument  # The currently active document.
      op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
      
      # The types of proxy tags which we want to find on the selected object.
      PROXY_TAG_TYPES: tuple[int, ...] = (
          c4d.Tcacheproxytagpointselection,
          c4d.Tcacheproxytagedgeselection,
          c4d.Tcacheproxytagpolyselection
      )
      
      def main() -> None:
          """Called by Cinema 4D when the script is being executed.
          """
          if op is None:
              return c4d.gui.MessageDialog('Please select an object.')
          
          # The proxy tags of #op. Proxy tags exist because selections (and some caches) only work directly
          # on a point object. A selection tag on a generator can be ambiguous, because it might not be 
          # clear which of the multiple point objects in the cache of the generator it should be applied 
          # to. Proxy tags solve this problem, as they point to one or multiple discrete selection tags 
          # in the cache of a generator, which should be used in place of the proxy.
          proxyTags: list[c4d.BaseTag] = [t for t in op.GetTags() if t.GetType() in PROXY_TAG_TYPES]
          if not proxyTags:
              return c4d.gui.MessageDialog('The selected object has no proxy tags.')
          
          # Print the partial scene graph of #op, so that we can see what is going on in the cache tree 
          # of it.We should see there the discrete selection tag(s) which are pointed to by the proxy tags 
          # of #op.
          print(mxutils.GetSceneGraphString(op))
          print("\n", "-" * 80, "\n")
      
          # Iterate over all proxy tags and find the discrete selection tags they point to, using the 
          # message c4d.MSG_GETREALTAGDATA. The result of this message is a dictionary, which contains 
          # references to the discrete selection tags in the cache of the generator, which are pointed 
          # to by the proxy tag.
          for proxyTag in proxyTags:
              res: dict = {}
              proxyTag.Message(c4d.MSG_GETREALTAGDATA, res)
              tagSymbol: str = mxutils.g_c4d_symbol_translation_cache.Get(proxyTag.GetType())[0]
              print(f"{proxyTag.GetName()}({tagSymbol}) points to: {res}")
      
          # NEVER modify the returned tags, as caches are by design static (but that is not physically 
          # enforced by Cinema 4D). Changing the content of caches can very easily lead to crashes, unless
          # you know exactly what you are doing. Reading data from caches is perfectly fine, though.
      
      if __name__ == '__main__':
          main()
      
      
      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: How to select multiple files using "c4d.storage.LoadDialog()"?

      Hello @Anlv,

      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

      What you are asking for is not possible in this form at the moment. The Cinema (C++) API has two functions for opening the native OS file and folder dialogs: FileSelect and FileSelectMultiple. The Python API makes this more complicated that it has to be with c4d.storage.LoadDialog and c4d.storage.SaveDialog but both just wrap FileSelect.

      With FileSelectMultiple you can do what you want, select multiple files in one go, but the Python API currently does not wrap this function. You must either open multiple dialogs or use a third party GUI API which can open such native OS dialog for you.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Can I have access to the Loop and Ring Selection algorithm ?

      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.

      c122abc5-8cfc-40da-90be-534532600b4a-image.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.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Can I have access to the Loop and Ring Selection algorithm ?

      Hello @Dimitris_Derm.,

      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

      I am not quite sure how your question is meant, but the loop and ring selection tools are accessible in the API. When you are literally asking for the algorithm, we cannot share that, as declared in our Support Procedures:

      We will not reveal non-public functionalities of our APIs.

      When you just want to use the tools programmatically, SendModelingCommand is the way to go. We also have a dedicated section in our examples for them.

      Cheers,
      Ferdinand

      Result

      af91631a-5119-4df2-86ac-d9539f3e80ed-image.png

      Code

      """Demonstrates how to use the loop selection command in the Python API. 
      
      The script creates a cylinder, makes it editable, and then performs a loop selection based on two 
      vertices and a polygon index. Finally, it inserts the modified object into the active document and 
      updates the scene.
      """
      import c4d
      import mxutils
      
      doc: c4d.documents.BaseDocument  # The currently active document.
      op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
      
      def main() -> None:
          """Called by Cinema 4D when the script is being executed.
          """
          # Instantiate a cylinder and insert it into a temporary working document.
          cylinder: c4d.BaseObject = mxutils.CheckType(c4d.BaseObject(c4d.Ocylinder))
          temp: c4d.documents.BaseDocument = mxutils.CheckType(c4d.documents.BaseDocument())
          temp.InsertObject(cylinder)
      
          # Make the object editable. We could also build the caches and get the cache, but since the 
          # subject is here SMC, we can also use SendModelingCommand and MODELINGCOMMAND_MAKEEDITABLE.
          res: list[c4d.BaseObject] | bool = c4d.utils.SendModelingCommand(
              c4d.MCOMMAND_MAKEEDITABLE, list=[cylinder], mode=c4d.MODELINGCOMMANDMODE_ALL, doc=temp)
          if not res:
              raise RuntimeError("Failed to make object editable.")
          
          # The cylinder is now editable.
          cylinder: c4d.PolygonObject = res[0]
      
          # Now we are going to do the loop selection. These are the IDs defined in toolloopselection.h:
      
          #     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
      
          settings: c4d.BaseContainer = c4d.BaseContainer()
      
          # Define the major input, two vertices and a polygon index. You need all three, regardless of the output mode 
          # you choose in SMC.
          settings[c4d.MDATA_LOOP_FIRST_VERTEX] = 2
          settings[c4d.MDATA_LOOP_SECOND_VERTEX] = 3
          settings[c4d.MDATA_LOOP_POLYGON_INDEX] = 1
      
          # Define the selection mode, this is more cosmetic, as SELECTION_NEW is the default.
          settings[c4d.MDATA_LOOP_SELECTION_TYPE] = c4d.SELECTION_NEW
      
          # Carry out the loop selection, targeting edge mode.
          res: list[c4d.BaseObject] | bool = c4d.utils.SendModelingCommand(
              c4d.ID_MODELING_LOOP_TOOL, list=[cylinder], mode=c4d.MODELINGCOMMANDMODE_EDGESELECTION, bc=settings, doc=temp)
          if not res:
              raise RuntimeError("Failed to perform loop selection.")
      
          # Scene elements can only be inserted once, the Python API removes nodes automatically when you call InsertObject, but 
          # C++ does not and there is no guarantee that the Python API babysits you in all cases where you can insert something, 
          # so it is good practice to ensure scene integrity yourself. (#cylinder is currently part of #temp).
          cylinder.Remove()
      
          # Insert the object into our scene, enable edge mode, make the object selected, and push an update event.
          doc.InsertObject(cylinder)
          doc.SetMode(c4d.Medges)
          doc.SetActiveObject(cylinder)
          c4d.EventAdd()
      
      if __name__ == '__main__':
          main()
      
      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: GetEffectiveRenderData does not return per-take overrides for RDATA_FRAMEFROM / RDATA_FRAMETO

      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

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: NETWORK_CONNECTTIMEOUT with SSL

      Timeouts should not happen unless the endpoint is indeed timing out. But as I said, I cannot help you unless you give me compilable code (i.e., a little self contained function) with which I can reproduce your claims. If possible, please also share your endpoint as it obviously plays a major role in this problem.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: NETWORK_CONNECTTIMEOUT with SSL

      Hey @Rox,

      Thank you for reaching out to us. Please provide a concrete executable code example as to what exactly does not work with SSL. I understand that you have put effort into make yourself understood, but in the current form it is very ambiguous what it not working for you.

      HTTPS methods surely work, we use them heavily internally, in all variants such as GET, POST, DELETE, etc. I looked at our code base and did not find an exact match for POSTing towards an HTTPs endpoint with a custom timeout, but found one for DELETEing.

      You can connect to an https URL without any extra steps. I am not quite sure what you would consider "setting the flags" in your code. Depending on the endpoint you want to reach, you might have to configure your headers though. UrlInterface is not a web framework which would automate these things for you.

      Here is some slightly obfuscated production code for posting towards an (https) endpoint:

      Bool DoRequestPost(
      	const maxon::String& endpoint, const maxon::CString& postData, Bool isFile = false, 
      	maxon::DataDictionary* responseAsDict = nullptr, 
      	maxon::BaseArray<maxon::DataDictionary>* responseAsArray = nullptr)
      {			
      	if (isFile)
      	{
      		additionalHeader.Set("Content-Type"_s, FormatString("multipart/form-data; boundary=@"_s, boundary)) iferr_cannot_fail("Cannot set content type"_s);
      		additionalHeader.Set("Some-Token"_s, "no-check"_s) iferr_cannot_fail("Cannot set Some-Token"_s);
      	}
      	else
      	{
      		additionalHeader.Set("Content-Type"_s, "application/json"_s) iferr_cannot_fail("Cannot set content-type"_s);
      		additionalHeader.Set("Accept"_s, "application/json"_s) iferr_cannot_fail("Cannot set accept datatype"_s);
      	}
      	url = maxon::Url();
      	url.Set(maxon::URLFLAGS::HTTP_ADDITIONAL_REQUEST_HEADER, additionalHeader) iferr_cannot_fail("Cannot set additional headers"_s);
      	url.Set(maxon::URLFLAGS::HTTP_POSTMETHOD, maxon::HTTPMETHOD::POST) iferr_cannot_fail("Cannot set httpmethod"_s);
      	url.Set(maxon::URLFLAGS::HTTP_POSTDATA, postData) iferr_cannot_fail("Cannot set post data"_s);
      	url.Set(maxon::URLFLAGS::HTTP_NO_PROXY_CACHING, true) iferr_cannot_fail("Cannot set NOPROXY");
      
      	return DoRequest(endpoint, responseAsDict, responseAsArray);
      }
      

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Command to create a Nodes Modifier

      Hey @ImperfectLink,
      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 posting you linked to was a legacy posting, I have deleted it. You can find all relevant information in this posting or in the Support entry of the site nav. Your question is a bit ambiguous but I assume you want to instantiate a nodes modifier? Or what do you mean by "the command"? I would say it works like this:

      import c4d
      import maxon
      
      from mxutils import CheckType
      
      doc: c4d.documents.BaseDocument  # The currently active document.
      op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
      
      def main() -> None:
          """Called by Cinema 4D when the script is being executed.
          """
          node: c4d.BaseObject = CheckType(c4d.BaseObject(maxon.neutron.DEFORMER_ID))
          doc.InsertObject(node)
          c4d.EventAdd()
      
      if __name__ == '__main__':
          main()
      

      You can find all the Neutron (the code name for scene nodes) IDs here. What stands out that this instantiates a scene node deformer and not a 'modifier', which is indeed a bit puzzling. But both share the same numeric value for their ID:

      c377ba54-581c-445d-bf0a-3b72111390fa-image.png

      In the API there is maxon.neutron.DEFORMER_ID but no modifier ID. And in the UI there is only a modifier. But since they share the type ID and also type name (Scene Nodes Deformer) they must be the same thing and the node editor just renames the entity when it is being inserted for some reason.

      Cheers,
      Ferdinand

      posted in General Talk
      ferdinandF
      ferdinand
    • RE: Create Motion Clip Source with Python API

      Hello @jaroslavnovotny,

      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

      BaseException: the plugin 'c4d.BaseList2D' (ID 465003004) is missing. Could not allocate instance.

      Just means that Cinema 4D cannot instantiate a node with such ID as it does find its implementation. In some VERY rare cases nodes are sealed and cannot be instantiated manually from the outside but that is very rare and not a difference between Python or C++ thing. If it fails in one API, it does so in the other.

      The other issue is you hard coded the ID. Where did you get this 465003004 for "motion source" from? Maxime did unfortunately the same in his old thread. You should never hardcode IDs when you can avoid it, i.e., when there is a symbol. With modern tools it also easier than ever to discover the correct symbols. Here I look with mxutils.GetSceneGraphString at the partial scene graph that is attached to my cube in the scene (op because my cube is selected).

      ed53288e-04da-4c83-ac4c-2ce7218c1547-image.png

      If you dig a little deeper (by passing the document, instead of just the cube) you can find out that there is also data in the motion branch of the document:

      79762613-bb37-44b3-a89e-c39dcf8cd597-image.png

      Which is why we keep seeing the motion source in my screen even though I deleted the cube. I do not know where you have digged out that ID MT_SOURCE = 465003004, because I could not find it when reverse searching for it. But assuming it is correct, it is probably just the ID for a sealed node to be instantiated by the timeline to realize its little display thingy of motion sources to the left.

      When you want to create an NLA animation on an object, you must create the motion system on it. And when you want to create one of the motion system 'templates' stored in the document, you just dump some entity (in my case the cube) into the motion branch of the document.

      The higher level problem is that I have no idea what you are tyring to achieve. You want to create motion system 'templates' (aka motion sources) inside a document without actually adding content to the document?

      Cheers,
      Ferdinand

      edit:
      Here is a little proof of concept, although I am not quite sure what one is supposed to do with such dangling motion sources?

      import c4d
      import mxutils
      
      doc: c4d.documents.BaseDocument  # The currently active document.
      op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
      
      def main() -> None:
          """Called by Cinema 4D when the script is being executed.
          """
          # Create a cube and add a little 3 second animation to its X position (I was lazy here and just
          # assumed the document would have 30 FPS instead of doing it more formally).
          cube: c4d.BaseObject = mxutils.CheckType(c4d.BaseList2D(c4d.Ocube))
          
          did: c4d.DescID = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION, c4d.DTYPE_VECTOR, 0),
                                       c4d.DescLevel(c4d.VECTOR_X, c4d.DTYPE_REAL, 0))
          track: c4d.CTrack = c4d.CTrack(cube, did)
          cube.InsertTrackSorted(track)
      
          curve: c4d.CCurve = track.GetCurve()
      
          curve.AddKey(c4d.BaseTime(0, 30))
          curve.AddKey(c4d.BaseTime(90, 30))
      
          curve.GetKey(0).SetValue(curve, 0.0)
          curve.GetKey(1).SetValue(curve, 1000.0)
      
          # Now insert the cube into the motion branch of the document. For that we have to first find
          # the motion branch (what we discovered before with mxutils.GetSceneGraphString).
          info: dict | None = next((b for b in doc.GetBranchInfo(c4d.GETBRANCHINFO_NONE) 
                                    if b['id'] == c4d.NLAbase), None)
          if not info or not info['head']:
              raise RuntimeError('Could not find valid motion branch in document')
          
          head: c4d.GeListHead = info['head']
          cnt: int = len(head.GetChildren())
          cube.SetName(f'Cube Motion Source {cnt}')
          cube.InsertUnderLast(head)
          c4d.EventAdd()
      
      if __name__ == '__main__':
          main()
      
      posted in Cinema 4D SDK
      ferdinandF
      ferdinand