def assignBindAttributes(joints=None): """ Assigns the bind matrix attribute to the given joints. Args: joints (list): Joints to assign bind matrix attribute to. If None given, will use selected or all joints. """ joints = myu.validateSelect(joints, find='joint') for joint in joints: if not joint.hasAttr(pcfg.length_attribute): joint.addAttr(pcfg.length_attribute, s=True, w=True, r=True, dv=0.001, min=0.001) joint_parent = joint.getParent() if joint_parent and isinstance(joint_parent, pm.nodetypes.Joint): distance_name = joint.name() + '_to_' + joint_parent.name( ) + pcfg.distance_suffix if pm.objExists(distance_name): pm.delete(distance_name) distance = pm.createNode('distanceBetween', n=distance_name) joint.worldMatrix >> distance.inMatrix1 joint_parent.worldMatrix >> distance.inMatrix2 distance.distance >> joint.attr(pcfg.length_attribute) pm.displayInfo('Finished assigning Piper joint attributes to ' + str(len(joints)) + ' joints.')
def parent(transforms, world=False): """ Parents transforms to the last given transform and gets rid of joint orient values if transform is a joint. Args: transforms (list or pm.nodetypes.DependNode): Transforms to parent. Last transform is the parent of the rest. Minimum of two objects. world (boolean): If True, will parent all the given transforms to world """ transforms = myu.validateSelect(transforms, minimum=1) if world: for transform in transforms: if isinstance(transform, pm.nodetypes.Joint): matrix = transform.worldMatrix.get() pm.parent(transform, w=True) transform.jointOrient.set(0, 0, 0) pm.xform(transform, ws=True, m=matrix) else: pm.parent(transform, w=True) else: for transform in transforms[:-1]: if isinstance(transform, pm.nodetypes.Joint): matrix = transform.worldMatrix.get() pm.parent(transform, transforms[-1]) transform.jointOrient.set(0, 0, 0) pm.xform(transform, ws=True, m=matrix) else: pm.parent(transform, transforms[-1])
def assignLabels(joints=None): """ Assigns labels and sides to the given joints based on their names. Args: joints (list): Joints to assign labels to. """ joints = myu.validateSelect(joints, find='joint') for joint in joints: joint_name = joint.nodeName() if joint_name.endswith(pcfg.left_suffix): joint.side.set(1) joint_name = pcu.removeSuffixes(joint_name, pcfg.left_suffix) elif joint_name.endswith(pcfg.right_suffix): joint.side.set(2) joint_name = pcu.removeSuffixes(joint_name, pcfg.right_suffix) # have to do string "type" because type is a built-in python function if joint_name in convert.JOINT_LABELS: label = convert.jointNameToLabel(joint_name) joint.attr('type').set(label) else: label = convert.jointNameToLabel('other') joint.attr('type').set(label) joint.otherType.set(joint_name)
def unbind(self, meshes=None, bind_pose=True): """ Unbinds the skin clusters from the given meshes (will use selection or all meshes in scene if None). Stores skin cluster weights in a temp file to be rebound with the rebind method. Args: meshes (list): Meshes to unbind. bind_pose (boolean): If True will move joints back to the bind pose before unbinding. Returns: (dictionary): All the info gathered from unbinding joints. """ # reset info self.info = {} scene_path = pm.sceneName() scene_name = os.path.splitext( scene_path.name)[0] + '_' if scene_path else '' meshes = myu.validateSelect(meshes, find='mesh', parent=True) pcu.validateDirectory(self.directory) for mesh in meshes: # get the skin of the mesh, if it doesnt exist then we don't need to store skin weights mesh_name = mesh.nodeName() skin = mesh.listHistory(type='skinCluster') if not skin: continue # get the info we need to rebind the mesh: skin name, max influences, and joints influencing mesh # stored as string in case object gets deleted and renamed after unbinding skin = skin[0].nodeName() max_influences = pm.skinCluster(mesh, q=True, mi=True) joints = [ joint.nodeName() for joint in pm.skinCluster(skin, q=True, influence=True) ] if bind_pose: returnToBindPose(joints) # select mesh, export skin weights, and detach skin using MEL because pm.bindSkin(delete=True) has errors. pm.select(mesh) deformer_name = scene_name + mesh_name + '.xml' path = pm.deformerWeights(deformer_name, export=True, deformer=skin, path=self.directory) pm.mel.eval('doDetachSkin "2" { "1","1" }') self.info[mesh_name] = { 'skin': skin, 'max_influences': max_influences, 'joints': joints, 'path': path } pm.select(meshes) return self.info
def createAtPivot(selected=None): """ Creates a joint at the current manipulator pivot point. """ joints = [] shift_held = myu.isShiftHeld() ctrl_held = myu.isCtrlHeld() alt_held = myu.isAltHeld() selected = myu.validateSelect(selected, minimum=1) if shift_held: for transform in selected: name = transform.nodeName() if alt_held else '' if isinstance(transform, pm.nodetypes.Transform): joint, position, _ = _createAtPivot(transform, name, joints=joints) xform.orientToTransform(transform, joint, ctrl_held) elif isinstance(transform, pm.general.MeshVertex): for i in transform.indices(): joint, position, vertex = _createAtPivot( transform, name, i, 'vtx', joints) xform.orientToVertex(joint, vertex, position, ctrl_held) elif isinstance(transform, pm.general.MeshEdge): for i in transform.indices(): joint, position, edge = _createAtPivot( transform, name, i, 'e', joints) xform.orientToEdge(joint, edge, position, ctrl_held) elif isinstance(transform, pm.general.MeshFace): for i in transform.indices(): joint, position, face = _createAtPivot( transform, name, i, 'f', joints) xform.orientToFace(joint, face, position, ctrl_held) else: transform = selected[-1] name = transform.nodeName() if alt_held else '' joint, position, _ = _createAtPivot(transform, name, joints=joints) if len(selected) == 1 and ctrl_held: if isinstance(transform, pm.nodetypes.Transform): xform.orientToTransform(transform, joint) elif isinstance(transform, pm.general.MeshVertex): xform.orientToVertex(joint, transform, position) elif isinstance(transform, pm.general.MeshEdge): xform.orientToEdge(joint, transform, position) elif isinstance(transform, pm.general.MeshFace): xform.orientToFace(joint, transform, position) return joints
def mirrorTranslate(transforms=None, axis=pcfg.default_mirror_axis, swap=None, duplicate=True): """ Mirrors the given transforms across the given axis set up to be used as a mirror translate transform. Args: transforms (list): Transforms to mirror across given axis. axis (string): Name of axis to mirror across. swap (list): Text to swap with each other for duplicates name. duplicate (boolean): If True will duplicate transforms before mirroring. Else will mirror the given transforms. Returns: (list): Transforms mirrored. """ transforms = myu.validateSelect(transforms) axis_vector = convert.axisToVector(axis, absolute=True) mirrored_axis = [value * -1 for value in axis_vector] mirrored_axis.append(1) to_mirror = [] if swap is None: swap = [pcfg.left_suffix, pcfg.right_suffix] if duplicate: for transform in transforms: name = transform.nodeName() new_name = pcu.swapText(name, *swap) new_transform = pm.duplicate(transform, ic=False, un=False, n=new_name)[0] to_mirror.append(new_transform) else: to_mirror = transforms for transform in to_mirror: matrix = transform.worldMatrix.get() identity = [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] mirrored_matrix = [ m * a if m != 0 and a != 0 else m for row in identity for m, a in zip(row, mirrored_axis) ] mirrored_matrix = matrix * pm.dt.Matrix(mirrored_matrix) pm.xform(transform, ws=True, m=mirrored_matrix) [ transform.attr('s' + axis).set( abs(transform.attr('s' + axis).get())) for axis in ['x', 'y', 'z'] ] return to_mirror
def mirrorRotate(transforms=None, axis=pcfg.default_mirror_axis, swap=None): """ Mirrors the given transforms across the given axis set up to be used as a mirror rotate transform. Args: transforms (list): Transforms to mirror across given axis. axis (string): Name of axis to mirror across. swap (list): Words to search and replace. Will search for first index, and replace with second index. Returns: (list): Joints that were mirrored. Note that all their children get mirrored as well. """ mirrored_transforms = [] transforms = myu.validateSelect(transforms) options = { 'mxy': False, 'myz': False, 'mxz': False, 'mb': True, 'sr': swap } if axis == 'x': options['myz'] = True elif axis == 'y': options['mxz'] = True elif axis == 'z': options['mxy'] = True else: pm.error('No valid axis given. Pick "x", "y", or "z".') for transform in transforms: name = transform.nodeName() if not swap: if name.endswith(pcfg.left_suffix): options['sr'] = [pcfg.left_suffix, pcfg.right_suffix] elif name.endswith(pcfg.right_suffix): options['sr'] = [pcfg.right_suffix, pcfg.left_suffix] else: options['sr'] = ['', ''] mirrored_joint = pm.mirrorJoint(transform, **options)[0] mirrored_joint = pm.PyNode(mirrored_joint) mirrored_transforms.append(mirrored_joint) joint_parent = mirrored_joint.getParent() if joint_parent: pm.parent(mirrored_joint, w=True) parent([mirrored_joint, joint_parent]) return mirrored_transforms
def createTensionDisplay(transforms=None, shape_display=pm.warning, skin_display=pm.warning): """ Creates tension nodes and hooks them up to mesh by intercepting the skin cluster. Args: transforms (list): Transforms with mesh shapes that will get tension nodes hooked up. shape_display (method): Error to display if there are not two shapes. skin_display (method): Error to display if no skin clusters found. Returns: (list): Tension nodes created. """ tension_nodes = [] transforms = myu.validateSelect(transforms, find='mesh', parent=True) for transform in transforms: original_shape = None deformed_shape = None skin_cluster = None shapes = transform.getShapes() if len(shapes) != 2: shape_display( 'Need two shapes! A deformed shape and an original one.') continue # get skin cluster and figure out which shape is the original and which is the deformed for i, shape in enumerate(shapes): skin_cluster = shape.listHistory(type='skinCluster') if skin_cluster: skin_cluster = skin_cluster[0] deformed_shape = shape original_shape = shapes[0] if i == 1 else shapes[1] break if not skin_cluster: skin_display('No skin cluster found.') continue # create tension node and hook it up with necessary data tension = pm.createNode('tensionNode', name=transform.nodeName() + '_tension') skin_cluster.outputGeometry[0] >> tension.deformedShape original_shape.worldMesh >> tension.origShape deformed_shape.inMesh.disconnect() tension.out >> deformed_shape.inMesh tension_nodes.append(tension) return tension_nodes
def addDelete(transforms=None): """ Adds a "delete" attribute to the given transforms that marks them to be delete on export. Args: transforms (list): List of pm.nodetypes.transform to add "delete" attribute to. """ transforms = myu.validateSelect(transforms, display=pm.warning) for transform in transforms: addSeparator(transform) transform.addAttr(pcfg.delete_node_attribute, at='bool', k=True, dv=1, max=1, min=1) nonKeyable(transform.delete)
def returnToBindPose(joints=None): """ Returns the associated bindPoses of the given joints to the pose when they were originally bound. Args: joints (list): Joints to find bind poses of. Note, these are NOT necessarily all the joints that will be restored since joints can share bindPose nodes. Returns: (set): Bind poses restored. """ # Get joints, find all the bind poses all the joints are using, restore the bind poses for each pose found. joints = myu.validateSelect(joints, find='joint') poses = { pose for joint in joints for pose in pm.dagPose(joint, bp=True, q=True) } [pm.dagPose(pose, g=True, restore=True) for pose in poses] return poses
def assignBindAttributes(joints=None): """ Assigns the bind matrix attribute to the given joints. Args: joints (list): Joints to assign bind matrix attribute to. If None given, will use selected or all joints. """ joints = myu.validateSelect(joints, find='joint') for joint in joints: if not joint.hasAttr(pcfg.length_attribute): joint.addAttr(pcfg.length_attribute, s=True, w=True, r=True, dv=0.001, min=0.001) joint_parent = joint.getParent() if joint_parent and isinstance(joint_parent, pm.nodetypes.Joint): length = pipermath.getDistance(joint_parent, joint) joint.bindLength.set(length) pm.displayInfo('Finished assigning Piper joint attributes to ' + str(len(joints)) + ' joints.')