def create_skincluster_backup(shape, skin_node): """ Creates a skinning backup object :param shape: the shape node you want to duplicate (should use orig shape) :type shape: str :param skin_node: the given shape skin cluster node :type skin_node: str :return: the skin cluster node backup :rtype: str """ logger.info("Creating skin backup for {}".format(skin_node)) # gets the skin cluster influences influences = cmds.listConnections("{}.matrix".format(skin_node)) # creates a duplicate shape of the given shape holder_name = "{}_flex_skin_shape_holder".format( get_prefix_less_name(shape)) shape_duplicate = create_duplicate(shape, holder_name) # creates new skin cluster node on duplicate skin_holder = cmds.skinCluster(influences, shape_duplicate, bindMethod=0, obeyMaxInfluences=False, skinMethod=0, weightDistribution=0, normalizeWeights=1, removeUnusedInfluence=False, name="{}_SKN" .format(holder_name)) # copy the given skin node weights to back up shape copy_skin_weights(skin_node, skin_holder[0]) return ["{}".format(skin_holder[0])]
def add_attribute(source, target, attribute_name): """ Adds the given attribute to the given object .. note:: This is a generic method to **addAttr** all type of attributes inside Maya. Using the getAddAttrCmd from the MFnAttribute class allows avoiding to create one method for each type of attribute inside Maya as the addAttr command will differ depending on the attribute type and data. :param source: the maya source node :type source: str :param target: the maya target node :type target: str :param attribute_name: the attribute name to add in the given element :type attribute_name: str """ # check if attribute already exists on target if cmds.objExists("{}.{}".format(target, attribute_name)): return logger.info("Adding {} attribute on {}".format(attribute_name, target)) # gets the given attribute_name plug attribute m_depend_node = get_dependency_node(source) m_attribute = m_depend_node.findPlug(attribute_name).attribute() # gets the addAttr command from the MFnAttribute function fn_attr = OpenMaya.MFnAttribute(m_attribute) add_attr_cmd = fn_attr.getAddAttrCmd()[1:-1] # creates the attribute on the target mel.eval("{} {}".format(add_attr_cmd, target))
def create_clusters_backup(shape, nodes): """ Generates weight files for the given cluster nodes in the given shape :param shape: the shape node name containing the cluster deformers nodes :type shape: str :param nodes: the cluster nodes :type nodes: list :return: cluster weight files names :rtype: dict """ logger.info("Creating cluster weights backup for {}".format(nodes)) # gets the temp folder path temp_path = get_temp_folder() # prefix less shape name shape = get_prefix_less_name(shape) # dict for weights files weight_files = {} for node in nodes: # If there is not weights creating the deformer maps is useless try: cmds.getAttr("{}.weightList[0].weights".format(node)) except RuntimeError: weight_files[node] = None continue # Creates the weight map if weights are found on shape points cmds.deformerWeights('{}_{}.xml'.format(shape, node), export=True, vertexConnections=True, weightPrecision=5, shape=shape, deformer=node, path=temp_path) weight_files[node] = '{}_{}.xml'.format(shape, node) return weight_files
def update_clusters_nodes(shape, weight_files): """ Updates the given shape cluster weights using the given files :param shape: the shape node name containing the cluster deformers :type shape: str :param weight_files: weight files names for each cluster deformer :type weight_files: list(str) """ if not shape and not weight_files: return if shape and not weight_files: return logger.info("Copying cluster weights on {}".format(shape)) # update cluster weights copy_cluster_weights(shape, weight_files)
def update_skincluster_node(source_skin, target_skin): """ Updates the skin weights on the given target skin from the source skin :param source_skin: the source skin cluster node name :type source_skin: str :param target_skin: the target skin cluster node name :type target_skin: str """ if not source_skin and not target_skin: return if not source_skin and target_skin: logger.error('No backup skinning found for {}'.format(target_skin)) return logger.info("Copying skinning from {} to {}".format( source_skin[0], target_skin)) # copy skin weights copy_skin_weights(source_skin[0], target_skin[0])
def analyze_groups(source, target): """ Analyze the shapes found inside the source and target groups :param source: maya transform node :type source: str :param target: maya transform node :type target: str """ logger.debug( "Analysing the following groups - source: {} - target: {}".format( source, target)) # gets the matching shapes matching_shapes = get_matching_shapes_from_group(source, target) # gets mismatching shape types mismatched_types = [ x for x in matching_shapes if not is_matching_type(x, matching_shapes[x]) ] # gets mismatching shape vertices count mismatched_count = [ x for x in matching_shapes if not is_matching_count(x, matching_shapes[x]) ] # gets mismatching shape bounding box mismatched_bbox = [ x for x in matching_shapes if not is_matching_bouding_box(x, matching_shapes[x]) ] logger.info("-" * 90) logger.info("Mismatch shapes types: {}".format(mismatched_types)) logger.info("Mismatch vertices shapes: {}".format(mismatched_count)) logger.info("Mismatch volume shapes: {}".format(mismatched_bbox)) logger.warning("-" * 90) logger.warning("Source missing shapes: {}".format( get_missing_shapes_from_group(source, target))) logger.warning("Target missing shapes: {}".format( get_missing_shapes_from_group(target, source))) logger.warning("-" * 90) return matching_shapes, mismatched_types, mismatched_count, mismatched_bbox
def update_rig(source, target, options): """ Updates all shapes from the given source group to the target group :param source: maya transform node :type source: str :param target: maya transform node :type target: str :param options: update options :type options: dict """ # gets the matching shapes matching_shapes = get_matching_shapes_from_group(source, target) logger.info("-" * 90) logger.info("Matching shapes: {}".format(matching_shapes)) logger.info("-" * 90) for shape in matching_shapes: logger.debug("-" * 90) logger.debug("Updating: {}".format(matching_shapes[shape])) if options["deformed"]: update_deformed_shape(shape, matching_shapes[shape], options["mismatched_topologies"]) if options["transformed"]: update_transformed_shape(shape, matching_shapes[shape], options["hold_transform_values"]) if options["user_attributes"]: update_user_attributes(shape, matching_shapes[shape]) if options["object_display"]: logger.debug("Updating object display attributes on {}".format( matching_shapes[shape])) update_maya_attributes(shape, matching_shapes[shape], OBJECT_DISPLAY_ATTRIBUTES) if options["component_display"]: logger.debug("Updating component display attributes on {}".format( matching_shapes[shape])) update_maya_attributes(shape, matching_shapes[shape], COMPONENT_DISPLAY_ATTRIBUTES) if options["render_attributes"]: logger.debug("Updating render attributes on {}".format( matching_shapes[shape])) update_maya_attributes(shape, matching_shapes[shape], RENDER_STATS_ATTRIBUTES) if options["plugin_attributes"]: update_plugin_attributes(shape, matching_shapes[shape]) logger.info("-" * 90) logger.info("Source missing shapes: {}".format( get_missing_shapes_from_group(source, target))) logger.info("Target missing shapes: {}".format( get_missing_shapes_from_group(target, source))) logger.info("-" * 90)