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)
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 pmclass 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!
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)
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)
Thatās a great idea!