Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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
    • Unread
    • Recent
    • Tags
    • Users
    • Login
    1. Maxon Developers Forum
    2. wen
    W
    • Profile
    • Following 0
    • Followers 0
    • Topics 5
    • Posts 16
    • Best 0
    • Controversial 0
    • Groups 0

    wen

    @wen

    0
    Reputation
    18
    Profile views
    16
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    wen Unfollow Follow

    Latest posts made by wen

    • RE: adding assets to a userdatabase in the assetbrower with Python

      @ferdinand
      Thanks for the clarification. I saw you replying to other post and thought: "Perhaps he didn't see or there is no easy answer"
      It's nice to know someone will have a further look and come back to it later on. On some support forums that's not always the case.
      I had my collegues try the function aswell and it doesn't work for them either. Let's hope Maxime know's what's happening.

      posted in Bugs
      W
      wen
    • RE: adding assets to a userdatabase in the assetbrower with Python

      @ferdinand Could you or someone else please confirm this code works on your end? It's from the examples. I tried it in 2023 and 2025 and can't really think of anything to get it running. I had a look at the decorators.py that's trowing the error but that stuff's a bit over my head.

      Thanks, Bart

      import maxon
      
      def CreateRepositories():
          """Creates repositories for all user databases.
      
          Doing this is usually not necessary for performing light- to medium-sized asset operations, and
          the user preferences repository can then be used instead. Only when there is a substantial
          amount of assets that must be processed, a repository should be constructed to limit the
          search space for search operations. The method CreateRepositoryFromUrl() used in this example
          can also be used to create a repository and its underlying database from scratch when the
          provided URL points to location where no database has been established yet.
          """
          # Wait for all asset databases to be loaded, abort when this is not possible.
          if not maxon.AssetDataBasesInterface.WaitForDatabaseLoading():
              return RuntimeError("Could not load asset databases.")
      
          # Get the default language of Cinema 4D (en-US) for retrieving the repository names.
          defaultLanguage = maxon.Resource.GetDefaultLanguage()
      
          # Iterate over all currently mounted databases and create an asset repository for each of them.
          # Doing this is usually not necessary as user asset databases are automatically part of the
          # the user preferences repository which is easier to retrieve. Creating a repository for a
          # specific user asset database can be useful to speed up asset searches.
          for database in maxon.AssetDataBasesInterface.GetDatabases():
      
              # Create a unique identifier for the repository.
              rid = maxon.AssetInterface.MakeUuid(str(database._dbUrl), True)
      
              # Repositories can be composed out of other repositories which are called bases. In this
              # case no bases are used to construct the repository. But with bases a repository for all
              # user databases could be constructed for example.
              bases = maxon.BaseArray(maxon.AssetRepositoryRef)
      
              # Create a writable and persistent repository for the database URL. If #_dbUrl would point
              # to a location where no database has been yet stored, the necessary data would be created.
              repository = maxon.AssetInterface.CreateRepositoryFromUrl(
                  rid, bases, database._dbUrl, True, False, False)
              if not repository:
                  raise RuntimeError("Repository construction failed.")
      
              # Access some properties of the newly created repository.
              repoId = repository.GetId()
              isWriteable = repository.IsWritable()
              name = repository.GetRepositoryName(defaultLanguage)
      
              print(f"{repository} ({name}): id - {repoId}, writeable: {isWriteable}")
      
      CreateRepositories()
      
      posted in Bugs
      W
      wen
    • RE: adding assets to a userdatabase in the assetbrower with Python

      @ferdinand
      Trying the CreateRepositories() function from the example I'm getting an error. I did not make any changes to the code. Did something change internally perhaps?

      Traceback (most recent call last):
        File "scriptmanager", line 42, in <module>
        File "scriptmanager", line 32, in CreateRepositories
        File "C:\Program Files\Maxon Cinema 4D 2025\resource\modules\python\libs\python311\maxon\decorators.py", line 495, in Auto
          ExecStaticMethod(*args)
      TypeError: unable to convert builtins.NativePyData to @net.maxon.interface.class-cR
      

      This line seems to be the problem:

      repository = maxon.AssetInterface.CreateRepositoryFromUrl(rid, bases, database._dbUrl, True, False, False)
      
      posted in Bugs
      W
      wen
    • RE: adding assets to a userdatabase in the assetbrower with Python

      Hi @ferdinand

      Going over it a bit more indepth I see this could work for what I want. It does leave me with a question though:

      # Iterate over all currently mounted databases and create an asset repository for each of them.
      # Doing this is usually not necessary as user asset databases are automatically part of the
      # the user preferences repository which is easier to retrieve. Creating a repository for a
      # specific user asset database can be useful to speed up asset searches.
      

      I was under the assumption userdatabases are by default already part of some other repository than the standard ones. Here it's stated they automaticlally become part of the user preferences repository. Does that mean I can somehow specify which database to use if there are multiple in the user preferences repository?

      posted in Bugs
      W
      wen
    • adding assets to a userdatabase in the assetbrower with Python

      I'm trying to add my materials to the asset browser through a python script. I'm basing my script on the code examples from: https://github.com/Maxon-Computer/Cinema-4D-Python-API-Examples/tree/master/scripts/05_modules/assets
      The thing I can't seem to figure out is how to add an asset to a user database instead of one of the standard databases.
      In the examples a repository is given as an argument to the storeAssetStruct function who's result is passed to the CreateMaterialAsset function that stores the asset to the assetbrowser.

      repository = maxon.AssetInterface.GetUserPrefsRepository()
      storeAssetStruct = maxon.StoreAssetStruct(assetCategoryId, repository, repository)
      assetDescription = maxon.AssetCreationInterface.CreateMaterialAsset(doc, mat, storeAssetStruct, assetId, assetName, assetVersion, assetMetadata, True)
      

      From what I understand the UserPrefsRepository tells the function to use the standard database Preferences. This leads me to think I would need to find the repository for the userdatabases. I can find the database object but have no clue how to get to the repository from there. Can you point me in the right direction?

      Thanks, Bart

      posted in Bugs python
      W
      wen
    • RE: connect material to reference node

      Hi Ferdinant,
      I didn't understand what you meant regarding the difference of setting an attribute and a port. I was trying to set the object slot as an attr in SetValue. But the presence of a separate command makes it clear. I changed SetValue to SetPortValue and it works.
      I found the examples on github before but the graph descriptions page is new to me. I'll have a look.
      Thanks!
      Bart

      posted in Cinema 4D SDK
      W
      wen
    • RE: connect material to reference node

      @ferdinand
      Hi Ferdinant,
      Thanks for helping out. I am however still not able to achieve what I want to do with your example. I see i forgot to specify the "object" port resulting in a null value.

      I am however still running in to the same error as before:

      Traceback (most recent call last):
        File "C:\C4D_LIB\scripts\SetupMUS.py", line 180, in <module>
          new_materials.append(create_redshift_material(line, keys))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "C:\C4D_LIB\scripts\SetupMUS.py", line 130, in create_redshift_material
          reference_input_port.SetValue(materialUuid)
      TypeError: GraphNode.SetValue() missing 1 required positional argument: 'value'
      

      I did not want to post the whole script as it's a bit messy still but perhaps it helps to clarify what I'm doing.
      I'm importing an excelsheet containing the names of the materials i want to setup. The creating of the materials works. I'm running into trouble trying to link other materials to the reference nodes i created.

      import c4d  # Import the Cinema 4D module
      import maxon
      import pandas as pd  # Import the pandas library for data manipulation
      import numpy as np  # Import the numpy library for numerical operations
      
      # Reference to the active Cinema 4D document
      doc: c4d.documents.BaseDocument
      
      def read_mus(file_path: str) -> tuple:
          """Reads an Excel file and returns its content as a list of lists and the column keys."""
      
          df = pd.read_excel(file_path)  # Read the Excel file into a pandas DataFrame
          keys = df.keys()
          mus = df.apply(lambda row: [int(value) if isinstance(value, np.int64) else value for value in row], axis=1).tolist() #process each row (axis=1) of the DataFrame and convert certain values to integers.
          if is_nan(mus):
              c4d.gui.MessageDialog("MUS contains empty fields. Please fill those with a material.")
              raise RuntimeError("{0} has NaN values".format(file_path))
          else:
              return mus, keys
      
      def is_nan(list_of_lists):
          """check list for NaN values"""
          flattened_list = [item for sublist in list_of_lists for item in sublist]
          return (pd.Series(flattened_list).isna().any())
      
      
      def find_reference_material(reference_node) -> c4d.Material:
          scene_materials  = doc.GetMaterials()
          for mat in scene_materials:
              if mat.GetName() == reference_node.GetValue(maxon.NODE.BASE.NAME):
                  return mat
      
      
      def get_materialUuid():
          pass
      
      def create_redshift_material(mus_line: list, keys: list) -> None:
          """Creates a Redshift material based on the provided data."""
          material_id, material_name, add_print, *cima_materials = mus_line
          cimas = keys[3:]
      
          # Define the node asset IDs for various Redshift nodes
          node_ids = {
              "output": maxon.Id("com.redshift3d.redshift4c4d.node.output"),
              "standard_material": maxon.Id("com.redshift3d.redshift4c4d.nodes.core.standardmaterial"),
              "reference": maxon.Id("com.redshift3d.redshift4c4d.node.reference"),
              "userdata_int": maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rsuserdatainteger"),
              "shader_switch": maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rsshaderswitch"),
              "material_blender": maxon.Id("com.redshift3d.redshift4c4d.nodes.core.materialblender"),
              "texture": maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler"),
          }
      
          # Create a new material
          material: c4d.BaseMaterial = c4d.BaseMaterial(c4d.Mmaterial)
          if not material:
              raise MemoryError("Material creation failed.")
      
          material.SetName("{0}_{1}".format(str(material_id).zfill(2),material_name ))
      
          # Create an empty graph for the Redshift material space
          node_material: c4d.NodeMaterial = material.GetNodeMaterialReference()
          graph: maxon.GraphModelRef = node_material.CreateEmptyGraph(maxon.Id("com.redshift3d.redshift4c4d.class.nodespace"))
          if graph.IsNullValue():
              raise RuntimeError("Could not add Redshift graph to material.")
      
          # Start an undo operation
          if not doc.StartUndo():
              raise RuntimeError("Could not start undo stack.")
      
          # Insert the material into the document
          doc.InsertMaterial(material)
          if not doc.AddUndo(c4d.UNDOTYPE_NEWOBJ, material):
              raise RuntimeError("Could not add undo item.")
      
          # Define user data for the transaction
          user_data: maxon.DataDictionary = maxon.DataDictionary()
          user_data.Set(maxon.nodes.UndoMode, maxon.nodes.UNDO_MODE.ADD)
      
          # Retrieve the current node space Id
          nodespaceId = c4d.GetActiveNodeSpaceId()
      
          # Retrieve the Nimbus reference for a specific nodeSpace
          nimbusRef = material.GetNimbusRef(nodespaceId)
          if nimbusRef is None:
              raise ValueError("Cannot retrieve the nimbus ref for that node space")
      
          # Begin a transaction to modify the graph
          with graph.BeginTransaction(user_data) as transaction:
              out_node: maxon.GraphNode = graph.AddChild(maxon.Id(), node_ids["output"])
              out_surface_port: maxon.GraphNode = out_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.node.output.surface")
              out_node.SetValue(maxon.NODE.BASE.NAME, material_name)
              out_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.node.output.materialid").SetPortValue(material_id)
      
              # Add user data integer node
              userdata_int_node: maxon.GraphNode = graph.AddChild(maxon.Id(), node_ids["userdata_int"])
              userdata_int_output_port: maxon.GraphNode = userdata_int_node.GetOutputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.rsuserdatainteger.out")
              userdata_int_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.rsuserdatainteger.attribute").SetPortValue("CIMA")
              userdata_int_node.SetValue(maxon.NODE.BASE.NAME, "CIMA SELECTOR")
      
              # Add shader switch node
              shader_switch_node: maxon.GraphNode = graph.AddChild(maxon.Id(), node_ids["shader_switch"])
              shader_switch_select_port: maxon.GraphNode = shader_switch_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.rsshaderswitch.selector")
              shader_switch_output_port: maxon.GraphNode = shader_switch_node.GetOutputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.rsshaderswitch.outcolor")
      
      
              print_added = False
              # Create and connect MaterialBlender and Reference nodes
              for num, material_reference in enumerate(cima_materials):
                  scaffold_node : maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.scaffold"))
                  scaffold_node.SetValue(maxon.NODE.BASE.NAME, cimas[num])
      
                  material_blender_node: maxon.GraphNode = graph.AddChild(maxon.Id(), node_ids["material_blender"])
                  material_blender_node.SetValue("net.maxon.node.attribute.scaffoldid", scaffold_node.GetId())
      
                  reference_node: maxon.GraphNode = graph.AddChild(maxon.Id(), node_ids["reference"])
                  reference_node.SetValue("net.maxon.node.attribute.scaffoldid", scaffold_node.GetId())
                  reference_node.SetValue(maxon.NODE.BASE.NAME, cima_materials[num])
      
                  #use "material_blender_node.GetInputs().GetChildren()" to list al the ports
                  material_blender_base_port: maxon.GraphNode = material_blender_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.materialblender.basecolor")
                  material_blender_blend1_port: maxon.GraphNode = material_blender_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.materialblender.blendcolor1")
                  material_blender_material1_port: maxon.GraphNode = material_blender_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.materialblender.layercolor1")
                  material_blender_output_port: maxon.GraphNode = material_blender_node.GetOutputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.materialblender.out")
      
                  reference_output_port: maxon.GraphNode = reference_node.GetOutputs().FindChild("com.redshift3d.redshift4c4d.node.reference.output.")
                  reference_input_port: maxon.GraphNode = reference_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.node.reference.object")
                  reference_output_port.Connect(material_blender_base_port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
      
                  materialUuid: maxon.Uuid = nimbusRef.BaseList2DToUuid(find_reference_material(reference_node))
                  #reference_input_port.SetValue(materialUuid)
      
      
                  shader_switch_shader_port: maxon.GraphNode = shader_switch_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.rsshaderswitch.shader"+str(num))
      
                  if add_print:
                      if not print_added:
                                  print_added = True
                                  texture_node: maxon.GraphNode = graph.AddChild(maxon.Id(), node_ids["texture"])
                                  texture_output_port: maxon.GraphNode = texture_node.GetOutputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor")
                      reference_node: maxon.GraphNode = graph.AddChild(maxon.Id(), node_ids["reference"])
                      reference_node.SetValue(maxon.NODE.BASE.NAME, "Print Color")
                      reference_node.SetValue("net.maxon.node.attribute.scaffoldid", scaffold_node.GetId())
                      reference_output_port: maxon.GraphNode = reference_node.GetOutputs().FindChild("com.redshift3d.redshift4c4d.node.reference.output.")
                      texture_output_port.Connect(material_blender_blend1_port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
                      reference_output_port.Connect(material_blender_material1_port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
      
                  material_blender_output_port.Connect(shader_switch_shader_port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
                  material_blender_node.SetValue(maxon.NODE.BASE.NAME, cimas[num])
      
                          # Optionally add texture node
      
              # Connect the nodes
              userdata_int_output_port.Connect(shader_switch_select_port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
              shader_switch_output_port.Connect(out_surface_port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
      
              # Commit the transaction
              transaction.Commit()
      
      
          # End the undo operation
          if not doc.EndUndo():
              raise RuntimeError("Could not end undo stack.")
      
          return material
      
      def alert_material_names(message, materials):
          """Pops up a message window with the message followed by the names of the materials"""
          for mat in materials:
              message += (mat.GetName()+"\n")
          c4d.gui.MessageDialog(message)
      
      # Entry point of the script
      """Only run this if this script called directly and not imported"""
      if __name__ == "__main__":
          excel_path = r"C:\Users\wen\Desktop\MUS.xlsx"  # Specify the path to the Excel file
          #excel_path = c4d.storage.LoadDialog(title = "Load EXCEL Document")
          mus, keys = read_mus(excel_path)
          new_materials = []
          for line in mus:
              new_materials.append(create_redshift_material(line, keys))
          alert_material_names("The following materials have been created: \n", new_materials)
      
          # Refresh the Cinema 4D interface
          c4d.EventAdd()
      
      posted in Cinema 4D SDK
      W
      wen
    • connect material to reference node

      Hi Forum,

      I'm trying to connect a material to a reference node. Icouldn't find any examples with the reference node in the code examples. I'm assuming i do this with SetValue() similar to setting the name, like this:

      reference_node.SetValue(maxon.NODE.BASE.NAME, material_reference)
      

      So I'm trying things like:

      reference_input_port: maxon.GraphNode = reference_node.GetInputs().FindChild("com.redshift3d.redshift4c4d.node.reference")
      reference_input_port.SetValue(maxon.NODE.BASE.CONNECTNODE, find_reference_material(reference_node))
      

      unfortunately that doesn't work as it's the wrong attr and crashes cinema4d.
      Can somebody help me and tell how i can findout what the attr is I should be using?

      Thanks,
      Bart

      posted in Cinema 4D SDK 2025 python
      W
      wen
    • RE: Access renderer specific settings with python

      Hi Ferdinand,

      I am indeed running R22. Your comment about using the document associated with the render was spot on. I assumed they would be the same document but apparently they are not. After changing this it works as expected.

      I've included a working example incase someone else is looking for the same thing.
      Render_viewTransform.c4d

      Got a new question though, what do you mean with:
      "In R25 Redshift does not have a "Raw" color profile anymore"
      Had a look at R25 and didn't see anything different in that regard.

      Thanks!

      posted in Cinema 4D SDK
      W
      wen
    • RE: Access renderer specific settings with python

      Hi Ferdinant,
      Thanks for the example.
      I'm trying to use a python tag to set the view to raw when doing final renders and have it on SDR during interactive renders.
      The settings are being set but somehow this doesnt trigger an update it appears. Only when manually forcing an update on the rendersetting it is changed. This is the code I'm using:

      import c4d
      import redshift
      
      def changeSettings(obj, videoPost, isRendering):
          if isRendering:
              segs = 24
              view = r"Raw"
          else:
              segs = 3
              view = r"ACES 1.0 SDR-video"
      
          # avoid applying redundant changes
          if obj[c4d.PRIM_SPHERE_SUB] != segs:
              print("Setting to %d" %segs)
              obj[c4d.PRIM_SPHERE_SUB] = segs
              print(view)
              videoPost[c4d.REDSHIFT_RENDERER_COLOR_MANAGEMENT_OCIO_VIEW] = view
              obj.Message(c4d.MSG_CHANGE)
      
              # EvenAdd is only needed when modifying the active document
              if doc == c4d.documents.GetActiveDocument():
                  c4d.EventAdd()
      
      def main():
          pass
      
      def message(msgType, data):
          print
          # Check for final renders
          if msgType==c4d.MSG_MULTI_RENDERNOTIFICATION:
              redshiftRenderEngineId = 1036219
              my_render_data = c4d.documents.GetActiveDocument().GetActiveRenderData()
              videoPost = my_render_data.GetFirstVideoPost()
      
              while (videoPost):
                  if videoPost.CheckType(redshiftRenderEngineId):
                      break
                  videoPost = videoPost.GetNext()
              started = data["start"]
              if started:
                 print("Render Started")
              else:
                 print("Render Finished")
      
              changeSettings(op.GetObject(), videoPost, started)
      

      I've also incuded a test file
      Render_viewTransform.c4d

      posted in Cinema 4D SDK
      W
      wen