Skip to content

Instantly share code, notes, and snippets.

@thirstydevil
Created February 10, 2021 20:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thirstydevil/5d12d7e1484675adc07fd47b98706e8d to your computer and use it in GitHub Desktop.
Save thirstydevil/5d12d7e1484675adc07fd47b98706e8d to your computer and use it in GitHub Desktop.
import mgear.shifter.custom_step as cstp
import pymel.core as pm
import pprint
import logging
log = logging.getLogger("PostSetp")
DEGUB = False
def find_components(stepDict, to_find=[]):
return [c for c in stepDict["mgearRun"].components.keys() if any(comp_name in c for comp_name in to_find)]
def remove_global_icon():
"""
We don't need this icon in the rig and the animator isn't going to animate it. Lets just delete the shape node.
It should already be channel locked because of the guide settings. It's used by the rig as a space switch.
"""
try:
ctrl = pm.ls("global_C0_ctl")[0]
pm.delete(ctrl.getShapes())
except Exception as e:
log.exception(e)
def reparent_arm_leaf_twist_joints(stepDict):
"""
Reparent the twist joints so that they are leaf joints for Unreal. We're grabbing the settings from the guide here so
this should update if the guide updates and just work.
NB - This only works if this follows the div0 settings param. Which this component does.
"""
arm_components = find_components(stepDict, ["arm"])
try:
for key in arm_components:
comp = stepDict["mgearRun"].components[key]
if comp.name == "arm":
upper_twist_count, lower_twist_count = [comp.settings["div0"], comp.settings["div1"]]
start_joint = comp.jointList[0]
elbow_idx = upper_twist_count + 2
elbow_joint = comp.jointList[elbow_idx]
jnt_copy = comp.jointList[:]
jnt_copy.reverse()
for jnt in jnt_copy[:lower_twist_count+1]:
jnt.setParent(elbow_joint)
pm.reorder(jnt, front=1)
if DEGUB:
cube = pm.polyCube(n="{}_debug".format(jnt.shortName()))[0]
pm.parentConstraint([jnt, cube], mo=0)
jnt_copy.reverse()
for jnt in jnt_copy[1:elbow_idx]:
jnt.setParent(start_joint)
if DEGUB:
cube = pm.polyCube(n="{}_debug".format(jnt.shortName()))[0]
pm.parentConstraint([jnt, cube], mo=0)
elbow_joint.setParent(start_joint)
except Exception as e:
log.exception(e)
def reparent_leg_leaf_twist_joints(stepDict):
"""
Reparent the twist joints so that they are leaf joints for Unreal. We're grabbing the settings from the guide here so
this should update if the guide updates and just work.
NB - This only works if this follows the div0 settings param. Which this component does.
"""
arm_components = find_components(stepDict, ["leg"])
try:
for key in arm_components:
comp = stepDict["mgearRun"].components[key]
if comp.name == "leg":
start_joint = comp.jointList[0]
knee_idx = int(comp.settings["div0"]) + 2
knee_joint = comp.jointList[knee_idx]
for jnt in comp.jointList[1:knee_idx]:
jnt.setParent(start_joint)
knee_joint.setParent(start_joint)
children = knee_joint.getChildren(ad=True)
children.reverse()
for jnt in children[:int(comp.settings["div0"]) + 2]:
jnt.setParent(knee_joint)
except Exception as e:
log.exception(e)
def create_joint_offset_inversve_matrix(jnt):
"""
When reparenting joints and removing the meta joints from the skin skeleton, the orientation is messed up.
This is because the matrix network has a matrix that has been filled from the old hirarchy. It's not a live connection,
from what I can tell its a calculated matrix that make sure the jointOffset is calculated for.
Here, I set that matricies rotation to identity, keeping the translate encoded in it. Then get the inverse joint orient
and multiply that back into the rotate of the joint.
This fixes the problem for the finger and thumbs when. The remove 8 unneeded joints from the build.
"""
# Get the joint orient and invert it
matrix = pm.createNode("composeMatrix", n="{}_jointOffset_Matrix".format(jnt))
inverse_matrix = pm.createNode("inverseMatrix")
matrix.inputRotateX.set(jnt.jointOrientX.get())
matrix.inputRotateY.set(jnt.jointOrientY.get())
matrix.inputRotateZ.set(jnt.jointOrientZ.get())
matrix.outputMatrix >> inverse_matrix.inputMatrix
desompose_matrix = jnt.rotateX.inputs()[0]
source_matrix = desompose_matrix.inputs()[0]
dest = source_matrix.matrixA
if source_matrix.matrixA.inputs():
dest = source_matrix.matrixB
# We need to reset this to identity rotation
m = dest.get()
m.data[0] = [1.0, 0.0, 0.0]
m.data[1] = [0.0, 1.0, 0.0]
m.data[2] = [0.0, 0.0, 1.0]
dest.set(m)
mul_matrix = pm.createNode("mgear_mulMatrix", n="{}_negateOffset_Matrix".format(jnt))
inverse_matrix.outputMatrix >> mul_matrix.matrixA
source_matrix.output >> mul_matrix.matrixB
mul_matrix.output >> desompose_matrix.inputMatrix
def reparent_finger_joints(stepDict):
"""
Grabs all the finger components from the build process and re parents the fingers to the arm_end joint. Finally removes the meta joints.
This relies on the parent component being a meta component.
"""
to_delete = []
finger_comps = [c for c in stepDict["mgearRun"].components.keys() if any(comp_name in c for comp_name in ["finger", "thumb"])]
for key in finger_comps:
# TODO : Check that the parent component is a meta component before reparenting
comp = stepDict["mgearRun"].components[key]
root_joint = comp.jointList[0]
root_joint.setParent(comp.parent_comp.parent_comp.jointList[-1])
create_joint_offset_inversve_matrix(root_joint)
# can't delete them yet as the other fingers may be children. Need to do it at the end
to_delete.extend(comp.parent_comp.jointList)
if to_delete:
for node in to_delete:
try:
pm.delete(node)
except:
pass
class CustomShifterStep(cstp.customShifterMainStep):
def __init__(self):
self.name = "Post Biped Custom Step"
def run(self, stepDict):
remove_global_icon()
reparent_finger_joints(stepDict)
reparent_arm_leaf_twist_joints(stepDict)
reparent_leg_leaf_twist_joints(stepDict)
pm.select([])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment