hello,
I’ve been working on an RFK spine guide and I want the top of the chain (the chest) to be able to switch between local and world space using an orient constraint. Right now I’m just using an orient constraint from applyops but looking at the arm component I can see there is an actual switching system. I’m having trouble figuring out how to use it. Im puttintg my init file below. Thanks.
"""Component cGear Spine module"""
import mgear.pymaya as pm
from mgear.pymaya import datatypes
from mgear.shifter import component
from mgear.core import transform, primitive, vector
from mgear.core import applyop
#this init file is copied from chain_loc_ori_01
##########################################################
# COMPONENT
##########################################################
class Component(component.Main):
"""Shifter component Class"""
# =====================================================
# OBJECTS
# =====================================================
def addObjects(self):
self.WIP = self.options["mode"]
if self.negate and self.settings["overrideNegate"]:
self.negate = False
self.n_factor = 1
if self.settings["overrideNegate"]:
self.mirror_conf = [0, 0, 1,
1, 1, 0,
0, 0, 0]
else:
self.mirror_conf = [0, 0, 0,
0, 0, 0,
0, 0, 0]
self.fk_npo = []
self.fk_ctl = []
self.rfk_npo = []
self.ik_npo = []
self.ik_ctl = []
parent = self.root
tOld = False
self.previusTag = self.parentCtlTag
for i, t in enumerate(self.guide.atra[:-1]):
t = transform.setMatrixScale(t)
if self.settings["neutralpose"] or not tOld:
tnpo = t
else:
tnpo = transform.setMatrixPosition(
tOld, transform.getPositionFromMatrix(t))
end_ctl = (i == len(self.guide.atra) - 2)
#FK controls
if end_ctl:
self.end_ik_cns = primitive.addTransform(
parent, self.getName("fk%s_ik_cns" % i), tnpo)
fk_npo = primitive.addTransform(
self.end_ik_cns, self.getName("fk%s_npo" % i), tnpo)
else:
fk_npo = primitive.addTransform(
parent, self.getName("fk%s_npo" % i), tnpo)
fk_ctl = self.addCtl(
fk_npo,
"fk%s_ctl" % i,
t,
self.color_fk,
"circle",
w=self.size * .4,
ro=datatypes.Vector([0, 0, 1.5708]),
tp=self.previusTag,
mirrorConf=self.mirror_conf)
#RFK nodes
if i != 0 and i != len(self.guide.atra) - 2:
rfk_npo = primitive.addTransform(
fk_ctl, self.getName("rfk%s_npo" % i), t)
ik_npo = primitive.addTransform(
rfk_npo, self.getName("ik%s_npo" % i), t)
self.rfk_npo.append(rfk_npo)
else:
ik_npo = primitive.addTransform(
fk_ctl, self.getName("ik%s_npo" % i), t)
ik_ctl = self.addCtl(
ik_npo,
"ik%s_ctl" % i,
t,
self.color_ik,
"square",
w=self.size * .25,
ro=datatypes.Vector([0, 0, 1.5708]),
tp=fk_ctl,
mirrorConf=self.mirror_conf)
self.fk_npo.append(fk_npo)
self.fk_ctl.append(fk_ctl)
self.ik_npo.append(ik_npo)
self.ik_ctl.append(ik_ctl)
tOld = t
self.previusTag = fk_ctl
parent = fk_ctl
if self.settings["addJoints"]:
self.jnt_pos.append([ik_ctl, i, None, False])
# =====================================================
# ATTRIBUTES
# =====================================================
def addAttributes(self):
self.scale_factor_attrs = []
#get world positions of base and top
base_pos = self.fk_ctl[0].getTranslation(space = "world")
top_pos = self.fk_ctl[-1].getTranslation(space = "world")
total = (top_pos - base_pos).length()
for i, npo in enumerate(self.rfk_npo):
#get position on chain to calculate scale factor
npo_pos = npo.getTranslation(space = "world")
dist_from_base = (npo_pos - base_pos).length()
scale_factor = dist_from_base/total
attr = self.addAnimParam(
"scale_factor_%i" % i,
"scale_factor_%i" % i,
"double",
scale_factor,
0,
1
)
self.scale_factor_attrs.append(attr)
self.addAnimEnumParam(
"top_orient_ref",
"Top Orient",
0,
["local", "world"]
)
# =====================================================
# OPERATORS
# =====================================================
def addOperators(self):
print([m for m in dir(self) if "host" in m.lower() or "ui" in m.lower()])
#create the rfk system by getting twist between base and top of spine
#and then distributing through mid segments
#get foward axes (set in guide oiptions)
axes = ["X", "Y", "Z"]
spine_axis = axes[self.settings["spineAxis"]]
world_forward = axes[self.settings["worldForward"]]
#ID rfk drivers
base_ctl = self.fk_ctl[0]
top_ctl = self.fk_ctl[-1]
#get matrices from drivers
base_dcm = pm.createNode("decomposeMatrix", n = self.getName("base_dcm"))
top_dcm = pm.createNode("decomposeMatrix", n = self.getName("top_dcm"))
pm.connectAttr(base_ctl.worldMatrix[0], base_dcm.inputMatrix)
pm.connectAttr(top_ctl.worldMatrix[0], top_dcm.inputMatrix)
#ID mid segments
mid_segments = len(self.rfk_npo)
#connect mid segments to rfk solver
for i, npo in enumerate(self.rfk_npo):
scale_factor = (i + 1)/(mid_segments + 1)
base_weight = 1 - scale_factor
top_weight = scale_factor
#base multiply divide
base_md = pm.createNode("multiplyDivide", n = self.getName("base_md%s" % i))
pm.connectAttr(base_dcm.attr("outputRotate%s" % world_forward), base_md.input1X)
pm.connectAttr(self.scale_factor_attrs[i], base_md.input2X)
#top multiply divide
top_md = pm.createNode("multiplyDivide", n = self.getName("top_md%s" % i))
pm.connectAttr(top_dcm.attr("outputRotate%s" % world_forward), top_md.input1X)
pm.connectAttr(self.scale_factor_attrs[i], top_md.input2X)
#blender
blend = pm.createNode("plusMinusAverage", n = self.getName("twist_blend%s" % i))
blend.operation.set(2)
pm.connectAttr(base_md.outputX, blend.input1D[1])
pm.connectAttr(top_md.outputX, blend.input1D[0])
#connect
pm.connectAttr(blend.output1D, npo.attr("rotate%s" % spine_axis))
#get world ctl
global_ctl = pm.ls("global_C0_ctl")[0]
#orient constrain to global
ori_cns = applyop.oriCns(global_ctl, self.end_ik_cns, maintainOffset=True)
pm.setAttr(f"{ori_cns}.{global_ctl.name()}W0", 0)
#connect attr to weight
space_attr = self.uihost.attr("spine_top_orient_ref")
pm.connectAttr(space_attr, f"{ori_cns}.{global_ctl.name()}W0")
# =====================================================
# CONNECTOR
# =====================================================
def setRelation(self):
self.relatives["root"] = self.fk_ctl[0]
self.controlRelatives["root"] = self.fk_ctl[0]
self.jointRelatives["root"] = 0
for i in range(0, len(self.fk_ctl) - 1):
self.relatives["%s_loc" % i] = self.fk_ctl[i + 1]
self.controlRelatives["%s_loc" % i] = self.fk_ctl[i + 1]
self.jointRelatives["%s_loc" % i] = i + 1
self.aliasRelatives["%s_ctl" % i] = i + 1
self.relatives["%s_loc" % (len(self.fk_ctl) - 1)] = self.fk_ctl[-1]
self.controlRelatives["%s_loc" % (len(self.fk_ctl) - 1)] = self.fk_ctl[-1]
self.jointRelatives["%s_loc" % (len(self.fk_ctl) - 1)] = len(self.fk_ctl) - 1
self.aliasRelatives["%s_loc" % (len(self.fk_ctl) - 1)] = len(self.fk_ctl) - 1