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 copy_cluster_weights(shape, weight_file, method="bilinear"): """ Copy cluster weights to the given shape from the given weight files :param shape: the shape node name containing the cluster deformers :type shape: str :param weight_file: containing the deformers and weight filter names :type weight_file: dict :param method: method type that should be used when updating the weights :type method: str """ # gets the temporary folder path temp_path = get_temp_folder() short_name = get_prefix_less_name(shape) for node in weight_file: if not weight_file[node]: continue cmds.deformerWeights(weight_file[node], im=True, shape=short_name, deformer=node, path=temp_path, method=method, vertexConnections=True)
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 create_blendshapes_backup(source, target, nodes): """ Creates an updated backup for the given blendshapes nodes on source .. important:: This method does not work as the other source/target type of methods in flex. The source is the current geometry before topology update containing the blendshape nodes. We use it in order to create a wrap to the newer target geometry topology. :param source: current shape node :type source: str :param target: new shape node :type target: str :return: backup blendshape nodes :rtype: list """ logger.debug("Creating blendshapes backup") # gets simpler shape name shape_name = get_prefix_less_name(target) # get attributes types attrs = get_shape_type_attributes(target) # creates source duplicate intermediate = get_shape_orig(source)[0] source_duplicate = create_duplicate(intermediate, "{}_flex_bs_sourceShape" .format(shape_name)) # first loops to create a clean copy of the blendshape nodes nodes_copy = [] for node in nodes: duplicate = copy_blendshape_node(node, source_duplicate) if duplicate: nodes_copy.append(duplicate) # creates wrapped target shape warp_target = create_duplicate(target, "{}_flex_bs_warpShape" .format(shape_name)) # wraps the duplicate to the source create_wrap(source_duplicate, warp_target) # creates blendshape target shape target_duplicate = create_duplicate(target, "{}_flex_bs_targetShape" .format(shape_name)) return_nodes = [] # loops on the blendshape nodes for node in nodes_copy: # creates transfer blendshape transfer_node = cmds.deformer(target_duplicate, type="blendShape", name="flex_transfer_{}".format(node))[0] # get blendshape targets indices. We skip verification because at this # stage the copied blendshapes nodes will always have targets targets_idx = cmds.getAttr("{}.weight".format(node), multiIndices=True) # loop on blendshape targets indices for idx in targets_idx or []: # input target group attribute attr_name = (BLENDSHAPE_TARGET.format(node, idx)) # blendshape target name target_name = cmds.aliasAttr("{}.weight[{}]".format(node, idx), query=True) # loop on actual targets and in-between targets for target in cmds.getAttr(attr_name, multiIndices=True): # gets and sets the blendshape weight value weight = float((target - 5000) / 1000.0) cmds.setAttr("{}.weight[{}]".format(node, idx), weight) # geometry target attribute geometry_target_attr = "{}[{}].inputGeomTarget".format( attr_name, target) shape_target = geometry_target_attr.replace( geometry_target_attr.split(".")[0], transfer_node) # updates the target cmds.connectAttr("{}.{}".format(warp_target, attrs["output"]), shape_target, force=True) cmds.disconnectAttr("{}.{}" .format(warp_target, attrs["output"]), shape_target) cmds.setAttr("{}.weight[{}]".format(node, idx), 0) cmds.setAttr("{}.weight[{}]".format(transfer_node, idx), 0) if target_name: cmds.aliasAttr(target_name, "{}.weight[{}]".format( transfer_node, idx)) # adds blendshape node to nodes to return return_nodes.append("{}".format(transfer_node)) # deletes backup process shapes cmds.delete(cmds.listRelatives(source_duplicate, parent=True), cmds.listRelatives(warp_target, parent=True)) # forces refresh cmds.refresh() return return_nodes