class FKChainComponentRig(FKChainComponent): """FK Chain Leg Rig""" def __init__(self, name='FKChain', parent=None): Profiler.getInstance().push("Construct FK Chain Rig Component:" + name) super(FKChainComponentRig, self).__init__(name, parent) # ========= # Controls # ========= # FK self.fkCtrlSpaces = [] self.fkCtrls = [] self.setNumControls(4) # Add Component Params to IK control legSettingsAttrGrp = AttributeGroup("DisplayInfo_ChainSettings", parent=self.fkCtrls[0]) legdrawDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=legSettingsAttrGrp) # Connect IO to controls self.drawDebugInputAttr.connect(legdrawDebugInputAttr) # ========== # Deformers # ========== deformersLayer = self.getOrCreateLayer('deformers') self.defCmpGrp = ComponentGroup(self.getName(), self, parent=deformersLayer) self.deformerJoints = [] self.boneOutputsTgt = [] self.setNumDeformers(4) # ===================== # Create Component I/O # ===================== # Set IO Targets self.boneOutputs.setTarget(self.boneOutputsTgt) # ============== # Constrain I/O # ============== # Constraint inputs self.rootInputConstraint = PoseConstraint('_'.join([ self.fkCtrlSpaces[0].getName(), 'To', self.rootInputTgt.getName() ])) self.rootInputConstraint.setMaintainOffset(True) self.rootInputConstraint.addConstrainer(self.rootInputTgt) self.fkCtrlSpaces[0].addConstraint(self.rootInputConstraint) # =============== # Add Splice Ops # =============== # Add Output Splice Op self.outputsToControlsKLOp = KLOperator('fkChainOutputKLOp', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.outputsToControlsKLOp) # Add Att Inputs self.outputsToControlsKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.outputsToControlsKLOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs self.outputsToControlsKLOp.setInput('constrainers', self.fkCtrls) # Add Xfo Outputs self.outputsToControlsKLOp.setOutput('constrainees', self.boneOutputsTgt) # Add Deformer Splice Op self.deformersToOutputsKLOp = KLOperator('fkChainDeformerKLOp', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.deformersToOutputsKLOp) # Add Att Inputs self.deformersToOutputsKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.deformersToOutputsKLOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs self.deformersToOutputsKLOp.setInput('constrainers', self.boneOutputsTgt) # Add Xfo Outputs self.deformersToOutputsKLOp.setOutput('constrainees', self.deformerJoints) Profiler.getInstance().pop() def setNumControls(self, numControls): # Add more controls if numControls > len(self.fkCtrlSpaces): for i in xrange(len(self.fkCtrlSpaces), numControls): if i == 0: parent = self.ctrlCmpGrp else: parent = self.fkCtrls[i - 1] boneName = 'bone' + str(i + 1).zfill(2) + 'FK' boneFKCtrlSpace = CtrlSpace(boneName, parent=parent) boneFKCtrl = Control(boneName, parent=boneFKCtrlSpace, shape="cube") boneFKCtrl.alignOnXAxis() boneFKCtrl.lockScale(x=True, y=True, z=True) boneFKCtrl.lockTranslation(x=True, y=True, z=True) self.fkCtrlSpaces.append(boneFKCtrlSpace) self.fkCtrls.append(boneFKCtrl) # Remove extra ctrls elif numControls < len(self.fkCtrlSpaces): numExtraCtrls = len(self.fkCtrls) - numControls for i in xrange(numExtraCtrls): extraCtrlSpace = self.fkCtrlSpaces.pop() extraCtrl = self.fkCtrls.pop() extraCtrlSpace.getParent().removeChild(extraCtrlSpace) extraCtrl.getParent().removeChild(extraCtrl) def setNumDeformers(self, numDeformers): # Add more deformers and outputs if numDeformers > len(self.boneOutputsTgt): for i in xrange(len(self.boneOutputsTgt), numDeformers): name = 'bone' + str(i + 1).zfill(2) legOutput = ComponentOutput(name, parent=self.outputHrcGrp) self.boneOutputsTgt.append(legOutput) boneDef = Joint(name, parent=self.defCmpGrp) boneDef.setComponent(self) self.deformerJoints.append(boneDef) # Remove extra deformers and outputs elif numDeformers < len(self.boneOutputsTgt): numExtraOutputs = len(self.boneOutputsTgt) - numDeformers numExtraDefs = len(self.deformerJoints) - numDeformers for i in xrange(numExtraOutputs): extraOutput = self.boneOutputsTgt.pop() extraDef = self.deformerJoints.pop() extraOutput.getParent().removeChild(extraOutput) extraDef.getParent().removeChild(extraDef) return True def loadData(self, data=None): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(FKChainComponentRig, self).loadData(data) boneXfos = data['boneXfos'] boneLengths = data['boneLengths'] numJoints = data['numJoints'] # Add extra controls and outputs self.setNumControls(numJoints) self.setNumDeformers(numJoints) for i in xrange(numJoints): self.fkCtrlSpaces[i].xfo = boneXfos[i] self.fkCtrls[i].xfo = boneXfos[i] self.fkCtrls[i].scalePoints( Vec3(boneLengths[i], boneLengths[i] * 0.45, boneLengths[i] * 0.45)) # ========================== # Create Output Constraints # ========================== # This needs to be done here since the 'numJoints' attribute resizes the # number of controls and outputs self.chainEndXfoOutputConstraint = PoseConstraint('_'.join([ self.chainEndXfoOutputTgt.getName(), 'To', self.boneOutputsTgt[-1].getName() ])) self.chainEndXfoOutputConstraint.setMaintainOffset(True) self.chainEndXfoOutputConstraint.addConstrainer( self.boneOutputsTgt[-1]) self.chainEndXfoOutputTgt.addConstraint( self.chainEndXfoOutputConstraint) self.chainEndPosOutputConstraint = PositionConstraint('_'.join([ self.chainEndPosOutputTgt.getName(), 'To', self.boneOutputsTgt[-1].getName() ])) self.chainEndPosOutputConstraint.setMaintainOffset(True) self.chainEndPosOutputConstraint.addConstrainer( self.boneOutputsTgt[-1]) self.chainEndPosOutputTgt.addConstraint( self.chainEndPosOutputConstraint) # ============ # Set IO Xfos # ============ self.rootInputTgt.xfo = boneXfos[0] for i in xrange(numJoints): self.boneOutputsTgt[i].xfo = boneXfos[i] self.chainEndXfoOutputTgt.xfo = data['endXfo'] self.chainEndPosOutputTgt.xfo = data['endXfo'] # ============= # Set IO Attrs # ============= # ==================== # Evaluate Splice Ops # ==================== # Eval Outputs to Controls Op to evaulate with new outputs and controls self.outputsToControlsKLOp.evaluate() # evaluate the output splice op to evaluate with new outputs and deformers self.deformersToOutputsKLOp.evaluate() # evaluate the constraints to ensure the outputs are now in the correct location. self.rootInputConstraint.evaluate() self.chainEndXfoOutputConstraint.evaluate()