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

    WeightManager/Autoweight > set the amount of Joints in Python?

    General Talk
    r23 s24 python
    2
    6
    983
    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.
    • jochemdkJ
      jochemdk
      last edited by

      For a particular setup in R23/24, I’m trying to restrict the auto weighting to 1 joint - to avoid blending between weights (which will save me trouble down the line..).

      Since R21 the “ID_CA_WEIGHT_MGR_AUTOWEIGHT_JOINTS” is removed so I can’t set it directly (see the simplified code below).

      I tried to figure out a workaround, with no luck. My thought was that if I could read the autoweightDictonary, I could also set it.
      The function “GetAutoWeightDictionary” needs a stringId (which is a maxon.Id, but that didn’t help me any further..)

      So, the main question: How can I set the amount of Joints (to 1) when autoweighting?
      And of course I don’t mean mannualy :} tia, Jochem

      import c4d, maxon
      
      def message(id, data):
          if id == c4d.MSG_DESCRIPTION_COMMAND:
              id2 = data['id'][0].id
              if id2 == c4d.ID_USERDATA:
                  userDataId = data['id'][1].id
                  if userDataId == 1:
                      accessWM()
                      c4d.EventAdd()
      
      
      def accessWM():
          doc = op.GetDocument()
          for tag in op.GetObject().GetTags():
              if tag.GetType() == 1019365: wTag = tag
          doc.SetActiveTag(wTag, c4d.SELECTION_NEW)
          wmgr = c4d.modules.character.CAWeightMgr
          wmgr.SetParameter(doc,c4d.ID_CA_WEIGHT_MGR_AUTOWEIGHT_MODE,1) # heatmap
          wmgr.SetParameter(doc,c4d.ID_CA_WEIGHT_MGR_AUTOWEIGHT_IN_BIND_POSE,True)
          # ID_CA_WEIGHT_MGR_AUTOWEIGHT_JOINTS // removed since R21 :{
          wmgr.AutoWeight(doc)
          wmgr.Update(doc)
          
          """
          hmmm1 = wmgr.GetAutoWeightDictionary(doc, maxon.Id("AutoWeight"))
          hmmm2 = wmgr.GetAutoWeightDictionary(doc, maxon.Id)
          print (hmmm1, type(hmmm1))
          print (hmmm2, type(hmmm2))
          # both print: <class 'maxon.reference.DataDictionary'>
          """
      
      def main():
          pass
      
      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @jochemdk, weight has been rewritten to make use of the new MAXON API and ease the new implementation of weight algorithms. Theoretically, a C++ 3rd party developer may create a new weight algorithm and have it incorporated into the Weight Manager.

        But this Maxon API is slightly different than the classic API, so here some basics information.

        MAXON API does not use any more integer value (e.g. Ocube to describe the ID corresponding to a cube) to represent things instead they use reverse domain approach (e.g. "net.maxon.animation.autoweight.base.jointcount" represent the joint count parameter).
        These reverse domains are strings but the type to represent them is maxon.Id.

        Then come the DataDictionarry part, this is almost similar to a BaseContainer, except that it acts like a Python dict where a key can be anything, and the value can be any maxon.Data.

        So finally find an example of how to do it

        import c4d
        import maxon
        from maxon.frameworks import animation
        
        
        # Main function
        def main():
            wmgr = c4d.modules.character.CAWeightMgr
            # Retrieve the maxon id corresponding to the current weight algorithm used
            # 1 == the second entry, in our case the heatmap
            heatmap_id = wmgr.GetAutoWeightAlgoId(doc, 1)
            
            # Retrieve the current settings (only changed values will appear here)
            settings = wmgr.GetAutoWeightDictionary(doc, heatmap_id)
        
            # Change the value for the joint count
            settings.Set(maxon.frameworks.animation.AUTOWEIGHTPARAMETERS.JOINTCOUNT, 2)
            wmgr.SetAutoWeightDictionary(doc, settings, heatmap_id)
            
            # Update the Weight Manager
            c4d.EventAdd()
            
        
        # Execute main()
        if __name__=='__main__':
            main()
        

        Regarding how I find the ID, I just looked at the python file located within '{c4d_install_dir}/resource/modules/python/libs/python39/maxon/frameworks/animation.py'.

        Unfortunately, this is not documented in the Python online documentation I will add a note to do it.
        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • jochemdkJ
          jochemdk
          last edited by

          Super, thx a lot! Will check first thing in the morning :}

          1 Reply Last reply Reply Quote 0
          • jochemdkJ
            jochemdk
            last edited by jochemdk

            Hi @m_adam, thx for your input, it does reset the WeightManager, but doesn’t do the autoWeighting accordingly..

            _First thing I noticed: a difference between int 64 & 32. Not sure if this might be a problem..
            Reading the GET> AutoWeight…base.jointcount : <int64> “number of joints”
            Reading the SET> AutoWeight…base.jointcount : <int32> “number of joints”

            _After the WeightManager is being set (to 1 joint in my case), I can’t click on the “Calculate button” manually.
            Nothing happens, unless I change the joint count manually to another number. So something in the update hasn’t been applied..
            Note that reading the dict says <int32>, until manually changed, than is says <int64> again..

            _I also tried wmgr.SetDirty(doc) / wmgr.Update(doc) / followed by another c4d.EventAdd().. Perhaps these need a different approach as well?
            I tried to find something in the “maxon/frameworks” folders you linked to, but couldn’t find any info on how to tackle this issue.

            So the current status is still that “default weighting” is applied.
            If you can please help in the right direction, it would be greatly appreciated, tia, Jochem

            import c4d, maxon
            from maxon.frameworks import animation
            
            
            def main():
                doc = c4d.documents.GetActiveDocument()
                wmgr = c4d.modules.character.CAWeightMgr
                #wmgr.SetDirty(doc)
                
                heatmap_id = wmgr.GetAutoWeightAlgoId(doc, 1) # heatmap
                settings = wmgr.GetAutoWeightDictionary(doc, heatmap_id)
                settings.Set(maxon.frameworks.animation.AUTOWEIGHTPARAMETERS.JOINTCOUNT, 1)
                settings.Set(maxon.frameworks.animation.AUTOWEIGHTPARAMETERS.SELECTEDPOINTS, False)
                settings.Set(maxon.frameworks.animation.AUTOWEIGHTPARAMETERS.ALLOWZEROLENGTH, False)
                wmgr.SetAutoWeightDictionary(doc, settings, heatmap_id)
                #doc.ExecutePasses(None,True,True,True,flags=c4d.BUILDFLAGS_NONE)
                c4d.EventAdd()
                
                # getWeightTag - setActive
                firstJoint = doc.GetFirstObject().GetDown().GetDown() # just in my testDoc..
                weightTag = (firstJoint.GetWeightTag())["op"]
                doc.SetActiveTag(weightTag, c4d.SELECTION_NEW)
                #weightTag.GetObject().SetBit(c4d.BIT_ACTIVE)
                    
                # update weightManager / doesn't make any difference..
                #wmgr.SetDirty(doc)
                #wmgr.Update(doc)
                #c4d.EventAdd()
                
                # autoWeight func
                wmgr.SelectAllJoints(doc)
                bla = wmgr.AutoWeight(doc)
                print(bla) # prints True, but not in the right way :{
                c4d.EventAdd()
            
            if __name__=='__main__':
                main()
            
            1 Reply Last reply Reply Quote 1
            • M
              m_adam
              last edited by m_adam

              Hi @jochemdk, sorry for the delay, looks like the autoconversion from Python to C++ fail,
              so you will need to pass settings.Set(maxon.frameworks.animation.AUTOWEIGHTPARAMETERS.JOINTCOUNT, maxon.Int(1))

              For bool the autoconversion should work out of the box otherwise use maxon.Bool(False).
              Since there is only 1 boolean type in C++ the bool conversion is ok, while there is maxon.Int, maxon.Int32, maxon.Int64 for integer value, so the Python system has to do some guesswork.

              How could you know that? For the moment the only way is looking where this parameter is declared in 'sdk.zip/frameworks/animation.framework/source/maxon/autoweight_attributes.h' with line MAXON_ATTRIBUTE(Int, JOINTCOUNT, "net.maxon.animation.autoweight.base.jointcount");
              So this attribute accepts a maxon.Int.

              This is indeed something that we are aware of and will need to address sooner or later in our documentation.

              Cheers,
              Maxime.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              1 Reply Last reply Reply Quote 1
              • jochemdkJ
                jochemdk
                last edited by

                So, now we have a maxon.Int :}
                Yes, the system is working - thx @m_adam
                Consider it solved // more info in general on the maxon framework - especially on the python side - would we be welcome..

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