Home Website Youtube GitHub

Pre and Post scripts sharing

I did and it worked. Thanks.

I think this is a really good idea. Iā€™ve written about a few of those, but it would be nice to have a nice little collection of examples to start with, and include it somewhere in the mGear distribution maybe? Iā€™ll put this on my TODO list, but if anyone beats me to it, cool! (0.5 to 2 weeks maybe)

4 Likes

Hello there,
In my last project, there was a need to drastically scale all characters. I want into an issue that lips rigger was not scaling properly. The solution I found was to scale CTLs group and scale rope transforms (but not up vectors).
Not sure if itā€™s the best way to solve that, but it worked.

If anyone has similar issues, hereā€™s the code:

import mgear.shifter.custom_step as cstp
from mgear.core import node
import pymel.core as pm

class CustomShifterStep(cstp.customShifterMainStep):
def init(self):
self.name = ā€œfix lips rigger scaleā€

def run(self, stepDict):
    """Run method.

        i.e:  stepDict["mgearRun"].global_ctl  gets the global_ctl from
                shifter rig build bas
        i.e:  stepDict["mgearRun"].components["control_C0"].ctl  gets the
                ctl from shifter component called control_C0
        i.e:  stepDict["otherCustomStepName"].ctlMesh  gets the ctlMesh
                from a previous custom step called "otherCustomStepName"
    Arguments:
        stepDict (dict): Dictionary containing the objects from
            the previous steps

    Returns:
        None: None
    """
    ####lips scale FIX

    ropesGrp = [pm.PyNode("lips_C_rope"),
                pm.PyNode("brow_L_rope"),
                pm.PyNode("brow_R_rope")]

    controls = ["lips_R_corner_npo",
                "lips_C_upper_npo",
                "lips_L_corner_npo",
                "lips_C_lower_npo"]
                
    parentJoint = pm.PyNode("squash_C0_0_jnt")

    searchStr = "Rope"

    #controls           
    for ctl in controls:
        ctl = pm.PyNode(ctl)
        pm.scaleConstraint(parentJoint, ctl, mo=True)
        
    #ropes
    for grp in ropesGrp:
        ropes = [rope for rope
                  in grp.listRelatives(allDescendents=True, type="transform")
                  if rope.split("|")[-1].split("_")[-1].endswith(searchStr)]
                  
        for rope in ropes:
            rope = pm.PyNode(rope)

            mulmat_node = node.createMultMatrixNode(
                parentJoint + ".worldMatrix", rope + ".parentInverseMatrix")

            dm_node = node.createDecomposeMatrixNode(
                mulmat_node + ".matrixSum")
                
            pm.connectAttr(dm_node + ".outputScale", rope + ".s")              


    return

Cheers!

1 Like

This is not a direct pre or post script, but a set of functions for duplicating out the skin joints to a separate hierarchy, and connecting and disconnecting them from the rigā€¦which could be run as a pre/post script.

mGear is built around importing all the data when you build the rig, but we wanted to have all the deformation stuff (skinning, shapes, deformers etc.) saved with the joints, and then just apply the animation rig to it. This saves us having to implement support for exporting/importing every kind of of deformer we may use, plus itā€™s a bit quicker.

It should be pretty self explanatory. Just note that you need to run detach_joints before deleting the mGear rig, as otherwise all the joints will jump to the origin. Build the mGear rig, and then use duplicate_mgear_bones() to create a duplicate hierarchy, and use attach_joints() and detach_joints(), to attach/detach it from the mGear rig.

Here is the code:

from itertools import izip
import pymel.core as pm
from mgear.core import applyop, node


def recursive_search_replace(node, a, b):
    """Recursively replace a with b in node names
    """
    node.rename(node.name().replace(a, b))
    for child in node.getChildren():
        recursive_search_replace(child, a, b)

def mgear_constraint(obj, jnt, gearMulMatrix=True):
    """Constraint using mGear nodes
    """
    if gearMulMatrix:
        mulmat_node = applyop.gear_mulmatrix_op(
            obj + ".worldMatrix", jnt + ".parentInverseMatrix")
        dm_node = node.createDecomposeMatrixNode(
            mulmat_node + ".output")
        m = mulmat_node.attr('output').get()
    else:
        mulmat_node = node.createMultMatrixNode(
            obj + ".worldMatrix", jnt + ".parentInverseMatrix")
        dm_node = node.createDecomposeMatrixNode(
            mulmat_node + ".matrixSum")
        m = mulmat_node.attr('matrixSum').get()
    pm.connectAttr(dm_node + ".outputTranslate", jnt + ".t")
    pm.connectAttr(dm_node + ".outputRotate", jnt + ".r")

def duplicate_mgear_bones(attach=False):
    """Break out the mgear joints to it's own hierarchy
    """
    jnt_org = pm.SCENE.jnt_org
    jnt_skin = jnt_org.duplicate(name='skin_joints', renameChildren=False)[0]
    pm.parent(jnt_skin, world=True)
    recursive_search_replace(jnt_skin, 'jnt', 'skin')
    if attach:
        attach_joints(jnt_skin, jnt_org)

def attach_joints(source=None, target=None):
    """Recursively attach the joints of one hierarchy to that of another
    """
    if not source:
        source = pm.SCENE.skin_joints
    if not target:
        target = pm.SCENE.jnt_org
    for src, trg in izip(source.getChildren(), target.getChildren()):
        pm.displayInfo("Attaching {source} to {target}".format(
            source=src, 
            target=trg
        ))
        attach_joints(src, trg)
    if (isinstance(source, pm.nodetypes.Joint) and
        isinstance(target, pm.nodetypes.Joint)):
        mgear_constraint(target, source, gearMulMatrix=False)

def detach_joints(source=None):
    """Recursively break all incoming transform connection
    """
    if not source:
        source = pm.SCENE.skin_joints
    for src in source.getChildren():
        pm.displayInfo("Detatching {child}".format(child=src))
        src.translate.disconnect()
        src.rotate.disconnect()
        src.parentInverseMatrix[0].disconnect()
        detach_joints(src)
10 Likes

Sorry to reboot an old thread, but this was very important for me when looking for reference to custom steps and how to correctly access elements. So I thought Iā€™d add another example.

Some of the examples here are finding rig elements by strings, here Iā€™m getting to the components via the stepDict variable and using the elements defined by the build process directly. This is in the hope that the code is less brittle and survives name changes etc.

[https://gist.github.com/thirstydevil/5d12d7e1484675adc07fd47b98706e8d](http://Post Custom Step Game Engine Cleanup)

6 Likes

A post was split to a new topic: Importing pose files via script

Thatā€™s a great idea!