def transfer_uvs_to_skinned_geometry(source_mesh=None, target_mesh=None, use_intermediate_shape=False, **kwargs): out_dict = {'success': False, 'result': None} selection = dcc.selected_nodes_of_type('transform') source_transform = source_mesh or ( selection[0] if python.index_exists_in_list(selection, 0) else None) target_transform = target_mesh or ( selection[1] if python.index_exists_in_list(selection, 1) else None) if not source_transform or not target_transform: out_dict[ 'msg'] = 'Select source mesh and target mesh before executing Transfers UVs to skinned geometry.' return out_dict try: result = skin_utils.transfer_uvs_to_skinned_geometry( source_mesh=source_mesh, target_mesh=target_mesh, use_intermediate_shape=use_intermediate_shape, **kwargs) out_dict['result'] = result except Exception as exc: out_dict[ 'msg'] = 'Was not possible to transfers UVs to skinned geometry: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def check_joint_labels(joints=None): out_dict = {'success': False, 'result': False} valid_joints = list() joints = joints or dcc.selected_nodes_of_type(node_type='joint') joints = python.force_list(joints) for joint in joints: if not dcc.object_type(joint) == 'joint': continue valid_joints.append(joint) if not valid_joints: out_dict['msg'] = 'No joints to check found.' return out_dict try: result = joint_utils.check_joint_labels(valid_joints) out_dict['result'] = result except Exception as exc: out_dict['msg'] = 'Was not possible to check joints label: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def restore_to_bind_pose(skinned_mesh=None): out_dict = {'success': False, 'result': None} skinned_meshes = skinned_mesh or dcc.selected_nodes_of_type('transform') skinned_meshes = python.force_list(skinned_meshes) if not skinned_meshes: skinned_meshes = list() meshes = dcc.list_nodes(node_type='mesh') for mesh in meshes: skinned_meshes.append( maya.cmds.listRelatives(mesh, parent=True)[0]) if not skinned_meshes: out_dict['msg'] = 'No skinned meshes to restore bind poses of found.' return out_dict try: result = skin_utils.restore_to_bind_pose(skinned_mesh) out_dict['result'] = result except Exception as exc: out_dict[ 'msg'] = 'Was not possible to restore skinned mesh to bind pose: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def unlock_visibility(transforms=None): """ Locks visibility channel of the given transforms nodes """ out_dict = {'success': False, 'result': list()} transforms = python.force_list( transforms or dcc.selected_nodes_of_type(node_type='transform') or list()) if not transforms: out_dict[ 'msg'] = 'No transforms to unlock all scale channels of. Select at least one.' return out_dict percentage = 100.0 / len(transforms) for i, node in enumerate(transforms): library.Command.progressCommand.emit( percentage * (i + 1), 'Unlocking scale channels: {}'.format(node)) try: dcc.unlock_visibility_attribute(node) out_dict['result'].append(node) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to unlock visibility channel in node: "{}" : {}'.format( node, exc) return out_dict out_dict['success'] = True return out_dict
def detach_bind_skin(geo=None, show_options=False): out_dict = {'success': False, 'result': list()} geo_nodes = geo or dcc.selected_nodes_of_type(node_type='transform') geo_nodes = python.force_list(geo_nodes) valid_geo_nodes = list() for geo_node in geo_nodes: if not mesh_utils.is_a_mesh(geo_node): continue valid_geo_nodes.append(geo_node) if not valid_geo_nodes: out_dict['msg'] = 'No meshes to apply rigid bind skin into found.' return out_dict try: result = skin_utils.detach_bind_skin(geo=valid_geo_nodes, show_options=show_options) out_dict['result'].append(result) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to apply smooth bind skin: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def insert_joints(joints=None, num_joints=1): """ Inserts new joints between selected joint and its direct child :param joints: int :param num_joints: int """ out_dict = {'success': False, 'result': None} joints = joints or dcc.selected_nodes_of_type(node_type='joint') joints = python.force_list(joints) if not joints: out_dict['msg'] = 'No joints to insert joints into found.' return out_dict try: result = joint_utils.insert_joints(joints=joints, joint_count=num_joints) out_dict['result'] = result except Exception as exc: out_dict['msg'] = 'Was not possible to insert joints: {}'.format(exc) return out_dict out_dict['success'] = True return out_dict
def create_joints_on_curve(curve=None, num_joints=1): out_dict = {'success': False, 'result': list()} valid_curves = list() curves = curve or dcc.selected_nodes_of_type(node_type='transform') curves = python.force_list(curves) for curve in curves: if not curve_utils.is_a_curve(curve): continue valid_curves.append(curve) if not valid_curves: out_dict['msg'] = 'No curves to create joints on found.' return out_dict try: for curve in valid_curves: new_joint = joint_utils.create_oriented_joints_along_curve( curve, num_joints) out_dict['result'].append(new_joint) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to create joints on curve: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def freeze_transforms(transforms=None): """ Freeze selected transforms """ out_dict = {'success': False, 'result': list()} transforms = python.force_list( transforms or dcc.selected_nodes_of_type(node_type='transform') or list()) if not transforms: out_dict[ 'msg'] = 'No transforms to freeze transforms of. Select at least one.' return out_dict percentage = 100.0 / len(transforms) for i, node in enumerate(transforms): library.Command.progressCommand.emit( percentage * (i + 1), 'Freezing transforms: {}'.format(node)) try: dcc.freeze_transforms(node) out_dict['result'].append(node) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to freeze transforms in node: "{}" : {}'.format( node, exc) return out_dict out_dict['success'] = True return out_dict
def match_rotation(source_transform=None, target_transform=None): """ Matches rotation of the source node to the rotation of the given target node(s) """ out_dict = {'success': False, 'result': list()} selection = dcc.selected_nodes_of_type(node_type='transform') source_transform = source_transform or selection[ 0] if python.index_exists_in_list(selection, 0) else None if not source_transform: out_dict[ 'msg'] = 'No source transform given to match against target rotation.' return out_dict target_transform = target_transform or selection[1:] if len( selection) > 1 else None if not source_transform: out_dict[ 'msg'] = 'No target transform(s) given to match source rotation against.' return out_dict source_transform = python.force_list(source_transform) target_transform = python.force_list(target_transform) percentage = 100.0 / len(source_transform) for i, source in enumerate(source_transform): library.Command.progressCommand.emit( percentage * (i + 1), 'Matching rotation: {}'.format(source)) try: maya.cmds.delete( maya.cmds.orientConstraint(target_transform, source, maintainOffset=False)) # For joints, we store now rotation data in jointOrient attribute if dcc.node_type(source) == 'joint': for axis in 'XYZ': joint_orient_attr = 'jointOrient{}'.format(axis) joint_rotation_attr = 'rotate{}'.format(axis) dcc.set_attribute_value(source, joint_orient_attr, 0.0) joint_rotation = dcc.get_attribute_value( source, joint_rotation_attr) dcc.set_attribute_value(source, joint_orient_attr, joint_rotation) dcc.set_attribute_value(source, joint_rotation_attr, 0.0) out_dict['result'].append(source) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to match node "{}" rotation to "{}" : {}'.format( source_transform, target_transform, exc) return out_dict matched_nodes = out_dict.get('result', None) if matched_nodes: dcc.select_node(matched_nodes) out_dict['success'] = True return out_dict
def separate_meshes(meshes=None, new_mesh_name=None): """ Separates given meshes into one transform """ out_dict = {'success': False, 'result': None} meshes = meshes or dcc.selected_nodes_of_type(node_type='transform') meshes = python.force_list(meshes) if not meshes: out_dict['msg'] = 'No meshes to separate selected.' return out_dict new_mesh_name = new_mesh_name or dcc.node_short_name(meshes[0]) try: result_meshes = list() separated_meshes = dcc.separate_meshes(construction_history=False) if not separated_meshes: out_dict[ 'msg'] = 'Separate operation was done but not separated mesh was generated' return out_dict for separated_mesh in separated_meshes: separated_mesh = dcc.rename_node(separated_mesh, new_mesh_name) result_meshes.append(separated_mesh) out_dict['result'] = result_meshes except Exception as exc: out_dict[ 'msg'] = 'Was not possible to separate meshes "{}" : {}'.format( meshes, exc) return out_dict out_dict['success'] = True return out_dict
def copy_skin_weights(source_mesh=None, target_mesh=None, show_options=False, **kwargs): out_dict = {'success': False, 'result': None} selection = dcc.selected_nodes_of_type('transform') source_transform = source_mesh or ( selection[0] if python.index_exists_in_list(selection, 1) else None) target_transform = target_mesh or ( selection[1] if python.index_exists_in_list(selection, 1) else None) if not source_transform or not target_transform: out_dict[ 'msg'] = 'Select source mesh and target mesh before executing Copy Skin Weights.' return out_dict try: result = skin_utils.copy_skin_weights(source_mesh=source_mesh, target_mesh=target_mesh, show_options=show_options, **kwargs) out_dict['result'] = result except Exception as exc: out_dict['msg'] = 'Was not possible to copy skin weights: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def move_pivot_to_zero(transforms=None): """ Moves selected nodes pivots to zero (0, 0, 0 in the world) """ out_dict = {'success': False, 'result': list()} transforms = python.force_list( transforms or dcc.selected_nodes_of_type(node_type='transform') or list()) if not transforms: out_dict[ 'msg'] = 'No transforms to move pivot to zero of. Select at least one.' return out_dict percentage = 100.0 / len(transforms) for i, node in enumerate(transforms): library.Command.progressCommand.emit( percentage * (i + 1), 'Moving pivot to zero: {}'.format(node)) try: dcc.move_pivot_to_zero(node) out_dict['result'].append(node) except Exception as exc: out_dict[ 'msg'] = 'Was not possible move pivot to zero for node: "{}" : {}'.format( node, exc) return out_dict out_dict['success'] = True return out_dict
def freeze_skinned_mesh(skinned_mesh, **kwargs): out_dict = {'success': False, 'result': list()} meshes = skinned_mesh or dcc.selected_nodes_of_type('transform') meshes = python.force_list(meshes) if not meshes: return False if kwargs.pop('auto_assign_labels', False): joint_utils.auto_assign_labels_to_mesh_influences( meshes, input_left=kwargs.pop('left_side_label', None), input_right=kwargs.pop('right_side_label', None), check_labels=True) percentage = 100.0 / len(meshes) for i, mesh in enumerate(meshes): library.Command.progressCommand.emit( percentage * (i + 1), 'Cleaning Skinned Mesh: {}'.format(mesh)) try: skin_cluster_name = skin_utils.find_related_skin_cluster(mesh) if not skin_cluster_name: continue attached_joints = maya.cmds.skinCluster(skin_cluster_name, query=True, inf=True) mesh_shape_name = maya.cmds.listRelatives(mesh, shapes=True)[0] out_influences_array = api_skin.get_skin_weights( skin_cluster_name, mesh_shape_name) maya.cmds.skinCluster(mesh_shape_name, edit=True, unbind=True) maya.cmds.delete(mesh, ch=True) maya.cmds.makeIdentity(mesh, apply=True) new_skin_cluster_name = maya.cmds.skinCluster( attached_joints, mesh, toSelectedBones=True, bindMethod=0, normalizeWeights=True)[0] api_skin.set_skin_weights(new_skin_cluster_name, mesh_shape_name, out_influences_array) out_dict['result'].append(mesh) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to freeze skinned meshes: "{}" | {}'.format( meshes, exc) return out_dict dcc.select_node(meshes) out_dict['success'] = True return out_dict
def get_valid_joints(joints=None): valid_joints = list() joints = joints or dcc.selected_nodes_of_type(node_type='joint', full_path=False) joints = python.force_list(joints) for joint in joints: if not dcc.object_type(joint) == 'joint': continue valid_joints.append(joint) if not valid_joints: valid_joints = dcc.list_nodes(node_type='joint') return valid_joints
def snap_joints_to_curve(joints=None, curve=None, num_joints=1): out_dict = {'success': False, 'result': dict()} valid_joints = list() joints = joints or dcc.selected_nodes_of_type(node_type='joint') joints = python.force_list(joints) for joint in joints: if not dcc.object_type(joint) == 'joint': continue valid_joints.append(joint) if not valid_joints: out_dict['msg'] = 'No joints to snap to curve found.' return out_dict valid_curves = list() curves = curve or dcc.selected_nodes_of_type(node_type='transform') curves = python.force_list(curves) for curve in curves: if not curve_utils.is_a_curve(curve): continue valid_curves.append(curve) try: for curve in valid_curves: new_joints = curve_utils.snap_joints_to_curve(valid_joints, curve=curve, count=num_joints) out_dict['result'][curve] = new_joints except Exception as exc: out_dict[ 'msg'] = 'Was not possible to snap joints to curve: {}'.format(exc) return out_dict out_dict['success'] = True return out_dict
def match_scale(source_transform=None, target_transform=None): """ Matches scale of the source node to the scale of the given target node(s) """ out_dict = {'success': False, 'result': list()} selection = dcc.selected_nodes_of_type(node_type='transform') source_transform = source_transform or selection[ 0] if python.index_exists_in_list(selection, 0) else None if not source_transform: out_dict[ 'msg'] = 'No source transform given to match against target scale.' return out_dict target_transform = target_transform or selection[1:] if len( selection) > 1 else None if not source_transform: out_dict[ 'msg'] = 'No target transform(s) given to match source scale against.' return out_dict source_transform = python.force_list(source_transform) target_transform = python.force_list(target_transform) percentage = 100.0 / len(source_transform) for i, source in enumerate(source_transform): library.Command.progressCommand.emit( percentage * (i + 1), 'Matching scale: {}'.format(source)) try: maya.cmds.delete( maya.cmds.scaleConstraint(target_transform, source, maintainOffset=False)) out_dict['result'].append(source) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to match node "{}" scale to "{}" : {}'.format( source_transform, target_transform, exc) return out_dict matched_nodes = out_dict.get('result', None) if matched_nodes: dcc.select_node(matched_nodes) out_dict['success'] = True return out_dict
def manual_orient_joints(self, data, reply): orient_type = data.get('orient_type', 'add') x_axis = data.get('x_axis', 0.0) y_axis = data.get('y_axis', 0.0) z_axis = data.get('z_axis', 0.0) affect_children = data.get('affect_children', False) if orient_type == 'add': tweak = 1.0 else: tweak = -1.0 tweak_rot = [x_axis * tweak, y_axis * tweak, z_axis * tweak] joints = dcc.selected_nodes_of_type(node_type='joint') if not joints: return for jnt in joints: dcc.set_node_rotation_axis_in_object_space(jnt, tweak_rot[0], tweak_rot[1], tweak_rot[2]) dcc.zero_scale_joint(jnt) dcc.freeze_transforms(jnt, preserve_pivot_transforms=True) if affect_children: childs = dcc.list_children( jnt, children_type=['transform', 'joint'], full_path=False, all_hierarchy=True) or list() for child in childs: parent = dcc.node_parent(child) dcc.set_parent_to_world(child) dcc.set_node_rotation_axis_in_object_space( child, tweak_rot[0], tweak_rot[1], tweak_rot[2]) dcc.zero_scale_joint(child) dcc.freeze_transforms(child, preserve_pivot_transforms=True) dcc.set_parent(child, parent) dcc.select_node(joints, replace_selection=True) reply['success'] = True
def mirror_mesh(mesh=None): """ Mirror given meshes """ out_dict = {'success': False, 'result': list()} meshes = mesh or dcc.selected_nodes_of_type(node_type='transform') meshes = python.force_list(meshes) if not meshes: out_dict['msg'] = 'No meshes to mirror selected.' return out_dict for mesh in meshes: try: parent_node = dcc.node_parent(mesh) mirror_geo_name = xform_utils.find_transform_right_side( mesh, check_if_exists=False) mirror_geo = maya.cmds.duplicate(mesh, n=mirror_geo_name or None) root = maya.cmds.group(empty=True, world=True) maya.cmds.parent(mirror_geo, root) maya.cmds.setAttr('{}.rx'.format(root), 180) for axis in 'xyz': maya.cmds.setAttr('{}.s{}'.format(root, axis), -1) maya.cmds.parent(mirror_geo, world=True) maya.cmds.delete(root) maya.cmds.makeIdentity(mirror_geo, apply=True, t=False, r=True, s=True, n=False, pn=True) if parent_node: dcc.set_parent(mirror_geo, parent_node) out_dict['result'].append(mirror_geo) except Exception as exc: out_dict[ 'msg'] = 'Was not possible to mirror meshes "{}" : {}'.format( meshes, exc) return out_dict out_dict['success'] = True return out_dict
def reset_joints_orient_to_world(self, data, reply): apply_to_hierarchy = data.get('apply_to_hierarchy', False) if apply_to_hierarchy: dcc.select_hierarchy() joints = dcc.selected_nodes_of_type(node_type='joint', full_path=False) if not joints: reply['msg'] = 'No joints selected' reply['success'] = False return for jnt in reversed(joints): childs = dcc.list_children(jnt, all_hierarchy=False, children_type=['transform', 'joint']) # If the joints has direct childs, unparent that childs and store names if childs: if len(childs) > 0: childs = dcc.set_parent_to_world(childs) # Get parent of this joints for later use parent = dcc.node_parent(jnt, full_path=False) or '' if parent: dcc.set_parent_to_world(jnt) # Clear joint axis dcc.zero_scale_joint(jnt) dcc.freeze_transforms(jnt, preserve_pivot_transforms=True) dcc.zero_orient_joint(jnt) # Reparent if parent: dcc.set_parent(jnt, parent) # Reparent child if childs: if len(childs) > 0: dcc.set_parent(childs, jnt) dcc.select_node(joints, replace_selection=True) reply['success'] = True
def set_rotation_axis(self, data, reply): rotation_axis = data.get('rotation_axis', '') affect_children = data.get('affect_children', False) sel = dcc.selected_nodes_of_type( node_type=['joint', 'transform']) or list() for obj in sel: dcc.set_rotation_axis(obj, rotation_axis) if affect_children: childs = dcc.list_children( obj, children_type=['transform', 'joint'], full_path=True, all_hierarchy=True) or list() for child in childs: dcc.set_rotation_axis(child, rotation_axis) reply['success'] = True
def toggle_selected_local_rotation_axis(flag=None): """ Toggles the visibility of selected joints local rotation axis """ out_dict = {'success': False, 'result': dict()} joints = dcc.selected_nodes_of_type(node_type='joint') if not joints: out_dict['msg'] = 'No joints to toggle LRA of found.' return out_dict dcc.set_joint_local_rotation_axis_visibility(flag=flag, joints_to_apply=joints) out_dict['success'] = True return out_dict
def combine_meshes(meshes=None, new_mesh_name=None): """ Combines given meshes into one transform """ out_dict = {'success': False, 'result': None} meshes = meshes or dcc.selected_nodes_of_type(node_type='transform') meshes = python.force_list(meshes) if not meshes: out_dict['msg'] = 'No meshes to combine selected.' return out_dict if len(meshes) < 2: out_dict['msg'] = 'You need to select at least two meshes to combine.' return out_dict new_mesh_name = new_mesh_name or dcc.node_short_name(meshes[0]) parent_node = None node_parents = list(set([dcc.node_parent(mesh) for mesh in meshes])) if all(parent == node_parents[0] for parent in node_parents): parent_node = node_parents[0] try: combined_mesh = dcc.combine_meshes(construction_history=False) if not combined_mesh: out_dict[ 'msg'] = 'Combine operation was done but not combined mesh was generated' return out_dict combined_mesh = dcc.rename_node(combined_mesh, new_mesh_name) if parent_node: dcc.set_parent(combined_mesh, parent_node) out_dict['result'] = combined_mesh except Exception as exc: out_dict[ 'msg'] = 'Was not possible to combine meshes "{}" : {}'.format( meshes, exc) return out_dict out_dict['success'] = True return out_dict
def set_manual_orient_joints(self, data, reply): x_axis = data.get('x_axis', 0.0) y_axis = data.get('y_axis', 0.0) z_axis = data.get('z_axis', 0.0) affect_children = data.get('affect_children', False) childs = list() tweak_rot = [x_axis, y_axis, z_axis] joints = dcc.selected_nodes_of_type(node_type='joint', full_path=False) if not joints: return for jnt in joints: if not affect_children: childs = dcc.list_children( jnt, children_type=['transform', 'joint'], full_path=False, all_hierarchy=False) or list() for child in childs: dcc.set_parent_to_world(child) # Set the rotation axis for i, axis in enumerate(['x', 'y', 'z']): dcc.set_attribute_value(jnt, 'jointOrient{}'.format(axis.upper()), tweak_rot[i]) # Clear joint axis dcc.zero_scale_joint(jnt) dcc.freeze_transforms(jnt, preserve_pivot_transforms=True) if childs: for child in childs: dcc.set_parent(child, jnt) dcc.select_node(joints, replace_selection=True) reply['success'] = True
def combine_skinned_meshes(meshes=None): out_dict = {'success': False, 'result': None} meshes = meshes or dcc.selected_nodes_of_type('transform') if not meshes: out_dict['msg'] = 'No meshes to combine found.' return out_dict try: result = skin_utils.combine_skinned_meshes(meshes) out_dict['result'] = result except Exception as exc: out_dict[ 'msg'] = 'Was not possible to transfers UVs to skinned geometry: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def select_influencing_joints(mesh_node=None): out_dict = {'success': False, 'result': None} mesh_nodes = mesh_node or dcc.selected_nodes_of_type(node_type='transform') mesh_nodes = python.force_list(mesh_nodes) mesh_node = mesh_nodes[0] if mesh_nodes else None if not mesh_node: out_dict['msg'] = 'No mesh selected to retrieve influences of' return out_dict try: result = skin_utils.select_influencing_joints(mesh_node) out_dict['result'] = result except Exception as exc: out_dict[ 'msg'] = 'Was not possible to select influencing joints: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def toggle_local_rotation_axis(joints=None): """ Toggles the visibility of all (if the user has nothing selected) or all joints local rotation axis """ out_dict = {'success': False, 'result': dict()} valid_joints = list() joints = joints or dcc.selected_nodes_of_type(node_type='joint') joints = python.force_list(joints) for joint in joints: if not dcc.object_type(joint) == 'joint': continue valid_joints.append(joint) if not valid_joints: valid_joints = None dcc.set_joint_local_rotation_axis_visibility(flag=None, joints_to_apply=valid_joints) out_dict['success'] = True return out_dict
def prune_skin_weights(mesh=None, show_options=False, **kwargs): out_dict = {'success': False, 'result': None} transforms = mesh or dcc.selected_nodes_of_type('transform') transforms = python.force_list(transforms) if not transforms: out_dict['msg'] = 'No meshes to prune skin weights of found.' return out_dict try: result = skin_utils.prune_skin_weights(mesh=mesh, show_options=show_options, **kwargs) out_dict['result'] = result except Exception as exc: out_dict['msg'] = 'Was not possible to prune skin weights: {}'.format( exc) return out_dict out_dict['success'] = True return out_dict
def unbind_influences_quick(skinned_objects=None, influences_to_unbind=None, delete=False): """ Unbind given influences from given meshes and stores the unbind influences weights into other influences The weights reassignation is handled by Maya :param skinned_objects: list(str), meshes which joints need to be removed :param influences_to_unbind: list(str), list of joints that need to be unbind :param delete: bool, Whether or not to delete unbind influences after unbind process is completed :return: bool """ selected_transforms = dcc.selected_nodes_of_type('transform') selected_joints = dcc.selected_nodes_of_type('joint') influences_to_unbind = influences_to_unbind or selected_joints if not skinned_objects: skinned_objects = [ xform for xform in selected_transforms if xform not in selected_joints ] if not skinned_objects or not influences_to_unbind: return False skinned_objects = python.force_list(skinned_objects) influences_to_unbind = python.force_list(influences_to_unbind) influences_to_unbind_short = [ dcc.node_short_name(joint_node) for joint_node in influences_to_unbind ] skin_clusters = list() skin_percentage = 100.0 / len(skinned_objects) for i, skin_object in enumerate(skinned_objects): library.Command.progressCommand.emit( skin_percentage * (i + 1), 'Unbinding Influence: {}'.format(i)) skin_cluster_name = skin_utils.find_related_skin_cluster(skin_object) if not skin_cluster_name: continue joints_attached = maya.cmds.skinCluster(skin_cluster_name, query=True, inf=True) influence_verts = skin_utils.get_influence_vertices( influences_to_unbind, skin_object) if not influence_verts: continue joints = list() for joint_to_remove in influences_to_unbind_short: if joint_to_remove not in joints_attached: continue joints.append((joint_to_remove, 0.0)) maya.cmds.select(influence_verts, replace=True) maya.cmds.skinPercent(skin_cluster_name, transformValue=joints, normalize=True) skin_clusters.append(skin_cluster_name) for skin_cluster in skin_clusters: joints_attached = maya.cmds.skinCluster(skin_cluster, query=True, inf=True) for jnt in influences_to_unbind_short: if jnt not in joints_attached: continue maya.cmds.skinCluster(skin_cluster, edit=True, removeInfluence=jnt) if delete: for joint_to_remove in influences_to_unbind: child_joints = maya.cmds.listRelatives(joint_to_remove, children=True) parent = maya.cmds.listRelatives(joint_to_remove, parent=True) if not child_joints: continue if not parent: maya.cmds.parent(child_joints, world=True) continue maya.cmds.parent(child_joints, parent) maya.cmds.delete(influences_to_unbind) return True
def unbind_influences(skinned_objects=None, influences_to_unbind=None, delete=False, use_parent=True): """ Unbind given influences from given meshes and stores the unbind influences weights into other influences :param skinned_objects: list(str), meshes which joints need to be removed :param influences_to_unbind: list(str), list of joints that need to be unbind :param delete: bool, Whether or not to delete unbind influences after unbind process is completed :param use_parent: bool, If True, removed influences weights will be stored on its parent; if False it will look for the closest joint using a point cloud system :return: bool """ selected_transforms = dcc.selected_nodes_of_type('transform') selected_joints = dcc.selected_nodes_of_type('joint') influences_to_unbind = influences_to_unbind or selected_joints if not skinned_objects: skinned_objects = [ xform for xform in selected_transforms if xform not in selected_joints ] if not skinned_objects or not influences_to_unbind: return False skinned_objects = python.force_list(skinned_objects) influences_to_unbind = python.force_list(influences_to_unbind) influences_to_unbind_short = [ dcc.node_short_name(joint_node) for joint_node in influences_to_unbind ] skin_clusters = list() skin_percentage = 100.0 / len(skinned_objects) for skin_index, skin_object in enumerate(skinned_objects): skin_cluster_name = skin_utils.find_related_skin_cluster(skin_object) if not skin_cluster_name: continue joints_attached = maya.cmds.skinCluster(skin_cluster_name, query=True, inf=True) if not use_parent: for joint_to_remove in influences_to_unbind_short: if joint_to_remove in joints_attached: joints_attached.remove(joint_to_remove) source_positions = list() source_joints = list() for joint_attached in joints_attached: pos = maya.cmds.xform(joint_attached, query=True, worldSpace=True, t=True) source_positions.append(pos) source_joints.append([joint_attached, pos]) source_kdtree = kdtree.KDTree.construct_from_data(source_positions) joint_percentage = skin_percentage / len(influences_to_unbind) for joint_index, jnt in enumerate(influences_to_unbind): jnt1 = jnt if use_parent: jnt2 = maya.cmds.listRelatives(jnt, parent=True) jnt2 = jnt2[0] if jnt2 else None if jnt2 is None: remove_pos = maya.cmds.xform(jnt, query=True, worldSpace=True, t=True) points = source_kdtree.query(query_point=remove_pos, t=1) for index, position in enumerate(source_joints): if position[1] != points[0]: continue jnt2 = position[0] else: remove_pos = maya.cmds.xform(jnt, query=True, worldSpace=True, t=True) points = source_kdtree.query(query_point=remove_pos, t=True) for index, position in enumerate(source_joints): if position[1] != points[0]: continue jnt2 = position[0] move_skin_weights(jnt1, jnt2, skin_object) library.Command.progressCommand.emit( ((joint_index + 1) * joint_percentage) + (skin_index * skin_percentage), 'Unbinding Influence: {}') skin_clusters.append(skin_cluster_name) for skin_cluster in skin_clusters: joints_attached = maya.cmds.skinCluster(skin_cluster, query=True, inf=True) for jnt in influences_to_unbind_short: if jnt not in joints_attached: continue maya.cmds.skinCluster(skin_cluster, edit=True, removeInfluence=jnt) if delete: for joint_to_remove in influences_to_unbind: child_joints = maya.cmds.listRelatives(joint_to_remove, children=True) parent = maya.cmds.listRelatives(joint_to_remove, parent=True) if not child_joints: continue if not parent: maya.cmds.parent(child_joints, world=True) continue maya.cmds.parent(child_joints, parent) maya.cmds.delete(influences_to_unbind) return True
def orient_joints(self, data, reply): aim_axis_index = data.get('aim_axis_index', 0.0) aim_axis_reverse = data.get('aim_axis_reverse', False) up_axis_index = data.get('up_axis_index', 0.0) up_axis_reverse = data.get('up_axis_reverse', False) up_world_axis_x = data.get('up_world_axis_x', 0.0) up_world_axis_y = data.get('up_world_axis_y', 0.0) up_world_axis_z = data.get('up_world_axis_z', 0.0) apply_to_hierarchy = data.get('apply_to_hierarchy', False) reset_joints = list() # Get up and aim axis aim_axis = [0, 0, 0] up_axis = [0, 0, 0] world_up_axis = [up_world_axis_x, up_world_axis_y, up_world_axis_z] if aim_axis_index == up_axis_index: LOGGER.warning( 'aim and up axis are the same, maybe orientation wont work correctly!' ) aim_axis_reverse_value = 1.0 if not aim_axis_reverse else -1.0 up_axis_reverse_value = 1.0 if not up_axis_reverse else -1.0 aim_axis[aim_axis_index] = aim_axis_reverse_value up_axis[up_axis_index] = up_axis_reverse_value # Get selected joints if apply_to_hierarchy: dcc.select_hierarchy() joints = dcc.selected_nodes_of_type(node_type='joint', full_path=False) if not joints: reply['msg'] = 'No joints selected' reply['success'] = False return for jnt in reversed(joints): childs = dcc.list_children(jnt, all_hierarchy=False, children_type=['transform', 'joint']) # If the joints has direct childs, unparent that childs and store names if childs: if len(childs) > 0: childs = dcc.set_parent_to_world(childs) childs = python.force_list(childs) # Get parent of this joints for later use parent = '' parents = dcc.node_parent(jnt) if parents: parent = parents[0] # Aim to the child aim_target = '' if childs: for child in childs: if dcc.node_type(child) == 'joint': aim_target = child break if aim_target != '': # Apply an aim constraint from the joint to its child (target) dcc.delete_node( dcc.create_aim_constraint(jnt, aim_target, aim_axis=aim_axis, up_axis=up_axis, world_up_axis=world_up_axis, world_up_type='vector', weight=1.0)) # Clear joint axis dcc.zero_scale_joint(jnt) dcc.freeze_transforms(jnt, preserve_pivot_transforms=True) elif parent != '': reset_joints.append(jnt) # Reparent child if childs: if len(childs) > 0: dcc.set_parent(childs, jnt) for jnt in reset_joints: # If there is no target, the joint will take its parent orientation for axis in ['x', 'y', 'z']: dcc.set_attribute_value( jnt, 'jointOrient{}'.format(axis.upper()), dcc.get_attribute_value(jnt, 'r{}'.format(axis))) dcc.set_attribute_value(jnt, 'r{}'.format(axis), 0) dcc.select_node(joints, replace_selection=True) reply['success'] = True