def __init__(self, name='InsectLeg', parent=None, data=None): Profiler.getInstance().push("Construct InsectLeg Guide Component:" + name) super(InsectLegComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numJoints = IntegerAttribute('numJoints', value=5, minValue=2, maxValue=20, parent=guideSettingsAttrGrp) self.numJoints.setValueChangeCallback(self.updateNumLegControls) self.jointCtrls = [] if data is None: numJoints = self.numJoints.getValue() jointPositions = self.generateGuidePositions(numJoints) for i in xrange(numJoints): self.jointCtrls.append(Control('leg' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="sphere")) data = { "location": "L", "jointPositions": jointPositions, "numJoints": self.numJoints.getValue() } self.loadData(data) Profiler.getInstance().pop()
def __init__(self, name='spine', parent=None, *args, **kwargs): Profiler.getInstance().push("Construct Spine Guide Component:" + name) super(SpineComponentGuide, self).__init__(name, parent, *args, **kwargs) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) # Guide Controls self.cog = Control('cogPosition', parent=self.ctrlCmpGrp, shape="sphere") self.cog.scalePoints(Vec3(1.2, 1.2, 1.2)) self.cog.setColor('red') self.spine01Ctrl = Control('spine01Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine02Ctrl = Control('spine02Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine03Ctrl = Control('spine03Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine04Ctrl = Control('spine04Position', parent=self.ctrlCmpGrp, shape='sphere') data = { 'name': name, 'location': 'M', 'cogPosition': Vec3(0.0, 11.1351, -0.1382), 'spine01Position': Vec3(0.0, 11.1351, -0.1382), 'spine02Position': Vec3(0.0, 11.8013, -0.1995), 'spine03Position': Vec3(0.0, 12.4496, -0.3649), 'spine04Position': Vec3(0.0, 13.1051, -0.4821), 'numDeformers': 6 } self.loadData(data) Profiler.getInstance().pop()
def __init__(self, name='hand', parent=None, *args, **kwargs): Profiler.getInstance().push("Construct Hand Guide Component:" + name) super(HandComponentGuide, self).__init__(name, parent, *args, **kwargs) # ========= # Controls # ========= # Guide Controls self.guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.digitNamesAttr = StringAttribute( 'digitNames', value="thumb,index,middle,ring,pinky", parent=self.guideSettingsAttrGrp) self.digitNamesAttr.setValueChangeCallback(self.updateFingers) self.numJointsAttr = IntegerAttribute('numJoints', value=4, minValue=2, maxValue=20, parent=self.guideSettingsAttrGrp) self.numJointsAttr.setValueChangeCallback(self.resizeDigits) self.fingers = OrderedDict() self.handCtrl = Control('hand', parent=self.ctrlCmpGrp, shape="square") self.handCtrl.rotatePoints(0.0, 0.0, 90.0) self.handCtrl.scalePoints(Vec3(1.0, 0.75, 1.0)) self.handCtrl.setColor('yellow') self.handGuideSettingsAttrGrp = AttributeGroup("Settings", parent=self.handCtrl) self.ctrlShapeToggle = BoolAttribute( 'ctrlShape_vis', value=False, parent=self.handGuideSettingsAttrGrp) self.handDebugInputAttr = BoolAttribute( 'drawDebug', value=False, parent=self.handGuideSettingsAttrGrp) self.drawDebugInputAttr.connect(self.handDebugInputAttr) self.guideCtrlHrcGrp = HierarchyGroup('controlShapes', parent=self.ctrlCmpGrp) self.default_data = { "name": name, "location": "L", "handXfo": Xfo(Vec3(7.1886, 12.2819, 0.4906)), "digitNames": self.digitNamesAttr.getValue(), "numJoints": self.numJointsAttr.getValue(), "fingers": self.fingers } self.loadData(self.default_data) Profiler.getInstance().pop()
def __init__(self, name='twist', parent=None): Profiler.getInstance().push('Construct Spine Guide Component:' + name) super(TwistComponentGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup('GuideSettings', parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.blendBiasAttr = ScalarAttribute('blendBias', value=0.0, minValue=0, maxValue=1.0, parent=guideSettingsAttrGrp) # Guide Controls triangleCtrl = Control('triangle', shape='triangle') triangleCtrl.rotatePoints(90, 0, 0) triangleCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) triangleCtrl.scalePoints(Vec3(1.0, 0.5, 1.0)) triangleCtrl.translatePoints(Vec3(0.0, 1.25, 0.0)) triangleCtrl.rotatePoints(0, 90, 0) self.originCtrl = Control('origin', parent=self.ctrlCmpGrp, shape='circle') self.originCtrl.rotatePoints(90, 0, 0) self.originCtrl.rotatePoints(0, 90, 0) self.originCtrl.appendCurveData(triangleCtrl.getCurveData()) self.insertCtrl = Control('insert', parent=self.ctrlCmpGrp, shape='circle') self.insertCtrl.rotatePoints(90, 0, 0) self.insertCtrl.rotatePoints(0, 90, 0) self.insertCtrl.appendCurveData(triangleCtrl.getCurveData()) self.default_data = { 'name': name, 'location': 'M', 'blendBias': 0.5, 'originXfo': Xfo(Vec3(0.0, 0.0, 0.0)), 'insertXfo': Xfo(Vec3(5.0, 0.0, 0.0)), 'numDeformers': 5 } self.loadData(self.default_data) Profiler.getInstance().pop()
def __init__(self, name='Tentacle', parent=None, data=None): Profiler.getInstance().push("Construct Tentacle Guide Component:" + name) super(TentacleComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numJoints = IntegerAttribute('numJoints', value=5, minValue=2, maxValue=20, parent=guideSettingsAttrGrp) self.numJoints.setValueChangeCallback(self.updateNumControls) self.jointCtrls = [] self.tentacleOutputs = [] if data is None: numJoints = self.numJoints.getValue() jointPositions = self.generateGuidePositions(numJoints) for i in xrange(numJoints): self.jointCtrls.append(Control('tentacle' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="sphere")) self.tentacleOutputs.append(ComponentOutput('tentacle' + str(i + 1).zfill(2), parent=self.outputHrcGrp)) self.boneOutputs.setTarget(self.tentacleOutputs) data = { "location": "L", "jointPositions": jointPositions, "numJoints": self.numJoints.getValue() } self.loadData(data) Profiler.getInstance().pop()
def createOutput(self, name, dataType, **kwargs): """Creates an output object and also a connected target object that matches the data type that is passed. Args: name (str): Name of the output to create. dataType (str): Data type of the output. Returns: Object: The connected target object for the output. """ componentOutputPort = self.addOutput(name, dataType) if dataType.endswith('[]'): newOutputTgt = [] else: # Create object if dataType.startswith('Xfo'): newOutputTgt = ComponentOutput(name) elif dataType.startswith('Boolean'): newOutputTgt = BoolAttribute(name) elif dataType.startswith('Float'): newOutputTgt = ScalarAttribute(name) elif dataType.startswith('Integer'): newOutputTgt = IntegerAttribute(name) elif dataType.startswith('String'): newOutputTgt = StringAttribute(name) # Handle keyword arguments for k, v in kwargs.iteritems(): if k == 'value': newOutputTgt.setValue(v) elif k == 'minValue': newOutputTgt.setMin(v) elif k == 'maxValue': newOutputTgt.setMax(v) elif k == 'parent': if isinstance(newOutputTgt, list): raise Exception( "Array outputs cannot be assigned to a parent. Each element in the array must be parented individually: " + name + ".") if dataType.startswith('Xfo'): v.addChild(newOutputTgt) else: v.addAttribute(newOutputTgt) else: logger.warning( "Keyword '%s' is not supported with createOutput method!" % k) componentOutputPort.setTarget(newOutputTgt) return componentOutputPort
def __init__(self, name='FKChain', parent=None, data=None): Profiler.getInstance().push("Construct FKCHain Guide Component:" + name) super(FKChainComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numJoints = IntegerAttribute('numJoints', value=4, minValue=1, maxValue=20, parent=guideSettingsAttrGrp) self.numJoints.setValueChangeCallback(self.updateNumJointControls) self.jointCtrls = [] if data is None: numJoints = self.numJoints.getValue() jointPositions = self.generateGuidePositions(numJoints) for i in xrange(numJoints + 1): if i == 0: ctrlParent = self.ctrlCmpGrp else: ctrlParent = self.jointCtrls[i - 1] newCtrl = Control('chain' + str(i + 1).zfill(2), parent=ctrlParent, shape="sphere") newCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) self.jointCtrls.append(newCtrl) data = { "location": "L", "jointPositions": jointPositions, "numJoints": self.numJoints.getValue() } self.loadData(data) Profiler.getInstance().pop()
def createInput(self, name, dataType, **kwargs): """Creates an input object and also a connected target object that matches the data type that is passed. Args: name (str): Name of the input to create. dataType (str): Data type of the input. Returns: Object: The connected target object for the input. """ componentInputPort = self.addInput(name, dataType) # Create object if dataType.startswith('Xfo'): newInputTgt = ComponentInput(name) elif dataType.startswith('Boolean'): newInputTgt = BoolAttribute(name) elif dataType.startswith('Float'): newInputTgt = ScalarAttribute(name) elif dataType.startswith('Integer'): newInputTgt = IntegerAttribute(name) elif dataType.startswith('String'): newInputTgt = StringAttribute(name) # Handle keyword arguments for k, v in kwargs.iteritems(): if k == 'value': newInputTgt.setValue(v) elif k == 'minValue': newInputTgt.setMin(v) newInputTgt.setUIMin(v) elif k == 'maxValue': newInputTgt.setMax(v) newInputTgt.setUIMax(v) elif k == 'parent': if dataType.startswith('Xfo'): v.addChild(newInputTgt) else: v.addAttribute(newInputTgt) else: logger.warning( "Keyword '%s' is not supported with createInput method!" % k) componentInputPort.setTarget(newInputTgt) return componentInputPort
def __init__(self, name='MultiSpring', parent=None): Profiler.getInstance().push("Construct FKCHain Guide Component:" + name) super(MultiSpringComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numSprings = IntegerAttribute('numSprings', value=5, minValue=1, maxValue=100, parent=guideSettingsAttrGrp) self.numSprings.setValueChangeCallback(self.updateNumJointControls) self.springCtrls = [] numSprings = self.numSprings.getValue() springXfos = self.generateGuideXfos(numSprings) for i in xrange(numSprings): newCtrl = Control('spring' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="squarePointed") newCtrl.alignOnXAxis() self.springCtrls.append(newCtrl) data = { "location": "L", "springXfos": springXfos, "numSprings": self.numSprings.getValue() } self.loadData(data) Profiler.getInstance().pop()
def __init__(self, name='hand', parent=None, *args, **kwargs): Profiler.getInstance().push("Construct Hand Guide Component:" + name) super(HandComponentGuide, self).__init__(name, parent, *args, **kwargs) # ========= # Controls # ========= # Guide Controls self.guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.digitNamesAttr = StringAttribute('digitNames', value="thumb,index,middle,ring,pinky", parent=self.guideSettingsAttrGrp) self.digitNamesAttr.setValueChangeCallback(self.updateFingers) self.numJointsAttr = IntegerAttribute('numJoints', value=4, minValue=2, maxValue=20, parent=self.guideSettingsAttrGrp) self.numJointsAttr.setValueChangeCallback(self.resizeDigits) self.fingers = OrderedDict() self.handCtrl = Control('hand', parent=self.ctrlCmpGrp, shape="square") self.handCtrl.rotatePoints(0.0, 0.0, 90.0) self.handCtrl.scalePoints(Vec3(1.0, 0.75, 1.0)) self.handCtrl.setColor('yellow') self.handGuideSettingsAttrGrp = AttributeGroup("Settings", parent=self.handCtrl) self.ctrlShapeToggle = BoolAttribute('ctrlShape_vis', value=False, parent=self.handGuideSettingsAttrGrp) self.handDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=self.handGuideSettingsAttrGrp) self.drawDebugInputAttr.connect(self.handDebugInputAttr) self.guideCtrlHrcGrp = HierarchyGroup('controlShapes', parent=self.ctrlCmpGrp) self.default_data = { "name": name, "location": "L", "handXfo": Xfo(Vec3(7.1886, 12.2819, 0.4906)), "digitNames": self.digitNamesAttr.getValue(), "numJoints": self.numJointsAttr.getValue(), "fingers": self.fingers } self.loadData(self.default_data) Profiler.getInstance().pop()
def __init__(self, name="spine", parent=None): Profiler.getInstance().push("Construct Spine Guide Component:" + name) super(SpineComponentGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute( "numDeformers", value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp ) # Guide Controls self.cog = Control("cogPosition", parent=self.ctrlCmpGrp, shape="sphere") self.cog.scalePoints(Vec3(1.2, 1.2, 1.2)) self.cog.setColor("red") self.spine01Ctrl = Control("spine01Position", parent=self.ctrlCmpGrp, shape="sphere") self.spine02Ctrl = Control("spine02Position", parent=self.ctrlCmpGrp, shape="sphere") self.spine03Ctrl = Control("spine03Position", parent=self.ctrlCmpGrp, shape="sphere") self.spine04Ctrl = Control("spine04Position", parent=self.ctrlCmpGrp, shape="sphere") self.loadData( { "name": name, "location": "M", "cogPosition": Vec3(0.0, 11.1351, -0.1382), "spine01Position": Vec3(0.0, 11.1351, -0.1382), "spine02Position": Vec3(0.0, 11.8013, -0.1995), "spine03Position": Vec3(0.0, 12.4496, -0.3649), "spine04Position": Vec3(0.0, 13.1051, -0.4821), "numDeformers": 6, } ) Profiler.getInstance().pop()
def __init__(self, name='InsectLeg', parent=None): Profiler.getInstance().push("Construct InsectLeg Rig Component:" + name) super(InsectLegComponentRig, self).__init__(name, parent) # ========= # Controls # ========= # Chain Base self.chainBase = Locator('ChainBase', parent=self.ctrlCmpGrp) self.chainBase.setShapeVisibility(False) # FK self.fkCtrlSpaces = [] self.fkCtrls = [] self.setNumControls(4) # IK Control self.legIKCtrlSpace = CtrlSpace('IK', parent=self.ctrlCmpGrp) self.legIKCtrl = Control('IK', parent=self.legIKCtrlSpace, shape="pin") if self.getLocation() == 'R': self.legIKCtrl.rotatePoints(0, 90, 0) self.legIKCtrl.translatePoints(Vec3(-1.0, 0.0, 0.0)) else: self.legIKCtrl.rotatePoints(0, -90, 0) self.legIKCtrl.translatePoints(Vec3(1.0, 0.0, 0.0)) # Add Component Params to IK control legSettingsAttrGrp = AttributeGroup("DisplayInfo_LegSettings", parent=self.legIKCtrl) legdrawDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=legSettingsAttrGrp) legUseInitPoseInputAttr = BoolAttribute('useInitPose', value=True, parent=legSettingsAttrGrp) self.rootIndexInputAttr = IntegerAttribute('rootIndex', value=0, parent=legSettingsAttrGrp) legFkikInputAttr = ScalarAttribute('fkik', value=1.0, minValue=0.0, maxValue=1.0, parent=legSettingsAttrGrp) # Connect IO to controls self.drawDebugInputAttr.connect(legdrawDebugInputAttr) # UpV self.legUpVCtrlSpace = CtrlSpace('UpV', parent=self.ctrlCmpGrp) self.legUpVCtrl = Control('UpV', parent=self.legUpVCtrlSpace, shape="triangle") self.legUpVCtrl.alignOnZAxis() self.legUpVCtrl.rotatePoints(0, 90, 0) # ========== # Deformers # ========== deformersLayer = self.getOrCreateLayer('deformers') self.defCmpGrp = ComponentGroup(self.getName(), self, parent=deformersLayer) self.addItem('defCmpGrp', self.defCmpGrp) self.deformerJoints = [] self.boneOutputsTgt = [] self.setNumDeformers(4) # ===================== # Create Component I/O # ===================== # Set IO Targets self.boneOutputs.setTarget(self.boneOutputsTgt) # ============== # Constrain I/O # ============== # Constraint inputs legRootInputConstraint = PoseConstraint('_'.join([ self.fkCtrlSpaces[0].getName(), 'To', self.rootInputTgt.getName() ])) legRootInputConstraint.setMaintainOffset(True) legRootInputConstraint.addConstrainer(self.rootInputTgt) self.fkCtrlSpaces[0].addConstraint(legRootInputConstraint) chainBaseInputConstraint = PoseConstraint('_'.join( [self.chainBase.getName(), 'To', self.rootInputTgt.getName()])) chainBaseInputConstraint.setMaintainOffset(True) chainBaseInputConstraint.addConstrainer(self.rootInputTgt) self.chainBase.addConstraint(chainBaseInputConstraint) # =============== # Add Canvas Ops # =============== # Add Canvas Op self.nBoneSolverKLOp = KLOperator('leg', 'NBoneIKSolver', 'Kraken') self.addOperator(self.nBoneSolverKLOp) # # Add Att Inputs self.nBoneSolverKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.nBoneSolverKLOp.setInput('rigScale', self.rigScaleInputAttr) self.nBoneSolverKLOp.setInput('useInitPose', legUseInitPoseInputAttr) self.nBoneSolverKLOp.setInput('ikblend', legFkikInputAttr) self.nBoneSolverKLOp.setInput('rootIndex', self.rootIndexInputAttr) self.nBoneSolverKLOp.setInput('tipBoneLen', self.tipBoneLenInputAttr) # Add Xfo Inputs self.nBoneSolverKLOp.setInput('chainBase', self.chainBase) self.nBoneSolverKLOp.setInput('ikgoal', self.legIKCtrl) self.nBoneSolverKLOp.setInput('upVector', self.legUpVCtrl) self.nBoneSolverKLOp.setInput('fkcontrols', self.fkCtrls) # Add Xfo Outputs self.nBoneSolverKLOp.setOutput('pose', self.boneOutputsTgt) self.nBoneSolverKLOp.setOutput('legEnd', self.legEndPosOutputTgt) # Add Deformer Canvas Op self.outputsToDeformersKLOp = KLOperator('defConstraint', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.outputsToDeformersKLOp) # Add Att Inputs self.outputsToDeformersKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.outputsToDeformersKLOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs self.outputsToDeformersKLOp.setInput('constrainers', self.boneOutputsTgt) # Add Xfo Outputs self.outputsToDeformersKLOp.setOutput('constrainees', self.deformerJoints) Profiler.getInstance().pop()
class InsectLegComponentRig(InsectLegComponent): """Insect Leg Rig""" def __init__(self, name='InsectLeg', parent=None): Profiler.getInstance().push("Construct InsectLeg Rig Component:" + name) super(InsectLegComponentRig, self).__init__(name, parent) # ========= # Controls # ========= # Chain Base self.chainBase = Locator('ChainBase', parent=self.ctrlCmpGrp) self.chainBase.setShapeVisibility(False) # FK self.fkCtrlSpaces = [] self.fkCtrls = [] self.setNumControls(4) # IK Control self.legIKCtrlSpace = CtrlSpace('IK', parent=self.ctrlCmpGrp) self.legIKCtrl = Control('IK', parent=self.legIKCtrlSpace, shape="pin") if self.getLocation() == 'R': self.legIKCtrl.rotatePoints(0, 90, 0) self.legIKCtrl.translatePoints(Vec3(-1.0, 0.0, 0.0)) else: self.legIKCtrl.rotatePoints(0, -90, 0) self.legIKCtrl.translatePoints(Vec3(1.0, 0.0, 0.0)) # Add Component Params to IK control legSettingsAttrGrp = AttributeGroup("DisplayInfo_LegSettings", parent=self.legIKCtrl) legdrawDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=legSettingsAttrGrp) legUseInitPoseInputAttr = BoolAttribute('useInitPose', value=True, parent=legSettingsAttrGrp) self.rootIndexInputAttr = IntegerAttribute('rootIndex', value=0, parent=legSettingsAttrGrp) legFkikInputAttr = ScalarAttribute('fkik', value=1.0, minValue=0.0, maxValue=1.0, parent=legSettingsAttrGrp) # Connect IO to controls self.drawDebugInputAttr.connect(legdrawDebugInputAttr) # UpV self.legUpVCtrlSpace = CtrlSpace('UpV', parent=self.ctrlCmpGrp) self.legUpVCtrl = Control('UpV', parent=self.legUpVCtrlSpace, shape="triangle") self.legUpVCtrl.alignOnZAxis() self.legUpVCtrl.rotatePoints(0, 90, 0) # ========== # Deformers # ========== deformersLayer = self.getOrCreateLayer('deformers') self.defCmpGrp = ComponentGroup(self.getName(), self, parent=deformersLayer) self.addItem('defCmpGrp', self.defCmpGrp) self.deformerJoints = [] self.boneOutputsTgt = [] self.setNumDeformers(4) # ===================== # Create Component I/O # ===================== # Set IO Targets self.boneOutputs.setTarget(self.boneOutputsTgt) # ============== # Constrain I/O # ============== # Constraint inputs legRootInputConstraint = PoseConstraint('_'.join([ self.fkCtrlSpaces[0].getName(), 'To', self.rootInputTgt.getName() ])) legRootInputConstraint.setMaintainOffset(True) legRootInputConstraint.addConstrainer(self.rootInputTgt) self.fkCtrlSpaces[0].addConstraint(legRootInputConstraint) chainBaseInputConstraint = PoseConstraint('_'.join( [self.chainBase.getName(), 'To', self.rootInputTgt.getName()])) chainBaseInputConstraint.setMaintainOffset(True) chainBaseInputConstraint.addConstrainer(self.rootInputTgt) self.chainBase.addConstraint(chainBaseInputConstraint) # =============== # Add Canvas Ops # =============== # Add Canvas Op self.nBoneSolverKLOp = KLOperator('leg', 'NBoneIKSolver', 'Kraken') self.addOperator(self.nBoneSolverKLOp) # # Add Att Inputs self.nBoneSolverKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.nBoneSolverKLOp.setInput('rigScale', self.rigScaleInputAttr) self.nBoneSolverKLOp.setInput('useInitPose', legUseInitPoseInputAttr) self.nBoneSolverKLOp.setInput('ikblend', legFkikInputAttr) self.nBoneSolverKLOp.setInput('rootIndex', self.rootIndexInputAttr) self.nBoneSolverKLOp.setInput('tipBoneLen', self.tipBoneLenInputAttr) # Add Xfo Inputs self.nBoneSolverKLOp.setInput('chainBase', self.chainBase) self.nBoneSolverKLOp.setInput('ikgoal', self.legIKCtrl) self.nBoneSolverKLOp.setInput('upVector', self.legUpVCtrl) self.nBoneSolverKLOp.setInput('fkcontrols', self.fkCtrls) # Add Xfo Outputs self.nBoneSolverKLOp.setOutput('pose', self.boneOutputsTgt) self.nBoneSolverKLOp.setOutput('legEnd', self.legEndPosOutputTgt) # Add Deformer Canvas Op self.outputsToDeformersKLOp = KLOperator('defConstraint', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.outputsToDeformersKLOp) # Add Att Inputs self.outputsToDeformersKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.outputsToDeformersKLOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs self.outputsToDeformersKLOp.setInput('constrainers', self.boneOutputsTgt) # Add Xfo Outputs self.outputsToDeformersKLOp.setOutput('constrainees', self.deformerJoints) Profiler.getInstance().pop() def setNumControls(self, numControls): # Add new control spaces and controls 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' fkCtrlSpace = CtrlSpace(boneName, parent=parent) fkCtrl = Control(boneName, parent=fkCtrlSpace, shape="cube") fkCtrl.alignOnXAxis() fkCtrl.lockScale(x=True, y=True, z=True) fkCtrl.lockTranslation(x=True, y=True, z=True) self.fkCtrlSpaces.append(fkCtrlSpace) self.fkCtrls.append(fkCtrl) def setNumDeformers(self, numDeformers): # Add new deformers and outputs 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) for i in xrange(len(self.deformerJoints), numDeformers): name = 'bone' + str(i + 1).zfill(2) boneDef = Joint(name, parent=self.defCmpGrp) boneDef.setComponent(self) self.deformerJoints.append(boneDef) return True def calculateUpVXfo(self, boneXfos, endXfo): """Calculates the transform for the UpV control. Args: boneXfos (list): Bone transforms. endXfo (Xfo): Transform for the end of the chain. Returns: Xfo: Up Vector transform. """ # Calculate FW toFirst = boneXfos[1].tr.subtract(boneXfos[0].tr).unit() toTip = endXfo.tr.subtract(boneXfos[0].tr).unit() fw = toTip.cross(toFirst).unit() chainNormal = fw.cross(toTip).unit() chainZAxis = toTip.cross(chainNormal).unit() chainXfo = Xfo() chainXfo.setFromVectors(toTip.unit(), chainNormal, chainZAxis, boneXfos[0].tr) rootToTip = endXfo.tr.subtract(boneXfos[0].tr).length() upVXfo = Xfo() upVXfo.tr = chainXfo.transformVector( Vec3(rootToTip / 2.0, rootToTip / 2.0, 0.0)) return upVXfo 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(InsectLegComponentRig, self).loadData(data) boneXfos = data['boneXfos'] boneLengths = data['boneLengths'] numJoints = data['numJoints'] endXfo = data['endXfo'] # Add extra controls and outputs self.setNumControls(numJoints) self.setNumDeformers(numJoints) # Scale controls based on bone lengths for i, each in enumerate(self.fkCtrlSpaces): self.fkCtrlSpaces[i].xfo = boneXfos[i] self.fkCtrls[i].xfo = boneXfos[i] self.fkCtrls[i].scalePoints(Vec3(boneLengths[i], 1.75, 1.75)) self.chainBase.xfo = boneXfos[0] self.legIKCtrlSpace.xfo = endXfo self.legIKCtrl.xfo = endXfo upVXfo = self.calculateUpVXfo(boneXfos, endXfo) self.legUpVCtrlSpace.xfo = upVXfo self.legUpVCtrl.xfo = upVXfo # Set max on the rootIndex attribute self.rootIndexInputAttr.setMax(len(boneXfos)) # ============ # Set IO Xfos # ============ self.rootInputTgt.xfo = boneXfos[0] for i in xrange(len(boneLengths)): self.boneOutputsTgt[i].xfo = boneXfos[i] self.legEndXfoOutputTgt.xfo = endXfo self.legEndPosOutputTgt.xfo = endXfo # ============= # Set IO Attrs # ============= tipBoneLen = boneLengths[len(boneLengths) - 1] self.tipBoneLenInputAttr.setMax(tipBoneLen * 2.0) self.tipBoneLenInputAttr.setValue(tipBoneLen) # ==================== # Evaluate Splice Ops # ==================== # evaluate the nbone op so that all the output transforms are updated. self.nBoneSolverKLOp.evaluate() self.outputsToDeformersKLOp.evaluate()
class InsectLegComponentRig(InsectLegComponent): """Insect Leg Rig""" def __init__(self, name='InsectLeg', parent=None): Profiler.getInstance().push("Construct InsectLeg Rig Component:" + name) super(InsectLegComponentRig, self).__init__(name, parent) # ========= # Controls # ========= # Chain Base self.chainBase = Locator('ChainBase', parent=self.ctrlCmpGrp) self.chainBase.setShapeVisibility(False) # FK self.fkCtrlSpaces = [] self.fkCtrls = [] self.setNumControls(4) # IK Control self.legIKCtrlSpace = CtrlSpace('IK', parent=self.ctrlCmpGrp) self.legIKCtrl = Control('IK', parent=self.legIKCtrlSpace, shape="pin") if self.getLocation() == 'R': self.legIKCtrl.rotatePoints(0, 90, 0) self.legIKCtrl.translatePoints(Vec3(-1.0, 0.0, 0.0)) else: self.legIKCtrl.rotatePoints(0, -90, 0) self.legIKCtrl.translatePoints(Vec3(1.0, 0.0, 0.0)) # Add Component Params to IK control legSettingsAttrGrp = AttributeGroup("DisplayInfo_LegSettings", parent=self.legIKCtrl) legdrawDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=legSettingsAttrGrp) legUseInitPoseInputAttr = BoolAttribute('useInitPose', value=True, parent=legSettingsAttrGrp) self.rootIndexInputAttr = IntegerAttribute('rootIndex', value=0, parent=legSettingsAttrGrp) legFkikInputAttr = ScalarAttribute('fkik', value=1.0, minValue=0.0, maxValue=1.0, parent=legSettingsAttrGrp) # Connect IO to controls self.drawDebugInputAttr.connect(legdrawDebugInputAttr) # UpV self.legUpVCtrlSpace = CtrlSpace('UpV', parent=self.ctrlCmpGrp) self.legUpVCtrl = Control('UpV', parent=self.legUpVCtrlSpace, shape="triangle") self.legUpVCtrl.alignOnZAxis() self.legUpVCtrl.rotatePoints(0, 90, 0) # ========== # 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 legRootInputConstraint = PoseConstraint('_'.join([self.fkCtrlSpaces[0].getName(), 'To', self.rootInputTgt.getName()])) legRootInputConstraint.setMaintainOffset(True) legRootInputConstraint.addConstrainer(self.rootInputTgt) self.fkCtrlSpaces[0].addConstraint(legRootInputConstraint) chainBaseInputConstraint = PoseConstraint('_'.join([self.chainBase.getName(), 'To', self.rootInputTgt.getName()])) chainBaseInputConstraint.setMaintainOffset(True) chainBaseInputConstraint.addConstrainer(self.rootInputTgt) self.chainBase.addConstraint(chainBaseInputConstraint) # =============== # Add Splice Ops # =============== # Add Splice Op self.nBoneSolverSpliceOp = SpliceOperator('legSpliceOp', 'NBoneIKSolver', 'Kraken') self.addOperator(self.nBoneSolverSpliceOp) # # Add Att Inputs self.nBoneSolverSpliceOp.setInput('drawDebug', self.drawDebugInputAttr) self.nBoneSolverSpliceOp.setInput('rigScale', self.rigScaleInputAttr) self.nBoneSolverSpliceOp.setInput('useInitPose', legUseInitPoseInputAttr) self.nBoneSolverSpliceOp.setInput('ikblend', legFkikInputAttr) self.nBoneSolverSpliceOp.setInput('rootIndex', self.rootIndexInputAttr) self.nBoneSolverSpliceOp.setInput('tipBoneLen', self.tipBoneLenInputAttr) # Add Xfo Inputs self.nBoneSolverSpliceOp.setInput('chainBase', self.chainBase) self.nBoneSolverSpliceOp.setInput('ikgoal', self.legIKCtrl) self.nBoneSolverSpliceOp.setInput('upVector', self.legUpVCtrl) self.nBoneSolverSpliceOp.setInput('fkcontrols', self.fkCtrls) # Add Xfo Outputs self.nBoneSolverSpliceOp.setOutput('pose', self.boneOutputsTgt) self.nBoneSolverSpliceOp.setOutput('legEnd', self.legEndPosOutputTgt) # Add Deformer Splice Op self.outputsToDeformersSpliceOp = SpliceOperator('insectLegDeformerSpliceOp', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.outputsToDeformersSpliceOp) # Add Att Inputs self.outputsToDeformersSpliceOp.setInput('drawDebug', self.drawDebugInputAttr) self.outputsToDeformersSpliceOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs self.outputsToDeformersSpliceOp.setInput('constrainers', self.boneOutputsTgt) # Add Xfo Outputs self.outputsToDeformersSpliceOp.setOutput('constrainees', self.deformerJoints) Profiler.getInstance().pop() def setNumControls(self, numControls): # Add new control spaces and controls 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' fkCtrlSpace = CtrlSpace(boneName, parent=parent) fkCtrl = Control(boneName, parent=fkCtrlSpace, shape="cube") fkCtrl.alignOnXAxis() fkCtrl.lockScale(x=True, y=True, z=True) fkCtrl.lockTranslation(x=True, y=True, z=True) self.fkCtrlSpaces.append(fkCtrlSpace) self.fkCtrls.append(fkCtrl) def setNumDeformers(self, numDeformers): # Add new deformers and outputs 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) for i in xrange(len(self.deformerJoints), numDeformers): name = 'bone' + str(i + 1).zfill(2) boneDef = Joint(name, parent=self.defCmpGrp) boneDef.setComponent(self) self.deformerJoints.append(boneDef) return True def calculateUpVXfo(self, boneXfos, endXfo): """Calculates the transform for the UpV control. Args: boneXfos (list): Bone transforms. endXfo (Xfo): Transform for the end of the chain. Returns: Xfo: Up Vector transform. """ # Calculate FW toFirst = boneXfos[1].tr.subtract(boneXfos[0].tr).unit() toTip = endXfo.tr.subtract(boneXfos[0].tr).unit() fw = toTip.cross(toFirst).unit() chainNormal = fw.cross(toTip).unit() chainZAxis = toTip.cross(chainNormal).unit() chainXfo = Xfo() chainXfo.setFromVectors(toTip.unit(), chainNormal, chainZAxis, boneXfos[0].tr) rootToTip = endXfo.tr.subtract(boneXfos[0].tr).length() upVXfo = Xfo() upVXfo.tr = chainXfo.transformVector(Vec3(rootToTip / 2.0, rootToTip / 2.0, 0.0)) return upVXfo 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(InsectLegComponentRig, self).loadData( data ) boneXfos = data['boneXfos'] boneLengths = data['boneLengths'] numJoints = data['numJoints'] endXfo = data['endXfo'] # Add extra controls and outputs self.setNumControls(numJoints) self.setNumDeformers(numJoints) # Scale controls based on bone lengths for i, each in enumerate(self.fkCtrlSpaces): self.fkCtrlSpaces[i].xfo = boneXfos[i] self.fkCtrls[i].xfo = boneXfos[i] self.fkCtrls[i].scalePoints(Vec3(boneLengths[i], 1.75, 1.75)) self.chainBase.xfo = boneXfos[0] self.legIKCtrlSpace.xfo = endXfo self.legIKCtrl.xfo = endXfo upVXfo = self.calculateUpVXfo(boneXfos, endXfo) self.legUpVCtrlSpace.xfo = upVXfo self.legUpVCtrl.xfo = upVXfo # Set max on the rootIndex attribute self.rootIndexInputAttr.setMax(len(boneXfos)) # ============ # Set IO Xfos # ============ self.rootInputTgt.xfo = boneXfos[0] for i in xrange(len(boneLengths)): self.boneOutputsTgt[i].xfo = boneXfos[i] self.legEndXfoOutputTgt.xfo = endXfo self.legEndPosOutputTgt.xfo = endXfo # ============= # Set IO Attrs # ============= tipBoneLen = boneLengths[len(boneLengths) - 1] self.tipBoneLenInputAttr.setMax(tipBoneLen * 2.0) self.tipBoneLenInputAttr.setValue(tipBoneLen) # ==================== # Evaluate Splice Ops # ==================== # evaluate the nbone op so that all the output transforms are updated. self.nBoneSolverSpliceOp.evaluate() self.outputsToDeformersSpliceOp.evaluate()
class MultiSpringComponentGuide(MultiSpringComponent): """MultiSpring Component Guide""" def __init__(self, name='MultiSpring', parent=None): Profiler.getInstance().push("Construct FKCHain Guide Component:" + name) super(MultiSpringComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numSprings = IntegerAttribute('numSprings', value=5, minValue=1, maxValue=100, parent=guideSettingsAttrGrp) self.numSprings.setValueChangeCallback(self.updateNumJointControls) self.springCtrls = [] numSprings = self.numSprings.getValue() springXfos = self.generateGuideXfos(numSprings) for i in xrange(numSprings): newCtrl = Control('spring' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="squarePointed") newCtrl.alignOnXAxis() self.springCtrls.append(newCtrl) data = { "location": "L", "springXfos": springXfos, "numSprings": self.numSprings.getValue() } self.loadData(data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(MultiSpringComponentGuide, self).saveData() springXfos = [] for i in xrange(len(self.springCtrls)): springXfos.append(self.springCtrls[i].xfo) data['springXfos'] = springXfos return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(MultiSpringComponentGuide, self).loadData(data) for i in xrange(len(data['springXfos'])): self.springCtrls[i].xfo = data['springXfos'][i] return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig.. Return: The JSON rig data object. """ data = super(MultiSpringComponentGuide, self).getRigBuildData() numSprings = self.numSprings.getValue() boneXfos = [] for i in xrange(numSprings): boneXfos.append(self.springCtrls[i].xfo) data['boneXfos'] = boneXfos data['numSprings'] = self.numSprings.getValue() return data # ========== # Callbacks # ========== def updateNumJointControls(self, numSprings): """Load a saved guide representation from persisted data. Arguments: numSprings -- object, The number of joints inthe chain. Return: True if successful. """ if numSprings == 0: raise IndexError("'numSprings' must be > 0") if numSprings > len(self.springCtrls): for i in xrange(len(self.springCtrls), numSprings): newCtrl = Control('spring' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="squarePointed") newCtrl.alignOnXAxis() self.springCtrls.append(newCtrl) elif numSprings < len(self.springCtrls): numExtraCtrls = len(self.springCtrls) - numSprings for i in xrange(numExtraCtrls): extraCtrl = self.springCtrls.pop() extraCtrl.getParent().removeChild(extraCtrl) # Reset the control positions based on new number of joints springXfos = self.generateGuideXfos(numSprings) for i in xrange(len(self.springCtrls)): self.springCtrls[i].xfo = springXfos[i] return True def generateGuideXfos(self, numSprings): """Generates the positions for the guide controls based on the number of joints. Args: numSprings (int): Number of joints to generate a transform for. Returns: list: Guide control positions. """ guideXfos = [] j = 0 for i in xrange(numSprings): springXfo = Xfo() springXfo.tr.x = i % 5 * 2 springXfo.tr.z = j * 2 if i % 5 == 4: j += 1 guideXfos.append(springXfo) return guideXfos # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return MultiSpringComponentRig
def construct(self, jsonData): """Returns a constructed scene item based on the provided json data. Args: jsondata (dict): the JSON data to use to decode into a Math value. Returns: object: The constructed scene item. """ if '__typeHierarchy__' not in jsonData or 'name' not in jsonData: raise Exception("Invalid JSON data for constructing scene item:" + str(jsonData)) # ========= # Controls # ========= if "Control" in jsonData['__typeHierarchy__']: item = Control(jsonData['name']) # =========== # Attributes # =========== elif "AttributeGroup" in jsonData['__typeHierarchy__']: item = AttributeGroup(jsonData['name']) elif "BoolAttribute" in jsonData['__typeHierarchy__']: item = BoolAttribute(jsonData['name']) elif "ScalarAttribute" in jsonData['__typeHierarchy__']: item = ScalarAttribute(jsonData['name']) elif "IntegerAttribute" in jsonData['__typeHierarchy__']: item = IntegerAttribute(jsonData['name']) elif "StringAttribute" in jsonData['__typeHierarchy__']: item = StringAttribute(jsonData['name']) elif "ComponentInput" in jsonData['__typeHierarchy__']: item = ComponentInput(jsonData['name']) elif "ComponentOutput" in jsonData['__typeHierarchy__']: item = ComponentOutput(jsonData['name']) # ============ # Constraints # ============ elif "OrientationConstraint" in jsonData['__typeHierarchy__']: item = OrientationConstraint(jsonData['name']) elif "PoseConstraint" in jsonData['__typeHierarchy__']: item = PoseConstraint(jsonData['name']) elif "PositionConstraint" in jsonData['__typeHierarchy__']: item = PositionConstraint(jsonData['name']) elif "ScaleConstraint" in jsonData['__typeHierarchy__']: item = ScaleConstraint(jsonData['name']) elif "BaseConstraint" in jsonData['__typeHierarchy__']: item = BaseConstraint(jsonData['name']) # ========== # Operators # ========== elif "KLOperator" in jsonData['__typeHierarchy__']: item = KLOperator(jsonData['name']) # ============ # Scene Items # ============ elif "Group" in jsonData['__typeHierarchy__']: item = Group(jsonData['name']) elif "Null" in jsonData['__typeHierarchy__']: item = Null(jsonData['name']) elif "Chain" in jsonData['__typeHierarchy__']: item = Chain(jsonData['name']) elif "Joint" in jsonData['__typeHierarchy__']: item = Joint(jsonData['name']) elif "Container" in jsonData['__typeHierarchy__']: item = Container(jsonData['name']) elif "Curve" in jsonData['__typeHierarchy__']: item = Curve(jsonData['name']) elif "HierarchyGroup" in jsonData['__typeHierarchy__']: item = HierarchyGroup(jsonData['name']) elif "Joint" in jsonData['__typeHierarchy__']: item = Joint(jsonData['name']) elif "Layer" in jsonData['__typeHierarchy__']: item = Layer(jsonData['name']) elif "Locator" in jsonData['__typeHierarchy__']: item = Locator(jsonData['name']) elif "SceneItem" in jsonData['__typeHierarchy__']: item = SceneItem(jsonData['name']) else: raise Exception("KrakenLoader does not support the given type:" + jsonData['__typeHierarchy__']) # Before registering or decoding, set the parent so that the full name contains the entire path. if len(self.parentItems) > 0: item.setParent(self.parentItems[-1]) self.registerItem(item) # Store the item as the parent item before decoding the object # which in turn decodes the children items. self.parentItems.append(item) item.jsonDecode(self, jsonData) # Pop the parent item stack, which reverts the current parent item # to the previous value. self.parentItems.pop() return item
def __init__(self, name='mjEyelid', parent=None): Profiler.getInstance().push("Construct Eyelid Rig Component:" + name) super(mjEyelidComponentRig, self).__init__(name, parent) # ========= # Controls // Get the Guide Xfos data and create the final controllers, offset them if needed. # ========= # Inputs self.eyelidCtrlSpace = CtrlSpace('eyelid', parent=self.ctrlCmpGrp) self.eyeballLocator = Locator('eyeball', parent=self.ctrlCmpGrp) self.eyeballLocator.setShapeVisibility(False) self.eyelidUpVLocator = Locator('eyelid_Upv', parent=self.eyelidCtrlSpace) self.eyelidUpVLocator.setShapeVisibility(False) # Lid Sides self.lidMedialLocator = Locator('lid_Medial', parent=self.eyelidCtrlSpace) self.lidMedialLocator.setShapeVisibility(False) self.lidLateralLocator = Locator('lid_Lateral', parent=self.eyelidCtrlSpace) self.lidLateralLocator.setShapeVisibility(False) # Lid Upper self.lidUpCtrlSpace = CtrlSpace('lid_Up', parent=self.eyelidCtrlSpace) self.lidUpCtrl = Control('lid_Up', parent=self.lidUpCtrlSpace, shape="cube") self.lidUpCtrl.scalePoints(Vec3(0.05, 0.05, 0.05)) self.lidUpCtrl.lockTranslation(x=True, y=False, z=True) self.lidUpCtrl.setColor("yellow") self.lipUpMedialLocator = Locator('lid_Up_Medial', parent=self.eyelidCtrlSpace) self.lipUpMedialLocator.setShapeVisibility(False) self.lipUpLateralLocator = Locator('lid_Up_Lateral', parent=self.eyelidCtrlSpace) self.lipUpLateralLocator.setShapeVisibility(False) # Lid Lower self.lidLowCtrlSpace = CtrlSpace('lid_Low', parent=self.eyelidCtrlSpace) self.lidLowCtrl = Control('lid_Low', parent=self.lidLowCtrlSpace, shape="cube") self.lidLowCtrl.scalePoints(Vec3(0.05, 0.05, 0.05)) self.lidLowCtrl.lockTranslation(x=True, y=False, z=True) self.lidLowCtrl.setColor("yellow") self.lidLowMedialLocator = Locator('lid_Low_Medial', parent=self.eyelidCtrlSpace) self.lidLowMedialLocator.setShapeVisibility(False) self.lidLowLateralLocator = Locator('lid_Low_Lateral', parent=self.eyelidCtrlSpace) self.lidLowLateralLocator.setShapeVisibility(False) # Lid Attributes lidUp_AttrGrp = AttributeGroup("Eyelid_Settings", parent=self.lidUpCtrl) lidLow_AttrGrp = AttributeGroup("Eyelid_Settings", parent=self.lidLowCtrl) self.lidUp_OffsetInputAttr = BoolAttribute('Eyeball_Offset', value=True, parent=lidUp_AttrGrp) self.lidUp_FollowFactorInputAttr = ScalarAttribute( 'Eyeball_Follow_Factor', value=1.0, parent=lidUp_AttrGrp) self.lidUp_DebugInputAttr = BoolAttribute('DrawDebug', value=False, parent=lidUp_AttrGrp) self.lidUp_MedialBlinkInputAttr = ScalarAttribute( 'Medial_Blink_Factor', value=0.25, parent=lidUp_AttrGrp) self.lidUp_LateralBlinkInputAttr = ScalarAttribute( 'Lateral_Blink_Factor', value=0.65, parent=lidUp_AttrGrp) self.lidUp_DefCountInputAttr = IntegerAttribute('numDeformers', value=10, parent=lidUp_AttrGrp) self.lidLow_OffsetInputAttr = BoolAttribute('Eyeball_Offset', value=True, parent=lidLow_AttrGrp) self.lidLow_FollowFactorInputAttr = ScalarAttribute( 'Eyeball_Follow_Factor', value=0.8, parent=lidLow_AttrGrp) self.lidLow_DebugInputAttr = BoolAttribute('DrawDebug', value=False, parent=lidLow_AttrGrp) self.lidLow_MedialBlinkInputAttr = ScalarAttribute( 'Medial_Blink_Factor', value=0.25, parent=lidLow_AttrGrp) self.lidLow_LateralBlinkInputAttr = ScalarAttribute( 'Lateral_Blink_Factor', value=0.65, parent=lidLow_AttrGrp) self.lidLow_DefCountInputAttr = IntegerAttribute('numDeformers', value=10, parent=lidLow_AttrGrp) self.lidUp_DebugInputAttr.connect(self.drawDebugInputAttr) self.lidLow_DebugInputAttr.connect(self.drawDebugInputAttr) self.lidUp_DefCountInputAttr.connect(self.numUpDeformersInputAttr) self.lidLow_DefCountInputAttr.connect(self.numLowDeformersInputAttr) # ========== # Deformers # ========== deformersLayer = self.getOrCreateLayer('deformers') self.defCmpGrp = ComponentGroup(self.getName(), self, parent=deformersLayer) # Lid Sides lidMedialDef = Joint('lid_Medial', parent=self.defCmpGrp) lidMedialDef.setComponent(self) lidLateralDef = Joint('lid_Lateral', parent=self.defCmpGrp) lidLateralDef.setComponent(self) # Lid Up self.eyelidUpDef = [] self.eyelidUpOutputs = [] self.setNumUpDeformers(1) # Lid Low self.eyelidLowDef = [] self.eyelidLowOutputs = [] self.setNumLowDeformers(1) # ===================== # Create Component I/O # ===================== # Setup component Xfo I/O's self.eyelidUpOutput.setTarget(self.eyelidUpOutputs) self.eyelidLowOutput.setTarget(self.eyelidLowOutputs) # ============== # Constrain I/O # ============== # Constraint inputs self.headInputConstraint = PoseConstraint('_'.join([ self.eyelidCtrlSpace.getName(), 'To', self.headInputTgt.getName() ])) self.headInputConstraint.addConstrainer(self.headInputTgt) self.eyelidCtrlSpace.addConstraint(self.headInputConstraint) self.eyeballInputConstraint = PoseConstraint('_'.join([ self.eyeballLocator.getName(), 'To', self.eyeballInputTgt.getName() ])) self.eyeballInputConstraint.setMaintainOffset(True) self.eyeballInputConstraint.addConstrainer(self.eyeballInputTgt) self.eyeballLocator.addConstraint(self.eyeballInputConstraint) # =============== # Add Splice Ops # =============== # Add MultiPoseConstraint Joints Splice Op self.outputsToDeformersKLOp = KLOperator('Canvas_Eyelid_Side_Op', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.outputsToDeformersKLOp) # Add Att Inputs self.outputsToDeformersKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.outputsToDeformersKLOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs self.outputsToDeformersKLOp.setInput('constrainers', [ self.lidMedialLocator, self.lidLateralLocator, ]) # Add Xfo Outputs self.outputsToDeformersKLOp.setOutput('constrainees', [ lidMedialDef, lidLateralDef, ]) # Add Lid Up Canvas Op self.lidUpCanvasOp = CanvasOperator( 'Canvas_Eyelid_Up_Op', 'MJCG.Solvers.mjEyelidConstraintSolver') self.addOperator(self.lidUpCanvasOp) # Add Attributes Inputs self.lidUpCanvasOp.setInput('drawDebug', self.lidUp_DebugInputAttr) self.lidUpCanvasOp.setInput('rigScale', self.rigScaleInputAttr) self.lidUpCanvasOp.setInput('Eyeball_Offset', self.lidUp_OffsetInputAttr) self.lidUpCanvasOp.setInput('Eyeball_Follow_Factor', self.lidUp_FollowFactorInputAttr) self.lidUpCanvasOp.setInput('Medial_Blink_Factor', self.lidUp_MedialBlinkInputAttr) self.lidUpCanvasOp.setInput('Lateral_Blink_Factor', self.lidUp_LateralBlinkInputAttr) self.lidUpCanvasOp.setInput('Deformer_Count', self.lidUp_DefCountInputAttr) # Add Xfo Inputs self.lidUpCanvasOp.setInput('Eye_Center', self.eyeballLocator) self.lidUpCanvasOp.setInput('Lid_Global', self.eyelidCtrlSpace) self.lidUpCanvasOp.setInput('Lid_UpV', self.eyelidUpVLocator) self.lidUpCanvasOp.setInput('Lid_Medial', self.lidMedialLocator) self.lidUpCanvasOp.setInput('Lid_MedialCen', self.lipUpMedialLocator) self.lidUpCanvasOp.setInput('Lid_Center_Ref', self.lidUpCtrlSpace) self.lidUpCanvasOp.setInput('Lid_Center_Ctrl', self.lidUpCtrl) self.lidUpCanvasOp.setInput('Lid_LateralCen', self.lipUpLateralLocator) self.lidUpCanvasOp.setInput('Lid_Lateral', self.lidLateralLocator) #Add Xfo Outputs self.lidUpCanvasOp.setOutput('result', self.eyelidUpDef) # Add Lid Low Canvas Op self.lidLowCanvasOp = CanvasOperator( 'Canvas_Eyelid_Low_Op', 'MJCG.Solvers.mjEyelidConstraintSolver') self.addOperator(self.lidLowCanvasOp) # Add Attributes Inputs self.lidLowCanvasOp.setInput('drawDebug', self.lidLow_DebugInputAttr) self.lidLowCanvasOp.setInput('rigScale', self.rigScaleInputAttr) self.lidLowCanvasOp.setInput('Eyeball_Offset', self.lidLow_OffsetInputAttr) self.lidLowCanvasOp.setInput('Eyeball_Follow_Factor', self.lidLow_FollowFactorInputAttr) self.lidLowCanvasOp.setInput('Medial_Blink_Factor', self.lidLow_MedialBlinkInputAttr) self.lidLowCanvasOp.setInput('Lateral_Blink_Factor', self.lidLow_LateralBlinkInputAttr) self.lidLowCanvasOp.setInput('Deformer_Count', self.lidLow_DefCountInputAttr) # Add Xfo Inputs self.lidLowCanvasOp.setInput('Eye_Center', self.eyeballLocator) self.lidLowCanvasOp.setInput('Lid_Global', self.eyelidCtrlSpace) self.lidLowCanvasOp.setInput('Lid_UpV', self.eyelidUpVLocator) self.lidLowCanvasOp.setInput('Lid_Medial', self.lidMedialLocator) self.lidLowCanvasOp.setInput('Lid_MedialCen', self.lidLowMedialLocator) self.lidLowCanvasOp.setInput('Lid_Center_Ref', self.lidLowCtrlSpace) self.lidLowCanvasOp.setInput('Lid_Center_Ctrl', self.lidLowCtrl) self.lidLowCanvasOp.setInput('Lid_LateralCen', self.lidLowLateralLocator) self.lidLowCanvasOp.setInput('Lid_Lateral', self.lidLateralLocator) #Add Xfo Outputs self.lidLowCanvasOp.setOutput('result', self.eyelidLowDef) Profiler.getInstance().pop()
def __init__(self, name='tail', parent=None): Profiler.getInstance().push("Construct Fabrice Tail Guide Component:" + name) super(FabriceTailGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.numDeformersAttr.setValueChangeCallback(self.updateNumDeformers) # Guide Controls self.tailBaseCtrl = Control('tailBase', parent=self.ctrlCmpGrp, shape='sphere') self.tailBaseCtrl.scalePoints(Vec3(1.2, 1.2, 1.2)) self.tailBaseCtrl.lockScale(x=True, y=True, z=True) self.tailBaseCtrl.setColor("turqoise") self.tailBaseHandleCtrl = Control('tailBaseHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailBaseHandleCtrl.rotatePoints(90, 0, 0) self.tailBaseHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailBaseHandleCtrl.lockScale(x=True, y=True, z=True) self.tailBaseHandleCtrl.setColor("turqoise") self.tailEndHandleCtrl = Control('tailEndHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailEndHandleCtrl.rotatePoints(90, 0, 0) self.tailEndHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndHandleCtrl.lockScale(x=True, y=True, z=True) self.tailEndHandleCtrl.setColor("turqoise") self.tailEndCtrl = Control('tailEnd', parent=self.ctrlCmpGrp, shape='pin') self.tailEndCtrl.rotatePoints(90, 0, 0) self.tailEndCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndCtrl.lockScale(x=True, y=True, z=True) self.tailEndCtrl.setColor("turqoise") # =============== # Add Splice Ops # =============== # Add Tail Splice Op self.bezierSpineSpliceOp = SpliceOperator('spineGuideSpliceOp', 'BezierSpineSolver', 'Kraken', alwaysEval=True) self.bezierSpineSpliceOp.setOutput('outputs', self.tailVertebraeOutput.getTarget()) self.addOperator(self.bezierSpineSpliceOp) # Add Att Inputs self.bezierSpineSpliceOp.setInput('drawDebug', self.drawDebugInputAttr) self.bezierSpineSpliceOp.setInput('rigScale', self.rigScaleInputAttr) self.bezierSpineSpliceOp.setInput('length', self.lengthInputAttr) # Add Xfo Inputs self.bezierSpineSpliceOp.setInput('base', self.tailBaseCtrl) self.bezierSpineSpliceOp.setInput('baseHandle', self.tailBaseHandleCtrl) self.bezierSpineSpliceOp.setInput('tipHandle', self.tailEndHandleCtrl) self.bezierSpineSpliceOp.setInput('tip', self.tailEndCtrl) self.loadData({ 'name': name, 'location': 'M', 'tailBasePos': Vec3(0.0, 0.65, -3.1), 'tailBaseHandlePos': Vec3(0.0, 0.157, -4.7), 'tailBaseHandleCtrlCrvData': self.tailBaseHandleCtrl.getCurveData(), 'tailEndHandlePos': Vec3(0.0, 0.0625, -6.165), 'tailEndHandleCtrlCrvData': self.tailEndHandleCtrl.getCurveData(), 'tailEndPos': Vec3(0.0, -0.22, -7.42), 'tailEndCtrlCrvData': self.tailEndCtrl.getCurveData(), 'numDeformers': 6 }) Profiler.getInstance().pop()
def __init__(self, name='spine', parent=None): Profiler.getInstance().push( "Construct Fabrice Spine Guide Component:" + name) super(FabriceSpineGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.numDeformersAttr.setValueChangeCallback(self.updateNumDeformers) # Guide Controls self.cogCtrl = Control('cog', parent=self.ctrlCmpGrp, shape="circle") self.cogCtrl.rotatePoints(90, 0, 0) self.cogCtrl.scalePoints(Vec3(3.0, 3.0, 3.0)) self.cogCtrl.setColor('red') self.spineBaseCtrl = Control('spineBase', parent=self.ctrlCmpGrp, shape='pin') self.spineBaseCtrl.rotatePoints(90, 0, 0) self.spineBaseCtrl.translatePoints(Vec3(0, 1.0, 0)) self.spineBaseHandleCtrl = Control('spineBaseHandle', parent=self.ctrlCmpGrp, shape='pin') self.spineBaseHandleCtrl.rotatePoints(90, 0, 0) self.spineBaseHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.spineEndHandleCtrl = Control('spineEndHandle', parent=self.ctrlCmpGrp, shape='pin') self.spineEndHandleCtrl.rotatePoints(90, 0, 0) self.spineEndHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.spineEndCtrl = Control('spineEnd', parent=self.ctrlCmpGrp, shape='pin') self.spineEndCtrl.rotatePoints(90, 0, 0) self.spineEndCtrl.translatePoints(Vec3(0, 1.0, 0)) # =============== # Add Canvas Ops # =============== # Add Spine Canvas Op self.bezierSpineKLOp = KLOperator('guide', 'BezierSpineSolver', 'Kraken') self.addOperator(self.bezierSpineKLOp) # Add Att Inputs self.bezierSpineKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.bezierSpineKLOp.setInput('rigScale', self.rigScaleInputAttr) self.bezierSpineKLOp.setInput('length', self.lengthInputAttr) # Add Xfo Inputs self.bezierSpineKLOp.setInput('base', self.spineBaseCtrl) self.bezierSpineKLOp.setInput('baseHandle', self.spineBaseHandleCtrl) self.bezierSpineKLOp.setInput('tipHandle', self.spineEndHandleCtrl) self.bezierSpineKLOp.setInput('tip', self.spineEndCtrl) # Add Xfo Outputs self.bezierSpineKLOp.setOutput('outputs', self.spineVertebraeOutput.getTarget()) data = { 'name': name, 'location': 'M', 'cogPos': Vec3(0.0, 1.65, 0.75), 'cogCtrlCrvData': self.cogCtrl.getCurveData(), 'spineBasePos': Vec3(0.0, 1.65, 0.75), 'spineBaseCtrlCrvData': self.spineBaseCtrl.getCurveData(), 'spineBaseHandlePos': Vec3(0.0, 1.6, -0.7), 'spineBaseHandleCtrlCrvData': self.spineBaseHandleCtrl.getCurveData(), 'spineEndHandlePos': Vec3(0.0, 1.15, -2.0), 'spineEndHandleCtrlCrvData': self.spineEndHandleCtrl.getCurveData(), 'spineEndPos': Vec3(0.0, 0.65, -3.1), 'spineEndCtrlCrvData': self.spineEndCtrl.getCurveData(), 'numDeformers': 6 } self.loadData(data) Profiler.getInstance().pop()
class FabriceTailGuide(FabriceTail): """Fabrice Tail Component Guide""" def __init__(self, name='tail', parent=None): Profiler.getInstance().push("Construct Fabrice Tail Guide Component:" + name) super(FabriceTailGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.numDeformersAttr.setValueChangeCallback(self.updateNumDeformers) # Guide Controls self.tailBaseCtrl = Control('tailBase', parent=self.ctrlCmpGrp, shape='sphere') self.tailBaseCtrl.scalePoints(Vec3(1.2, 1.2, 1.2)) self.tailBaseCtrl.lockScale(x=True, y=True, z=True) self.tailBaseCtrl.setColor("turqoise") self.tailBaseHandleCtrl = Control('tailBaseHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailBaseHandleCtrl.rotatePoints(90, 0, 0) self.tailBaseHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailBaseHandleCtrl.lockScale(x=True, y=True, z=True) self.tailBaseHandleCtrl.setColor("turqoise") self.tailEndHandleCtrl = Control('tailEndHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailEndHandleCtrl.rotatePoints(90, 0, 0) self.tailEndHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndHandleCtrl.lockScale(x=True, y=True, z=True) self.tailEndHandleCtrl.setColor("turqoise") self.tailEndCtrl = Control('tailEnd', parent=self.ctrlCmpGrp, shape='pin') self.tailEndCtrl.rotatePoints(90, 0, 0) self.tailEndCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndCtrl.lockScale(x=True, y=True, z=True) self.tailEndCtrl.setColor("turqoise") # =============== # Add Splice Ops # =============== # Add Tail Splice Op self.bezierSpineKLOp = KLOperator('spineGuideKLOp', 'BezierSpineSolver', 'Kraken') self.bezierSpineKLOp.setOutput('outputs', self.tailVertebraeOutput.getTarget()) self.addOperator(self.bezierSpineKLOp) # Add Att Inputs self.bezierSpineKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.bezierSpineKLOp.setInput('rigScale', self.rigScaleInputAttr) self.bezierSpineKLOp.setInput('length', self.lengthInputAttr) # Add Xfo Inputs self.bezierSpineKLOp.setInput('base', self.tailBaseCtrl) self.bezierSpineKLOp.setInput('baseHandle', self.tailBaseHandleCtrl) self.bezierSpineKLOp.setInput('tipHandle', self.tailEndHandleCtrl) self.bezierSpineKLOp.setInput('tip', self.tailEndCtrl) self.loadData({ 'name': name, 'location': 'M', 'tailBasePos': Vec3(0.0, 0.65, -3.1), 'tailBaseHandlePos': Vec3(0.0, 0.157, -4.7), 'tailBaseHandleCtrlCrvData': self.tailBaseHandleCtrl.getCurveData(), 'tailEndHandlePos': Vec3(0.0, 0.0625, -6.165), 'tailEndHandleCtrlCrvData': self.tailEndHandleCtrl.getCurveData(), 'tailEndPos': Vec3(0.0, -0.22, -7.42), 'tailEndCtrlCrvData': self.tailEndCtrl.getCurveData(), 'numDeformers': 6 }) Profiler.getInstance().pop() # ========== # Callbacks # ========== def updateNumDeformers(self, count): """Generate the guide controls for the variable outputes array. Arguments: count -- object, The number of joints inthe chain. Return: True if successful. """ if count == 0: raise IndexError("'count' must be > 0") vertebraeOutputs = self.tailVertebraeOutput.getTarget() if count > len(vertebraeOutputs): for i in xrange(len(vertebraeOutputs), count): debugCtrl = Control('spine' + str(i+1).zfill(2), parent=self.outputHrcGrp, shape="vertebra") debugCtrl.rotatePoints(0, -90, 0) debugCtrl.scalePoints(Vec3(0.5, 0.5, 0.5)) debugCtrl.setColor('turqoise') vertebraeOutputs.append(debugCtrl) elif count < len(vertebraeOutputs): numExtraCtrls = len(vertebraeOutputs) - count for i in xrange(numExtraCtrls): extraCtrl = vertebraeOutputs.pop() self.outputHrcGrp.removeChild(extraCtrl) return True # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(FabriceTailGuide, self).saveData() data['tailBasePos'] = self.tailBaseCtrl.xfo.tr data['tailBaseHandlePos'] = self.tailBaseHandleCtrl.xfo.tr data['tailBaseHandleCtrlCrvData'] = self.tailBaseHandleCtrl.getCurveData() data['tailEndHandlePos'] = self.tailEndHandleCtrl.xfo.tr data['tailEndHandleCtrlCrvData'] = self.tailEndHandleCtrl.getCurveData() data['tailEndPos'] = self.tailEndCtrl.xfo.tr data['tailEndCtrlCrvData'] = self.tailEndCtrl.getCurveData() data['numDeformers'] = self.numDeformersAttr.getValue() return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(FabriceTailGuide, self).loadData( data ) self.tailBaseCtrl.xfo.tr = data["tailBasePos"] self.tailBaseHandleCtrl.xfo.tr = data["tailBaseHandlePos"] self.tailBaseHandleCtrl.setCurveData(data['tailBaseHandleCtrlCrvData']) self.tailEndHandleCtrl.xfo.tr = data["tailEndHandlePos"] self.tailEndHandleCtrl.setCurveData(data['tailEndHandleCtrlCrvData']) self.tailEndCtrl.xfo.tr = data["tailEndPos"] self.tailEndCtrl.setCurveData(data['tailEndCtrlCrvData']) self.numDeformersAttr.setValue(data["numDeformers"]) length = data["tailBasePos"].distanceTo(data["tailBaseHandlePos"]) + data["tailBaseHandlePos"].distanceTo(data["tailEndHandlePos"]) + data["tailEndHandlePos"].distanceTo(data["tailEndPos"]) self.lengthInputAttr.setMax(length * 3.0) self.lengthInputAttr.setValue(length) self.bezierSpineKLOp.evaluate() return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig. Return: The JSON rig data object. """ data = super(FabriceTailGuide, self).getRigBuildData() data['tailBasePos'] = self.tailBaseCtrl.xfo.tr data['tailBaseHandlePos'] = self.tailBaseHandleCtrl.xfo.tr data['tailBaseHandleCtrlCrvData'] = self.tailBaseHandleCtrl.getCurveData() data['tailEndHandlePos'] = self.tailEndHandleCtrl.xfo.tr data['tailEndHandleCtrlCrvData'] = self.tailEndHandleCtrl.getCurveData() data['tailEndPos'] = self.tailEndCtrl.xfo.tr data['tailEndCtrlCrvData'] = self.tailEndCtrl.getCurveData() data['numDeformers'] = self.numDeformersAttr.getValue() return data # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return FabriceTailRig
class TwistComponentGuide(TwistComponent): """Twist Component Guide""" def __init__(self, name='twist', parent=None): Profiler.getInstance().push('Construct Spine Guide Component:' + name) super(TwistComponentGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup('GuideSettings', parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.blendBiasAttr = ScalarAttribute('blendBias', value=0.0, minValue=0, maxValue=1.0, parent=guideSettingsAttrGrp) # Guide Controls triangleCtrl = Control('triangle', shape='triangle') triangleCtrl.rotatePoints(90, 0, 0) triangleCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) triangleCtrl.scalePoints(Vec3(1.0, 0.5, 1.0)) triangleCtrl.translatePoints(Vec3(0.0, 1.25, 0.0)) triangleCtrl.rotatePoints(0, 90, 0) self.originCtrl = Control('origin', parent=self.ctrlCmpGrp, shape='circle') self.originCtrl.rotatePoints(90, 0, 0) self.originCtrl.rotatePoints(0, 90, 0) self.originCtrl.appendCurveData(triangleCtrl.getCurveData()) self.insertCtrl = Control('insert', parent=self.ctrlCmpGrp, shape='circle') self.insertCtrl.rotatePoints(90, 0, 0) self.insertCtrl.rotatePoints(0, 90, 0) self.insertCtrl.appendCurveData(triangleCtrl.getCurveData()) self.default_data = { 'name': name, 'location': 'M', 'blendBias': 0.5, 'originXfo': Xfo(Vec3(0.0, 0.0, 0.0)), 'insertXfo': Xfo(Vec3(5.0, 0.0, 0.0)), 'numDeformers': 5 } self.loadData(self.default_data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(TwistComponentGuide, self).saveData() data['blendBias'] = self.blendBiasAttr.getValue() data['originXfo'] = self.originCtrl.xfo data['insertXfo'] = self.insertCtrl.xfo data['numDeformers'] = self.numDeformersAttr.getValue() return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(TwistComponentGuide, self).loadData(data) self.blendBiasAttr.setValue(data.get('blendBias', 0.0)) self.originCtrl.xfo = data.get('originXfo', Xfo()) self.insertCtrl.xfo = data.get('insertXfo', Xfo()) self.numDeformersAttr.setValue(data.get('numDeformers', 5)) return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig. Return: The JSON rig data object. """ data = super(TwistComponentGuide, self).getRigBuildData() data['blendBias'] = self.blendBiasAttr.getValue() data['originXfo'] = self.originCtrl.xfo data['insertXfo'] = self.insertCtrl.xfo originUpVXfo = Xfo(Vec3(0.0, 1.0, 0.0)) insertUpVXfo = Xfo(Vec3(0.0, 1.0, 0.0)) data['originUpVXfo'] = self.originCtrl.xfo * originUpVXfo data['insertUpVXfo'] = self.insertCtrl.xfo * insertUpVXfo data['numDeformers'] = self.numDeformersAttr.getValue() return data # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return TwistComponentRig
class SpineComponentGuide(SpineComponent): """Spine Component Guide""" def __init__(self, name='spine', parent=None, *args, **kwargs): Profiler.getInstance().push("Construct Spine Guide Component:" + name) super(SpineComponentGuide, self).__init__(name, parent, *args, **kwargs) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) # Guide Controls self.cog = Control('cogPosition', parent=self.ctrlCmpGrp, shape="sphere") self.cog.scalePoints(Vec3(1.2, 1.2, 1.2)) self.cog.setColor('red') self.spine01Ctrl = Control('spine01Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine02Ctrl = Control('spine02Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine03Ctrl = Control('spine03Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine04Ctrl = Control('spine04Position', parent=self.ctrlCmpGrp, shape='sphere') data = { 'name': name, 'location': 'M', 'cogPosition': Vec3(0.0, 11.1351, -0.1382), 'spine01Position': Vec3(0.0, 11.1351, -0.1382), 'spine02Position': Vec3(0.0, 11.8013, -0.1995), 'spine03Position': Vec3(0.0, 12.4496, -0.3649), 'spine04Position': Vec3(0.0, 13.1051, -0.4821), 'numDeformers': 6 } self.loadData(data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(SpineComponentGuide, self).saveData() data['cogPosition'] = self.cog.xfo.tr data['spine01Position'] = self.spine01Ctrl.xfo.tr data['spine02Position'] = self.spine02Ctrl.xfo.tr data['spine03Position'] = self.spine03Ctrl.xfo.tr data['spine04Position'] = self.spine04Ctrl.xfo.tr data['numDeformers'] = self.numDeformersAttr.getValue() return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(SpineComponentGuide, self).loadData( data ) self.cog.xfo.tr = data["cogPosition"] self.spine01Ctrl.xfo.tr = data["spine01Position"] self.spine02Ctrl.xfo.tr = data["spine02Position"] self.spine03Ctrl.xfo.tr = data["spine03Position"] self.spine04Ctrl.xfo.tr = data["spine04Position"] self.numDeformersAttr.setValue(data["numDeformers"]) return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig. Return: The JSON rig data object. """ data = super(SpineComponentGuide, self).getRigBuildData() data['cogPosition'] = self.cog.xfo.tr data['spine01Position'] = self.spine01Ctrl.xfo.tr data['spine02Position'] = self.spine02Ctrl.xfo.tr data['spine03Position'] = self.spine03Ctrl.xfo.tr data['spine04Position'] = self.spine04Ctrl.xfo.tr data['numDeformers'] = self.numDeformersAttr.getValue() return data # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return SpineComponentRig
class InsectLegComponentGuide(InsectLegComponent): """InsectLeg Component Guide""" def __init__(self, name='InsectLeg', parent=None): Profiler.getInstance().push("Construct InsectLeg Guide Component:" + name) super(InsectLegComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numJoints = IntegerAttribute('numJoints', value=5, minValue=2, maxValue=20, parent=guideSettingsAttrGrp) self.numJoints.setValueChangeCallback(self.updateNumLegControls) self.jointCtrls = [] numJoints = self.numJoints.getValue() jointPositions = self.generateGuidePositions(numJoints) for i in xrange(numJoints): self.jointCtrls.append( Control('leg' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="sphere")) jointXfos = [] for i in xrange(numJoints): jointXfos.append(Xfo(jointPositions[i])) data = { "location": "L", "jointPositions": jointXfos, "numJoints": self.numJoints.getValue() } self.loadData(data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(InsectLegComponentGuide, self).saveData() jointPositions = [] for i in xrange(len(self.jointCtrls)): jointPositions.append(self.jointCtrls[i].xfo) data['jointPositions'] = jointPositions return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(InsectLegComponentGuide, self).loadData(data) for i in xrange(len(data['jointPositions'])): self.jointCtrls[i].xfo = data['jointPositions'][i] return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig.. Return: The JSON rig data object. """ data = super(InsectLegComponentGuide, self).getRigBuildData() numJoints = self.numJoints.getValue() # Calculate FW toFirst = self.jointCtrls[0].xfo.tr.subtract( self.jointCtrls[1].xfo.tr).unit() toTip = self.jointCtrls[0].xfo.tr.subtract( self.jointCtrls[-1].xfo.tr).unit() fw = toTip.cross(toFirst).unit() # Calculate Xfos boneXfos = [] boneLengths = [] for i in xrange(numJoints): boneVec = self.jointCtrls[i + 1].xfo.tr.subtract( self.jointCtrls[i].xfo.tr) boneLengths.append(boneVec.length()) bone1Normal = fw.cross(boneVec).unit() bone1ZAxis = boneVec.cross(bone1Normal).unit() xfo = Xfo() xfo.setFromVectors(boneVec.unit(), bone1Normal, bone1ZAxis, self.jointCtrls[i].xfo.tr) boneXfos.append(xfo) data['boneXfos'] = boneXfos data['endXfo'] = self.jointCtrls[-1].xfo data['boneLengths'] = boneLengths return data # ========== # Callbacks # ========== def updateNumLegControls(self, numJoints): """Generate the guide controls for the variable outputes array. Arguments: numJoints -- object, The number of joints in the chain. Return: True if successful. """ if numJoints == 0: raise IndexError("'numJoints' must be > 0") if numJoints + 1 > len(self.jointCtrls): for i in xrange(len(self.jointCtrls), numJoints + 1): newCtrl = Control('leg' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="sphere") self.jointCtrls.append(newCtrl) elif numJoints + 1 < len(self.jointCtrls): numExtraCtrls = len(self.jointCtrls) - (numJoints + 1) for i in xrange(numExtraCtrls): extraCtrl = self.jointCtrls.pop() self.ctrlCmpGrp.removeChild(extraCtrl) # Reset the control positions based on new number of joints jointPositions = self.generateGuidePositions(numJoints) for i in xrange(len(self.jointCtrls)): self.jointCtrls[i].xfo.tr = jointPositions[i] return True def generateGuidePositions(self, numJoints): """Generates the positions for the guide controls based on the number of joints. Args: numJoints (int): Number of joints to generate a transform for. Returns: list: Guide control positions. """ halfPi = math.pi / 2.0 step = halfPi / numJoints xValues = [] yValues = [] for i in xrange(numJoints + 1): xValues.append(math.cos((i * step) + halfPi) * -10) yValues.append(math.sin((i * step) + halfPi) * 10) guidePositions = [] for i in xrange(numJoints + 1): guidePositions.append(Vec3(xValues[i], yValues[i], 0.0)) return guidePositions # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return InsectLegComponentRig
def __init__(self, name='mjEyelid', parent=None): Profiler.getInstance().push("Construct Eyelid Guide Component:" + name) super(mjEyelidComponentGuide, self).__init__(name, parent) # ========= # Attributes // Create Attributes Controls. # ========= guideUpSettingsAttrGrp = AttributeGroup("Eyelid Up", parent=self) guideLowSettingsAttrGrp = AttributeGroup("Eyelid Low", parent=self) self.numUpDeformersAttr = IntegerAttribute( 'Num Deformers', value=10, minValue=1, maxValue=50, parent=guideUpSettingsAttrGrp) self.upMedialFactorAttr = ScalarAttribute( 'Medial Blink Factor', value=0.25, minValue=0, maxValue=1, parent=guideUpSettingsAttrGrp) self.upLateralFactorAttr = ScalarAttribute( 'Lateral Blink Factor', value=0.65, minValue=0, maxValue=1, parent=guideUpSettingsAttrGrp) self.numLowDeformersAttr = IntegerAttribute( 'Num Deformers', value=10, minValue=1, maxValue=50, parent=guideLowSettingsAttrGrp) self.lowMedialFactorAttr = ScalarAttribute( 'Medial Blink Factor', value=0.25, minValue=0, maxValue=1, parent=guideLowSettingsAttrGrp) self.lowLateralFactorAttr = ScalarAttribute( 'Lateral Blink Factor', value=0.65, minValue=0, maxValue=1, parent=guideLowSettingsAttrGrp) self.numUpDeformersAttr.setValueChangeCallback( self.updateNumUpDeformers) self.numLowDeformersAttr.setValueChangeCallback( self.updateNumLowDeformers) # ========= # Controls // Create the Guide Controls, Name them, give them a shape, a color and scale it. # ========= self.eyeballCtrl = Control('eyeball', parent=self.ctrlCmpGrp, shape="sphere") self.eyeballCtrl.scalePoints(Vec3(0.35, 0.35, 0.35)) self.eyeballCtrl.setColor("red") self.lidMedialCtrl = Control('lidMedial', parent=self.eyeballCtrl, shape="sphere") self.lidMedialCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidMedialCtrl.setColor("peach") self.lidLateralCtrl = Control('lidLateral', parent=self.eyeballCtrl, shape="sphere") self.lidLateralCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLateralCtrl.setColor("peach") self.lidUpCtrl = Control('lidUp', parent=self.eyeballCtrl, shape="sphere") self.lidUpCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidUpCtrl.setColor("peach") self.lidUpMedialCtrl = Control('lidUpMedial', parent=self.eyeballCtrl, shape="sphere") self.lidUpMedialCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidUpMedialCtrl.setColor("peach") self.lidUpLateralCtrl = Control('lidUpLateral', parent=self.eyeballCtrl, shape="sphere") self.lidUpLateralCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidUpLateralCtrl.setColor("peach") self.lidLowCtrl = Control('lidLow', parent=self.eyeballCtrl, shape="sphere") self.lidLowCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLowCtrl.setColor("peach") self.lidLowMedialCtrl = Control('lidLowMedial', parent=self.eyeballCtrl, shape="sphere") self.lidLowMedialCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLowMedialCtrl.setColor("peach") self.lidLowLateralCtrl = Control('lidLowLateral', parent=self.eyeballCtrl, shape="sphere") self.lidLowLateralCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLowLateralCtrl.setColor("peach") # =============== # Add Debug Splice Ops # =============== # Add Lid Up Canvas Op self.debugLidUpCanvasOp = CanvasOperator( 'Debug_Canvas_Eyelid_Up_Op', 'MJCG.Solvers.mjEyelidDebugSolver') self.addOperator(self.debugLidUpCanvasOp) # Add Attributes Inputs self.debugLidUpCanvasOp.setInput('drawDebug', self.drawDebugInputAttr) self.debugLidUpCanvasOp.setInput('rigScale', self.rigScaleInputAttr) self.debugLidUpCanvasOp.setInput('Deformer_Count', self.numUpDeformersInputAttr) # Add Xfo Inputs self.debugLidUpCanvasOp.setInput('Eye_Center', self.eyeballCtrl) self.debugLidUpCanvasOp.setInput('Lid_Medial', self.lidMedialCtrl) self.debugLidUpCanvasOp.setInput('Lid_MedialCen', self.lidUpMedialCtrl) self.debugLidUpCanvasOp.setInput('Lid_Center_Ref', self.lidUpCtrl) self.debugLidUpCanvasOp.setInput('Lid_Center_Ctrl', self.lidUpCtrl) self.debugLidUpCanvasOp.setInput('Lid_LateralCen', self.lidUpLateralCtrl) self.debugLidUpCanvasOp.setInput('Lid_Lateral', self.lidLateralCtrl) # Add Xfo Outputs self.debugLidUpCanvasOp.setOutput('result', self.eyelidUpOutput.getTarget()) # Add Lid Low Canvas Op self.debugLidLowCanvasOp = CanvasOperator( 'Debug_Canvas_Eyelid_Low_Op', 'MJCG.Solvers.mjEyelidDebugSolver') self.addOperator(self.debugLidLowCanvasOp) # Add Attributes Inputs self.debugLidLowCanvasOp.setInput('drawDebug', self.drawDebugInputAttr) self.debugLidLowCanvasOp.setInput('rigScale', self.rigScaleInputAttr) self.debugLidLowCanvasOp.setInput('Deformer_Count', self.numLowDeformersInputAttr) # Add Xfo Inputs self.debugLidLowCanvasOp.setInput('Eye_Center', self.eyeballCtrl) self.debugLidLowCanvasOp.setInput('Lid_Medial', self.lidMedialCtrl) self.debugLidLowCanvasOp.setInput('Lid_MedialCen', self.lidLowMedialCtrl) self.debugLidLowCanvasOp.setInput('Lid_Center_Ref', self.lidLowCtrl) self.debugLidLowCanvasOp.setInput('Lid_Center_Ctrl', self.lidLowCtrl) self.debugLidLowCanvasOp.setInput('Lid_LateralCen', self.lidLowLateralCtrl) self.debugLidLowCanvasOp.setInput('Lid_Lateral', self.lidLateralCtrl) # Add Xfo Outputs self.debugLidLowCanvasOp.setOutput('result', self.eyelidLowOutput.getTarget()) # ========= # Position Data // Get the Guide Controls Position data, else set them at their initial position. # ========= self.default_data = { "name": name, "location": "L", "eyeballXfo": Xfo(Vec3(0.322, 15.500, 0.390)), "lidMedialXfo": Xfo(Vec3(0.168, 15.445, 0.520)), "lidLateralXfo": Xfo(Vec3(0.465, 15.47, 0.465)), "lidUpXfo": Xfo(Vec3(0.322, 15.585, 0.605)), "lidUpMedialXfo": Xfo(Vec3(0.203, 15.515, 0.525)), "lidUpLateralXfo": Xfo(Vec3(0.432, 15.55, 0.538)), "lidLowXfo": Xfo(Vec3(0.322, 15.434, 0.6)), "lidLowMedialXfo": Xfo(Vec3(0.24, 15.45, 0.513)), "lidLowLateralXfo": Xfo(Vec3(0.413, 15.44, 0.525)), "lidUpMedialBlink": self.upMedialFactorAttr.getValue(), "lidUpLateralBlink": self.upLateralFactorAttr.getValue(), "lidLowMedialBlink": self.lowMedialFactorAttr.getValue(), "lidLowLateralBlink": self.lowLateralFactorAttr.getValue(), "numUpDeformers": self.numUpDeformersAttr.getValue(), "numLowDeformers": self.numLowDeformersAttr.getValue(), } self.loadData(self.default_data) Profiler.getInstance().pop()
class FabriceTailGuide(FabriceTail): """Fabrice Tail Component Guide""" def __init__(self, name='tail', parent=None): Profiler.getInstance().push("Construct Fabrice Tail Guide Component:" + name) super(FabriceTailGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.numDeformersAttr.setValueChangeCallback(self.updateNumDeformers) # Guide Controls self.tailBaseCtrl = Control('tailBase', parent=self.ctrlCmpGrp, shape='sphere') self.tailBaseCtrl.scalePoints(Vec3(1.2, 1.2, 1.2)) self.tailBaseCtrl.lockScale(x=True, y=True, z=True) self.tailBaseCtrl.setColor("turqoise") self.tailBaseHandleCtrl = Control('tailBaseHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailBaseHandleCtrl.rotatePoints(90, 0, 0) self.tailBaseHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailBaseHandleCtrl.lockScale(x=True, y=True, z=True) self.tailBaseHandleCtrl.setColor("turqoise") self.tailEndHandleCtrl = Control('tailEndHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailEndHandleCtrl.rotatePoints(90, 0, 0) self.tailEndHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndHandleCtrl.lockScale(x=True, y=True, z=True) self.tailEndHandleCtrl.setColor("turqoise") self.tailEndCtrl = Control('tailEnd', parent=self.ctrlCmpGrp, shape='pin') self.tailEndCtrl.rotatePoints(90, 0, 0) self.tailEndCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndCtrl.lockScale(x=True, y=True, z=True) self.tailEndCtrl.setColor("turqoise") # =============== # Add Splice Ops # =============== # Add Tail Splice Op self.bezierSpineSpliceOp = SpliceOperator('spineGuideSpliceOp', 'BezierSpineSolver', 'Kraken', alwaysEval=True) self.bezierSpineSpliceOp.setOutput('outputs', self.tailVertebraeOutput.getTarget()) self.addOperator(self.bezierSpineSpliceOp) # Add Att Inputs self.bezierSpineSpliceOp.setInput('drawDebug', self.drawDebugInputAttr) self.bezierSpineSpliceOp.setInput('rigScale', self.rigScaleInputAttr) self.bezierSpineSpliceOp.setInput('length', self.lengthInputAttr) # Add Xfo Inputs self.bezierSpineSpliceOp.setInput('base', self.tailBaseCtrl) self.bezierSpineSpliceOp.setInput('baseHandle', self.tailBaseHandleCtrl) self.bezierSpineSpliceOp.setInput('tipHandle', self.tailEndHandleCtrl) self.bezierSpineSpliceOp.setInput('tip', self.tailEndCtrl) self.loadData({ 'name': name, 'location': 'M', 'tailBasePos': Vec3(0.0, 0.65, -3.1), 'tailBaseHandlePos': Vec3(0.0, 0.157, -4.7), 'tailBaseHandleCtrlCrvData': self.tailBaseHandleCtrl.getCurveData(), 'tailEndHandlePos': Vec3(0.0, 0.0625, -6.165), 'tailEndHandleCtrlCrvData': self.tailEndHandleCtrl.getCurveData(), 'tailEndPos': Vec3(0.0, -0.22, -7.42), 'tailEndCtrlCrvData': self.tailEndCtrl.getCurveData(), 'numDeformers': 6 }) Profiler.getInstance().pop() # ========== # Callbacks # ========== def updateNumDeformers(self, count): """Generate the guide controls for the variable outputes array. Arguments: count -- object, The number of joints inthe chain. Return: True if successful. """ if count == 0: raise IndexError("'count' must be > 0") vertebraeOutputs = self.tailVertebraeOutput.getTarget() if count > len(vertebraeOutputs): for i in xrange(len(vertebraeOutputs), count): debugCtrl = Control('spine' + str(i+1).zfill(2), parent=self.outputHrcGrp, shape="vertebra") debugCtrl.rotatePoints(0, -90, 0) debugCtrl.scalePoints(Vec3(0.5, 0.5, 0.5)) debugCtrl.setColor('turqoise') vertebraeOutputs.append(debugCtrl) elif count < len(vertebraeOutputs): numExtraCtrls = len(vertebraeOutputs) - count for i in xrange(numExtraCtrls): extraCtrl = vertebraeOutputs.pop() self.outputHrcGrp.removeChild(extraCtrl) return True # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(FabriceTailGuide, self).saveData() data['tailBasePos'] = self.tailBaseCtrl.xfo.tr data['tailBaseHandlePos'] = self.tailBaseHandleCtrl.xfo.tr data['tailBaseHandleCtrlCrvData'] = self.tailBaseHandleCtrl.getCurveData() data['tailEndHandlePos'] = self.tailEndHandleCtrl.xfo.tr data['tailEndHandleCtrlCrvData'] = self.tailEndHandleCtrl.getCurveData() data['tailEndPos'] = self.tailEndCtrl.xfo.tr data['tailEndCtrlCrvData'] = self.tailEndCtrl.getCurveData() data['numDeformers'] = self.numDeformersAttr.getValue() return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(FabriceTailGuide, self).loadData( data ) self.tailBaseCtrl.xfo.tr = data["tailBasePos"] self.tailBaseHandleCtrl.xfo.tr = data["tailBaseHandlePos"] self.tailBaseHandleCtrl.setCurveData(data['tailBaseHandleCtrlCrvData']) self.tailEndHandleCtrl.xfo.tr = data["tailEndHandlePos"] self.tailEndHandleCtrl.setCurveData(data['tailEndHandleCtrlCrvData']) self.tailEndCtrl.xfo.tr = data["tailEndPos"] self.tailEndCtrl.setCurveData(data['tailEndCtrlCrvData']) self.numDeformersAttr.setValue(data["numDeformers"]) length = data["tailBasePos"].distanceTo(data["tailBaseHandlePos"]) + data["tailBaseHandlePos"].distanceTo(data["tailEndHandlePos"]) + data["tailEndHandlePos"].distanceTo(data["tailEndPos"]) self.lengthInputAttr.setMax(length * 3.0) self.lengthInputAttr.setValue(length) self.bezierSpineSpliceOp.evaluate() return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig. Return: The JSON rig data object. """ data = super(FabriceTailGuide, self).getRigBuildData() data['tailBasePos'] = self.tailBaseCtrl.xfo.tr data['tailBaseHandlePos'] = self.tailBaseHandleCtrl.xfo.tr data['tailBaseHandleCtrlCrvData'] = self.tailBaseHandleCtrl.getCurveData() data['tailEndHandlePos'] = self.tailEndHandleCtrl.xfo.tr data['tailEndHandleCtrlCrvData'] = self.tailEndHandleCtrl.getCurveData() data['tailEndPos'] = self.tailEndCtrl.xfo.tr data['tailEndCtrlCrvData'] = self.tailEndCtrl.getCurveData() data['numDeformers'] = self.numDeformersAttr.getValue() return data # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return FabriceTailRig
class FKChainComponentGuide(FKChainComponent): """FKChain Component Guide""" def __init__(self, name='FKChain', parent=None, data=None): Profiler.getInstance().push("Construct FKCHain Guide Component:" + name) super(FKChainComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numJoints = IntegerAttribute('numJoints', value=4, minValue=1, maxValue=20, parent=guideSettingsAttrGrp) self.numJoints.setValueChangeCallback(self.updateNumJointControls) self.jointCtrls = [] if data is None: numJoints = self.numJoints.getValue() jointPositions = self.generateGuidePositions(numJoints) for i in xrange(numJoints + 1): if i == 0: ctrlParent = self.ctrlCmpGrp else: ctrlParent = self.jointCtrls[i - 1] newCtrl = Control('chain' + str(i + 1).zfill(2), parent=ctrlParent, shape="sphere") newCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) self.jointCtrls.append(newCtrl) data = { "location": "L", "jointPositions": jointPositions, "numJoints": self.numJoints.getValue() } self.loadData(data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(FKChainComponentGuide, self).saveData() jointPositions = [] for i in xrange(len(self.jointCtrls)): jointPositions.append(self.jointCtrls[i].xfo.tr) data['jointPositions'] = jointPositions return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(FKChainComponentGuide, self).loadData(data) for i in xrange(len(data['jointPositions'])): self.jointCtrls[i].xfo.tr = data['jointPositions'][i] return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig.. Return: The JSON rig data object. """ data = super(FKChainComponentGuide, self).getRigBuildData() numJoints = self.numJoints.getValue() # Calculate Xfos fw = Vec3(0, 0, 1) boneXfos = [] boneLengths = [] for i in xrange(numJoints): boneVec = self.jointCtrls[i + 1].xfo.tr.subtract( self.jointCtrls[i].xfo.tr) boneLengths.append(boneVec.length()) bone1Normal = fw.cross(boneVec).unit() bone1ZAxis = boneVec.cross(bone1Normal).unit() xfo = Xfo() xfo.setFromVectors(boneVec.unit(), bone1Normal, bone1ZAxis, self.jointCtrls[i].xfo.tr) boneXfos.append(xfo) data['boneXfos'] = boneXfos data['endXfo'] = self.jointCtrls[-1].xfo data['boneLengths'] = boneLengths return data # ========== # Callbacks # ========== def updateNumJointControls(self, numJoints): """Load a saved guide representation from persisted data. Arguments: numJoints -- object, The number of joints inthe chain. Return: True if successful. """ if numJoints == 0: raise IndexError("'numJoints' must be > 0") if numJoints + 1 > len(self.jointCtrls): for i in xrange(len(self.jointCtrls), numJoints + 1): if i == 0: ctrlParent = self.ctrlCmpGrp else: ctrlParent = self.jointCtrls[i - 1] newCtrl = Control('chain' + str(i + 1).zfill(2), parent=ctrlParent, shape="sphere") newCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) # Generate thew new ctrl off the end of the existing one. newCtrl.xfo = self.jointCtrls[i - 1].xfo.multiply( Xfo(Vec3(10.0, 0.0, 0.0))) self.jointCtrls.append(newCtrl) elif numJoints + 1 < len(self.jointCtrls): numExtraCtrls = len(self.jointCtrls) - (numJoints + 1) for i in xrange(numExtraCtrls): extraCtrl = self.jointCtrls.pop() extraCtrl.getParent().removeChild(extraCtrl) # Reset the control positions based on new number of joints jointPositions = self.generateGuidePositions(numJoints) for i in xrange(len(self.jointCtrls)): self.jointCtrls[i].xfo.tr = jointPositions[i] return True def generateGuidePositions(self, numJoints): """Generates the positions for the guide controls based on the number of joints. Args: numJoints (int): Number of joints to generate a transform for. Returns: list: Guide control positions. """ guidePositions = [] for i in xrange(numJoints + 1): guidePositions.append(Vec3(0, 0, i)) return guidePositions # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return FKChainComponentRig
class HandComponentGuide(HandComponent): """Hand Component Guide""" def __init__(self, name='hand', parent=None, *args, **kwargs): Profiler.getInstance().push("Construct Hand Guide Component:" + name) super(HandComponentGuide, self).__init__(name, parent, *args, **kwargs) # ========= # Controls # ========= # Guide Controls self.guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.digitNamesAttr = StringAttribute('digitNames', value="thumb,index,middle,ring,pinky", parent=self.guideSettingsAttrGrp) self.digitNamesAttr.setValueChangeCallback(self.updateFingers) self.numJointsAttr = IntegerAttribute('numJoints', value=4, minValue=2, maxValue=20, parent=self.guideSettingsAttrGrp) self.numJointsAttr.setValueChangeCallback(self.resizeDigits) self.fingers = OrderedDict() self.handCtrl = Control('hand', parent=self.ctrlCmpGrp, shape="square") self.handCtrl.rotatePoints(0.0, 0.0, 90.0) self.handCtrl.scalePoints(Vec3(1.0, 0.75, 1.0)) self.handCtrl.setColor('yellow') self.handGuideSettingsAttrGrp = AttributeGroup("Settings", parent=self.handCtrl) self.ctrlShapeToggle = BoolAttribute('ctrlShape_vis', value=False, parent=self.handGuideSettingsAttrGrp) self.handDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=self.handGuideSettingsAttrGrp) self.drawDebugInputAttr.connect(self.handDebugInputAttr) self.guideCtrlHrcGrp = HierarchyGroup('controlShapes', parent=self.ctrlCmpGrp) self.default_data = { "name": name, "location": "L", "handXfo": Xfo(Vec3(7.1886, 12.2819, 0.4906)), "digitNames": self.digitNamesAttr.getValue(), "numJoints": self.numJointsAttr.getValue(), "fingers": self.fingers } self.loadData(self.default_data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(HandComponentGuide, self).saveData() data['handXfo'] = self.handCtrl.xfo data['digitNames'] = self.digitNamesAttr.getValue() data['numJoints'] = self.numJointsAttr.getValue() fingerXfos = {} fingerShapeCtrlData = {} for finger in self.fingers.keys(): fingerXfos[finger] = [x.xfo for x in self.fingers[finger]] fingerShapeCtrlData[finger] = [] for i, digit in enumerate(self.fingers[finger]): if i != len(self.fingers[finger]) - 1: fingerShapeCtrlData[finger].append(digit.shapeCtrl.getCurveData()) data['fingersGuideXfos'] = fingerXfos data['fingerShapeCtrlData'] = fingerShapeCtrlData return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(HandComponentGuide, self).loadData(data) self.handCtrl.xfo = data.get('handXfo') self.numJointsAttr.setValue(data.get('numJoints')) self.digitNamesAttr.setValue(data.get('digitNames')) fingersGuideXfos = data.get('fingersGuideXfos') fingerShapeCtrlData = data.get('fingerShapeCtrlData') if fingersGuideXfos is not None: for finger in self.fingers.keys(): for i in xrange(len(self.fingers[finger])): self.fingers[finger][i].xfo = fingersGuideXfos[finger][i] if hasattr(self.fingers[finger][i], 'shapeCtrl'): if fingerShapeCtrlData is not None: if finger in fingerShapeCtrlData: self.fingers[finger][i].shapeCtrl.setCurveData(fingerShapeCtrlData[finger][i]) for op in self.getOperators(): guideOpName = ''.join([op.getName().split('FingerGuideOp')[0], self.getLocation(), 'FingerGuideOp']) op.setName(guideOpName) return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig.. Return: The JSON rig data object. """ data = super(HandComponentGuide, self).getRigBuildData() data['handXfo'] = self.handCtrl.xfo fingerData = {} for finger in self.fingers.keys(): fingerData[finger] = [] for i, joint in enumerate(self.fingers[finger]): if i == len(self.fingers[finger]) - 1: continue # Calculate Xfo boneVec = self.fingers[finger][i + 1].xfo.tr - self.fingers[finger][i].xfo.tr bone1Normal = self.fingers[finger][i].xfo.ori.getZaxis().cross(boneVec).unit() bone1ZAxis = boneVec.cross(bone1Normal).unit() jointXfo = Xfo() jointXfo.setFromVectors(boneVec.unit(), bone1Normal, bone1ZAxis, self.fingers[finger][i].xfo.tr) jointData = { 'curveData': self.fingers[finger][i].shapeCtrl.getCurveData(), 'length': self.fingers[finger][i].xfo.tr.distanceTo(self.fingers[finger][i + 1].xfo.tr), 'xfo': jointXfo } fingerData[finger].append(jointData) data['fingerData'] = fingerData return data # ========== # Callbacks # ========== def addFinger(self, name): digitSizeAttributes = [] fingerGuideCtrls = [] firstDigitCtrl = Control(name + "01", parent=self.handCtrl, shape='sphere') firstDigitCtrl.scalePoints(Vec3(0.125, 0.125, 0.125)) firstDigitShapeCtrl = Control(name + "Shp01", parent=self.guideCtrlHrcGrp, shape='square') firstDigitShapeCtrl.setColor('yellow') firstDigitShapeCtrl.scalePoints(Vec3(0.175, 0.175, 0.175)) firstDigitShapeCtrl.translatePoints(Vec3(0.0, 0.125, 0.0)) fingerGuideCtrls.append(firstDigitShapeCtrl) firstDigitCtrl.shapeCtrl = firstDigitShapeCtrl firstDigitVisAttr = firstDigitShapeCtrl.getVisibilityAttr() firstDigitVisAttr.connect(self.ctrlShapeToggle) triangleCtrl = Control('tempCtrl', parent=None, shape='triangle') triangleCtrl.rotatePoints(90.0, 0.0, 0.0) triangleCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) triangleCtrl.translatePoints(Vec3(0.0, 0.0875, 0.0)) firstDigitCtrl.appendCurveData(triangleCtrl.getCurveData()) firstDigitCtrl.lockScale(True, True, True) digitSettingsAttrGrp = AttributeGroup("DigitSettings", parent=firstDigitCtrl) digitSizeAttr = ScalarAttribute('size', value=0.25, parent=digitSettingsAttrGrp) digitSizeAttributes.append(digitSizeAttr) # Set Finger self.fingers[name] = [] self.fingers[name].append(firstDigitCtrl) parent = firstDigitCtrl numJoints = self.numJointsAttr.getValue() if name == "thumb": numJoints = 3 for i in xrange(2, numJoints + 2): digitCtrl = Control(name + str(i).zfill(2), parent=parent, shape='sphere') if i != numJoints + 1: digitCtrl.scalePoints(Vec3(0.125, 0.125, 0.125)) digitCtrl.appendCurveData(triangleCtrl.getCurveData()) digitShapeCtrl = Control(name + 'Shp' + str(i).zfill(2), parent=self.guideCtrlHrcGrp, shape='circle') digitShapeCtrl.setColor('yellow') digitShapeCtrl.scalePoints(Vec3(0.175, 0.175, 0.175)) digitShapeCtrl.getVisibilityAttr().connect(self.ctrlShapeToggle) digitCtrl.shapeCtrl = digitShapeCtrl if i == 2: digitShapeCtrl.translatePoints(Vec3(0.0, 0.125, 0.0)) else: digitShapeCtrl.rotatePoints(0.0, 0.0, 90.0) fingerGuideCtrls.append(digitShapeCtrl) # Add size attr to all but last guide control digitSettingsAttrGrp = AttributeGroup("DigitSettings", parent=digitCtrl) digitSizeAttr = ScalarAttribute('size', value=0.25, parent=digitSettingsAttrGrp) digitSizeAttributes.append(digitSizeAttr) else: digitCtrl.scalePoints(Vec3(0.0875, 0.0875, 0.0875)) digitCtrl.lockScale(True, True, True) self.fingers[name].append(digitCtrl) parent = digitCtrl # =========================== # Create Canvas Operators # =========================== # Add Finger Guide Canvas Op fingerGuideCanvasOp = CanvasOperator(name + 'FingerGuide', 'Kraken.Solvers.Biped.BipedFingerGuideSolver') self.addOperator(fingerGuideCanvasOp) # Add Att Inputs fingerGuideCanvasOp.setInput('drawDebug', self.drawDebugInputAttr) fingerGuideCanvasOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs fingerGuideCanvasOp.setInput('controls', self.fingers[name]) fingerGuideCanvasOp.setInput('planeSizes', digitSizeAttributes) # Add Xfo Outputs fingerGuideCanvasOp.setOutput('result', fingerGuideCtrls) fingerGuideCanvasOp.setOutput('forceEval', firstDigitCtrl.getVisibilityAttr()) return firstDigitCtrl def removeFinger(self, name): self.handCtrl.removeChild(self.fingers[name][0]) del self.fingers[name] def placeFingers(self): spacing = 0.25 length = spacing * (len(self.fingers.keys()) - 1) mid = length / 2.0 startOffset = length - mid for i, finger in enumerate(self.fingers.keys()): parentCtrl = self.handCtrl numJoints = self.numJointsAttr.getValue() if finger == "thumb": numJoints = 3 for y in xrange(numJoints + 1): if y == 1: xOffset = 0.375 else: xOffset = 0.25 if y == 0: offsetVec = Vec3(xOffset, 0, startOffset - (i * spacing)) else: offsetVec = Vec3(xOffset, 0, 0) fingerPos = parentCtrl.xfo.transformVector(offsetVec) fingerXfo = Xfo(tr=fingerPos, ori=self.handCtrl.xfo.ori) self.fingers[finger][y].xfo = fingerXfo parentCtrl = self.fingers[finger][y] def updateFingers(self, fingers): if " " in fingers: self.digitNamesAttr.setValue(fingers.replace(" ", "")) return fingerNames = fingers.split(',') # Delete fingers that don't exist any more for finger in list(set(self.fingers.keys()) - set(fingerNames)): self.removeFinger(finger) # Add Fingers for finger in fingerNames: if finger in self.fingers.keys(): continue self.addFinger(finger) self.placeFingers() def resizeDigits(self, numJoints): initNumJoints = numJoints for finger in self.fingers.keys(): if finger == "thumb": numJoints = 3 else: numJoints = initNumJoints if numJoints + 1 == len(self.fingers[finger]): continue elif numJoints + 1 > len(self.fingers[finger]): for i in xrange(len(self.fingers[finger]), numJoints + 1): prevDigit = self.fingers[finger][i - 1] digitCtrl = Control(finger + str(i + 1).zfill(2), parent=prevDigit, shape='sphere') digitCtrl.setColor('orange') digitCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) digitCtrl.lockScale(True, True, True) self.fingers[finger].append(digitCtrl) elif numJoints + 1 < len(self.fingers[finger]): numExtraCtrls = len(self.fingers[finger]) - (numJoints + 1) for i in xrange(numExtraCtrls): removedJoint = self.fingers[finger].pop() removedJoint.getParent().removeChild(removedJoint) self.placeFingers() # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return HandComponentRig
def __init__(self, name='InsectLeg', parent=None): Profiler.getInstance().push("Construct InsectLeg Rig Component:" + name) super(InsectLegComponentRig, self).__init__(name, parent) # ========= # Controls # ========= # Chain Base self.chainBase = Locator('ChainBase', parent=self.ctrlCmpGrp) self.chainBase.setShapeVisibility(False) # FK self.fkCtrlSpaces = [] self.fkCtrls = [] self.setNumControls(4) # IK Control self.legIKCtrlSpace = CtrlSpace('IK', parent=self.ctrlCmpGrp) self.legIKCtrl = Control('IK', parent=self.legIKCtrlSpace, shape="pin") if self.getLocation() == 'R': self.legIKCtrl.rotatePoints(0, 90, 0) self.legIKCtrl.translatePoints(Vec3(-1.0, 0.0, 0.0)) else: self.legIKCtrl.rotatePoints(0, -90, 0) self.legIKCtrl.translatePoints(Vec3(1.0, 0.0, 0.0)) # Add Component Params to IK control legSettingsAttrGrp = AttributeGroup("DisplayInfo_LegSettings", parent=self.legIKCtrl) legdrawDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=legSettingsAttrGrp) legUseInitPoseInputAttr = BoolAttribute('useInitPose', value=True, parent=legSettingsAttrGrp) self.rootIndexInputAttr = IntegerAttribute('rootIndex', value=0, parent=legSettingsAttrGrp) legFkikInputAttr = ScalarAttribute('fkik', value=1.0, minValue=0.0, maxValue=1.0, parent=legSettingsAttrGrp) # Connect IO to controls self.drawDebugInputAttr.connect(legdrawDebugInputAttr) # UpV self.legUpVCtrlSpace = CtrlSpace('UpV', parent=self.ctrlCmpGrp) self.legUpVCtrl = Control('UpV', parent=self.legUpVCtrlSpace, shape="triangle") self.legUpVCtrl.alignOnZAxis() self.legUpVCtrl.rotatePoints(0, 90, 0) # ========== # 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 legRootInputConstraint = PoseConstraint('_'.join([self.fkCtrlSpaces[0].getName(), 'To', self.rootInputTgt.getName()])) legRootInputConstraint.setMaintainOffset(True) legRootInputConstraint.addConstrainer(self.rootInputTgt) self.fkCtrlSpaces[0].addConstraint(legRootInputConstraint) chainBaseInputConstraint = PoseConstraint('_'.join([self.chainBase.getName(), 'To', self.rootInputTgt.getName()])) chainBaseInputConstraint.setMaintainOffset(True) chainBaseInputConstraint.addConstrainer(self.rootInputTgt) self.chainBase.addConstraint(chainBaseInputConstraint) # =============== # Add Splice Ops # =============== # Add Splice Op self.nBoneSolverSpliceOp = SpliceOperator('legSpliceOp', 'NBoneIKSolver', 'Kraken') self.addOperator(self.nBoneSolverSpliceOp) # # Add Att Inputs self.nBoneSolverSpliceOp.setInput('drawDebug', self.drawDebugInputAttr) self.nBoneSolverSpliceOp.setInput('rigScale', self.rigScaleInputAttr) self.nBoneSolverSpliceOp.setInput('useInitPose', legUseInitPoseInputAttr) self.nBoneSolverSpliceOp.setInput('ikblend', legFkikInputAttr) self.nBoneSolverSpliceOp.setInput('rootIndex', self.rootIndexInputAttr) self.nBoneSolverSpliceOp.setInput('tipBoneLen', self.tipBoneLenInputAttr) # Add Xfo Inputs self.nBoneSolverSpliceOp.setInput('chainBase', self.chainBase) self.nBoneSolverSpliceOp.setInput('ikgoal', self.legIKCtrl) self.nBoneSolverSpliceOp.setInput('upVector', self.legUpVCtrl) self.nBoneSolverSpliceOp.setInput('fkcontrols', self.fkCtrls) # Add Xfo Outputs self.nBoneSolverSpliceOp.setOutput('pose', self.boneOutputsTgt) self.nBoneSolverSpliceOp.setOutput('legEnd', self.legEndPosOutputTgt) # Add Deformer Splice Op self.outputsToDeformersSpliceOp = SpliceOperator('insectLegDeformerSpliceOp', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.outputsToDeformersSpliceOp) # Add Att Inputs self.outputsToDeformersSpliceOp.setInput('drawDebug', self.drawDebugInputAttr) self.outputsToDeformersSpliceOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs self.outputsToDeformersSpliceOp.setInput('constrainers', self.boneOutputsTgt) # Add Xfo Outputs self.outputsToDeformersSpliceOp.setOutput('constrainees', self.deformerJoints) Profiler.getInstance().pop()
class mjEyelidComponentGuide(mjEyelidComponent): """Eyelid Component Guide""" def __init__(self, name='mjEyelid', parent=None): Profiler.getInstance().push("Construct Eyelid Guide Component:" + name) super(mjEyelidComponentGuide, self).__init__(name, parent) # ========= # Attributes // Create Attributes Controls. # ========= guideUpSettingsAttrGrp = AttributeGroup("Eyelid Up", parent=self) guideLowSettingsAttrGrp = AttributeGroup("Eyelid Low", parent=self) self.numUpDeformersAttr = IntegerAttribute( 'Num Deformers', value=10, minValue=1, maxValue=50, parent=guideUpSettingsAttrGrp) self.upMedialFactorAttr = ScalarAttribute( 'Medial Blink Factor', value=0.25, minValue=0, maxValue=1, parent=guideUpSettingsAttrGrp) self.upLateralFactorAttr = ScalarAttribute( 'Lateral Blink Factor', value=0.65, minValue=0, maxValue=1, parent=guideUpSettingsAttrGrp) self.numLowDeformersAttr = IntegerAttribute( 'Num Deformers', value=10, minValue=1, maxValue=50, parent=guideLowSettingsAttrGrp) self.lowMedialFactorAttr = ScalarAttribute( 'Medial Blink Factor', value=0.25, minValue=0, maxValue=1, parent=guideLowSettingsAttrGrp) self.lowLateralFactorAttr = ScalarAttribute( 'Lateral Blink Factor', value=0.65, minValue=0, maxValue=1, parent=guideLowSettingsAttrGrp) self.numUpDeformersAttr.setValueChangeCallback( self.updateNumUpDeformers) self.numLowDeformersAttr.setValueChangeCallback( self.updateNumLowDeformers) # ========= # Controls // Create the Guide Controls, Name them, give them a shape, a color and scale it. # ========= self.eyeballCtrl = Control('eyeball', parent=self.ctrlCmpGrp, shape="sphere") self.eyeballCtrl.scalePoints(Vec3(0.35, 0.35, 0.35)) self.eyeballCtrl.setColor("red") self.lidMedialCtrl = Control('lidMedial', parent=self.eyeballCtrl, shape="sphere") self.lidMedialCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidMedialCtrl.setColor("peach") self.lidLateralCtrl = Control('lidLateral', parent=self.eyeballCtrl, shape="sphere") self.lidLateralCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLateralCtrl.setColor("peach") self.lidUpCtrl = Control('lidUp', parent=self.eyeballCtrl, shape="sphere") self.lidUpCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidUpCtrl.setColor("peach") self.lidUpMedialCtrl = Control('lidUpMedial', parent=self.eyeballCtrl, shape="sphere") self.lidUpMedialCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidUpMedialCtrl.setColor("peach") self.lidUpLateralCtrl = Control('lidUpLateral', parent=self.eyeballCtrl, shape="sphere") self.lidUpLateralCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidUpLateralCtrl.setColor("peach") self.lidLowCtrl = Control('lidLow', parent=self.eyeballCtrl, shape="sphere") self.lidLowCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLowCtrl.setColor("peach") self.lidLowMedialCtrl = Control('lidLowMedial', parent=self.eyeballCtrl, shape="sphere") self.lidLowMedialCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLowMedialCtrl.setColor("peach") self.lidLowLateralCtrl = Control('lidLowLateral', parent=self.eyeballCtrl, shape="sphere") self.lidLowLateralCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) self.lidLowLateralCtrl.setColor("peach") # =============== # Add Debug Splice Ops # =============== # Add Lid Up Canvas Op self.debugLidUpCanvasOp = CanvasOperator( 'Debug_Canvas_Eyelid_Up_Op', 'MJCG.Solvers.mjEyelidDebugSolver') self.addOperator(self.debugLidUpCanvasOp) # Add Attributes Inputs self.debugLidUpCanvasOp.setInput('drawDebug', self.drawDebugInputAttr) self.debugLidUpCanvasOp.setInput('rigScale', self.rigScaleInputAttr) self.debugLidUpCanvasOp.setInput('Deformer_Count', self.numUpDeformersInputAttr) # Add Xfo Inputs self.debugLidUpCanvasOp.setInput('Eye_Center', self.eyeballCtrl) self.debugLidUpCanvasOp.setInput('Lid_Medial', self.lidMedialCtrl) self.debugLidUpCanvasOp.setInput('Lid_MedialCen', self.lidUpMedialCtrl) self.debugLidUpCanvasOp.setInput('Lid_Center_Ref', self.lidUpCtrl) self.debugLidUpCanvasOp.setInput('Lid_Center_Ctrl', self.lidUpCtrl) self.debugLidUpCanvasOp.setInput('Lid_LateralCen', self.lidUpLateralCtrl) self.debugLidUpCanvasOp.setInput('Lid_Lateral', self.lidLateralCtrl) # Add Xfo Outputs self.debugLidUpCanvasOp.setOutput('result', self.eyelidUpOutput.getTarget()) # Add Lid Low Canvas Op self.debugLidLowCanvasOp = CanvasOperator( 'Debug_Canvas_Eyelid_Low_Op', 'MJCG.Solvers.mjEyelidDebugSolver') self.addOperator(self.debugLidLowCanvasOp) # Add Attributes Inputs self.debugLidLowCanvasOp.setInput('drawDebug', self.drawDebugInputAttr) self.debugLidLowCanvasOp.setInput('rigScale', self.rigScaleInputAttr) self.debugLidLowCanvasOp.setInput('Deformer_Count', self.numLowDeformersInputAttr) # Add Xfo Inputs self.debugLidLowCanvasOp.setInput('Eye_Center', self.eyeballCtrl) self.debugLidLowCanvasOp.setInput('Lid_Medial', self.lidMedialCtrl) self.debugLidLowCanvasOp.setInput('Lid_MedialCen', self.lidLowMedialCtrl) self.debugLidLowCanvasOp.setInput('Lid_Center_Ref', self.lidLowCtrl) self.debugLidLowCanvasOp.setInput('Lid_Center_Ctrl', self.lidLowCtrl) self.debugLidLowCanvasOp.setInput('Lid_LateralCen', self.lidLowLateralCtrl) self.debugLidLowCanvasOp.setInput('Lid_Lateral', self.lidLateralCtrl) # Add Xfo Outputs self.debugLidLowCanvasOp.setOutput('result', self.eyelidLowOutput.getTarget()) # ========= # Position Data // Get the Guide Controls Position data, else set them at their initial position. # ========= self.default_data = { "name": name, "location": "L", "eyeballXfo": Xfo(Vec3(0.322, 15.500, 0.390)), "lidMedialXfo": Xfo(Vec3(0.168, 15.445, 0.520)), "lidLateralXfo": Xfo(Vec3(0.465, 15.47, 0.465)), "lidUpXfo": Xfo(Vec3(0.322, 15.585, 0.605)), "lidUpMedialXfo": Xfo(Vec3(0.203, 15.515, 0.525)), "lidUpLateralXfo": Xfo(Vec3(0.432, 15.55, 0.538)), "lidLowXfo": Xfo(Vec3(0.322, 15.434, 0.6)), "lidLowMedialXfo": Xfo(Vec3(0.24, 15.45, 0.513)), "lidLowLateralXfo": Xfo(Vec3(0.413, 15.44, 0.525)), "lidUpMedialBlink": self.upMedialFactorAttr.getValue(), "lidUpLateralBlink": self.upLateralFactorAttr.getValue(), "lidLowMedialBlink": self.lowMedialFactorAttr.getValue(), "lidLowLateralBlink": self.lowLateralFactorAttr.getValue(), "numUpDeformers": self.numUpDeformersAttr.getValue(), "numLowDeformers": self.numLowDeformersAttr.getValue(), } self.loadData(self.default_data) Profiler.getInstance().pop() # ========== # Callbacks # ========== def updateNumUpDeformers(self, countUp): if countUp == 0: raise IndexError("'count' must be > 0") #Lip Up lidUpOutputs = self.eyelidUpOutput.getTarget() if countUp > len(lidUpOutputs): for i in xrange(len(lidUpOutputs), countUp): debugUpCtrl = Control('Lid_Up_' + str(i + 1).zfill(2), parent=self.outputHrcGrp, shape="sphere") debugUpCtrl.rotatePoints(90, -90, 180) debugUpCtrl.scalePoints(Vec3(0.01, 0.01, 0.01)) debugUpCtrl.setColor("yellowLight") lidUpOutputs.append(debugUpCtrl) elif countUp < len(lidUpOutputs): numExtraUpCtrls = len(lidUpOutputs) - countUp for i in xrange(numExtraUpCtrls): extraUpCtrl = lidUpOutputs.pop() self.outputHrcGrp.removeChild(extraUpCtrl) return True def updateNumLowDeformers(self, countLow): if countLow == 0: raise IndexError("'count' must be > 0") #Lip Low lidLowOutputs = self.eyelidLowOutput.getTarget() if countLow > len(lidLowOutputs): for i in xrange(len(lidLowOutputs), countLow): debugLowCtrl = Control('Lid_Low_' + str(i + 1).zfill(2), parent=self.outputHrcGrp, shape="sphere") debugLowCtrl.rotatePoints(90, -90, 180) debugLowCtrl.scalePoints(Vec3(0.01, 0.01, 0.01)) debugLowCtrl.setColor("yellowLight") lidLowOutputs.append(debugLowCtrl) elif countLow < len(lidLowOutputs): numExtraLowCtrls = len(lidLowOutputs) - countLow for i in xrange(numExtraLowCtrls): extraLowCtrl = lidLowOutputs.pop() self.outputHrcGrp.removeChild(extraLowCtrl) return True # ============= # Data Methods # ============= def saveData(self): data = super(mjEyelidComponentGuide, self).saveData() data['eyeballXfo'] = self.eyeballCtrl.xfo data['lidMedialXfo'] = self.lidMedialCtrl.xfo data['lidLateralXfo'] = self.lidLateralCtrl.xfo data['lidUpXfo'] = self.lidUpCtrl.xfo data['lidUpMedialXfo'] = self.lidUpMedialCtrl.xfo data['lidUpLateralXfo'] = self.lidUpLateralCtrl.xfo data['lidLowXfo'] = self.lidLowCtrl.xfo data['lidLowMedialXfo'] = self.lidLowMedialCtrl.xfo data['lidLowLateralXfo'] = self.lidLowLateralCtrl.xfo data['numUpDeformers'] = self.numUpDeformersAttr.getValue() data['numLowDeformers'] = self.numLowDeformersAttr.getValue() data['lidUpMedialBlink'] = self.upMedialFactorAttr.getValue() data['lidUpLateralBlink'] = self.upLateralFactorAttr.getValue() data['lidLowMedialBlink'] = self.lowMedialFactorAttr.getValue() data['lidLowLateralBlink'] = self.lowLateralFactorAttr.getValue() return data def loadData(self, data): super(mjEyelidComponentGuide, self).loadData(data) self.eyeballCtrl.xfo = data['eyeballXfo'] self.lidMedialCtrl.xfo = data['lidMedialXfo'] self.lidLateralCtrl.xfo = data['lidLateralXfo'] self.lidUpCtrl.xfo = data['lidUpXfo'] self.lidUpMedialCtrl.xfo = data['lidUpMedialXfo'] self.lidUpLateralCtrl.xfo = data['lidUpLateralXfo'] self.lidLowCtrl.xfo = data['lidLowXfo'] self.lidLowMedialCtrl.xfo = data['lidLowMedialXfo'] self.lidLowLateralCtrl.xfo = data['lidLowLateralXfo'] self.numUpDeformersAttr.setValue(data["numUpDeformers"]) self.numLowDeformersAttr.setValue(data["numLowDeformers"]) self.numUpDeformersInputAttr.setValue(data["numUpDeformers"]) self.numLowDeformersInputAttr.setValue(data["numLowDeformers"]) self.upMedialFactorInputAttr.setValue(data['lidUpMedialBlink']) self.upLateralFactorInputAttr.setValue(data['lidUpLateralBlink']) self.lowMedialFactorInputAttr.setValue(data['lidLowMedialBlink']) self.lowLateralFactorInputAttr.setValue(data['lidLowLateralBlink']) self.debugLidUpCanvasOp.evaluate() self.debugLidLowCanvasOp.evaluate() return True def getRigBuildData(self): data = super(mjEyelidComponentGuide, self).getRigBuildData() eyeballPosition = self.eyeballCtrl.xfo.tr eyeballOriXfo = Xfo() eyeballOriXfo.tr = eyeballPosition eyeballOriOffset = Quat(Vec3(0.0, 0.894, 0.0), -0.448) if self.getLocation() == "R": eyeballOriXfo.ori.subtract(eyeballOriOffset) data['eyeballXfo'] = eyeballOriXfo eyelidUpVOffset = Vec3(0.0, 0.2, 0.0) eyelidUpVXfo = Xfo() eyelidUpVXfo.tr = eyeballPosition.add(eyelidUpVOffset) data['eyelidUpVXfo'] = eyelidUpVXfo data['lidMedialXfo'] = self.lidMedialCtrl.xfo data['lidLateralXfo'] = self.lidLateralCtrl.xfo data['lidUpXfo'] = self.lidUpCtrl.xfo data['lidUpMedialXfo'] = self.lidUpMedialCtrl.xfo data['lidUpLateralXfo'] = self.lidUpLateralCtrl.xfo data['lidLowXfo'] = self.lidLowCtrl.xfo data['lidLowMedialXfo'] = self.lidLowMedialCtrl.xfo data['lidLowLateralXfo'] = self.lidLowLateralCtrl.xfo data['numUpDeformers'] = self.numUpDeformersAttr.getValue() data['numLowDeformers'] = self.numLowDeformersAttr.getValue() data['lidUpMedialBlink'] = self.upMedialFactorAttr.getValue() data['lidUpLateralBlink'] = self.upLateralFactorAttr.getValue() data['lidLowMedialBlink'] = self.lowMedialFactorAttr.getValue() data['lidLowLateralBlink'] = self.lowLateralFactorAttr.getValue() return data # ============== # Class Methods # ============== @classmethod def getComponentType(cls): return 'Guide' @classmethod def getRigComponentClass(cls): return mjEyelidComponentRig
class TentacleComponentGuide(TentacleComponent): """Tentacle Component Guide""" def __init__(self, name='Tentacle', parent=None, data=None): Profiler.getInstance().push("Construct Tentacle Guide Component:" + name) super(TentacleComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numJoints = IntegerAttribute('numJoints', value=5, minValue=2, maxValue=20, parent=guideSettingsAttrGrp) self.numJoints.setValueChangeCallback(self.updateNumControls) self.jointCtrls = [] self.tentacleOutputs = [] if data is None: numJoints = self.numJoints.getValue() jointPositions = self.generateGuidePositions(numJoints) for i in xrange(numJoints): self.jointCtrls.append(Control('tentacle' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="sphere")) self.tentacleOutputs.append(ComponentOutput('tentacle' + str(i + 1).zfill(2), parent=self.outputHrcGrp)) self.boneOutputs.setTarget(self.tentacleOutputs) data = { "location": "L", "jointPositions": jointPositions, "numJoints": self.numJoints.getValue() } self.loadData(data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(TentacleComponentGuide, self).saveData() jointPositions = [] for i in xrange(len(self.jointCtrls)): jointPositions.append(self.jointCtrls[i].xfo.tr) data['jointPositions'] = jointPositions return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(TentacleComponentGuide, self).loadData(data) for i in xrange(len(data['jointPositions'])): self.jointCtrls[i].xfo.tr = data['jointPositions'][i] return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig.. Return: The JSON rig data object. """ data = super(TentacleComponentGuide, self).getRigBuildData() numJoints = self.numJoints.getValue() # Calculate FW toFirst = self.jointCtrls[0].xfo.tr.subtract(self.jointCtrls[1].xfo.tr).unit() toTip = self.jointCtrls[0].xfo.tr.subtract(self.jointCtrls[-1].xfo.tr).unit() fw = toTip.cross(toFirst).unit() # Calculate Xfos boneXfos = [] boneLengths = [] for i in xrange(numJoints): boneVec = self.jointCtrls[i + 1].xfo.tr.subtract(self.jointCtrls[i].xfo.tr) boneLengths.append(boneVec.length()) bone1Normal = fw.cross(boneVec).unit() bone1ZAxis = boneVec.cross(bone1Normal).unit() xfo = Xfo() xfo.setFromVectors(boneVec.unit(), bone1Normal, bone1ZAxis, self.jointCtrls[i].xfo.tr) boneXfos.append(xfo) data['boneXfos'] = boneXfos data['endXfo'] = self.jointCtrls[-1].xfo data['boneLengths'] = boneLengths return data # ========== # Callbacks # ========== def updateNumControls(self, numJoints): """Load a saved guide representation from persisted data. Arguments: numJoints -- object, The number of joints inthe chain. Return: True if successful. """ if numJoints == 0: raise IndexError("'numJoints' must be > 0") if numJoints + 1 > len(self.jointCtrls): for i in xrange(len(self.jointCtrls), numJoints + 1): newCtrl = Control('tentacle' + str(i + 1).zfill(2), parent=self.ctrlCmpGrp, shape="sphere") self.jointCtrls.append(newCtrl) newOutput = ComponentOutput('tentacle' + str(i + 1).zfill(2), parent=self.outputHrcGrp) self.tentacleOutputs.append(newOutput) elif numJoints + 1 < len(self.jointCtrls): numExtraCtrls = len(self.jointCtrls) - (numJoints + 1) for i in xrange(numExtraCtrls): extraCtrl = self.jointCtrls.pop() self.ctrlCmpGrp.removeChild(extraCtrl) extraOutput = self.tentacleOutputs.pop() self.outputHrcGrp.removeChild(extraOutput) # Reset the control positions based on new number of joints jointPositions = self.generateGuidePositions(numJoints) for i in xrange(len(self.jointCtrls)): self.jointCtrls[i].xfo.tr = jointPositions[i] return True def generateGuidePositions(self, numJoints): """Generates the positions for the guide controls based on the number of joints. Args: numJoints (int): Number of joints to generate a transform for. Returns: list: Guide control positions. """ halfPi = math.pi / 2.0 step = halfPi / numJoints guidePositions = [] for i in xrange(numJoints + 1): x = math.cos((i * step) + halfPi) * -10 y = math.sin((i * step) + halfPi) * 10 guidePositions.append(Vec3(x, y, 0.0)) return guidePositions # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return TentacleComponentRig
class SpineComponentGuide(SpineComponent): """Spine Component Guide""" def __init__(self, name='spine', parent=None): Profiler.getInstance().push("Construct Spine Guide Component:" + name) super(SpineComponentGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) # Guide Controls self.cog = Control('cogPosition', parent=self.ctrlCmpGrp, shape="sphere") self.cog.scalePoints(Vec3(1.2, 1.2, 1.2)) self.cog.setColor('red') self.spine01Ctrl = Control('spine01Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine02Ctrl = Control('spine02Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine03Ctrl = Control('spine03Position', parent=self.ctrlCmpGrp, shape='sphere') self.spine04Ctrl = Control('spine04Position', parent=self.ctrlCmpGrp, shape='sphere') self.loadData({ 'name': name, 'location': 'M', 'cogPosition': Vec3(0.0, 11.1351, -0.1382), 'spine01Position': Vec3(0.0, 11.1351, -0.1382), 'spine02Position': Vec3(0.0, 11.8013, -0.1995), 'spine03Position': Vec3(0.0, 12.4496, -0.3649), 'spine04Position': Vec3(0.0, 13.1051, -0.4821), 'numDeformers': 6 }) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(SpineComponentGuide, self).saveData() data['cogPosition'] = self.cog.xfo.tr data['spine01Position'] = self.spine01Ctrl.xfo.tr data['spine02Position'] = self.spine02Ctrl.xfo.tr data['spine03Position'] = self.spine03Ctrl.xfo.tr data['spine04Position'] = self.spine04Ctrl.xfo.tr data['numDeformers'] = self.numDeformersAttr.getValue() return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(SpineComponentGuide, self).loadData(data) self.cog.xfo.tr = data["cogPosition"] self.spine01Ctrl.xfo.tr = data["spine01Position"] self.spine02Ctrl.xfo.tr = data["spine02Position"] self.spine03Ctrl.xfo.tr = data["spine03Position"] self.spine04Ctrl.xfo.tr = data["spine04Position"] self.numDeformersAttr.setValue(data["numDeformers"]) return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig. Return: The JSON rig data object. """ data = super(SpineComponentGuide, self).getRigBuildData() data['cogPosition'] = self.cog.xfo.tr data['spine01Position'] = self.spine01Ctrl.xfo.tr data['spine02Position'] = self.spine02Ctrl.xfo.tr data['spine03Position'] = self.spine03Ctrl.xfo.tr data['spine04Position'] = self.spine04Ctrl.xfo.tr data['numDeformers'] = self.numDeformersAttr.getValue() return data # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return SpineComponentRig
def __init__(self, name='spine', parent=None): Profiler.getInstance().push("Construct Fabrice Spine Guide Component:" + name) super(FabriceSpineGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.numDeformersAttr.setValueChangeCallback(self.updateNumDeformers) # Guide Controls self.cogCtrl = Control('cog', parent=self.ctrlCmpGrp, shape="circle") self.cogCtrl.rotatePoints(90, 0, 0) self.cogCtrl.scalePoints(Vec3(3.0, 3.0, 3.0)) self.cogCtrl.setColor('red') self.spineBaseCtrl = Control('spineBase', parent=self.ctrlCmpGrp, shape='pin') self.spineBaseCtrl.rotatePoints(90, 0, 0) self.spineBaseCtrl.translatePoints(Vec3(0, 1.0, 0)) self.spineBaseHandleCtrl = Control('spineBaseHandle', parent=self.ctrlCmpGrp, shape='pin') self.spineBaseHandleCtrl.rotatePoints(90, 0, 0) self.spineBaseHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.spineEndHandleCtrl = Control('spineEndHandle', parent=self.ctrlCmpGrp, shape='pin') self.spineEndHandleCtrl.rotatePoints(90, 0, 0) self.spineEndHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.spineEndCtrl = Control('spineEnd', parent=self.ctrlCmpGrp, shape='pin') self.spineEndCtrl.rotatePoints(90, 0, 0) self.spineEndCtrl.translatePoints(Vec3(0, 1.0, 0)) # =============== # Add Splice Ops # =============== # Add Spine Splice Op self.bezierSpineSpliceOp = SpliceOperator('spineGuideSpliceOp', 'BezierSpineSolver', 'Kraken', alwaysEval=True) self.addOperator(self.bezierSpineSpliceOp) # Add Att Inputs self.bezierSpineSpliceOp.setInput('drawDebug', self.drawDebugInputAttr) self.bezierSpineSpliceOp.setInput('rigScale', self.rigScaleInputAttr) self.bezierSpineSpliceOp.setInput('length', self.lengthInputAttr) # Add Xfo Inputs self.bezierSpineSpliceOp.setInput('base', self.spineBaseCtrl) self.bezierSpineSpliceOp.setInput('baseHandle', self.spineBaseHandleCtrl) self.bezierSpineSpliceOp.setInput('tipHandle', self.spineEndHandleCtrl) self.bezierSpineSpliceOp.setInput('tip', self.spineEndCtrl) # Add Xfo Outputs self.bezierSpineSpliceOp.setOutput('outputs', self.spineVertebraeOutput.getTarget()) self.loadData({ 'name': name, 'location': 'M', 'cogPos': Vec3(0.0, 1.65, 0.75), 'cogCtrlCrvData': self.cogCtrl.getCurveData(), 'spineBasePos': Vec3(0.0, 1.65, 0.75), 'spineBaseCtrlCrvData': self.spineBaseCtrl.getCurveData(), 'spineBaseHandlePos': Vec3(0.0, 1.6, -0.7), 'spineBaseHandleCtrlCrvData': self.spineBaseHandleCtrl.getCurveData(), 'spineEndHandlePos': Vec3(0.0, 1.15, -2.0), 'spineEndHandleCtrlCrvData': self.spineEndHandleCtrl.getCurveData(), 'spineEndPos': Vec3(0.0, 0.65, -3.1), 'spineEndCtrlCrvData': self.spineEndCtrl.getCurveData(), 'numDeformers': 6 }) Profiler.getInstance().pop()
def __init__(self, name='MultiSpring', parent=None): Profiler.getInstance().push("Construct Multi Spring Rig Component:" + name) super(MultiSpringComponentRig, self).__init__(name, parent) # ========= # Controls # ========= # Spring Ctrls self.mainSpringCtrl = Control('springSettings', parent=self.ctrlCmpGrp, shape='pin') self.springCtrlSpaces = [] self.springCtrls = [] self.setNumControls(1) # Add Component Params to FK control springSettingsAttrGrp = AttributeGroup("DisplayInfo_SpringSettings", parent=self.mainSpringCtrl) self.springDrawDebugInputAttr = BoolAttribute( 'drawDebug', value=False, parent=springSettingsAttrGrp) self.springtargetOffsetXInputAttr = ScalarAttribute( 'targetOffset_X', value=3.0, minValue=0.0, maxValue=10.0, parent=springSettingsAttrGrp) self.springtargetOffsetYInputAttr = ScalarAttribute( 'targetOffset_Y', value=0.0, minValue=0.0, maxValue=10.0, parent=springSettingsAttrGrp) self.springtargetOffsetZInputAttr = ScalarAttribute( 'targetOffset_Z', value=0.0, minValue=0.0, maxValue=10.0, parent=springSettingsAttrGrp) self.springFrameInputAttr = IntegerAttribute( 'frame', value=1, parent=springSettingsAttrGrp) self.springResetFrameInputAttr = IntegerAttribute( 'reset_frame', value=1, parent=springSettingsAttrGrp) self.springMassInputAttr = ScalarAttribute( 'mass', value=0.5, minValue=0.0, maxValue=20.0, parent=springSettingsAttrGrp) self.springSpringStrengthInputAttr = ScalarAttribute( 'springStrength', value=6.0, minValue=0.0, maxValue=20.0, parent=springSettingsAttrGrp) self.springDampingInputAttr = ScalarAttribute( 'damping', value=0.125, minValue=0.0, maxValue=5.0, parent=springSettingsAttrGrp) # Connect IO to controls self.drawDebugInputAttr.connect(self.springDrawDebugInputAttr) # ========== # Deformers # ========== deformersLayer = self.getOrCreateLayer('deformers') self.defCmpGrp = ComponentGroup(self.getName(), self, parent=deformersLayer) self.addItem('defCmpGrp', self.defCmpGrp) 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.springCtrlSpaces[0].getName(), 'To', self.rootInputTgt.getName() ])) self.rootInputConstraint.setMaintainOffset(True) self.rootInputConstraint.addConstrainer(self.rootInputTgt) self.springCtrlSpaces[0].addConstraint(self.rootInputConstraint) # =============== # Add Splice Ops # =============== # Add Solver Canvas Op self.springOp = CanvasOperator('springSolverOp', 'Kraken.Solvers.SpringOffsetSolver') self.addOperator(self.springOp) # Add Att Inputs self.springOp.setInput('drawDebug', self.drawDebugInputAttr) self.springOp.setInput('rigScale', self.rigScaleInputAttr) self.springOp.setInput('targetOffset_X', self.springtargetOffsetXInputAttr) self.springOp.setInput('targetOffset_Y', self.springtargetOffsetYInputAttr) self.springOp.setInput('targetOffset_Z', self.springtargetOffsetZInputAttr) self.springOp.setInput('frame', self.springFrameInputAttr) self.springOp.setInput('reset_frame', self.springResetFrameInputAttr) self.springOp.setInput('mass', self.springMassInputAttr) self.springOp.setInput('spring_strength', self.springSpringStrengthInputAttr) self.springOp.setInput('damping', self.springDampingInputAttr) # Add Xfo Inputs self.springOp.setInput('inputs', self.springCtrls) # Add Xfo Outputs self.springOp.setOutput('outputs', self.boneOutputsTgt) # Add Deformer Splice Op self.deformersToOutputsKLOp = KLOperator('springDeformerKLOp', 'MultiPoseConstraintSolver', 'Kraken') self.addOperator(self.deformersToOutputsKLOp) # Add Att Inputs self.deformersToOutputsKLOp.setInput('drawDebug', False) 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()
class HandComponentGuide(HandComponent): """Hand Component Guide""" def __init__(self, name='hand', parent=None, *args, **kwargs): Profiler.getInstance().push("Construct Hand Guide Component:" + name) super(HandComponentGuide, self).__init__(name, parent, *args, **kwargs) # ========= # Controls # ========= # Guide Controls self.guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.digitNamesAttr = StringAttribute('digitNames', value="thumb,index,middle,ring,pinky", parent=self.guideSettingsAttrGrp) self.digitNamesAttr.setValueChangeCallback(self.updateFingers) self.numJointsAttr = IntegerAttribute('numJoints', value=4, minValue=2, maxValue=20, parent=self.guideSettingsAttrGrp) self.numJointsAttr.setValueChangeCallback(self.resizeDigits) self.fingers = OrderedDict() self.handCtrl = Control('hand', parent=self.ctrlCmpGrp, shape="square") self.handCtrl.rotatePoints(0.0, 0.0, 90.0) self.handCtrl.scalePoints(Vec3(1.0, 0.75, 1.0)) self.handCtrl.setColor('yellow') self.handGuideSettingsAttrGrp = AttributeGroup("Settings", parent=self.handCtrl) self.ctrlShapeToggle = BoolAttribute('ctrlShape_vis', value=False, parent=self.handGuideSettingsAttrGrp) self.handDebugInputAttr = BoolAttribute('drawDebug', value=False, parent=self.handGuideSettingsAttrGrp) self.drawDebugInputAttr.connect(self.handDebugInputAttr) self.guideCtrlHrcGrp = HierarchyGroup('controlShapes', parent=self.ctrlCmpGrp) self.default_data = { "name": name, "location": "L", "handXfo": Xfo(Vec3(7.1886, 12.2819, 0.4906)), "digitNames": self.digitNamesAttr.getValue(), "numJoints": self.numJointsAttr.getValue(), "fingers": self.fingers } self.loadData(self.default_data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(HandComponentGuide, self).saveData() data['handXfo'] = self.handCtrl.xfo data['digitNames'] = self.digitNamesAttr.getValue() data['numJoints'] = self.numJointsAttr.getValue() fingerXfos = {} fingerShapeCtrlData = {} for finger in self.fingers.keys(): fingerXfos[finger] = [x.xfo for x in self.fingers[finger]] fingerShapeCtrlData[finger] = [] for i, digit in enumerate(self.fingers[finger]): if i != len(self.fingers[finger]) - 1: fingerShapeCtrlData[finger].append(digit.shapeCtrl.getCurveData()) data['fingersGuideXfos'] = fingerXfos data['fingerShapeCtrlData'] = fingerShapeCtrlData return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(HandComponentGuide, self).loadData(data) self.handCtrl.xfo = data.get('handXfo') self.numJointsAttr.setValue(data.get('numJoints')) self.digitNamesAttr.setValue(data.get('digitNames')) fingersGuideXfos = data.get('fingersGuideXfos') fingerShapeCtrlData = data.get('fingerShapeCtrlData') if fingersGuideXfos is not None: for finger in self.fingers.keys(): for i in xrange(len(self.fingers[finger])): self.fingers[finger][i].xfo = fingersGuideXfos[finger][i] if hasattr(self.fingers[finger][i], 'shapeCtrl'): if fingerShapeCtrlData is not None: if finger in fingerShapeCtrlData: self.fingers[finger][i].shapeCtrl.setCurveData(fingerShapeCtrlData[finger][i]) for op in self.getOperators(): guideOpName = ''.join([op.getName().split('FingerGuideOp')[0], self.getLocation(), 'FingerGuideOp']) op.setName(guideOpName) return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig.. Return: The JSON rig data object. """ data = super(HandComponentGuide, self).getRigBuildData() data['handXfo'] = self.handCtrl.xfo fingerData = {} for finger in self.fingers.keys(): fingerData[finger] = [] for i, joint in enumerate(self.fingers[finger]): if i == len(self.fingers[finger]) - 1: continue # Calculate Xfo boneVec = self.fingers[finger][i + 1].xfo.tr - self.fingers[finger][i].xfo.tr bone1Normal = self.fingers[finger][i].xfo.ori.getZaxis().cross(boneVec).unit() bone1ZAxis = boneVec.cross(bone1Normal).unit() jointXfo = Xfo() jointXfo.setFromVectors(boneVec.unit(), bone1Normal, bone1ZAxis, self.fingers[finger][i].xfo.tr) jointData = { 'curveData': self.fingers[finger][i].shapeCtrl.getCurveData(), 'length': self.fingers[finger][i].xfo.tr.distanceTo(self.fingers[finger][i + 1].xfo.tr), 'xfo': jointXfo } fingerData[finger].append(jointData) data['fingerData'] = fingerData return data # ========== # Callbacks # ========== def addFinger(self, name): digitSizeAttributes = [] fingerGuideCtrls = [] firstDigitCtrl = Control(name + "01", parent=self.handCtrl, shape='sphere') firstDigitCtrl.scalePoints(Vec3(0.125, 0.125, 0.125)) firstDigitShapeCtrl = Control(name + "Shp01", parent=self.guideCtrlHrcGrp, shape='square') firstDigitShapeCtrl.setColor('yellow') firstDigitShapeCtrl.scalePoints(Vec3(0.175, 0.175, 0.175)) firstDigitShapeCtrl.translatePoints(Vec3(0.0, 0.125, 0.0)) fingerGuideCtrls.append(firstDigitShapeCtrl) firstDigitCtrl.shapeCtrl = firstDigitShapeCtrl firstDigitVisAttr = firstDigitShapeCtrl.getVisibilityAttr() firstDigitVisAttr.connect(self.ctrlShapeToggle) triangleCtrl = Control('tempCtrl', parent=None, shape='triangle') triangleCtrl.rotatePoints(90.0, 0.0, 0.0) triangleCtrl.scalePoints(Vec3(0.025, 0.025, 0.025)) triangleCtrl.translatePoints(Vec3(0.0, 0.0875, 0.0)) firstDigitCtrl.appendCurveData(triangleCtrl.getCurveData()) firstDigitCtrl.lockScale(True, True, True) digitSettingsAttrGrp = AttributeGroup("DigitSettings", parent=firstDigitCtrl) digitSizeAttr = ScalarAttribute('size', value=0.25, parent=digitSettingsAttrGrp) digitSizeAttributes.append(digitSizeAttr) # Set Finger self.fingers[name] = [] self.fingers[name].append(firstDigitCtrl) parent = firstDigitCtrl numJoints = self.numJointsAttr.getValue() if name == "thumb": numJoints = 3 for i in xrange(2, numJoints + 2): digitCtrl = Control(name + str(i).zfill(2), parent=parent, shape='sphere') if i != numJoints + 1: digitCtrl.scalePoints(Vec3(0.125, 0.125, 0.125)) digitCtrl.appendCurveData(triangleCtrl.getCurveData()) digitShapeCtrl = Control(name + 'Shp' + str(i).zfill(2), parent=self.guideCtrlHrcGrp, shape='circle') digitShapeCtrl.setColor('yellow') digitShapeCtrl.scalePoints(Vec3(0.175, 0.175, 0.175)) digitShapeCtrl.getVisibilityAttr().connect(self.ctrlShapeToggle) digitCtrl.shapeCtrl = digitShapeCtrl if i == 2: digitShapeCtrl.translatePoints(Vec3(0.0, 0.125, 0.0)) else: digitShapeCtrl.rotatePoints(0.0, 0.0, 90.0) fingerGuideCtrls.append(digitShapeCtrl) # Add size attr to all but last guide control digitSettingsAttrGrp = AttributeGroup("DigitSettings", parent=digitCtrl) digitSizeAttr = ScalarAttribute('size', value=0.25, parent=digitSettingsAttrGrp) digitSizeAttributes.append(digitSizeAttr) else: digitCtrl.scalePoints(Vec3(0.0875, 0.0875, 0.0875)) digitCtrl.lockScale(True, True, True) self.fingers[name].append(digitCtrl) parent = digitCtrl # =========================== # Create Canvas Operators # =========================== # Add Finger Guide Canvas Op fingerGuideCanvasOp = CanvasOperator(name + 'FingerGuideOp', 'Kraken.Solvers.Biped.BipedFingerGuideSolver') self.addOperator(fingerGuideCanvasOp) # Add Att Inputs fingerGuideCanvasOp.setInput('drawDebug', self.drawDebugInputAttr) fingerGuideCanvasOp.setInput('rigScale', self.rigScaleInputAttr) # Add Xfo Inputs fingerGuideCanvasOp.setInput('controls', self.fingers[name]) fingerGuideCanvasOp.setInput('planeSizes', digitSizeAttributes) # Add Xfo Outputs fingerGuideCanvasOp.setOutput('result', fingerGuideCtrls) fingerGuideCanvasOp.setOutput('forceEval', firstDigitCtrl.getVisibilityAttr()) return firstDigitCtrl def removeFinger(self, name): self.handCtrl.removeChild(self.fingers[name][0]) del self.fingers[name] def placeFingers(self): spacing = 0.25 length = spacing * (len(self.fingers.keys()) - 1) mid = length / 2.0 startOffset = length - mid for i, finger in enumerate(self.fingers.keys()): parentCtrl = self.handCtrl numJoints = self.numJointsAttr.getValue() if finger == "thumb": numJoints = 3 for y in xrange(numJoints + 1): if y == 1: xOffset = 0.375 else: xOffset = 0.25 if y == 0: offsetVec = Vec3(xOffset, 0, startOffset - (i * spacing)) else: offsetVec = Vec3(xOffset, 0, 0) fingerPos = parentCtrl.xfo.transformVector(offsetVec) fingerXfo = Xfo(tr=fingerPos, ori=self.handCtrl.xfo.ori) self.fingers[finger][y].xfo = fingerXfo parentCtrl = self.fingers[finger][y] def updateFingers(self, fingers): if " " in fingers: self.digitNamesAttr.setValue(fingers.replace(" ", "")) return fingerNames = fingers.split(',') # Delete fingers that don't exist any more for finger in list(set(self.fingers.keys()) - set(fingerNames)): self.removeFinger(finger) # Add Fingers for finger in fingerNames: if finger in self.fingers.keys(): continue self.addFinger(finger) self.placeFingers() def resizeDigits(self, numJoints): initNumJoints = numJoints for finger in self.fingers.keys(): if finger == "thumb": numJoints = 3 else: numJoints = initNumJoints if numJoints + 1 == len(self.fingers[finger]): continue elif numJoints + 1 > len(self.fingers[finger]): for i in xrange(len(self.fingers[finger]), numJoints + 1): prevDigit = self.fingers[finger][i - 1] digitCtrl = Control(finger + str(i + 1).zfill(2), parent=prevDigit, shape='sphere') digitCtrl.setColor('orange') digitCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) digitCtrl.lockScale(True, True, True) self.fingers[finger].append(digitCtrl) elif numJoints + 1 < len(self.fingers[finger]): numExtraCtrls = len(self.fingers[finger]) - (numJoints + 1) for i in xrange(numExtraCtrls): removedJoint = self.fingers[finger].pop() removedJoint.getParent().removeChild(removedJoint) self.placeFingers() # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return HandComponentRig
def __init__(self, name='tail', parent=None): Profiler.getInstance().push("Construct Fabrice Tail Guide Component:" + name) super(FabriceTailGuide, self).__init__(name, parent) # ========= # Controls # ======== guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numDeformersAttr = IntegerAttribute('numDeformers', value=1, minValue=0, maxValue=20, parent=guideSettingsAttrGrp) self.numDeformersAttr.setValueChangeCallback(self.updateNumDeformers) # Guide Controls self.tailBaseCtrl = Control('tailBase', parent=self.ctrlCmpGrp, shape='sphere') self.tailBaseCtrl.scalePoints(Vec3(1.2, 1.2, 1.2)) self.tailBaseCtrl.lockScale(x=True, y=True, z=True) self.tailBaseCtrl.setColor("turqoise") self.tailBaseHandleCtrl = Control('tailBaseHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailBaseHandleCtrl.rotatePoints(90, 0, 0) self.tailBaseHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailBaseHandleCtrl.lockScale(x=True, y=True, z=True) self.tailBaseHandleCtrl.setColor("turqoise") self.tailEndHandleCtrl = Control('tailEndHandle', parent=self.ctrlCmpGrp, shape='pin') self.tailEndHandleCtrl.rotatePoints(90, 0, 0) self.tailEndHandleCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndHandleCtrl.lockScale(x=True, y=True, z=True) self.tailEndHandleCtrl.setColor("turqoise") self.tailEndCtrl = Control('tailEnd', parent=self.ctrlCmpGrp, shape='pin') self.tailEndCtrl.rotatePoints(90, 0, 0) self.tailEndCtrl.translatePoints(Vec3(0, 1.0, 0)) self.tailEndCtrl.lockScale(x=True, y=True, z=True) self.tailEndCtrl.setColor("turqoise") # =============== # Add Splice Ops # =============== # Add Tail Splice Op self.bezierSpineKLOp = KLOperator('spineGuideKLOp', 'BezierSpineSolver', 'Kraken') self.bezierSpineKLOp.setOutput('outputs', self.tailVertebraeOutput.getTarget()) self.addOperator(self.bezierSpineKLOp) # Add Att Inputs self.bezierSpineKLOp.setInput('drawDebug', self.drawDebugInputAttr) self.bezierSpineKLOp.setInput('rigScale', self.rigScaleInputAttr) self.bezierSpineKLOp.setInput('length', self.lengthInputAttr) # Add Xfo Inputs self.bezierSpineKLOp.setInput('base', self.tailBaseCtrl) self.bezierSpineKLOp.setInput('baseHandle', self.tailBaseHandleCtrl) self.bezierSpineKLOp.setInput('tipHandle', self.tailEndHandleCtrl) self.bezierSpineKLOp.setInput('tip', self.tailEndCtrl) self.loadData({ 'name': name, 'location': 'M', 'tailBasePos': Vec3(0.0, 0.65, -3.1), 'tailBaseHandlePos': Vec3(0.0, 0.157, -4.7), 'tailBaseHandleCtrlCrvData': self.tailBaseHandleCtrl.getCurveData(), 'tailEndHandlePos': Vec3(0.0, 0.0625, -6.165), 'tailEndHandleCtrlCrvData': self.tailEndHandleCtrl.getCurveData(), 'tailEndPos': Vec3(0.0, -0.22, -7.42), 'tailEndCtrlCrvData': self.tailEndCtrl.getCurveData(), 'numDeformers': 6 }) Profiler.getInstance().pop()
class FKChainComponentGuide(FKChainComponent): """FKChain Component Guide""" def __init__(self, name='FKChain', parent=None, data=None): Profiler.getInstance().push("Construct FKCHain Guide Component:" + name) super(FKChainComponentGuide, self).__init__(name, parent) # ========= # Controls # ========= guideSettingsAttrGrp = AttributeGroup("GuideSettings", parent=self) self.numJoints = IntegerAttribute('numJoints', value=4, minValue=1, maxValue=20, parent=guideSettingsAttrGrp) self.numJoints.setValueChangeCallback(self.updateNumJointControls) self.jointCtrls = [] if data is None: numJoints = self.numJoints.getValue() jointPositions = self.generateGuidePositions(numJoints) for i in xrange(numJoints + 1): if i == 0: ctrlParent = self.ctrlCmpGrp else: ctrlParent = self.jointCtrls[i - 1] newCtrl = Control('chain' + str(i + 1).zfill(2), parent=ctrlParent, shape="sphere") newCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) self.jointCtrls.append(newCtrl) data = { "location": "L", "jointPositions": jointPositions, "numJoints": self.numJoints.getValue() } self.loadData(data) Profiler.getInstance().pop() # ============= # Data Methods # ============= def saveData(self): """Save the data for the component to be persisted. Return: The JSON data object """ data = super(FKChainComponentGuide, self).saveData() jointPositions = [] for i in xrange(len(self.jointCtrls)): jointPositions.append(self.jointCtrls[i].xfo.tr) data['jointPositions'] = jointPositions return data def loadData(self, data): """Load a saved guide representation from persisted data. Arguments: data -- object, The JSON data object. Return: True if successful. """ super(FKChainComponentGuide, self).loadData(data) for i in xrange(len(data['jointPositions'])): self.jointCtrls[i].xfo.tr = data['jointPositions'][i] return True def getRigBuildData(self): """Returns the Guide data used by the Rig Component to define the layout of the final rig.. Return: The JSON rig data object. """ data = super(FKChainComponentGuide, self).getRigBuildData() numJoints = self.numJoints.getValue() # Calculate Xfos fw = Vec3(0, 0, 1) boneXfos = [] boneLengths = [] for i in xrange(numJoints): boneVec = self.jointCtrls[i + 1].xfo.tr.subtract(self.jointCtrls[i].xfo.tr) boneLengths.append(boneVec.length()) bone1Normal = fw.cross(boneVec).unit() bone1ZAxis = boneVec.cross(bone1Normal).unit() xfo = Xfo() xfo.setFromVectors(boneVec.unit(), bone1Normal, bone1ZAxis, self.jointCtrls[i].xfo.tr) boneXfos.append(xfo) data['boneXfos'] = boneXfos data['endXfo'] = self.jointCtrls[-1].xfo data['boneLengths'] = boneLengths return data # ========== # Callbacks # ========== def updateNumJointControls(self, numJoints): """Load a saved guide representation from persisted data. Arguments: numJoints -- object, The number of joints inthe chain. Return: True if successful. """ if numJoints == 0: raise IndexError("'numJoints' must be > 0") if numJoints + 1 > len(self.jointCtrls): for i in xrange(len(self.jointCtrls), numJoints + 1): if i == 0: ctrlParent = self.ctrlCmpGrp else: ctrlParent = self.jointCtrls[i - 1] newCtrl = Control('chain' + str(i + 1).zfill(2), parent=ctrlParent, shape="sphere") newCtrl.scalePoints(Vec3(0.25, 0.25, 0.25)) # Generate thew new ctrl off the end of the existing one. newCtrl.xfo = self.jointCtrls[i-1].xfo.multiply(Xfo(Vec3(10.0, 0.0, 0.0))) self.jointCtrls.append(newCtrl) elif numJoints + 1 < len(self.jointCtrls): numExtraCtrls = len(self.jointCtrls) - (numJoints + 1) for i in xrange(numExtraCtrls): extraCtrl = self.jointCtrls.pop() extraCtrl.getParent().removeChild(extraCtrl) # Reset the control positions based on new number of joints jointPositions = self.generateGuidePositions(numJoints) for i in xrange(len(self.jointCtrls)): self.jointCtrls[i].xfo.tr = jointPositions[i] return True def generateGuidePositions(self, numJoints): """Generates the positions for the guide controls based on the number of joints. Args: numJoints (int): Number of joints to generate a transform for. Returns: list: Guide control positions. """ guidePositions = [] for i in xrange(numJoints + 1): guidePositions.append(Vec3(0, 0, i)) return guidePositions # ============== # Class Methods # ============== @classmethod def getComponentType(cls): """Enables introspection of the class prior to construction to determine if it is a guide component. Return: The true if this component is a guide component. """ return 'Guide' @classmethod def getRigComponentClass(cls): """Returns the corresponding rig component class for this guide component class Return: The rig component class. """ return FKChainComponentRig