def test_RigCtrl(self): from classRigCtrl import RigCtrl from omtk.libs import libSerialization log.info("test_RigCtrl") foo = RigCtrl() foo.build() pymel.setKeyframe(foo.node) foo.unbuild() network = libSerialization.export_network(foo) pymel.select(network) foo.build()
class Dorito(RigPart): def build(self, _bConstraint=True, *args, **kwargs): # If there's no input, create it if len(self.input) == 0: self.input = [pymel.createNode('transform', name='untitled')] input = next(iter(self.input)) super(Dorito, self).build(_bCreateGrpAnm=True, _bCreateGrpRig=True, *args, **kwargs) self.ctrl = RigCtrl() self.ctrl.build() # Hack: Include the rotatePivot in our matrix calculation ref_matrix = pymel.datatypes.Matrix(1,0,0,0,0,1,0,0,0,0,1,0, *input.rotatePivot.get()) * input.getMatrix(worldSpace=True) self.ctrl.offset.setMatrix(ref_matrix, worldSpace=True) self.ctrl.setParent(self.grp_anm) # Initialize self.mesh self.mesh = None # Try to guess the output geometry, if nothing is found, create a fake one. is_cluster = any((shape for shape in input.getShapes() if isinstance(shape, pymel.nodetypes.ClusterHandle))) if is_cluster: cluster = next((hist for hist in input.listHistory(future=True) if isinstance(hist, pymel.nodetypes.Cluster)), None) if cluster: self.mesh = next(iter(cluster.outputGeometry.outputs()), None) if not self.mesh: self.mesh = create_plane() self.mesh.setParent(self.grp_rig) # djRivet is a noble tool that handle things well on it's own, we don't need to re-implement it path_djrivet = os.path.join('/', os.path.dirname(omtk.__file__), 'deps', 'djRivet.mel') mel.eval('source "{0}"'.format(path_djrivet)) pymel.select(self.ctrl.offset, self.mesh) mel.eval('djRivet') # Create the follicle using djRivet follicles = _reparent_djRivet_follicles(self.grp_rig) for child in self.ctrl.offset.getChildren(): if isinstance(child, pymel.nodetypes.Constraint): pymel.delete(child) # Hack: Hide follicle follicle = next(iter(follicles)) follicle.setParent(self.grp_rig) # Create an initial pose reference since the follicle won't necessary have the same transform as the reference obj. ref = pymel.createNode('transform') ref.setMatrix(ref_matrix, worldSpace=True) ref.setParent(follicle) # Overwrite the self.ctrl.offset node with the magic # Compute the follicle minus the inverse of the ctrl # Since a matrix is computed scale first, rotate second and translate last, we need to inverse # it using translate first and rotation last (we don't care about conter-rigging the scale). att_ctrl_pos_inv = libRigging.CreateUtilityNode( 'multiplyDivide', operation=2, input1=self.ctrl.node.t, input2=[-1,-1,-1] ).output att_pos_inv = libRigging.CreateUtilityNode( 'composeMatrix', inputTranslate = att_ctrl_pos_inv ).outputMatrix att_ctrl_rot_inv = libRigging.CreateUtilityNode( 'multiplyDivide', operation=2, input1=self.ctrl.node.r, input2=[-1,-1,-1] ).output att_rot_inv = libRigging.CreateUtilityNode( 'composeMatrix', inputRotate = att_ctrl_rot_inv ).outputMatrix uMatrixSum = libRigging.CreateUtilityNode( 'multMatrix', matrixIn=[ att_pos_inv, att_rot_inv, ref.worldMatrix ] ).matrixSum uResult = libRigging.CreateUtilityNode( 'decomposeMatrix', inputMatrix=uMatrixSum, ) pymel.connectAttr(uResult.outputTranslate, self.ctrl.offset.t) pymel.connectAttr(uResult.outputRotate, self.ctrl.offset.r) # Connect the ctrl local coords to the deformer handle pymel.connectAttr(self.ctrl.t, input.t, force=True) pymel.connectAttr(self.ctrl.r, input.r, force=True) pymel.connectAttr(self.ctrl.s, input.s, force=True) pymel.select(self.ctrl) def unbuild(self, *args, **kwargs): super(Dorito, self).unbuild(*args, **kwargs) self.ctrl = None