Home Website Youtube GitHub

Pre and Post scripts sharing

Eyes Rigger Importer

Usage

Name a folder next to the current maya file {maya_filename}.eyes and export your eye config there.

1 Like

Delta Mush Importer

Usage
Export your delta mush weights with Deform > Export Weights as json. Name a folder next to the current maya file “delta_mush” and name the file {maya_filename}.{mesh_name}.json.

2 Likes

Does Deform -> Export Weights actually work for you? It has been completely unusable for me, spitting out useless data and/or importing mangled data.

Yeah, it works. I export json files and import by index. Any of the other import options like “nearest” doesn’t really work for me.

BTW I’m on Maya 2019, maybe that makes a difference.

Maybe a better idea than sharing the scripts here, would be to include them in the distribution so they can be git versioned?

@Toke_Stuart_Jepsen maybe a gist?

Sure, I’ll do that instead.

With gists or posting you might forget to update the online version, but with a git repository you can see there are changes to be staged/pushed.

Hey guys, can anyone here guide us how to use these pre and post scripts? Some of us here are not TDs and all the code just looks confusing. Some visual aid would be of great assistance. I must also confess that Github is also very confusing to me.

1 Like

Hey @Ross_Daniel

Could you give us an example of which script you want to try?
There are some description of usage for some of the scripts, but don’t know where that documentation is failing you.

Can you just do a screen recording of you using anyone?

Hey @Toke_Stuart_Jepsen

Sharing the same sentiment as Daniel, I think the non full-time TD folk (such as myself) could benefit from basic fail-safe instructions on how to implement the custom steps at a local level, from a specified path.
What parts of the code can be copied from a resource template and what should be changed by the user (i.e. the path).

I think if there were such examples of:

  • import geo pre script
  • import skin pack post script
  • import face rig/lips rig/eyes rig/brows rig (I know the brows created by @Krzym aren’t official, just suggesting) post script
  • import shapes/blendshapes post script
  • import gimmick joints post script

Then even non coder can go through the full process and be able to readjust and rebuild the rig.
Some of these appear in Miguel’s workshop on YouTube, but it’s a bit complicated to follow (Different videos, different timings, sometimes he runs into errors because he writes the scripts and not uses a template and he’s using environment settings).

I know that I keep struggling with some of these and keep having to ask forum members for help.
I already nailed down the geo and skin steps, but am now trying to get the facial rigs to work.

Thank you.

1 Like

Hey @Tsahi,
I think a simple introduction to Python would help you a lot. Not saying that you should code anything, but it’s helpful to automatize repetitive tasks. Just to understand how load/unload modules and how to use some functions.

For example, to load facials, you need to load facial scripts first, and then call their functions with given parameters (in this example, JSON configs).

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

from mgear.rigbits import facial_rigger  #mGear\scripts\mgear\rigbits\facial_rigger 
from mgear.custom import brow_rigger2 #mGear\scripts\mgear\custom\brow_rigger2.py


class CustomShifterStep(cstp.customShifterMainStep):
    def __init__(self):
        self.name = "testscript"

    def run(self, stepDict):
        facial_rigger.eye_rigger.rig_from_file(r"D:\Dropbox\L_eyeSetup.eyes")
        facial_rigger.eye_rigger.rig_from_file(r"D:\Dropbox\R_eyeSetup.eyes")
        facial_rigger.lips_rigger.rig_from_file(r"D:\Dropbox\lipSetup.lips")
        brow_rigger2.browsFromfile(r"D:\Dropbox\browSetup.brows")

        return

If something is not working, you need to check the modules you’re trying to load.
For example, facial_rigger folder from the script above is located here, and it may vary if you have different mGear version.

mGear\scripts\mgear\rigbits\facial_rigger

@Miquel @Toke_Stuart_Jepsen Maybe it would be nice to create that support category for python scripts, just to keep that topic clean, just with pre/post scripts?

1 Like

@Krzym I think I understood these basic principles, and yet I’m struggling with it as we speak.

BTW- in the brows rig I downloaded from your Dropbox the file is called brow_rigger.py and not brow_rigger2.py
Couldn’t find any link in that thread leading to a brow_rigger2.

Sorry, I didn’t keep track of that. This will be consistent when I’ll have some time to update. You’ll need to use brow_rigger then and it should work just fine.

1 Like

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)

3 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)

5 Likes