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
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Building a Character Object [SOLVED]

    Scheduled Pinned Locked Moved PYTHON Development
    13 Posts 0 Posters 963 Views
    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.
    • H Offline
      Helper
      last edited by

      On 30/05/2016 at 16:43, xxxxxxxx wrote:

      Trying to figure out a way to build a character template with python. First, create the character object, then select the character type, then build the components.  An example would be to create an Advanced Biped, then build the root, spine, then arms. Can't seem to figure out how to mimic pushing the button to create the components.

      obj = c4d.BaseObject(c4d.Ocharacter) # Create Character Object 
      doc.InsertObject(obj)                # Insert object in document
      obj[c4d.ID_CA_CHARACTER_TEMPLATE] = 1# Select Advanced Biped

      Create Root some how ...

      Create Spine some how...

      Related question, does anyone know how I can make sure I am creating the right character template with [c4d.ID_CA_CHARACTER_TEMPLATE]? I guess I am asking how do I know the integer that corresponds to a template will be the same on other computers? If I have a bunch of different templates the integer corresponding to my template maybe be different on someone else(I think), I believe it is based upon how many you have saved? I want to figure out a way to make sure I build the correct template.

      Thank you to anyone reading this I appreciate all the help.

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 01/06/2016 at 01:44, xxxxxxxx wrote:

        Hello,

        since the Character object does not provide a dedicated API one must access its internal data to utilize it. This is not documented and not further supported.

        You would have to read the object's parameter description to search for the IDs of the templates and identify them by their name. Also you would have to access an internal container to get the settings of the long buttons that are used to create the components. You can identify the buttons by their names and "press" them by sending a specific message to the Character object.

          
        # get object description  
        description = op.GetDescription(c4d.DESCFLAGS_DESC_0)  
        if description is None:  
          return  
          
          
        # check parameter description  
        for bc, paramid, groupid in description:      
           
          # check "Template" parameter description  
          if paramid[0].id == c4d.ID_CA_CHARACTER_TEMPLATE:  
                
              # get cycle content  
              cycle = bc.GetContainer(c4d.DESC_CYCLE)  
              for id, data in cycle:  
                  print(str(id) + " " + data)  
                    
          # check for character components  
          if paramid[0].id == c4d.ID_CA_CHARACTER_TEMPLATE_CONTAINER:  
          
              print("Full Parameter ID: " + str(paramid))         
                
              # check cycle content  
              cycle = bc.GetContainer(c4d.DESC_CYCLE)  
              for id, data in cycle:  
                  print(str(id) + " " + data)  
                    
              # press the "button" by sending a message  
              message = {}  
              message['id'] = paramid  
                
              op.Message(c4d.MSG_DESCRIPTION_COMMAND, message)  
        

        Best wishes,
        Sebastian

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 01/06/2016 at 09:27, xxxxxxxx wrote:

          Woohoo this is super helpful thank you so much! I would have never been able to figure this all out on my own. I do have one more question, I can't seem to figure out how to find the IDs of the next components after I build the first one. Example: create the Advanced Biped Character, using your technique to create the "Root", now to build the "Spine" you need to be selected on the Root, but then I can not find the paramid for "Spine". I tried looking for the paramid for the "Spine" but can't seem to find it. Do you know how I can access the buttons that only show up after you build the parent components? Thank you so much. Bummer that the Character object does not have a documented API, I guess it is not used enough 😞

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 02/06/2016 at 00:18, xxxxxxxx wrote:

            Hello,

            to get the Description showing the buttons for the sub-components you must select the component object but access the Description of the actual Character object.

            Best wishes,
            Sebastian

            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 02/06/2016 at 08:08, xxxxxxxx wrote:

              Waaaa! Got it right a way! Why did I not to think of trying it thay way. Thank you very much Sebastian this is very helpful. I appreceate all of your help.

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                On 27/11/2016 at 00:08, xxxxxxxx wrote:

                I just stumbled upon this. I don't quite understand how to build subsequent components. The code Sebastian posted successfully builds the Root component. The issue I'm seeing is that regardless, the first paramid is the same. So even though Root was created, event if I select root but run GetDescription still on the character object, it will print the right component name, but it will not build the spine, even thought it worked just fine for the root. Am I missing something?

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 28/11/2016 at 00:39, xxxxxxxx wrote:

                  Hello,

                  could you please post some code showing what you are doing?

                  best wishes,
                  Sebastian

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    On 28/11/2016 at 09:22, xxxxxxxx wrote:

                    Hey Sebastian,

                    The code I was using was pretty much the same as the code you had posted. The only difference was instead of"
                    description = op.GetDescription(c4d.DESCFLAGS_DESC_0), I had replaced op with charObj, which is a variable i got via a doc.SearchObject("Character"). I did that because one of the things here mentioned running the code on the char object whilest a component was selected. This creates the root component and selects it but it doesn't create any others, despite the fact that it will print the next component(Spine FK/IK).

                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      On 29/11/2016 at 00:32, xxxxxxxx wrote:

                      Hello,

                      the posted script only does one thing. It loops through the description and "presses" the buttons. The script is only intended to show how to obtain the needed parameter IDs and how to "press" the button, nothing else.

                      So when you execute the script once, it only presses one button ("Root"). If the script should create something else it must run again (or you have to code the "pressing" of the next button yourself).

                      The script does not print "the next component".

                      best wishes,
                      Sebastian

                      1 Reply Last reply Reply Quote 0
                      • H Offline
                        Helper
                        last edited by

                        On 29/11/2016 at 23:49, xxxxxxxx wrote:

                        Hey Sebastian,

                        So here's my script. It's very much like the one you posted but changed as I mentioned and a couple things commented out.

                        import c4d
                        from c4d import gui
                        #Welcome to the world of Python

                        def main() :
                            # get object description
                            charObj=doc.SearchObject("Character")
                            description = charObj.GetDescription(c4d.DESCFLAGS_DESC_0)
                            if description is None:
                                return
                            
                            
                            # check parameter description
                            for bc, paramid, groupid in description:    
                                
                                # check "Template" parameter description
                                if paramid[0].id == c4d.ID_CA_CHARACTER_TEMPLATE:
                                    
                                    # get cycle content
                                    cycle = bc.GetContainer(c4d.DESC_CYCLE)
                                    #for id, data in cycle:
                                    #    print(str(id) + " " + data)
                                        
                                # check for character components
                                if paramid[0].id == c4d.ID_CA_CHARACTER_TEMPLATE_CONTAINER:
                            
                                    print("Full Parameter ID: " + str(paramid))       
                                    
                                    # check cycle content
                                    cycle = bc.GetContainer(c4d.DESC_CYCLE)
                                    for id, data in cycle:
                                        print(str(id) + " " + data)
                                        
                                    # press the "button" by sending a message
                                    message = {}
                                    message['id'] = paramid
                                    
                                    op.Message(c4d.MSG_DESCRIPTION_COMMAND, message)
                                    
                        if __name__=='__main__':
                            main()

                        Now, if you create a character object and select it and then run the script, it will print the following:

                        "Full Parameter ID: ((2113,5,0), (1000, 150))
                        1000 Root"

                        And it will create and then select the Root. So this gets the Description of the Character Object, and presses a button based on the selected object(op.Message).

                        Now, with the Root still selected, run the script again. This time it will print:

                        "Full Parameter ID: ((2113, 5,0),(1000,15,0))
                        1000 Spine (IK/FK Blend)"

                        yet it won't create that button. Even though op, is now our Root component object, and it displays the right component name, but when it tries to click the button like you did for Root, it doesn't do it. Why is that? That's the part I don't quite understand. It also seems to generate the same paramid, I assume that the first one always is that number(1000), and it goes up from there.

                        But why doesn't it keep creating components as I keep running the script?

                        1 Reply Last reply Reply Quote 0
                        • H Offline
                          Helper
                          last edited by

                          On 30/11/2016 at 08:04, xxxxxxxx wrote:

                          Hello,

                          you have to send the message to the character object, not the "Root" object. Just like in the original script.

                          best wishes,
                          Sebastian

                          1 Reply Last reply Reply Quote 0
                          • H Offline
                            Helper
                            last edited by

                            On 01/12/2016 at 23:14, xxxxxxxx wrote:

                            Thanks for that Sebastian. It  works. But now I'm running into an issue. I want to run through a loop and build components whos names I specify. Here's what I have:

                            import c4d
                            from c4d import gui
                            #Welcome to the world of Python

                            def main() :
                                # get object description
                                parents=['Character', 'Root', 'Spine', 'Spine', 'Spine', 'Spine']
                                buttonNames=['Root', 'Spine (IK/FK Blend)', 'Arm (IK/FK Bendy)', 'Jaw', 'Eye', 'Leg (IK/FK Bendy)']
                                charObj=doc.SearchObject('Character')
                                for id2, buttonName in enumerate(buttonNames) :
                                    description = charObj.GetDescription(c4d.DESCFLAGS_DESC_0)
                                    if description is None:
                                        return
                                    
                                    
                                    # check parameter description
                                    for bc, paramid, groupid in description:    
                                        
                                                
                                        # check for character components
                                        if paramid[0].id == c4d.ID_CA_CHARACTER_TEMPLATE_CONTAINER:
                                      
                                            
                                            # check cycle content
                                            cycle = bc.GetContainer(c4d.DESC_CYCLE)

                            for id, data in cycle:
                                                print(str(id) + " " + data)
                                                
                                                if data==buttonName:
                                                    # press the "button" by sending a message
                                                    message = {}
                                                    message['id'] = paramid
                                                    
                                                    charObj.Message(c4d.MSG_DESCRIPTION_COMMAND, message)
                                    c4d.DrawViews(c4d.DRAWFLAGS_FORCEFULLREDRAW)

                            if __name__=='__main__':
                                main()

                            However, it just is always saying Root first. The data from cycle is not updating? Is that the issue or am I doing something stupid?

                            The other question I have: There are different behaviors for clicking the button based on keyboard modifiers(ie different things happen if I SHIFT+Click on the button, CTRL+Click, or CTRL+SHIFT click). Is it possible to pass these modifiers into the message so that when i simulates the button click it can simulate the button click with CTRL+SHIFT pressed?

                            1 Reply Last reply Reply Quote 0
                            • H Offline
                              Helper
                              last edited by

                              On 02/12/2016 at 07:55, xxxxxxxx wrote:

                              Hello,

                              it seems that the Character object only works properly when used manually. The Description returned is always the same, the Character object (and the whole Character System in the background) seems to update internal data at several stages of the event system and scene execution. I'm afraid it is not possible to properly update the Character object from within a script.

                              If a key is pressed is detected with functions like GetInputState(). This has nothing to do with the MSG_DESCRIPTION_COMMAND and cannot be emulated.

                              best wishes,
                              Sebastian

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