def build(self, *args, **kwargs): super(Arm, self).build(*args, **kwargs) ''' # Create ikChain and fkChain self._aIkChain = pymel.duplicate(self.input, renameChildren=True, parentOnly=True) for oInput, oIk, in zip(self.input, self._aIkChain): pNameMap = NameMap(oInput, _sType='rig') oIk.rename(pNameMap.Serialize('ik')) self._aIkChain[0].setParent(self._oParent) # Trick the IK system (temporary solution) ''' # Rig ikChain and fkChain self.sysIK = IK(self.input); self.sysIK.build(**kwargs) self.sysFK = FK(self.input); self.sysFK.build(_bConstraint=False, **kwargs) self.sysIK.grp_anm.setParent(self.grp_anm) self.sysIK.grp_rig.setParent(self.grp_rig) self.sysFK.grp_anm.setParent(self.grp_anm) #self.sysFK.oGrpRig.setParent(self.oGrpRig) # Create attribute holder (this is where the IK/FK attribute will be stored) oAttHolder = RigAttHolder(name=self._pNameMapAnm.Serialize('atts'), _create=True) oAttHolder.setParent(self.grp_anm) pymel.parentConstraint(self.input[self.sysIK.iCtrlIndex], oAttHolder.offset) pymel.addAttr(oAttHolder, longName=self.kAttrName_State, hasMinValue=True, hasMaxValue=True, minValue=0, maxValue=1, defaultValue=1, k=True) attIkWeight = oAttHolder.attr(self.kAttrName_State) attFkWeight = libRigging.CreateUtilityNode('reverse', inputX=attIkWeight).outputX # Store the offset between the end fk ctrl and the end ik ctrl # TODO: Make libSerialization work with matrix #self.offsetCtrlIK = self.sysIK.ctrlIK.getMatrix(worldSpace=True) * self.sysFK.aCtrls[self.sysIK.iCtrlIndex].getMatrix(worldSpace=True).inverse() # Hold swivelSkinPose #self.swivelSkinPose = self.sysIK.ctrlSwivel.getMatrix() * self.aInput[self.sysIK.iCtrlIndex].getMatrix(worldSpace=True).inverse() # Blend ikChain with fkChain for oInput, oIk, oFk in zip(self.input, self.sysIK._chain_ik, self.sysFK.aCtrls): oConstraint = pymel.parentConstraint(oIk, oFk, oInput) attCurIkWeight, attCurFkWeight = oConstraint.getWeightAliasList() pymel.connectAttr(attIkWeight, attCurIkWeight) pymel.connectAttr(attFkWeight, attCurFkWeight) # Connect visibility pymel.connectAttr(attIkWeight, self.sysIK.grp_anm.visibility) pymel.connectAttr(attFkWeight, self.sysFK.grp_anm.visibility) self.attState = attIkWeight # Expose state
class Arm(RigPart): kAttrName_State = 'fkIk' # The name of the IK/FK attribute def build(self, *args, **kwargs): super(Arm, self).build(*args, **kwargs) ''' # Create ikChain and fkChain self._aIkChain = pymel.duplicate(self.input, renameChildren=True, parentOnly=True) for oInput, oIk, in zip(self.input, self._aIkChain): pNameMap = NameMap(oInput, _sType='rig') oIk.rename(pNameMap.Serialize('ik')) self._aIkChain[0].setParent(self._oParent) # Trick the IK system (temporary solution) ''' # Rig ikChain and fkChain self.sysIK = IK(self.input); self.sysIK.build(**kwargs) self.sysFK = FK(self.input); self.sysFK.build(_bConstraint=False, **kwargs) self.sysIK.grp_anm.setParent(self.grp_anm) self.sysIK.grp_rig.setParent(self.grp_rig) self.sysFK.grp_anm.setParent(self.grp_anm) #self.sysFK.oGrpRig.setParent(self.oGrpRig) # Create attribute holder (this is where the IK/FK attribute will be stored) oAttHolder = RigAttHolder(name=self._pNameMapAnm.Serialize('atts'), _create=True) oAttHolder.setParent(self.grp_anm) pymel.parentConstraint(self.input[self.sysIK.iCtrlIndex], oAttHolder.offset) pymel.addAttr(oAttHolder, longName=self.kAttrName_State, hasMinValue=True, hasMaxValue=True, minValue=0, maxValue=1, defaultValue=1, k=True) attIkWeight = oAttHolder.attr(self.kAttrName_State) attFkWeight = libRigging.CreateUtilityNode('reverse', inputX=attIkWeight).outputX # Store the offset between the end fk ctrl and the end ik ctrl # TODO: Make libSerialization work with matrix #self.offsetCtrlIK = self.sysIK.ctrlIK.getMatrix(worldSpace=True) * self.sysFK.aCtrls[self.sysIK.iCtrlIndex].getMatrix(worldSpace=True).inverse() # Hold swivelSkinPose #self.swivelSkinPose = self.sysIK.ctrlSwivel.getMatrix() * self.aInput[self.sysIK.iCtrlIndex].getMatrix(worldSpace=True).inverse() # Blend ikChain with fkChain for oInput, oIk, oFk in zip(self.input, self.sysIK._chain_ik, self.sysFK.aCtrls): oConstraint = pymel.parentConstraint(oIk, oFk, oInput) attCurIkWeight, attCurFkWeight = oConstraint.getWeightAliasList() pymel.connectAttr(attIkWeight, attCurIkWeight) pymel.connectAttr(attFkWeight, attCurFkWeight) # Connect visibility pymel.connectAttr(attIkWeight, self.sysIK.grp_anm.visibility) pymel.connectAttr(attFkWeight, self.sysFK.grp_anm.visibility) self.attState = attIkWeight # Expose state def unbuild(self, *args, **kwargs): super(Arm, self).unbuild(*args, **kwargs) self.sysIK = None # hack self.sysFK = None # hack self.attState = None # # Functions called for IK/FK switch (animation tools) # def snapIkToFk(self): # Position ikCtrl tmCtrlIk = self.input[self.sysIK.iCtrlIndex].getMatrix(worldSpace=True) self.sysIK.ctrlIK.setMatrix(self.ctrlIkOffset * tmCtrlIk, worldSpace=True) # Position swivel posRef = self.sysFK.aCtrls[self.sysIK.iCtrlIndex-1].getTranslation(space='world') posS = self.sysFK.aCtrls[0].getTranslation(space='world') posM = self.sysFK.aCtrls[self.sysIK.iCtrlIndex-1].getTranslation(space='world') posE = self.sysFK.aCtrls[self.sysIK.iCtrlIndex].getTranslation(space='world') fLengthS = posM.distanceTo(posS) fLengthE = posM.distanceTo(posE) fLengthRatio = fLengthS / (fLengthS+fLengthE) posRefPos = (posE-posS)*fLengthRatio + posS posDir = posM - posRefPos posDir.normalize() posSwivel = posDir * self.sysIK.swivelDistance + posRef #self.sysIK.ctrlSwivel.setMatrix(self.aInput[self.sysIK.iCtrlIndex-1].getMatrix(worldSpace=True), worldSpace=True) self.sysIK.ctrlSwivel.setTranslation(posSwivel, space='world') def snapFkToIk(self): for ctrl, jnt in zip(self.sysFK.aCtrls, self.input): ctrl.setMatrix(jnt.getMatrix(worldSpace=True), worldSpace=True) def switchToIk(self): self.snapIkToFk() self.attState.set(1.0) def switchToFk(self): self.snapFkToIk() self.attState.set(0.0)