예제 #1
0
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])]
예제 #2
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))
예제 #3
0
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
예제 #4
0
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)
예제 #5
0
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])
예제 #6
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
예제 #7
0
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)