SOLVED How to add Strengths of each Pose I set in Pose Morph as Ports into Xpresso?

I'm on a character rigging and I try to sort hand poses into Xpresso.
075406bd-4a4c-4b22-a1e0-6ca08f71655a-image.png

I didn't find out a DESC of each Pose, then I can't get each Pose Strength as a port in Xpresso by script which means I got to drag them in, it's a disaster.XD
https://developers.maxon.net/docs/Cinema4DPythonSDK/html/classic_resource/tag/tcaposemorph.html?highlight=pose morph
c56328dd-35db-4f8a-992b-4675bda41841-image.png

Is there any to way to do it?

Hi,

The "problem" here is to retrieve the right ID of each morph.
on the morph tag, the Data for each slider start at c4d.ID_CA_POSE_ANIMATE_OFFSET (1000). Each morph has a maximum of c4d.ID_CA_POSE_ANIMATE_CNT (100) parameters. The Strength parameter is the second one. (1).

So, the Strength of the first morph slider have the ID 1101, the second 1201.... 1301 etc
All those data are stored in the subcontainer c4d.ID_CA_POSE_ANIMATE_DATA (4000)
You can retrieve the number of morphs with GetMorphCount.

After that you can manipulate xpresso, we have a couple of examples about that on ou github repository.

You can build the descID with those information. You can have a look at this thread to understand a bit more how to use descID

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

# Main function
def main():
    morphTag = op.GetFirstTag()
    if morphTag is None:
        raise RuntimeError("Failed to retrieve the morpht tag.")
    xpressoTag = morphTag.GetNext()
    
    if xpressoTag is None:
        raise RuntimeError("Failed to retrieve the xpressoTag.")
    
    morphCount = morphTag.GetMorphCount()
    
     # Retrieves the node master
    gvNodeMaster = xpressoTag.GetNodeMaster()
    if gvNodeMaster is None:
        raise RuntimeError("Failed to retrieve the Node Master.")

    # Retrieves the Root node (the Main XGroup) that holds all others nodes
    gvRoot = gvNodeMaster.GetRoot()
    if gvRoot is None:
        raise RuntimeError("Failed to retrieve the Root Node.")

    # Creates a constant node in the GvRoot
    objectNode = gvNodeMaster.CreateNode(gvRoot, c4d.ID_OPERATOR_OBJECT, x=100, y=100)
    if objectNode is None:
        raise RuntimeError("Failed to create the const Node.")
    
    objectNode[c4d.GV_OBJECT_OBJECT_ID] = morphTag
    
    for i in range(0, morphCount):
        offsetID = c4d.ID_CA_POSE_ANIMATE_OFFSET + c4d.ID_CA_POSE_ANIMATE_CNT * i + 1
        morphDescId =  c4d.DescID(c4d.DescLevel(c4d.ID_CA_POSE_ANIMATE_DATA, c4d.DTYPE_SUBCONTAINER, 0), c4d.DescLevel(offsetID, c4d.DTYPE_REAL, 0))
        objectNode.AddPort(c4d.GV_PORT_INPUT, morphDescId, c4d.GV_PORT_FLAG_IS_VISIBLE, True)
        
    
    
    c4d.EventAdd()

# Execute main()
if __name__=='__main__':
    main()

@x_nerve your answer isn't clear. I don't fully understand the purpose here.

Cheers,
Manuel

Hi:

@PATPAT
First of all, the point movement algorithm of attitude deformation label is not complicated.

I've seen in some tutorials that you can add some data to a port with unconventional operations, but I forgot . So, I use Python nodes.

The data control label object weight value for the input port, so you need to add a user data of type link to the Python node.

Python is a dynamic language, and data types cannot be determined before compilation. There is no conditional right or wrong judgment in my code, so please add them by yourself.

import c4d

def main():

    obj = op[c4d.ID_USERDATA,1]

    Tags = obj.GetTags()
    
    Pose = [tag for tag in Tags if tag.GetRealType() == 1024237]

    #[4000,1101] is the ID of the strength value.  
 
    Pose[0][4000,1101] = Input1

    global Output1
    Output1 = Pose[0][4000,1101]

17.jpg

Oh dear, it's a fascinating method and it works well! Thank you, x_nerve!

Hi,

The "problem" here is to retrieve the right ID of each morph.
on the morph tag, the Data for each slider start at c4d.ID_CA_POSE_ANIMATE_OFFSET (1000). Each morph has a maximum of c4d.ID_CA_POSE_ANIMATE_CNT (100) parameters. The Strength parameter is the second one. (1).

So, the Strength of the first morph slider have the ID 1101, the second 1201.... 1301 etc
All those data are stored in the subcontainer c4d.ID_CA_POSE_ANIMATE_DATA (4000)
You can retrieve the number of morphs with GetMorphCount.

After that you can manipulate xpresso, we have a couple of examples about that on ou github repository.

You can build the descID with those information. You can have a look at this thread to understand a bit more how to use descID

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

# Main function
def main():
    morphTag = op.GetFirstTag()
    if morphTag is None:
        raise RuntimeError("Failed to retrieve the morpht tag.")
    xpressoTag = morphTag.GetNext()
    
    if xpressoTag is None:
        raise RuntimeError("Failed to retrieve the xpressoTag.")
    
    morphCount = morphTag.GetMorphCount()
    
     # Retrieves the node master
    gvNodeMaster = xpressoTag.GetNodeMaster()
    if gvNodeMaster is None:
        raise RuntimeError("Failed to retrieve the Node Master.")

    # Retrieves the Root node (the Main XGroup) that holds all others nodes
    gvRoot = gvNodeMaster.GetRoot()
    if gvRoot is None:
        raise RuntimeError("Failed to retrieve the Root Node.")

    # Creates a constant node in the GvRoot
    objectNode = gvNodeMaster.CreateNode(gvRoot, c4d.ID_OPERATOR_OBJECT, x=100, y=100)
    if objectNode is None:
        raise RuntimeError("Failed to create the const Node.")
    
    objectNode[c4d.GV_OBJECT_OBJECT_ID] = morphTag
    
    for i in range(0, morphCount):
        offsetID = c4d.ID_CA_POSE_ANIMATE_OFFSET + c4d.ID_CA_POSE_ANIMATE_CNT * i + 1
        morphDescId =  c4d.DescID(c4d.DescLevel(c4d.ID_CA_POSE_ANIMATE_DATA, c4d.DTYPE_SUBCONTAINER, 0), c4d.DescLevel(offsetID, c4d.DTYPE_REAL, 0))
        objectNode.AddPort(c4d.GV_PORT_INPUT, morphDescId, c4d.GV_PORT_FLAG_IS_VISIBLE, True)
        
    
    
    c4d.EventAdd()

# Execute main()
if __name__=='__main__':
    main()

@x_nerve your answer isn't clear. I don't fully understand the purpose here.

Cheers,
Manuel

Hello @PATPAT,

without any further questions or replies, we will consider this thread as solved by Monday the 20th and flag it accordingly.

Thank you for your understanding,
Ferdinand