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. Anlv
    3. Posts
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 4
    • Posts 19
    • Groups 0

    Posts

    Recent Best Controversial
    • RE: MergeDocument() crash C4D

      Hi, @chuanzhen

      I tested the same code as you in both saved projects and unsaved new documents, but no crash occurred. This might be a bug, possibly related to the ObjectData plugin in your project. I can't be certain that's the cause. You could try ruling out the plugin's influence first. But this is beyond my capability, so let's wait for more professional personnel to help.

      Cheers,
      Anlv

      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • RE: MergeDocument() crash C4D

      Hi, @chuanzhen

      This code runs fine on my end (Cinema 4D 2026.3.4). Analyzing the cause of the failure may require more detailed information, such as the Cinema 4D version number and the real path (path resolution may occur), and corruption of the path_str file is also one possibility.

      Cheers,
      Anlv

      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • RE: Disable all animation in document

      Hi @ferdinand,

      using the mxutils.RecurseGraph method is much clearer and simpler. Thank you, I've learned something new again.

      Cheers,
      Anlv

      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • RE: Disable all animation in document

      @ceen Hi, The Summary row mey only a UI aggregate; it is not a single CTrack that can be switched directly.
      To reproduce its Animation switch, collect the real CTrack objects and set their c4d.ID_CTRACK_ANIMOFF value:

      # True = animation enabled, False = animation disabled
      track[c4d.ID_CTRACK_ANIMOFF] = False
      

      This does not delete keyframes and does not hide Timeline rows. Do not use NBIT_TLx_HIDE for this, because those flags only hide rows in the Timeline.
      A complete document-wide solution must also traverse Motion Sources in doc.GetNLARoot() . Add Motion Source moves/copies animation into that separate NLA hierarchy, so iterating only normal scene objects and tags will miss tracks such as Time and 2D Tracks.

      It should be noted that doc.GetNLARoot() is marked as Private in the SDK, and I'm not sure whether it should be used.

      """Toggle the Summary Animation switch for all collected CTracks."""
      
      import c4d
      
      
      def iter_nodes(node):
          while node:
              yield node
              yield from iter_nodes(node.GetDown())
              node = node.GetNext()
      
      
      def main():
          doc = c4d.documents.GetActiveDocument()
          tracks, seen = [], set()
      
          def add_tracks(owner):
              for track in (owner.GetCTracks() or []) if owner else []:
                  if id(track) not in seen:
                      seen.add(id(track))
                      tracks.append(track)
      
          def add_tree(root, include_tags=False):
              for node in iter_nodes(root):
                  add_tracks(node)
                  if include_tags:
                      for tag in node.GetTags() or []:
                          add_tracks(tag)
      
          add_tracks(doc)
          add_tree(doc.GetFirstObject(), include_tags=True)
      
          material = doc.GetFirstMaterial()
          while material:
              add_tracks(material)
              add_tree(material.GetFirstShader())
              material = material.GetNext()
      
          render_data = doc.GetFirstRenderData()
          while render_data:
              add_tracks(render_data)
              video_post = render_data.GetFirstVideoPost()
              while video_post:
                  add_tracks(video_post)
                  video_post = video_post.GetNext()
              render_data = render_data.GetNext()
      
          layer_root = doc.GetLayerObjectRoot()
          add_tree(layer_root.GetDown() if layer_root else None)
      
          # Private API, but required for Add Motion Source tracks in C4D 2026.
          add_tree(doc.GetNLARoot().GetDown(), include_tags=True)
      
          enabled = any(track[c4d.ID_CTRACK_ANIMOFF] for track in tracks)
          for track in tracks:
              track[c4d.ID_CTRACK_ANIMOFF] = not enabled
          c4d.EventAdd()
      
      
      if __name__ == "__main__":
          main()
      

      Cheers,
      Anlv

      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • RE: Using SetWeightMap() multiple times can lead to inexplicable changes in weight values

      This appears to be a Float32-to-quantized-weight conversion or rounding issue in SetWeightMap(), rather than ordinary floating-point noise.

      Cinema 4D version: 2026.3.4
      Expected: unchanged values after every round-trip.
      Round  0: weight=0.14285496299687189 (14.28549630%), total=0.99998474097810308 (99.99847410%)
      Round  1: weight=0.1428397039749752 (14.28397040%), total=0.99987792782482621 (99.98779278%)
      Round 10: weight=0.14270237277790493 (14.27023728%), total=0.99891660944533434 (99.89166094%)
      Round 19: weight=0.14256504158083466 (14.25650416%), total=0.99795529106584246 (99.79552911%)
      Round 20: weight=0.14256504158083466 (14.25650416%), total=0.99795529106584246 (99.79552911%)
      Round 25: weight=0.14256504158083466 (14.25650416%), total=0.99795529106584246 (99.79552911%)
      
      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • RE: Mesh Emitter CallCommand works in Script Manager, no-op from plugin

      Hi, @atg Simply remove the invalid child IDs after the commands recorded in the script log, for example:

      c4d.CallCommand(1062577, 1067510) → c4d.CallCommand(1062577)
      

      I remember encountering the same issue before, but I can’t quite recall the details. I need to look it up.

      import c4d
      
      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.
          """
          c4d.CallCommand(1062577)  # Mesh Emitter
      
      if __name__ == '__main__':
          main()
      

      How do I retrieve a command call from it's index number ?

      Cheers,
      Anlv

      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • RE: [Free Plugin]Plugin Debug Manager v1.3.0— Python Plugin Reloading for Cinema 4D

      @ferdinand Thank you so much!
      I made some minor adjustments to the plugin, adding support for CTRL hotkey activation, which allows quick reloading of previously checked plugins that need to be reloaded without opening the window. As always, open source, and will continue to be open source.
      Download: Plugin Debug Manager v1.5.0.zip
      Cheers,
      Anlv

      posted in General Talk
      AnlvA
      Anlv
    • [Free Plugin]Plugin Debug Manager v1.3.0— Python Plugin Reloading for Cinema 4D

      Hi everyone, I’m releasing Plugin Debug Manager, a debugging utility for Cinema 4D Python plugin development.

      When working on a .pyp plugin, changing a single entry file can otherwise require reloading every Python plugin—or restarting Cinema 4D. Plugin Debug Manager reads the currently registered Python plugins and lets developers reload only the entries they are testing.

      Main features:

      • Reads registered .pyp and .pypv plugins from Cinema 4D
      • Groups multiple registrations by their actual entry-file path
      • Displays plugin names, icons, decimal IDs, registration types, and full paths
      • Filters entries by filename or plugin ID
      • Reloads one plugin, selected plugins, or all reloadable plugins
      • Supports click-and-drag checkbox painting for batch selection
      • Persists checked entries and can move them to the top on demand
      • Provides Reload Plugin, Reload All, Fold All, and Unfold All context commands
      • Locates plugin files in Explorer or Finder through c4d.storage.ShowInFinder()
      • Continues processing when an individual plugin fails to reload

      Implementation details:

      • Registry entries are collected with c4d.plugins.FilterPluginList(c4d.PLUGINTYPE_ANY, True)
      • Entry files and registration metadata are obtained through BasePlugin.GetFilename(), GetID(), and GetType()
      • Selective reloads are performed with c4d.plugins.ReloadPythonPlugin()
      • ReloadDocumentAfterReload(True) is called only once after the reload batch

      Before reloading, the manager copies and normalizes the target file paths instead of retaining BasePlugin objects that may become invalid during the reload process. The manager itself remains visible in the list but cannot be selected or reloaded.

      Compatibility:

      • Current target: Cinema 4D 2026.3.3
      • Selective reloading depends on c4d.plugins.ReloadPythonPlugin, available in this version
      • Other Cinema 4D versions have not yet been verified
        2d3c073d-21ea-4e6f-8bba-4a84aee4c964-Anlv_2026-07-27_14-40-53.png

      Version: 1.3.0
      Plugin ID: 1069486
      Author: Anlv
      Download: Plugin Debug Manager v1.3.0.zip

      By the way, this is open source, and you can edit and modify it yourself to make it better suit your work habits.

      Best regards,
      Anlv

      posted in General Talk plugin-information download programming
      AnlvA
      Anlv
    • RE: Problem with Undo when using COLOR field in a description resource

      @ferdinand Hi, I think the issue has been fixed. I just tried uploading an attachment (before uploading, I cleared the cache and changed the network environment), and it no longer prompts "Error: Something went wrong while parsing server response."

      Thanks for your help,
      Anlv

      posted in Bugs
      AnlvA
      Anlv
    • RE: Problem with Undo when using COLOR field in a description resource

      @ferdinand A small update:

      My first attempt to open the upload endpoint directly only returned Forbidden and did not display a visible Cloudflare verification page.

      I then used a small userscript to submit a real multipart file upload as a top-level browser navigation instead of an XHR request. That request succeeded and returned the normal NodeBB JSON response:

      {"status":{"code":"ok","message":"OK"}}
      

      More importantly, after this top-level request, the forum’s normal attachment uploader also started working successfully.

      This suggests that the top-level request allowed Cloudflare to complete or refresh its verification/clearance state, while the original XHR upload could not handle the HTML Challenge response. It appears to be a Cloudflare Challenge/clearance issue rather than a damaged file or a failure in NodeBB’s upload handler.

      posted in Bugs
      AnlvA
      Anlv
    • RE: Problem with Undo when using COLOR field in a description resource

      @ferdinand Hi Ferdinand,

      I reproduced the upload failure and found that it is caused by a Cloudflare Challenge, rather than NodeBB itself.

      The upload request completes, but the response is:

      • Endpoint: POST /forum/api/post/upload
      • Status: 403 Forbidden
      • Server: cloudflare
      • cf-mitigated: challenge
      • Content-Type: text/html; charset=UTF-8
      • Ray ID: a1c1af0daaf34f1a-LAX
      • Time: 16 July 2026, 14:26:46 UTC

      Cloudflare returns an HTML Challenge Page to the XHR upload request. NodeBB expects a JSON upload response, so its parser subsequently reports: “Something went wrong while parsing server response.” The 100% progress only indicates that the browser finished sending the request body.

      Could you please look up this Ray ID in Cloudflare Security Events to identify which WAF/Bot Management rule issued the challenge? A narrowly scoped exception for POST /forum/api/post/upload may resolve it, since an interactive Challenge Page cannot be completed inside this AJAX upload request.

      I tested with a small PNG file in Chrome on Windows. I can provide additional non-sensitive request details if needed.

      Cheers,
      Anlv

      posted in Bugs
      AnlvA
      Anlv
    • RE: Problem with Undo when using COLOR field in a description resource

      Hi Ferdinand,

      Here is an identical situation. I can see the file upload progress reaching 100%, followed by the error message: "Error: Something went wrong while parsing server response."

      Since I am unable to successfully upload the image, below is the console information I copied.

      nodebb.min.js?v=0b8ddba251d:65  POST https://developers.maxon.net/forum/api/post/upload 403 (Forbidden)
      send @ nodebb.min.js?v=0b8ddba251d:65
      ajax @ nodebb.min.js?v=0b8ddba251d:65
      (anonymous) @ nodebb.min.js?v=0b8ddba251d:51
      r.fn.ajaxSubmit @ nodebb.min.js?v=0b8ddba251d:51
      (anonymous) @ topic.1839ecb58ed413849a53.min.js:3
      dispatch @ nodebb.min.js?v=0b8ddba251d:62
      De.handle @ nodebb.min.js?v=0b8ddba251d:62
      trigger @ nodebb.min.js?v=0b8ddba251d:63
      (anonymous) @ nodebb.min.js?v=0b8ddba251d:63
      each @ nodebb.min.js?v=0b8ddba251d:62
      each @ nodebb.min.js?v=0b8ddba251d:62
      trigger @ nodebb.min.js?v=0b8ddba251d:63
      a.fn.<computed> @ nodebb.min.js?v=0b8ddba251d:65
      push.43103.v.ajaxSubmit @ topic.1839ecb58ed413849a53.min.js:3
      (anonymous) @ topic.1839ecb58ed413849a53.min.js:3
      dispatch @ nodebb.min.js?v=0b8ddba251d:62
      De.handle @ nodebb.min.js?v=0b8ddba251d:62
      

      Cheers,
      Anlv

      posted in Bugs
      AnlvA
      Anlv
    • Plugin Manager "Create Reload Script" generates invalid Python string path on Windows

      Hi Community,

      I noticed a small issue with Plugin Manager → Create Reload Script on Windows.

      I often use Reload Python Plugins while developing Python plugins, but it reloads all Python plugins. In some cases, especially with renderer-related plugins, this can also trigger viewport/material refreshes.

      Create Reload Script is very useful because it allows reloading a specific plugin only. However, on Windows, the generated script uses an unescaped path with backslashes:

      plugins.ReloadPythonPlugin(
          path="C:\Users\<user>\AppData\Roaming\Maxon\Maxon Cinema 4D 2026_XXXXXXXX\plugins\PluginName\PluginName.pyp",
          reloadDocumentAfterReload=False,
          reloadOnlyActiveDocument=False
      )
      

      Running the generated script in the Script Manager causes:

      SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
      

      Manually replacing \ with /, using a raw string, or escaping the backslashes fixes the issue.

      It would be great if Create Reload Script could generate a Python-safe path automatically on Windows.

      Thanks!

      posted in Bugs programming off-topic-question
      AnlvA
      Anlv
    • RE: How to start a new line in plugin help with localization?

      Another small tip: you can simply use a single <br> for line breaks — there’s no need to use <b> or </b>.

      Also, just like in the script example, scripts can support localized language strings as well:

      """
      Name-US:Example
      Name-CN:示例
      Description-US:Example line 1.<br>Example line 2.<br>Example line 3.
      Description-CN:示例第 1 行。<br>示例第 2 行。<br>示例第 3 行。
      """
      
      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • RE: How to select multiple files using "c4d.storage.LoadDialog()"?

      Hi @ferdinand,

      Yes, this example was written with the help of AI, and I performed a basic review;

      I wanted to avoid installing dependencies, so I used the currently supported ctypes, but I indeed did not fully consider the issue of supporting every operating system. Thank you for the reminder.

      Best regards,
      Anlv

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

      @ferdinand Thanks for the encouragement, much appreciated!

      posted in General Talk
      AnlvA
      Anlv
    • Is it okay to release a free plugin that overlaps with paid alternatives?

      Hi everyone,

      I’m looking for some community advice. I’ve accumulated a collection of personal scripts from my previous work, and I’m now planning to integrate them into a single plugin to release for free.

      However, I’ve realized that the integrated features are quite similar to several existing paid or subscription-based plugins on the market. I’m a bit concerned about whether releasing a free alternative would be seen as "harmful" to the developers who rely on those paid tools.

      What is the general etiquette regarding this in the developer community? I would love to hear your thoughts. Thank you!

      posted in General Talk off-topic
      AnlvA
      Anlv
    • RE: How to select multiple files using "c4d.storage.LoadDialog()"?

      Hello @ferdinand,

      Thank you very much for your detailed guidance and for pointing out the necessary forum procedures.

      Following your suggestion, I managed to implement the multi-file selection feature by utilizing a third-party GUI API, and I successfully outputted the selected file paths to the console.

      Please note that this solution has only been tested on the Windows so far. I am sharing my example script below in the hope that it might help other developers facing the same requirement:

      import ctypes
      from ctypes import wintypes
      
      
      # Flags used by the Windows file dialog.
      OFN_EXPLORER = 0x00080000          # Use the Explorer-style dialog.
      OFN_ALLOWMULTISELECT = 0x00000200  # Allow selecting multiple files.
      OFN_FILEMUSTEXIST = 0x00001000     # Require selected files to exist.
      OFN_PATHMUSTEXIST = 0x00000800     # Require the selected path to exist.
      MAX_BUFFER = 65536                 # Buffer size used to receive the result.
      
      
      # OPENFILENAMEW structure used by the Windows API.
      class OPENFILENAMEW(ctypes.Structure):
          _fields_ = [
              ("lStructSize", wintypes.DWORD),
              ("hwndOwner", wintypes.HWND),
              ("hInstance", wintypes.HINSTANCE),
              ("lpstrFilter", wintypes.LPCWSTR),
              ("lpstrCustomFilter", ctypes.c_wchar_p),
              ("nMaxCustFilter", wintypes.DWORD),
              ("nFilterIndex", wintypes.DWORD),
              ("lpstrFile", ctypes.c_wchar_p),
              ("nMaxFile", wintypes.DWORD),
              ("lpstrFileTitle", ctypes.c_wchar_p),
              ("nMaxFileTitle", wintypes.DWORD),
              ("lpstrInitialDir", wintypes.LPCWSTR),
              ("lpstrTitle", wintypes.LPCWSTR),
              ("Flags", wintypes.DWORD),
              ("nFileOffset", wintypes.WORD),
              ("nFileExtension", wintypes.WORD),
              ("lpstrDefExt", wintypes.LPCWSTR),
              ("lCustData", wintypes.LPARAM),
              ("lpfnHook", wintypes.LPVOID),
              ("lpTemplateName", wintypes.LPCWSTR),
              ("pvReserved", wintypes.LPVOID),
              ("dwReserved", wintypes.DWORD),
              ("FlagsEx", wintypes.DWORD),
          ]
      
      
      def open_multiple_files():
          # Create a writable Unicode buffer to receive the file path data from Windows.
          buffer = ctypes.create_unicode_buffer(MAX_BUFFER)
      
          # Configure the parameters for the file-open dialog.
          ofn = OPENFILENAMEW()
          ofn.lStructSize = ctypes.sizeof(OPENFILENAMEW)
          ofn.hwndOwner = None
          ofn.lpstrFilter = "All Files\0*.*\0Text Files\0*.txt\0\0"
          ofn.lpstrFile = ctypes.cast(buffer, ctypes.c_wchar_p)
          ofn.nMaxFile = MAX_BUFFER
          ofn.lpstrTitle = "Select Files"
          ofn.Flags = (
              OFN_EXPLORER
              | OFN_ALLOWMULTISELECT
              | OFN_FILEMUSTEXIST
              | OFN_PATHMUSTEXIST
          )
      
          # Call the native Windows file selection dialog.
          comdlg32 = ctypes.windll.comdlg32
          result = comdlg32.GetOpenFileNameW(ctypes.byref(ofn))
      
          # The user canceled the dialog, or the call failed.
          if not result:
              err = comdlg32.CommDlgExtendedError()
              if err:
                  print("GetOpenFileNameW failed, error code:", err)
              return []
      
          # Read the returned content from the buffer.
          # Single selection: returns a full file path.
          # Multiple selection: returns [directory, file1, file2, ...].
          raw = ctypes.wstring_at(ctypes.addressof(buffer), MAX_BUFFER)
          parts = [p for p in raw.split("\0") if p]
      
          if not parts:
              return []
      
          # If only one file was selected, return the full path directly.
          if len(parts) == 1:
              return [parts[0]]
      
          # If multiple files were selected, combine the directory with each filename.
          directory = parts[0]
          filenames = parts[1:]
          return [directory + "\\" + name for name in filenames]
      
      
      def main():
          paths = open_multiple_files()
      
          if not paths:
              print("No file selected.")
              return
      
          print("Selected files:")
          for path in paths:
              print(path)
      
      
      if __name__ == "__main__":
          main()
      
      

      Best regards,
      Anlv

      posted in Cinema 4D SDK
      AnlvA
      Anlv
    • How to select multiple files using "c4d.storage.LoadDialog()"?

      Hi everyone,
      I found that through the “Open...” or “Merge...” options in the File menu, I can open “Load File(s)”, which allows handling multiple files.
      However, with c4d.storage.LoadDialog(), I can only select a single folder or file.
      In the latest SDK documentation, I couldn’t find a method to load multiple files. Is this an internal API?
      My current workaround is using AddMultiLineEditText, but it’s not very user-friendly.

      PixPin_2026-04-03_16-35-15.png

      import c4d
      
      
      def main():
          path = c4d.storage.LoadDialog(
              title="Select File",
              type=c4d.FILESELECTTYPE_ANYTHING,
              flags=c4d.FILESELECT_LOAD,
          )
      
          print(path)
      
      
      if __name__ == '__main__':
          main()
      
      posted in Cinema 4D SDK python 2026 windows
      AnlvA
      Anlv