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

    Geometry Axis asset node and LoadAssets

    Cinema 4D SDK
    python s26
    4
    7
    1.3k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • iplaiI
      iplai
      last edited by iplai

      My script works and I got what I want, but there are two problems.

      • maxon.AssetManagerInterface.LoadAssets always return False event the asset loaded successfully.

      • I set the parameters of Geometry Axis by find the param's name. Is there a better way to change the parameters?

      import maxon, c4d
      
      def loadGeometryAxis(x=0, y=0, z=0, parent: c4d.BaseList2D = None):
          repository = maxon.AssetInterface.GetUserPrefsRepository()
          if not repository:
              raise RuntimeError("Could not access the user preferences repository.")
          # Geometry Axis asset id
          assetid = maxon.Id("net.maxon.neutron.asset.geo.geometryaxis")
          assetsToLoad = [(assetid, ""), ]
          sceneNodesHook = doc.FindSceneHook(c4d.SCENENODES_IDS_SCENEHOOK_ID)
          if not sceneNodesHook:
              raise RuntimeError("Could not retrieve Scene Nodes scene hook.")
          sceneNodesHook.Message(maxon.neutron.MSG_CREATE_IF_REQUIRED)
          sceneNodes = sceneNodesHook.GetNimbusRef(maxon.neutron.NODESPACE)
          if not sceneNodes:
              raise RuntimeError("Could not retrieve Scene Nodes graph model.")
          graph = sceneNodes.GetGraph()
          didLoad = maxon.AssetManagerInterface.LoadAssets(repository, assetsToLoad, graphModelRef=graph)
          if not didLoad:
              # `didLoad` is always False, event the asset loaded successfully.
              # What's wrong?
              # raise RuntimeError(f"Could not load assets for the ids: {assetsToLoad}")
              ...
          obj = doc.GetFirstObject()
          # Is there is a better way to change the parameters?
          for bc, descid, _ in obj.GetDescription(c4d.DESCFLAGS_DESC_0):
              name = bc[c4d.DESC_NAME]
              if name == "Axis X":
                  obj[descid] = x
              if name == "Axis Y":
                  obj[descid] = y
              if name == "Axis Z":
                  obj[descid] = z
          if parent is not None:
              obj.InsertUnderLast(parent)
      
      
      if __name__ == "__main__":
          cube = c4d.BaseObject(c4d.Ocube)
          loadGeometryAxis(y=1, parent=cube)
          doc.InsertObject(cube)
      
      

      Snipaste_2022-10-28_05-56-26.png

      C4DJSON -- a useful module to load an dump c4d objects in python dict format (similar to standard python json module).
      Examples on Notion.

      1 Reply Last reply Reply Quote 1
      • ManuelM
        Manuel
        last edited by

        Hi,

        In this case, the asset loaded is a capsule. For capsule, the return value can be false. This looks like a bug in our API. One remark about your code, as you want to load a capsule, you do not need to pass a graphModelRef to the LoadAssets function.

        How to access or change the parameter value, is a good question. To access the data, you must use the descID as you understood but the descID of capsules are exceptionally long. It seems those descID are based on either the path of the port or the ID of the port.
        I asked the devs but for now, it seems that the best attribut to identify the parameter is its name. Of course, this is bad as the name will change from languages to languages.

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        iplaiI 1 Reply Last reply Reply Quote 0
        • iplaiI
          iplai @Manuel
          last edited by iplai

          @manuel
          Thank you very much to answer my confusion. If I do not need to pass a graphModelRef to the LoadAssets function, my code can be simplified a lot. Can it be okay to identify the parameter by the index of iterating the capsule's description. Since the capsule is newly created, and there're no extra parameters, so it seems the index is fixed.

          First, get the index by following code.

          for i, (bc, descid, _) in enumerate(capsule.GetDescription(c4d.DESCFLAGS_DESC_0)):
              name = bc[c4d.DESC_NAME]
              if name == "Axis X":
                  print(i) # 59
              if name == "Axis Y":
                  print(i) # 60
              if name == "Axis Z":
                  print(i) # 61
          

          Then, the total function def:

          def loadGeometryAxis(x=0, y=0, z=0, parent: c4d.BaseObject = None):
              repository = maxon.AssetInterface.GetUserPrefsRepository()
              if not repository:
                  raise RuntimeError("Could not access the user preferences repository.")
              # Geometry Axis asset id
              assetid = maxon.Id("net.maxon.neutron.asset.geo.geometryaxis")
              assetsToLoad = [(assetid, ""), ]
              maxon.AssetManagerInterface.LoadAssets(repository, assetsToLoad)
              capsule = doc.GetFirstObject()
              for i, (bc, descid, _) in enumerate(capsule.GetDescription(c4d.DESCFLAGS_DESC_0)):
                  if i == 59:
                      capsule[descid] = x
                  if i == 60:
                      capsule[descid] = y
                  if i == 61:
                      capsule[descid] = z
              if parent is not None:
                  capsule.InsertUnderLast(parent)
              return capsule
          

          C4DJSON -- a useful module to load an dump c4d objects in python dict format (similar to standard python json module).
          Examples on Notion.

          1 Reply Last reply Reply Quote 0
          • DunhouD
            Dunhou
            last edited by Dunhou

            Hi there,

            In C4D 2024, the Geometry Axis can not accessible in python anymore, how can I fix that?

            from typing import Optional
            import c4d
            
            doc: c4d.documents.BaseDocument  # The active document
            op: Optional[c4d.BaseObject]  # The active object, None if unselected
            
            def main() -> None:
                for i, (bc, descid, _) in enumerate(op.GetDescription(c4d.DESCFLAGS_DESC_0)):
                    name = bc[c4d.DESC_NAME]
                    if name == "Axis X":
                        print(i,descid)
                        print(op[descid])
            if __name__ == '__main__':
                main()
            

            2024
            832ba1ea-2683-4deb-95de-67444dbcf033-image.png

            2023
            d37942ef-53b5-4e13-9cab-2946766c3fd6-image.png

            Cheers~
            DunHou

            https://boghma.com
            https://github.com/DunHouGo

            M 1 Reply Last reply Reply Quote 0
            • M
              m_adam
              last edited by m_adam

              Thanks a lot for the report !
              I will need to debug it properly but it appear that there is a bug in the conversion layer when subscription is used in conjunction of nested data like the one produced by Graph.
              In the meantime please use the next code:

              from typing import Optional
              import c4d
              
              doc: c4d.documents.BaseDocument  # The active document
              op: Optional[c4d.BaseObject]  # The active object, None if unselected
              
              def main() -> None:
                  for i, (bc, descid, _) in enumerate(op.GetDescription(c4d.DESCFLAGS_DESC_NONE)):
                      name = bc[c4d.DESC_NAME]
                      if name == "Axis X":
                          print(op.GetParameter(descid, c4d.DESCFLAGS_GET_NONE))
                          op.SetParameter(descid, 0.25, c4d.DESCFLAGS_SET_NONE)
              if __name__ == '__main__':
                  main()
              

              Cheers,
              Maxime.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              1 Reply Last reply Reply Quote 1
              • M
                m_adam
                last edited by m_adam

                This is indeed a regression and it will be fixed in the next Cinema 4D release.

                The issue is that Python was generating wrong DescId since forever in case of multiple sub level entry. Previously the system was able to return a value but due to some optimization on parameter access this was not working anymore.

                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                1 Reply Last reply Reply Quote 1
                • M
                  m_adam @Dunhou
                  last edited by

                  @Dunhou said in Geometry Axis asset node and LoadAssets:

                  Hi there,

                  In C4D 2024, the Geometry Axis can not accessible in python anymore, how can I fix that?

                  from typing import Optional
                  import c4d
                  
                  doc: c4d.documents.BaseDocument  # The active document
                  op: Optional[c4d.BaseObject]  # The active object, None if unselected
                  
                  def main() -> None:
                      for i, (bc, descid, _) in enumerate(op.GetDescription(c4d.DESCFLAGS_DESC_0)):
                          name = bc[c4d.DESC_NAME]
                          if name == "Axis X":
                              print(i,descid)
                              print(op[descid])
                  if __name__ == '__main__':
                      main()
                  

                  2024
                  832ba1ea-2683-4deb-95de-67444dbcf033-image.png

                  2023
                  d37942ef-53b5-4e13-9cab-2946766c3fd6-image.png

                  Cheers~
                  DunHou

                  Hi, this issue have been fixed in 2024.2 and your code is working as it was previously.

                  Cheers,
                  Maxime.

                  MAXON SDK Specialist

                  Development Blog, MAXON Registered Developer

                  1 Reply Last reply Reply Quote 1
                  • First post
                    Last post