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 17
    • Topics 59
    • Posts 3,313
    • Groups 2

    Posts

    Recent Best Controversial
    • RE: Cinema 4D 2027 SDK fails to build on macOS if the path contains spaces

      I forwarded this to the build team (who own this part of the build system). Let's see what they say, I will update this topic once I have an answer.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Cinema 4D 2027 SDK fails to build on macOS if the path contains spaces

      Hey @peter_horvath,

      Thank you for reporting this. I have never encountered this because I am habitually never use any white space in folders when it comes to coding but I understand this can be annoying. As far as I understand your posting correctly, you are placing the Cinema C++ SDK in the designated library folder of MacOS, more concretely its 'Application Support' sub folder, and the white space in that folder name is then causing issues with the prebuild event scripts?

      I would have to check if we can fix this, as this is a part of the build system (the frameworks) that is not owned by SDK. And just for clarity, you propose to change the relevant files to something like this:

      # Section: macOS
      set(exclude_from_build.MACOS /win)
      set(prebuild_event.MACOS.DEBUG "mkdir -p ~/Library/Application\\ Support/MAXON ; cp -f \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/maxon.py\" ~/Library/Application\\ Support/MAXON/maxon.py ; perl -w \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/copytypeviewer.pl\" maxon.py ~/Library/Application\\ Support/MAXON/maxon.py")
      set(prebuild_event.MACOS.RELEASE "mkdir -p ~/Library/Application\\ Support/MAXON ; cp -f \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/maxon.py\" ~/Library/Application\\ Support/MAXON/maxon.py ; perl -w \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/copytypeviewer.pl\" maxon.py ~/Library/Application\\ Support/MAXON/maxon.py")
      
      # Section: iOS
      set(exclude_from_build.IOS /win)
      set(prebuild_event.IOS.DEBUG "mkdir -p ~/Library/Application\\ Support/MAXON ; cp -f \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/maxon.py\" ~/Library/Application\\ Support/MAXON/maxon.py ; perl -w \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/copytypeviewer.pl\" maxon.py ~/Library/Application\\ Support/MAXON/maxon.py")
      set(prebuild_event.IOS.RELEASE "mkdir -p ~/Library/Application\\ Support/MAXON ; cp -f \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/maxon.py\" ~/Library/Application\\ Support/MAXON/maxon.py ; perl -w \"${CMAKE_CURRENT_SOURCE_DIR}/typeviewer/xcode/copytypeviewer.pl\" maxon.py ~/Library/Application\\ Support/MAXON/maxon.py")
      

      I.e., you want CMAKE_CURRENT_SOURCE_DIR compound paths to be quote escaped. If we will fix this, this will happen in an upcoming release and not a hotfix. For now you must either place the SDK in a path without whitespaces (or fix the CMake files yourself).

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Multi-Icon for Objects on OM and Icon placement on menus

      Hey @Dimitris_Derm.,

      • The example py_msc_licensing shows you how to change the icon of a node at runtime. The example uses this to change the icon of unlicensed nodes and the trick is to listen for the message MSG_GETCUSTOMICON.
      • The example py_obj_assetcontainer shows you how to place icons in cycles (Cinema slang for drop downs). The trick is to set the label of the cycle item to "{Label}&i{IconID}&", e.g., "Cube&i5159&" would display the cube icon next to the word "Cube", because 5159 is the cube object icon id. You can do this both in resource files and dynamically as the example does it.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • Maxon Cinema 4D 2027.0 SDK Release

      Dear development community,

      On October the 14th, 2026, Maxon Computer released Cinema 4D 2027.0. 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 the CMake build system, now using a pure CMake config workflow, deprecating the old projectdefinition.txt files.
      • Add three new examples revolving around changes in this SDK.

      Python API

      • Added agentic metadata to the SDK, improving performance and output of agentic workflows. Head to Working with the SDK for more information.
      • Reworked the documentation UI, porting over many features from the ZBrush SDK.
      • Reworked many code examples.
      • Reworked many manuals.
      • The Cinema API now offers vector image loading, better Javascript support for HTML controls, and node plugins can now implement custom branches.
      • In the Maxon API, there have been made improvements to graph descriptions, especially for querying graphs.
      • In the Mxutils API, scene traversal tools have been significantly improved, and new debug helper tools have been added.

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

      Happy rendering and coding,
      the Maxon SDK Team

      ℹ 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 news cinema 4d c++ python sdk information
      ferdinandF
      ferdinand
    • RE: Is there a Python equivalent of SceneHookData::Draw()?

      Unless I misunderstand the scope of the tool, you could implement this as a tool because a tool can draw. But with the caveat that the user has to enable it. But doing something like this as a scene hook is not great, even in C++. The reason is UX. Either you implement it as a pure scene hook with no feedback, then the user is stuck with always having this bounding box shown on the selected object. Or you add some kind of toggle that enables or disables it, but then you are already pretty close to reimplementing a tool.

      Question is: Do you really need this bounding box overlay to be able to coexist next to another activated tool. If so, you need a scene hook. Otherwise you should go with a tool.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Is there a Python equivalent of SceneHookData::Draw()?

      Hey Anlv,

      thank you for reaching out to us.

      There is no SceneHookData equivalent in Python yet. In this cycle we just tested internally a prototype but we haven't made a choice there yet. The main concern is performance, especially of Draw. It is currently unclear if we will ever go forward with the idea of a Python SceneHookData.

      The workaround we suggested in the past was to add a hidden object to a scene via a MessageData handler or any other node that has the methods you need. But that is not really better performance wise. In general is the idea to have a Python plugin which draws in each an every scene a bit of a mixed bag. I personally think it is not that much of a deal, because when the plugin slows down Cinema because the author wrote terrible Draw code, the user can just uninstall it. Some of my colleagues are more of the stance that we should not allow such setups at all, as the average user might be unable to pinpoint the plugin as the source of slowdowns.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: C4D 2026.4 — Supported API to release an imported Particle Group Alembic file handle?

      Hello @hey2495,

      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 would try closing the file into which you imported the Alembic file. I just checked it, when I import any Alembic file, Cinema holds a lock onto it while the file into which you imported is still open. That seems to be an Alembic specific behaviour, not to say a bug. But it should be avoidable by simply cloning or merging the imported document, so that you can close the import document.

      I will give the exchange team a heads up on this.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: How to find the closest primitive in a mesh

      First of all, you should open new topics for new questions, as one otherwise tends to derail old topics, which makes it hard to for others to follow things later. I forked your topic.

      And I also do not quite understand what your question is. GetClosestMeshPrimitive returns you the primitive type via primInfo.

      When you only want to get the closest point on a mesh, I would build a KD-Tree for its vertices. You then get the closest vertex and its index for your point p. Then you orthogonally project p onto the polygons attached to that vertex (via cinema:: Neighbor). Then you chose the closest point. We have this Python example for KDTree and I also used Neighbor there. Building a KD-tree or just brute forcing it depends a bit on how often you want to do it. For just a handful of points, brute forcing it is usually faster.

      I am sure you can also do this with DistanceQueryInterface and the uvw coordinate returned in the PrimitiveInformation, but all that extra work where you have to deal with all the primitive types seems like more work than it is worth. And when you want to do this in a generator (by the looks of your screens), using a manual KDTree approach will make it easier to parallelize it effectively and make it go zoom zoom instead of computing all that extra data.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: How to find the closest primitive in a mesh

      Hey @dex,

      distancequery.h is part of the mesh_misc.framework which you alreeady include. Sounds a bit like you have a corrupted build system on your hands or are not using the frameworks you think you are using. Where does the CMake fragment come from you show us? I assume you are using the old projectdefintion.txt sourced workflow (in which case you should us show that file). Or are you a beta member and have access to the 2027 SDK (which is natively pure CMake), in which case this would be invalid CMake markup, as some stuff has changed.

      Have you checked in the IDE of your choice that the mesh_misc.framework shows up as a dependency of the project in which you want to #include "maxon/distancequery.h"? And just for the recoord, this is not a std lib, so you cannot use #include <> but must use #include "". And since this is part of the Maxon API, you also need to specify the maxon folder.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: File import and doc merge -> InsertAfter or c4d.PREF_INTERFACE_I_BOTTOM

      Hey @mogh,

      let me clarify things first a bit.

      Reproduce:

      1. You have a scene A in an alien scene format such as FBX or OBJ.
      2. You have an existing native Cinema 4D scene B.
      3. You are trying to merge A into B.

      Result:
      The objects of A appear before the objects of B in the scene hierarchy of the merged scene. Even when you change the insertion order in Preferences > Interface.

      First of all, it is not very surprising that "insert at" does not work (and "paste at" does neither), because these are for individual objects within a scene, not for merging entire scenes. What you are effectively missing is a scene merge order option and this does not really have something to do with importers. This would be addressed best by a feature request in our Support Center.

      With a pinch of Python, you can solve this yourself as demonstrated by @Anlv (thanks!). Using BaseList2D.GetGUID as @Anlv did is okay, but the more native solution would be hash(obj), i.e., C4DAtom.__hash__. Scene elements are for quite a while now natively hashable, so you can for example do this:

      roots: set[int] = { hash(obj) for obj in doc.GetObjects() }
      new_roots: set[int] = roots.intersection({ hash(obj) for obj in new_doc.GetObjects() })
      

      And it will give you the set of all root level hashes (GeMarker IDs). I think also the transform copying @Anlv does at the end of the script should not be necessary, because these are root level objects, and therefore removing and re-adding them will not affect their transforms (as they have no parents to which their transform would be relative to). But I have not run @Anlv's full script myself, so it could be that I am overlooking something.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: TreeView DropDown Menu

      Hey,

      yes it is. The trick is c4d.LV_CHECKBOX_HIDE, the relevant bits happen in GetDropDownMenu.

      Cheers,
      Ferdinand

      I removed the command, you can directly run this in the script manager:

      import c4d 
      
      
      PLUGIN_ID = 12345678
      PLUGIN_NAME = "ListView Dropdown Prototype"
      
      ID_TREE_VIEW = 1000
      ID_FILE_NAME = 1001
      ID_IMPORT_OPTION = 1002
      
      ID_IMPORT_OPTION_DEFAULT = 1100
      ID_IMPORT_OPTION_HIGH = 1101
      ID_IMPORT_OPTION_MEDIUM = 1102
      ID_IMPORT_OPTION_LOW = 1103
      
      dummyfile_list = ["hud.stp", "material_reference.wrl", "front_axle.stp", "body.wrl", "wheel_variant.stp"]
      
      
      class DummyFile:
          def __init__(self, file_name, import_option="Default"):
              self.file_name = file_name
              self.import_option = import_option
      
      
      class DummyFileListView(c4d.gui.TreeViewFunctions):
          def __init__(self, dialog):
              self.dialog = dialog
              self.files = [DummyFile(file_name) for file_name in dummyfile_list]
      
          def GetFirst(self, root, userdata):
              return self.files[0] if self.files else None
      
          def GetNext(self, root, userdata, dummy_file):
              current_index = self.files.index(dummy_file)
              next_index = current_index + 1
              return self.files[next_index] if next_index < len(self.files) else None
      
          def GetDown(self, root, userdata, dummy_file):
              return None
      
          def GetId(self, root, userdata, dummy_file):
              return id(dummy_file)
      
          def GetName(self, root, userdata, dummy_file):
              return dummy_file.file_name
      
          def IsSelected(self, root, userdata, dummy_file):
              return False
      
          def GetColumnWidth(self, root, userdata, dummy_file, column_id, area):
              if column_id == ID_FILE_NAME:
                  return area.DrawGetTextWidth(dummy_file.file_name) + 24
              if column_id == ID_IMPORT_OPTION:
                  return 120
              return 96
      
          def GetDropDownMenu(self, root, userdata, dummy_file, column_id, menu_info):
              if column_id != ID_IMPORT_OPTION:
                  menu_info["state"] = c4d.LV_CHECKBOX_HIDE
                  return
      
              if not dummy_file.file_name.lower().endswith(".stp"):
                  menu_info["state"] = c4d.LV_CHECKBOX_HIDE
                  return
      
              options = {
                  ID_IMPORT_OPTION_DEFAULT: "Default",
                  ID_IMPORT_OPTION_HIGH: "High",
                  ID_IMPORT_OPTION_MEDIUM: "Medium",
                  ID_IMPORT_OPTION_LOW: "Low",
              }
              for option_id, label in options.items():
                  menu_info["menu"].SetString(option_id, label)
              menu_info["entry"] = next(
                  option_id for option_id, label in options.items()
                  if label == dummy_file.import_option
              )
              menu_info["state"] = c4d.LV_CHECKBOX_ENABLED
      
          def SetDropDownMenu(self, root, userdata, dummy_file, column_id, entry):
              if column_id != ID_IMPORT_OPTION:
                  return
      
          #this is logical but does not do the trick ....
      
              if not dummy_file.file_name.lower().endswith(".stp"):
                  return
      
              options = {
                  ID_IMPORT_OPTION_DEFAULT: "Default",
                  ID_IMPORT_OPTION_HIGH: "High",
                  ID_IMPORT_OPTION_MEDIUM: "Medium",
                  ID_IMPORT_OPTION_LOW: "Low",
              }
              dummy_file.import_option = options.get(entry, dummy_file.import_option)
              self.dialog.tree_view.Refresh()
      
      
      class ListViewDropdownDialog(c4d.gui.GeDialog):
          def __init__(self):
              self.tree_view = None
              self.file_list_view = DummyFileListView(self)
      
          def CreateLayout(self):
              self.SetTitle(PLUGIN_NAME)
      
              tree_view_settings = c4d.BaseContainer()
              tree_view_settings.SetBool(c4d.TREEVIEW_BORDER, c4d.BORDER_THIN_IN)
              tree_view_settings.SetBool(c4d.TREEVIEW_HAS_HEADER, True)
              tree_view_settings.SetBool(c4d.TREEVIEW_HIDE_LINES, True)
              tree_view_settings.SetBool(c4d.TREEVIEW_RESIZE_HEADER, True)
              tree_view_settings.SetBool(c4d.TREEVIEW_FIXED_LAYOUT, True)
              tree_view_settings.SetBool(c4d.TREEVIEW_ALTERNATE_BG, True)
              if c4d.GetC4DVersion() >= 24000:
                  tree_view_settings.SetInt32(c4d.TREEVIEW_VERTICAL_SPACE, 4)
      
              self.tree_view = self.AddCustomGui(ID_TREE_VIEW, c4d.CUSTOMGUI_TREEVIEW, "", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 500, 220, tree_view_settings, )
              if not self.tree_view:
                  return False
      
              layout = c4d.BaseContainer()
              layout.SetLong(ID_FILE_NAME, c4d.LV_TREE)
              layout.SetLong(ID_IMPORT_OPTION, c4d.LV_DROPDOWN)
              self.tree_view.SetLayout(2, layout)
              self.tree_view.SetHeaderText(ID_FILE_NAME, "Dummy file")
              self.tree_view.SetHeaderText(ID_IMPORT_OPTION, "STP import option")
              self.tree_view.SetRoot(self.tree_view, self.file_list_view, None)
              return True
      
          def InitValues(self):
              self.tree_view.Refresh()
              return True
      
      if __name__ == "__main__":
          dialog = ListViewDropdownDialog()
          dialog.Open(c4d.DLG_TYPE_MODAL, 0, -1, -1, 500, 220)
      
      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: c4d.RSCAMERAOBJECT_COLOR_CONTROLS_CURVE_RGB

      Hey @lasselauch,

      no, that is unfortunately not possible. Unlike for the other big custom data type of Redshift RSFILE, the curve data type RSPFXCURVE does not implement Get/SetParameter to access internals of the data type, as you can for the file type with REDSHIFT_FILE_PATH.

      It also stands a bit to question how such lower desc level access should work here? Maybe as a lower level which can read/write the curve as SplineData? But I am not sure if this type would be faithfully convertable to SplineData`.

      I cannot fix this as Redshift is not part of the Cinema code base where the Python API lives. I gave one of the RS developers a bump so that they maybe can implement Get/SetParameter for that custom data type.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Change render Space (Color Profile) - how?

      You likely have to call UpdateOcioColorSpaces, just follow the example. There is btw no guarantee at all that DOCUMENT_COLOR_MANAGEMENT entails a render space of ACEScg. That is just the default, the user could have changed that.

      I am also not sure what all that RDATA_IMAGECOLORPROFILE code is meant to do. It depends a bit on what your plugin does and what self.IsForceLinear is meant to express. Only so much: An OCIO document does not necessarily entail a bitmap with a non-linear color profile, and OCIO also does not mean that the bitmap has to be 32bit. You are however missing UNDOTYPE_PRIVATE_DOCUMENTDATA undo management for setting the color management.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Change render Space (Color Profile) - how?

      I do not quite understand your question. A node (e.g., an object) will always hold its color parameters in render space. The only exception is NodeData.Init and it is explained in the example.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Change render Space (Color Profile) - how?

      Yes, OCIO having become the standard color management entailed some changes. In case your plugin is some kind of NodeData, you should also look at ocio_node_2025.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Change render Space (Color Profile) - how?

      Hey @mogh,

      you cannot do that, because we do not provide access to GUIs as always, only to the data structures that stand behind them. When you see this dropdown in a document, it means it is in OCIO mode. Which in turns means all colors are in render space; which is the main idea of OCIO that all computations happen in render space. All color read and write operations happen in render space, i.e., ACEScg by default. You can use a color converter to convert a color from for example sRGB to render space. But there is no color space setting for a color, that is just UI fluff. See GetSetColorValuesInSceneElements.

      I would recommend to read:

      • open_color_io_2025_2.py
      • C++ SDK: Ocio Manual

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Change render Space (Color Profile) - how?

      Hey @mogh,

      the answer can be found in the OCIO examples, specifically here. In the example I do the exact opposite from what you want to do, I convert a scene from legacy/basic mode to OCIO. Its inverse would look somewhat like what I show below. I hope this helps.

      Cheers,
      Ferdinand

      """Demonstrates how to convert a document from OCIO color management to basic color management.
      """
      import c4d
      
      
      op: c4d.BaseObject | None # The primary selected object in the scene, can be None.
      doc: c4d.documents.BaseDocument # The currently active document.
      
      def main() -> None:
          """Runs the example.
          """
          # The document is already in basic mode, so no conversion is needed.
          if doc[c4d.DOCUMENT_COLOR_MANAGEMENT] == c4d.DOCUMENT_COLOR_MANAGEMENT_BASIC:
              return c4d.gui.MessageDialog("The document is already in basic mode. No conversion is needed.")
      
          # Get the converter, and the active render space, which by default will be ACEScg.
          converter: c4d.modules.render.SceneColorConverter = c4d.modules.render.SceneColorConverter()
          renderSpace: str = doc.GetOcioRenderingColorSpaceNames()[0]
      
          # Initialize the converter with:
          #              doc, from-low   , from-high   , to
          converter.Init(doc, renderSpace, renderSpace, "scene-linear Rec.709-sRGB")
      
          # Convert everything in the document (we pass the document itself as the second argument). The
          # undo management is only needed so that our DOCUMENT_COLOR_MANAGEMENT below is reversible. The
          # ConvertObject call creates undo steps on its own with the default flag we pass. 
          doc.StartUndo()
          doc.AddUndo(c4d.UNDOTYPE_PRIVATE_DOCUMENTDATA, doc)
          if not converter.ConvertObject(doc, doc):
              print(f"Failed to color convert document '{doc}'.")
      
          # Finally, set the color management mode to basic/legacy. It is absolutely important that we do
          # things in this order, otherwise SceneColorConverter will not work correctly.
          doc[c4d.DOCUMENT_COLOR_MANAGEMENT] = c4d.DOCUMENT_COLOR_MANAGEMENT_BASIC
          doc.EndUndo()
          c4d.EventAdd()
          
      if __name__ == "__main__":
          main()
      
      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: Using SetWeightMap() multiple times can lead to inexplicable changes in weight values

      Hey @chuanzhen,

      thanks for the update. I can reproduce the issue.

      The cause is that some frontend systems can work in a higher precision than the weighting backend can. We use there for some reason UInt16 in the character animation backend to store weights, while the smooth tool for example operates in Float64. Python operates always in 64bit with float. The error is caused by UInt16 normalization (make the value fit into one of the 65535 value bins there are in 16 bit for the range [0, 1]).

      I did not trace down why this happens not at once but in multiple steps, but the bottom line is that sooner or later weights are forced into a 16 bit format. You as a user cannot do anything about it, but it also is not really an issue. This is not a loss of data, the character weights internally use 16bit. It is more that some of the newer tools built around them provide more precise data than the old character animation core can handle.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: MergeDocument() crash C4D

      (As an aside, I found this issue in one of my plugins (which uses MergeDocument). This plugin was developed in C4D 2024, and the same code worked in older versions but crashes in 2026. Even with the same script code and merge same file, it works normally in 2024 but crashes in 2026)

      things can change in the backend of Cinema, without concrete code (the plugin) and example files, I cannot help you much. It could very well be that we added some corner case bug.

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand
    • RE: MergeDocument() crash C4D

      @chuanzhen said in MergeDocument() crash C4D:

      But I still have a question. If it's a plugin issue ( CopyTo Read Write function is not implemented), then why can the Merge command in C4D merge files normally?

      What I meant was this: Imagine you have an ObjectData plugin Foo which has a class instance attribute called _data. Many of Foo's methods rely on _data, as for example GetVirtualObjects, GetDDescription, etc. When you now copy an instance of Foo, Cinema will copy its data container but not _data when you have not implemented CopyTo. On the copied instance of Foo, the _data attribute will either not exist at all or be in uninitialized state. Cinema can then for example crash or freeze when you raise an AttributeError (because you try to access a non-existing _data; or any other error) in a GetDDescription call in some corner cases. _data being misaligned with the data container of a node could also lead to all sorts of bugs when your code assumes that they are somehow aligned.

      In short, Cinema can always read, write, and copy nodes, no matter what you do. But with CopyTo you can make sure that data outside of the data container of the node (BaseList2D.GetDataInstance) is also correctly copied. The lesson here is that when you have fields such as self._my_data on a node, and that field cannot be reestablished on the fly, you must implement Read, Write, and CopyTo, so that _my_data can be written, read, and copied from/to/between scene files. You therefore also usually implement all three of these methods and not just one of them when you need them.

      Cheers,
      Ferdinand

      posted in Cinema 4D SDK
      ferdinandF
      ferdinand