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

    How to create a child from the script manager?

    General Talk
    r20 python
    3
    8
    1.0k
    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.
    • JH23J
      JH23
      last edited by

      Hello
      I had quite a few doubts about how to create a cube but I don't know how to create a child for it, I will modify its values before creating it but I still have doubts about how to create a child for it.

      import c4d
      from c4d import documents
      def main():
          def tool():
              return plugins.FindPlugin(doc.GetAction(), c4d.PLUGINTYPE_TOOL)
          c4d.CallCommand(5159) # Cubo
      
      if __name__=='__main__':
          main()
          c4d.EventAdd()
      
      1 Reply Last reply Reply Quote 0
      • CairynC
        Cairyn
        last edited by

        Honestly, while CallCommand is fairly easy and the Script Log is logging you lots of CallCommands and some things are only possible through CallCommand...

        ...for things like object trees and other hierarchies, this is just the wrong way to go. CallCommand does not return the created object, and you would not have any variables to store references to other objects.

        In case of creating child objects, BaseDocument's method InsertObject would be the way to go:

        import c4d
        from c4d import gui
        
        def main():
            newCube = c4d.BaseObject(c4d.Ocube)
            doc.InsertObject(newCube)
            newChildCube = c4d.BaseObject(c4d.Ocube)
            doc.InsertObject(newChildCube, newCube)
            c4d.EventAdd()
        
        if __name__=='__main__':
            main()
        

        newCube and newChildCube are created here through the constructors of the BaseObject class, not by a CallCommand. In the second InsertObject call, the first cube is passed as the designated parent for the second cube.

        (I would add a link to the BaseDocument documentation, but the server for the API docs seems to be down at the moment.)


        (unavoidable advertising:)
        Learn more about Python for C4D scripting:
        https://www.patreon.com/cairyn

        1 Reply Last reply Reply Quote 1
        • JH23J
          JH23
          last edited by JH23

          Thanks, but also my question would be how to do what I did with the original script, let me explain, using the callcomand I managed to edit the size and number of divisions, as well as make it editable, I don't know how I could achieve it with the script that helped me
          my example:

          import c4d
          from c4d import gui
          def main():
              def tool():
                  return plugins.FindPlugin(doc.GetAction(), c4d.PLUGINTYPE_TOOL)
              def object():
                  return doc.GetActiveObject()
              c4d.CallCommand(5159)
              object()[c4d.ID_BASELIST_NAME] = "cubo"
              object()[c4d.PRIM_CUBE_LEN,c4d.VECTOR_X] = 32
              object()[c4d.PRIM_CUBE_LEN,c4d.VECTOR_Y] = 32
              object()[c4d.PRIM_CUBE_LEN,c4d.VECTOR_Z] = 32
              object()[c4d.PRIM_CUBE_SUBX] = 11
              object()[c4d.PRIM_CUBE_SUBY] = 11
              object()[c4d.PRIM_CUBE_SUBZ] = 11
              c4d.CallCommand(12236)
          if __name__=='__main__':
              main()
          

          excuse my ignorance, I am new and I quite like the field of scripting

          1 Reply Last reply Reply Quote 0
          • CairynC
            Cairyn
            last edited by

            Well, you forgot to include that code in your original script, so I wouldn't know that this is the question 😀

            Anyway, object() is just a function call that returns the currently active object, which happens to be the just created cube. In my code, the created code is stored in the variables newCube and newChildCube, respectively. So you can do the same modification of parameters by invoking it on the variables, once the object has been created:

            newCube[c4d.ID_BASELIST_NAME] = "cubo"
            

            etc.

            1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand
              last edited by ferdinand

              Hello @JH23,

              thank you for reaching out to us. I would second the advice from @Cairyn that using script log code is not the best idea (thank you for your help @Cairyn). Below you will a narrative code example which explains a few things which might be relevant for you when starting out with the Cinema 4D SDK.

              Cheers,
              Ferdinand

              """A script manger script that adds a cube with a cone object parented to it 
              to the scene.
              
              As discussed in:
                  plugincafe.maxon.net/topic/13331
              """
              
              import c4d
              
              
              def main():
                  # Assuming you want to use a CallCommand, you can do this. In practice
                  # instantiating a cube object is better done in the way shown by Cairyn
                  # in the forums.
              
                  # The CallCommand for creating a cube object which will also insert and
                  # select the cube.
                  c4d.CallCommand(5159)
              
                  # Get the currently active object; which is the new cube object due to the
                  # prior CallCommand. The function object() created by the script log, and 
                  # used in your code, does effectively something similar. But it has the 
                  # overhead of retrieving the active object each time it is being called, 
                  # which is not necessary here.
                  
                  # In a script environment there are also the predefined attributes op and
                  # doc, "variables" in non-Python terms. op is the currently active object
                  # when the script is being run and doc the currently active document.
                  
                  # We cannot use op here, since the CallCommand just did change that, but
                  # we can use doc, which we could retrieve also manually if we had to via
                  # c4d.documents.GetActiveDocument(). 
                  cube = doc.GetActiveObject()
              
                  # Set some of the parameters of that cube object.
                  cube[c4d.ID_BASELIST_NAME] = "Cube"
                  cube[c4d.PRIM_CUBE_LEN, c4d.VECTOR_X] = 32
                  cube[c4d.PRIM_CUBE_LEN, c4d.VECTOR_Y] = 32
                  cube[c4d.PRIM_CUBE_LEN, c4d.VECTOR_Z] = 32
                  cube[c4d.PRIM_CUBE_SUBX] = 11
                  cube[c4d.PRIM_CUBE_SUBY] = 11
                  cube[c4d.PRIM_CUBE_SUBZ] = 11
              
                  # Instantiate manually a cone object and insert it under that cube, i.e.,
                  # do it like Cairyn has shown it.
                  cone = c4d.BaseObject(c4d.Ocone)
                  # We can also set the name of a node like this, which is a bit easier to
                  # remember than the ID.
                  cone.SetName("Cone")
              
                  # Set some parameters of the cone. You can find out parameter ids via
                  # drag and drop and the console, read more about it here:
                  #   developers.maxon.net/docs/Cinema4DPythonSDK/html/misc/descriptions.html
                  cone[c4d.PRIM_CONE_HEIGHT] = 32
                  cone[c4d.PRIM_CONE_BRAD] = 16
                  cone[c4d.ID_BASEOBJECT_REL_POSITION, c4d.VECTOR_Y] = 32
              
                  # Create a phong tag for the cone, so that the cone is being shaded nicely.
                  phongTag = cone.MakeTag(c4d.Tphong)
                  # Enable the angle limit of the phong tag.
                  phongTag[c4d.PHONGTAG_PHONG_ANGLELIMIT] = True
              
                  # Insert the cone under the cube.
                  cone.InsertUnder(cube)
              
                  # When we are doing things "manually", i.e., do not use CallCommand, we
                  # have to push an update to Cinema 4D after we have modified the scene
                  # graph.
                  c4d.EventAdd()
              
              
              if __name__ == '__main__':
                  main()
              

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • JH23J
                JH23
                last edited by

                Thank you very much, they resolved my doubts 😄

                1 Reply Last reply Reply Quote 0
                • JH23J
                  JH23
                  last edited by

                  Thank, but In the case that I wanted to make the obj editable, with callcomand I could just put the command to make editable but how would I do it in the case of the cube?

                  1 Reply Last reply Reply Quote 0
                  • ferdinandF
                    ferdinand
                    last edited by

                    Hello @JH23,

                    first, I would like to point out that we ask the community here to post separate questions into separate postings, so that other users can find more easily answers when searching the forum. You can read more about the procedures of SDK support in our Forum Guidelines. It is okay in this case, but for future cases we have to ask you to open new topics for follow-up questions that are not directly related to the initial question of the topic (thread).

                    About your question - you have two options when you want to make an object editable:

                    1. In case you already have the object in question already inserted into the active document and are in the main thread, you can still use CallCommand. For CallCommand you have to keep in mind that it usually relies on an object selection. When running it in a script, you have then make sure that actually the objects you want to be affected are selected when you do run the CallCommand. I have provided an extension of my prior example at the end of this posting.
                    2. In all other cases, i.e., when the object is either in no document or not in the active one, or you are not on the main thread, then you must use c4d.utils.SendModelingCommand Link. In this case for example for the command MCOMMAND_MAKEEDITABLE. You can find more information about that in our SDK documentation and in the code examples on GitHub.

                    Cheers,
                    Ferdinand

                    Example code:

                    import c4d
                    
                    
                    def main():
                        # Assuming you want to use a CallCommand, you can do this. In practice
                        # instantiating a cube object is better done in the way shown by Cairyn
                        # in the forums.
                    
                        # The CallCommand for creating a cube object which will also insert and
                        # select the cube.
                        c4d.CallCommand(5159)
                    
                        # Get the currently active object; which is the new cube object due to the
                        # prior CallCommand. The function object() created by the script log, and 
                        # used in your code, does effectively something similar. But it has the 
                        # overhead of retrieving the active object each time it is being called, 
                        # which is not necessary here.
                        
                        # In a script environment there are also the predefined attributes op and
                        # doc, "variables" in non-Python terms. op is the currently active object
                        # when the script is being run and doc the currently active document.
                        
                        # We cannot use op here, since the CallCommand just did change that, but
                        # we can use doc, which we could retrieve also manually if we had to via
                        # c4d.documents.GetActiveDocument(). 
                        cube = doc.GetActiveObject()
                    
                        # Set some of the parameters of that cube object.
                        cube[c4d.ID_BASELIST_NAME] = "Cube"
                        cube[c4d.PRIM_CUBE_LEN, c4d.VECTOR_X] = 32
                        cube[c4d.PRIM_CUBE_LEN, c4d.VECTOR_Y] = 32
                        cube[c4d.PRIM_CUBE_LEN, c4d.VECTOR_Z] = 32
                        cube[c4d.PRIM_CUBE_SUBX] = 11
                        cube[c4d.PRIM_CUBE_SUBY] = 11
                        cube[c4d.PRIM_CUBE_SUBZ] = 11
                    
                        # Instantiate manually a cone object and insert it under that cube, i.e.,
                        # do it like Cairyn has shown it.
                        cone = c4d.BaseObject(c4d.Ocone)
                        # We can also set the name of a node like this, which is a bit easier to
                        # remember than the ID.
                        cone.SetName("Cone")
                    
                        # Set some parameters of the cone. You can find out parameter ids via
                        # drag and drop and the console, read more about it here:
                        #   developers.maxon.net/docs/Cinema4DPythonSDK/html/misc/descriptions.html
                        cone[c4d.PRIM_CONE_HEIGHT] = 32
                        cone[c4d.PRIM_CONE_BRAD] = 16
                        cone[c4d.ID_BASEOBJECT_REL_POSITION, c4d.VECTOR_Y] = 32
                    
                        # Create a phong tag for the cone, so that the cone is being shaded nicely.
                        phongTag = cone.MakeTag(c4d.Tphong)
                        # Enable the angle limit of the phong tag.
                        phongTag[c4d.PHONGTAG_PHONG_ANGLELIMIT] = True
                    
                        # Insert the cone under the cube.
                        cone.InsertUnder(cube)
                        
                        # When we are doing things "manually", i.e., do not use CallCommand, we
                        # have to push an update to Cinema 4D after we have modified the scene
                        # graph.
                        c4d.EventAdd()
                        
                        # Make the cube object the new active selection.
                        doc.SetActiveObject(cube, c4d.SELECTION_NEW)
                        # And run the " Make Editable" CallCommand on that
                        c4d.CallCommand(12236) # Make Editable
                    
                    
                    if __name__ == '__main__':
                        main()
                    

                    MAXON SDK Specialist
                    developers.maxon.net

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