WeightManager/Autoweight > set the amount of Joints in Python?
-
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, Jochemimport 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
-
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. -
Super, thx a lot! Will check first thing in the morning :}
-
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, Jochemimport 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()
-
Hi @jochemdk, sorry for the delay, looks like the autoconversion from Python to C++ fail,
so you will need to passsettings.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. -
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..