Character Defenition Tag - maxon.Id?
-
Hi,
Before release 2024, the Character Defenition Tag has always been a "Black Box" - at least for Python. I recently discovered that now there is/should be a way to get and set data. I tried to look in various .h-files, the C++ docs, Github etc. but I just can't find the corresponding maxon.InternedId to use.
# small non-working example.. import c4d, maxon def main() -> None: obj = op.GetObject() # from a pyTag.. csTag = None for tag in obj.GetTags(): if tag.GetType() == 1055068: csTag = tag # c4d.modules.character.MTCharacterDefinitionTag break print (csTag.GetExposedBodyPartSettings( > maxon.Id < ))
So, the base question is: what's the maxonId?
& the sub question: is there some python script to get the Ids?Thx in advance, Jochem
-
Hey @jochemdk, thanks for asking this question, because while investigating it, I discovered that MtCharacterDefintionTag is buggy since the beginning in Python and you can't retrieve any MTCharacterBodyPart since the method MTCharacterDefinitionTag.GetRootBodyPart is badly implemented and will cause a crash.
Moreover I also found out that GetExposedBodyPartSettings was also badly implemented so you can't pass a valid argument. Sadly you can't do anything about that. I will provide a fix for it in the next version.
Just in case find bellow a script that will works once the two previous bugs will be fixed. This script iterates over all character definition parts and display their Id and also use the GetExposedBodyPartSettings to get the current weight a given body part is assigned to.
import c4d import maxon doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. # A Generator to iterate over all children of a given skeleton body part. # This function is recursive by default it won't be able to proceed skeleton whith an element nested in 1000 or more elements. def SketeletonIterator(root: c4d.modules.character.MTCharacterBodyPart, level=0): yield root, level for childIndex in range(root.GetChildCount()): child = c4d.modules.character.MTCharacterBodyPart = root.GetChild(childIndex) yield from SketeletonIterator(child, level+1) # Prints all IDs for all skeletons def PrintAllCharacterDefinitionId(characterSolverTag): # Get the associated Character definition tag characterDefinitionTag = characterSolverTag[c4d.CS_TARGET_CHARACTER] if not characterDefinitionTag: return # Get the Character definition(skeleton) Root stored within the Character Definition Tag # Aka the Root element visible in the tree from the Character Definition Tag's Manager window. # WARNING: This will will crash when root will be deallocated, there is no workaround a fix is going to be provided. root: c4d.modules.character.MTCharacterBodyPart = characterDefinitionTag.GetRootBodyPart() for child, level in SketeletonIterator(root): # Get all the settings of this child childParam: c4d.modules.character.MTBodyPartParameters = child.GetParameters() # Print the name and their id print(f"{' ' * level * 2}{childParam._name}, Id:{childParam._identifier}") def main() -> None: if not op: return # Retrieve the motion tag characterSolverTag = op.GetTag(c4d.Tcharmotiontransfer) if not characterSolverTag: return PrintAllCharacterDefinitionId(characterSolverTag) # Print the weight of the torso body part bodyPartSetting = characterSolverTag.GetExposedBodyPartSettings("net.maxon.animation.retarget.defaulttemplate.torso") print(bodyPartSetting[c4d.CS_BPSS_IDENT_ID], bodyPartSetting[c4d.CS_BPSS_WEIGHT_ID]) if __name__ == '__main__': main()
Cheers,
Maxime. -
Thx Maxim, so I'll have to wait until the next version..