def _create_spline_ik(self): if self._curve: ik_handle = maya.cmds.ikHandle(name=dcc.find_unique_name( self._name), startJoint=self._start_joint, endEffector=self._end_joint, sol=self._solver_type, curve=self._curve, ccv=False, pcv=False) maya.cmds.rename(ik_handle[1], 'effector_{}'.format(ik_handle[0])) self._ik_handle = ik_handle[0] self._ik_effector = ik_handle[1] else: ik_handle = maya.cmds.ikHandle(name=dcc.find_unique_name( self._name), startJoint=self._start_joint, endEffector=self._end_joint, sol=self._solver_type, scv=False, pcv=False) maya.cmds.rename(ik_handle[1], 'effector_{}'.format(ik_handle[0])) self._ik_handle = ik_handle[0] self._ik_effector = ik_handle[1] self._curve = ik_handle[2] self._curve = maya.cmds.rename( self._curve, dcc.find_unique_name('curve_{}'.format(self._name)))
def _create_rivet(self): if self._create_joint: dcc.clear_selection() self._rivet = dcc.create_joint( name=dcc.find_unique_name('joint_{}'.format(self._name))) else: self._rivet = dcc.create_locator( name=dcc.find_unique_name('rivet_{}'.format(self._name)))
def _create_regular_ik(self): ik_handle, ik_effector = maya.cmds.ikHandle( name=dcc.find_unique_name(self._name), startJoint=self._start_joint, endEffector=self._end_joint, sol=self._solver_type) maya.cmds.rename(ik_effector, dcc.find_unique_name('effector_{}'.format(ik_handle))) self._ik_handle = ik_handle self._ik_effector = ik_effector
def make_unique_name(self, data, reply): rename_shape = data.get('rename_shape', True) search_hierarchy = data.get('hierarchy_check', False) selection_only = data.get('only_selection', True) filter_type = data.get('filter_type', None) dcc.find_unique_name(filter_type=filter_type, do_rename=True, rename_shape=rename_shape, search_hierarchy=search_hierarchy, selection_only=selection_only) reply['success'] = True
def _create_surface(self): mesh = self._edges[0].split('.')[0] shape = geometry.get_mesh_shape(mesh) edge_index_1 = name_utils.get_last_number(self._edges[0]) edge_index_2 = name_utils.get_last_number(self._edges[1]) vert_iterator = api.IterateEdges(shape) vert_ids = vert_iterator.get_connected_vertices(edge_index_1) edge_to_curve_1 = maya.cmds.createNode( 'polyEdgeToCurve', n=dcc.find_unique_name('rivetCurve1_{}'.format(self._name))) maya.cmds.setAttr('{}.inputComponents'.format(edge_to_curve_1), 2, 'vtx[{}]'.format(vert_ids[0]), 'vtx[{}]'.format(vert_ids[1]), type='componentList') vert_iterator = api.IterateEdges(shape) vert_ids = vert_iterator.get_connected_vertices(edge_index_2) edge_to_curve_2 = maya.cmds.createNode( 'polyEdgeToCurve', n=dcc.find_unique_name('rivetCurve2_{}'.format(self._name))) maya.cmds.setAttr('{}.inputComponents'.format(edge_to_curve_2), 2, 'vtx[{}]'.format(vert_ids[0]), 'vtx[{}]'.format(vert_ids[1]), type='componentList') maya.cmds.connectAttr('{}.worldMatrix'.format(mesh), '{}.inputMat'.format(edge_to_curve_1)) maya.cmds.connectAttr('{}.outMesh'.format(mesh), '{}.inputPolymesh'.format(edge_to_curve_1)) maya.cmds.connectAttr('{}.worldMatrix'.format(mesh), '{}.inputMat'.format(edge_to_curve_2)) maya.cmds.connectAttr('{}.outMesh'.format(mesh), '{}.inputPolymesh'.format(edge_to_curve_2)) loft = maya.cmds.createNode('loft', n=dcc.find_unique_name( 'rivetLoft_{}'.format(self._name))) maya.cmds.setAttr('{}.ic'.format(loft), s=2) maya.cmds.setAttr('{}.u'.format(loft), True) maya.cmds.setAttr('{}.rsn'.format(loft), True) maya.cmds.setAttr('{}.degree'.format(loft), 1) maya.cmds.setAttr('{}.autoReverse'.format(loft), 0) maya.cmds.connectAttr('{}.oc'.format(edge_to_curve_1), '{}.ic[0]'.format(loft)) maya.cmds.connectAttr('{}.oc'.format(edge_to_curve_2), '{}.ic[1]'.format(loft)) self._surface = loft self._surface_created = True
def _create_ik_buffer_joint(self): """ Internal function that creates Ik buffer joint This buffer is useful when multiple rigs are attached to the same target Ik handle joint to avoid transform cycles and also to have clean transforms channels in the target node which helps the Ik handle to behave in a more solid manner :return: str """ end_joint = self._ik_chain[self._end_index] buffer_name = dcc.find_unique_name('{}_ikBuffer'.format(end_joint)) buffer_joint = dcc.duplicate_node(end_joint, new_node_name=buffer_name, only_parent=True) end_joint = dcc.set_parent(end_joint, buffer_joint) if not dcc.is_attribute_connected_to_attribute( buffer_joint, 'scale', end_joint, 'inverseScale'): dcc.connect_attribute(buffer_joint, 'scale', end_joint, 'inverseScale') attributes = list() for axis in 'XYZ': for attr_name in ['rotate', 'jointOrient']: attributes.append('{}{}'.format(attr_name, axis)) for attribute in attributes: dcc.set_attribute_value(end_joint, attribute, 0) return buffer_joint
def solve_name(*args, **kwargs): """ Resolves name with given rule and attributes :param args: list :param kwargs: dict """ naming_file = kwargs.get('naming_file', None) dev = kwargs.get('dev', False) use_auto_suffix = kwargs.pop('use_auto_suffix', True) node_type = kwargs.get('node_type', None) rule_name = kwargs.pop('rule_name', None) or 'default' if use_auto_suffix and node_type: auto_suffixes = (get_auto_suffixes() or dict()).get(rule_name, dict()) if node_type in auto_suffixes: kwargs['node_type'] = auto_suffixes[node_type] name_lib = init_lib(naming_file=naming_file, dev=dev) fallback_default = False if name_lib.has_rule(rule_name): rule = name_lib.get_rule(rule_name) else: LOGGER.warning( 'Rule with name "{}" is not defined. Default rule used'.format( rule_name)) rule = name_lib.get_rule('default') fallback_default = True if not rule: LOGGER.warning( 'Impossible to retrieve name because rule name "{}" is not defined!' .format(rule_name)) return None current_rule = name_lib.active_rule() name_lib.set_active_rule(rule) solved_name = name_lib.solve(*args, **kwargs) if current_rule: if rule_name != current_rule.name: name_lib.set_active_rule(current_rule.name) else: name_lib.set_active_rule(None) solved_name = solved_name or kwargs.get('default', None) unique_name = kwargs.get('unique_name', False) if solved_name and unique_name: solved_name = dcc.find_unique_name(solved_name) if fallback_default: LOGGER.warning( 'Solved name with no rule (used default one): {}'.format( solved_name)) return solved_name
def _create_point_on_surface(self): self._point_on_surface = maya.cmds.createNode( 'pointOnSurfaceInfo', n=dcc.find_unique_name('pointOnSurface_{}'.format(self._surface))) maya.cmds.setAttr('{}.turnOnPercentage'.format(self._point_on_surface), self._percent_on) maya.cmds.setAttr('{}.parameterU'.format(self._point_on_surface), self._uv[0]) maya.cmds.setAttr('{}.parameterV'.format(self._point_on_surface), self._uv[1])
def create_simple_spline_ik_stretch(curve, joints, stretch_axis='Y'): """ Stretchs joints on curve. Joints must be attached to a SplienIk. :param curve: str, name of the curve that joints are attached to via SplineIk :param joints: list(str), listo f joints attached to SplineIk :param stretch_axis: str, stretch axis :return: """ arclen_node = maya.cmds.arclen(curve, ch=True, n=dcc.find_unique_name( 'curveInfo_{}'.format(curve))) arclen_node = maya.cmds.rename( arclen_node, dcc.find_unique_name('curveInfo_{}'.format(curve))) multiply_scale_offset = maya.cmds.createNode( 'multiplyDivide', n=dcc.find_unique_name('multiplyDivide_offset_{}'.format(arclen_node))) maya.cmds.setAttr('{}.operation'.format(multiply_scale_offset), 2) multiply = maya.cmds.createNode( 'multiplyDivide', n=dcc.find_unique_name('multiplyDivide_{}'.format(arclen_node))) maya.cmds.connectAttr('{}.arcLength'.format(arclen_node), '{}.input1X'.format(multiply_scale_offset)) maya.cmds.connectAttr('{}.outputX'.format(multiply_scale_offset), '{}.input1X'.format(multiply)) maya.cmds.setAttr('{}.input2X'.format(multiply), maya.cmds.getAttr('{}.arcLength'.format(arclen_node))) maya.cmds.setAttr('{}.operation'.format(multiply), 2) joint_count = len(joints) segment = 1.0 / joint_count percent = 0 for jnt in joints: attr = '{}.outputX'.format(multiply) maya.cmds.connectAttr(attr, '{}.scale{}'.format(jnt, stretch_axis)) percent += segment
def _create_aim_constraint(self): self._aim_constraint = maya.cmds.createNode( 'aimConstraint', n=dcc.find_unique_name('aimConstraint_{}'.format(self._surface))) maya.cmds.setAttr('{}.aimVector'.format(self._aim_constraint), 0, 1, 0, type='double3') maya.cmds.setAttr('{}.upVector'.format(self._aim_constraint), 0, 0, 1, type='double3')
def create_empty_follicle(name=None, uv=None, hide_follicle=True): """ Creates a new empty follicle :param name: str, name of the follicle :param uv: list(int, int), uv where follicle will be created :param hide_follicle: bool, Whether or not follicle should be hided by default :return: str, name of the created follicle """ uv = uv if uv is not None else [0, 0] follicle_shape = maya.cmds.createNode('follicle') if hide_follicle: maya.cmds.hide(follicle_shape) follicle = maya.cmds.listRelatives(follicle_shape, p=True)[0] maya.cmds.setAttr('{}.inheritsTransform'.format(follicle), False) follicle = maya.cmds.rename(follicle, dcc.find_unique_name(name or 'follicle')) maya.cmds.setAttr('{}.parameterU'.format(follicle), uv[0]) maya.cmds.setAttr('{}.parameterV'.format(follicle), uv[1]) return follicle
def _import_skin_weights(self, data_path, mesh): if not dcc.node_exists(mesh) or not os.path.isdir(data_path): return False try: if not dcc.is_plugin_loaded('ngSkinTools2'): dcc.load_plugin('ngSkinTools2') import ngSkinTools2 from ngSkinTools2 import api as ngst_api except ImportError: logger.warning( 'NgSkinTools 2.0 is not installed. Impossible to import ngSkin data' ) return False ng_skin_data_path = path_utils.join_path(data_path, 'ngdata.json') if not path_utils.is_file(ng_skin_data_path): logger.warning( 'No Ng Skin Data file found: "{}", aborting import skin weights operation ...' .format(ng_skin_data_path)) return False is_valid_mesh = False shape_types = ['mesh', 'nurbsSurface', 'nurbsCurve', 'lattice'] for shape_type in shape_types: if shape_utils.has_shape_of_type(mesh, shape_type): is_valid_mesh = True break if not is_valid_mesh: logger.warning( 'Node "{}" is not a valid mesh node! Currently supported nodes include: {}' .format(mesh, shape_types)) return False logger.info('Importing skin clusters {} --> "{}"'.format( mesh, data_path)) influence_dict = self._get_influences(data_path) if not influence_dict: logger.warning('No influences data found for: {}'.format(mesh)) return False influences = influence_dict.keys() if not influences: logger.warning('No influences found for: "{}"'.format(mesh)) return False influences.sort() logger.debug('Influences found for {}: {}'.format(mesh, influences)) short_name = dcc.node_short_name(mesh) transfer_mesh = None if shape_utils.has_shape_of_type(mesh, 'mesh'): orig_mesh = self._import_mesh_obj(data_path) if orig_mesh: mesh_match = geo_utils.is_mesh_compatible(orig_mesh, mesh) if not mesh_match: transfer_mesh = mesh mesh = orig_mesh else: dcc.delete_node(orig_mesh) # Check if there are duplicated influences and also for the creation of influences that does not currently # in the scene add_joints = list() remove_entries = list() for influence in influences: joints = dcc.list_nodes(influence, full_path=True) if type(joints) == list and len(joints) > 1: add_joints.append(joints[0]) conflicting_count = len(joints) logger.warning( 'Found {} joints with name {}. Using only the first one: {}' .format(conflicting_count, influence, joints[0])) remove_entries.append(influence) influence = joints[0] if not dcc.node_exists(influence): dcc.clear_selection() dcc.create_joint( name=influence, position=influence_dict[influence]['position']) for entry in remove_entries: influences.remove(entry) influences += add_joints settings_data = dict() settings_path = path_utils.join_path(data_path, 'settings.info') if path_utils.is_file(settings_path): lines = fileio.get_file_lines(settings_path) for line in lines: test_line = line.strip() if not test_line: continue line_list = eval(line) attr_name = line_list[0] value = line_list[1] settings_data[attr_name] = value # Create skin cluster and removes if it already exists skin_cluster = deform_utils.find_deformer_by_type(mesh, 'skinCluster') if skin_cluster: dcc.delete_node(skin_cluster) skin_node_name = settings_data.pop('skinNodeName', 'skin_{}'.format(short_name)) skin_cluster = maya.cmds.skinCluster( influences, mesh, tsb=True, n=dcc.find_unique_name(skin_node_name))[0] dcc.set_attribute_value(skin_cluster, 'normalizeWeights', 0) skin_utils.set_skin_weights_to_zero(skin_cluster) # TODO: This Influence mapping configuration should be generated during export and imported here as JSON file # Import ng skin data config = ngst_api.InfluenceMappingConfig() config.use_distance_matching = True config.use_label_matching = True config.use_name_matching = True ngst_api.import_json(mesh, file=ng_skin_data_path, influences_mapping_config=config) maya.cmds.skinCluster(skin_cluster, edit=True, normalizeWeights=1) maya.cmds.skinCluster(skin_cluster, edit=True, forceNormalizeWeights=True) for attr_name, value in settings_data.items(): if attr_name == 'blendWeights': skin_utils.set_skin_blend_weights(skin_cluster, value) else: if dcc.attribute_exists(skin_cluster, attr_name): dcc.set_attribute_value(skin_cluster, attr_name, value) if transfer_mesh: logger.info( 'Import sking weights: mesh topology does not match. Trying to transfer topology ...' ) skin_utils.skin_mesh_from_mesh(mesh, transfer_mesh) dcc.delete_node(mesh) logger.info('Import skinCluster weights: {} from {}'.format( short_name, data_path)) return True
def create_spline_ik_stretch(curve, joints, node_for_attribute=None, create_stretch_on_off=False, create_bulge=True, scale_axis='X'): """ Makes the joints stretch on the curve :param curve: str, name of the curve that joints are attached via Spline IK :param joints: list<str>, list of joints attached to Spline IK :param node_for_attribute: str, name of the node to create the attributes on :param create_stretch_on_off: bool, Whether to create or not extra attributes to slide the stretch value on/off :param create_bulge: bool, Whether to add bulging to the other axis that are not the scale axis :param scale_axis: str('X', 'Y', 'Z'), axis that the joints stretch on """ if scale_axis == 0: scale_axis = 'X' elif scale_axis == 1: scale_axis = 'Y' elif scale_axis == 2: scale_axis = 'Z' else: scale_axis = scale_axis.capitalize() name = 'curveInfo_{}'.format(curve) arclen_node = maya.cmds.arclen(curve, ch=True, n=dcc.find_unique_name(name)) arclen_node = maya.cmds.rename(arclen_node, dcc.find_unique_name(name)) name1 = 'multiplyDivide_offset_{}'.format(arclen_node) name2 = 'multiplyDivide_{}'.format(arclen_node) multiply_scale_offset = maya.cmds.createNode('multiplyDivide', n=dcc.find_unique_name(name1)) multiply = maya.cmds.createNode('multiplyDivide', n=dcc.find_unique_name(name2)) maya.cmds.setAttr('{}.operation'.format(multiply_scale_offset), 2) maya.cmds.connectAttr('{}.arcLength'.format(arclen_node), '{}.input1X'.format(multiply_scale_offset)) maya.cmds.connectAttr('{}.outputX'.format(multiply_scale_offset), '{}.input1X'.format(multiply)) maya.cmds.setAttr('{}.input2X'.format(multiply), maya.cmds.getAttr('{}.arcLength'.format(arclen_node))) maya.cmds.setAttr('{}.operation'.format(multiply), 2) joint_count = len(joints) segment = 1.00 / joint_count percent = 0 for jnt in joints: mult_attr = '{}.outputX'.format(multiply) if create_stretch_on_off and node_for_attribute: attr = attr_utils.NumericAttribute('stretchOnOff') attr.set_min_value(0) attr.set_max_value(1) attr.set_keyable(True) attr.create(node_for_attribute) blend_name = 'blendColors_stretchOnOff_{}'.format(curve) blend = maya.cmds.createNode('blendColors', n=blend_name) maya.cmds.connectAttr(mult_attr, '{}.color1R'.format(blend)) maya.cmds.setAttr('{}.color2R'.format(blend), 1) maya.cmds.connectAttr('{}.outputR'.format(blend), '{}.scale{}'.format(jnt, scale_axis)) maya.cmds.connectAttr('{}.stretchOnOff'.format(node_for_attribute), '{}.blender'.format(blend)) if not create_stretch_on_off: maya.cmds.connectAttr(mult_attr, '{}.scale{}'.format(jnt, scale_axis)) if create_bulge: plus_name = 'plusMinusAverage_bulge_scale_{}'.format(jnt) plus = maya.cmds.createNode('plusMinusAverage', n=plus_name) maya.cmds.addAttr(plus, ln='scaleOffset', dv=1, k=True) maya.cmds.addAttr(plus, ln='bulge', dv=1, k=True) arc_value = scalar.fade_sine(percent) attr_utils.connect_multiply( '{}.outputX'.format(multiply_scale_offset), '{}.bulge'.format(plus), arc_value) attr_utils.connect_plus('{}.scaleOffset'.format(plus), '{}.input1D[0]'.format(plus)) attr_utils.connect_plus('{}.bulge'.format(plus), '{}.input1D[1]'.format(plus)) scale_value = maya.cmds.getAttr('{}.output1D'.format(plus)) mult_offset_name = 'multiply_{}'.format(jnt) multiply_offset = maya.cmds.createNode('multiplyDivide', n=mult_offset_name) maya.cmds.setAttr('{}.operation'.format(multiply_offset), 2) maya.cmds.setAttr('{}.input1X'.format(multiply_offset), scale_value) maya.cmds.connectAttr('{}.output1D'.format(plus), '{}.input2X'.format(multiply_offset)) blend_name = 'blendColors_{}'.format(jnt) blend = maya.cmds.createNode('blendColors', n=blend_name) blend_attr = '{}.outputR'.format(blend) if node_for_attribute: maya.cmds.connectAttr('{}.outputX'.format(multiply_offset), '{}.color1R'.format(blend)) maya.cmds.setAttr('{}.color2R'.format(blend), 1) attr = attr_utils.NumericAttribute('stretchyBulge') attr.set_min_value(0) attr.set_max_value(10) attr.set_keyable(True) attr.create(node_for_attribute) attr_utils.connect_multiply( '{}.stretchyBulge'.format(node_for_attribute), '{}.blender'.format(blend), 0.1) else: blend_attr = '{}.outputX'.format(multiply_offset) if scale_axis == 'X': maya.cmds.connectAttr(blend_attr, '%s.scaleY' % jnt) maya.cmds.connectAttr(blend_attr, '%s.scaleZ' % jnt) if scale_axis == 'Y': maya.cmds.connectAttr(blend_attr, '%s.scaleX' % jnt) maya.cmds.connectAttr(blend_attr, '%s.scaleZ' % jnt) if scale_axis == 'Z': maya.cmds.connectAttr(blend_attr, '%s.scaleX' % jnt) maya.cmds.connectAttr(blend_attr, '%s.scaleY' % jnt) percent += segment
def attach_to_mesh(transform, mesh, deform=False, priority=None, face=None, point_constraint=False, auto_parent=False, hide_shape=True, inherit_transform=False, local=False, rotate_pivot=False, constraint=True): """ Attach the center point of a transform (including its hierarchy and shapes) to the mesh using a rivet NOTE: If you need to attach to the rotate pivot of the transform make sure to set rotate_pivot = True :param transform: str, name of a transform :param mesh: str, name of a mesh :param deform: bool, Whether to deform into position instead of transform. This will create a cluster :param priority: str, name of a transform to attach instead of transform. Useful i you need to attach to something close to transform, but actually you want to attach the parent instead :param face: int, index of a face on the mesh, to creat the rivet on. Useful i the algorithm does not automatically attach to the best face :param point_constraint: bool, Whether to attach with just a point constraint or not :param auto_parent: bool, Whether to parent the rivet under the same parent as transform :param hide_shape: bool, Whether to hide the shape of the rivet locator. Useful when parenting the rivet under a control :param inherit_transform: bool, Whether to have the inheritTransform attribute of the rivet on or off :param local: bool, Whether to constraint the transform to the rivet locally. This allow the rivet to be grouped and the group can move without affecting the transform :param rotate_pivot: bool, Whether to find the closest face to the rotate pivot of the transform. If not, it will search the center of the transform (including shapes) :param constraint: bool, Whether to parent the transform under the rivet or not :return: str, name of the rivet """ parent = None if auto_parent: parent = maya.cmds.listRelatives(transform, p=True) shape = geometry.get_mesh_shape(mesh) if not mesh_utils.is_a_mesh(transform): rotate_pivot = True if rotate_pivot: position = maya.cmds.xform(transform, q=True, rp=True, ws=True) else: position = transform_utils.get_center(transform) if not face: try: face_fn = api.MeshFunction(shape) face_id = face_fn.get_closest_face(position) except Exception: face_fn = api.IteratePolygonFaces(shape) face_id = face_fn.get_closest_face(position) if face: face_id = face face_iter = api.IteratePolygonFaces(shape) edges = face_iter.get_Edges(face_id) edge_1 = '{}.e[{}]'.format(mesh, edges[0]) edge_2 = '{}.e[{}]'.format(mesh, edges[2]) transform = python.force_list(transform) if not priority: priority = transform[0] rivet = Rivet(priority) rivet.set_edges([edge_1, edge_2]) rivet = rivet.create() orig_rivet = rivet rivet = maya.cmds.group(empty=True, n='offset_{}'.format(rivet), p=orig_rivet) transform_utils.MatchTransform(orig_rivet, rivet).translation_rotation() if deform: for xform in transform: cluster, handle = maya.cmds.cluster( xform, n=dcc.find_unique_name('rivetCluster_{}'.format(xform))) maya.cmds.hide(handle) maya.cmds.parent(handle, rivet) if constraint: if not deform and not local: for xform in transform: if point_constraint: maya.cmds.pointConstraint(rivet, xform, mo=True) else: maya.cmds.parentConstraint(rivet, xform, mo=True) if local and not deform: for xform in transform: if point_constraint: local, xform = constraint_utils.constraint_local( rivet, xform, constraint='pointConstraint') else: local, xform = constraint_utils.constraint_local( rivet, xform, constraint='parentConstraint') if auto_parent: maya.cmds.parent(xform, parent) attribute.connect_transforms(orig_rivet, xform) else: maya.cmds.parenet(transform, rivet) if not inherit_transform: maya.cmds.setAttr('{}.inheritsTransform'.format(orig_rivet), 0) if parent and auto_parent: maya.cmds.parent(rivet, parent) if hide_shape: maya.cmds.hide('{}Shape'.format(orig_rivet)) return orig_rivet
def solve_node_name_by_type(node_names=None, naming_file=None, dev=False, **kwargs): """ Resolves node name taking into account its type In this case, the type of the node will be used to retrieve an an automatic rule The rule name will be retrieved using auto_suffix dict from tpDcc-naming configuration file :param node_names: str or list, name of the node we want to take name of :param naming_file: str :param dev: bool :return: str """ if not dcc.is_maya(): LOGGER.warning( 'Solve Node Name by type functionality is only supported in Maya!') return None import maya.cmds from tpDcc.dccs.maya.core import name name_lib = init_lib(naming_file=naming_file, dev=dev) auto_suffix = get_auto_suffixes() if not auto_suffix: LOGGER.warning( 'Impossible to launch auto suffix functionality because no auto suffixes are defined!' ) return None solved_names = dict() return_names = list() if not node_names: node_names = dcc.selected_nodes() if not node_names: return node_names = python.force_list(node_names) for obj_name in node_names: obj_uuid = maya.cmds.ls(obj_name, uuid=True) if not obj_uuid: continue obj_uuid = obj_uuid[0] if obj_uuid in solved_names: LOGGER.warning( 'Node with name: "{} and UUID "{}" already renamed to "{}"! Skipping ...' .format(obj_name, obj_uuid, solved_names[obj_name])) continue # TODO: This code is a duplicated version of the one in # tpDcc.dccs.maya.core.name.auto_suffix_object function. Move this code to a DCC specific function obj_type = maya.cmds.objectType(obj_name) if obj_type == 'transform': shape_nodes = maya.cmds.listRelatives(obj_name, shapes=True, fullPath=True) if not shape_nodes: obj_type = 'group' else: obj_type = maya.cmds.objectType(shape_nodes[0]) elif obj_type == 'joint': shape_nodes = maya.cmds.listRelatives(obj_name, shapes=True, fullPath=True) if shape_nodes and maya.cmds.objectType( shape_nodes[0]) == 'nurbsCurve': obj_type = 'controller' if obj_type == 'nurbsCurve': connections = maya.cmds.listConnections( '{}.message'.format(obj_name)) if connections: for node in connections: if maya.cmds.nodeType(node) == 'controller': obj_type = 'controller' break if obj_type not in auto_suffix: rule_name = 'node' node_type = obj_type else: rule_name = auto_suffix[obj_type] node_type = auto_suffix[obj_type] if not name_lib.has_rule(rule_name): if not name_lib.has_rule('node'): LOGGER.warning( 'Impossible to rename node "{}" by its type "{}" because rule "{}" it is not defined and ' 'callback rule "node" either'.format( obj_name, obj_type, rule_name)) else: rule_name = 'node' if rule_name == 'node': solved_name = solve_name(obj_name, node_type=node_type, rule_name=rule_name, **kwargs) else: solved_name = solve_name(rule_name, obj_name, rule_name=rule_name, **kwargs) solved_names[obj_uuid] = solved_name if not solved_names: return unique_name = kwargs.get('unique_name', False) for obj_id, solved_name in solved_names.items(): obj_name = maya.cmds.ls(obj_id, long=True)[0] if not solved_names: return_names.append(obj_name) else: if unique_name: solved_name = dcc.find_unique_name(solved_name) new_name = name.rename(obj_name, solved_name, uuid=obj_id, rename_shape=True) return_names.append(new_name) return return_names
def auto_rename(self, tokens_dict, unique_id=True, last_joint_end=True): import maya.cmds active_rule = self._model.active_rule if not active_rule: LOGGER.warning('Impossible to auto rename because no active rule defined.') return False rule_name = active_rule.name hierarchy_check = self._model.hierarchy_check selection_type = self._model.selection_type rename_shape = self._model.rename_shape objs_to_rename = utils.get_objects_to_rename( hierarchy_check=hierarchy_check, selection_type=selection_type, uuid=False) or list() if not objs_to_rename: LOGGER.warning('No objects to rename. Please select at least one object!') return False # generated_names = self.generate_names(items=objs_to_rename, **kwargs) if not self._naming_lib.has_rule(rule_name): return False current_rule = self._naming_lib.active_rule() self._naming_lib.set_active_rule(rule_name) # TODO: Naming config should be define the name of the rule to use when using auto renaming solved_names = dict() if rule_name == 'node' and self._model.config: auto_suffix = self._model.naming_config.get('auto_suffixes', default=dict()) if auto_suffix: solved_names = dict() for i, obj_name in enumerate(reversed(objs_to_rename)): obj_uuid = maya.cmds.ls(obj_name, uuid=True)[0] if obj_uuid in solved_names: LOGGER.warning( 'Node with name: "{} and UUID "{}" already renamed to "{}"! Skipping ...'.format( obj_name, obj_uuid, solved_names[obj_name])) continue # TODO: This code is a duplicated version of the one in # tpDcc.dccs.maya.core.name.auto_suffix_object function. Move this code to a DCC specific function obj_type = maya.cmds.objectType(obj_name) if obj_type == 'transform': shape_nodes = maya.cmds.listRelatives(obj_name, shapes=True, fullPath=True) if not shape_nodes: obj_type = 'group' else: obj_type = maya.cmds.objectType(shape_nodes[0]) elif obj_type == 'joint': shape_nodes = maya.cmds.listRelatives(obj_name, shapes=True, fullPath=True) if shape_nodes and maya.cmds.objectType(shape_nodes[0]) == 'nurbsCurve': obj_type = 'controller' else: children = dcc.list_children(obj_name) if not children and last_joint_end: obj_type = 'jointEnd' if obj_type == 'nurbsCurve': connections = maya.cmds.listConnections('{}.message'.format(obj_name)) if connections: for node in connections: if maya.cmds.nodeType(node) == 'controller': obj_type = 'controller' break if obj_type not in auto_suffix: rule_name = 'node' node_type = obj_type else: rule_name = auto_suffix[obj_type] node_type = auto_suffix[obj_type] if 'node_type' in tokens_dict and tokens_dict['node_type']: node_type = tokens_dict.pop('node_type') node_name = dcc.node_short_name(obj_name) if 'description' in tokens_dict and tokens_dict['description']: description = tokens_dict['description'] else: description = node_name side = tokens_dict.get('side', None) if unique_id: solved_name = self._naming_lib.solve( description, side=side, node_type=node_type, id=i) else: solved_name = self._naming_lib.solve( description, side=side, node_type=node_type) if not solved_name: continue solved_name = dcc.find_unique_name(solved_name) solved_names[obj_uuid] = solved_name if solved_names: for obj_id, solved_name in solved_names.items(): obj_name = maya.cmds.ls(obj_id, long=True)[0] dcc.rename_node(obj_name, solved_name, uuid=obj_id, rename_shape=rename_shape) else: for obj_name in objs_to_rename: solve_name = self._naming_lib.solve(**tokens_dict) if not solve_name: LOGGER.warning( 'Impossible to rename "{}" with rule "{}" | "{}"'.format(obj_name, rule_name, tokens_dict)) continue try: dcc.rename_node(obj_name, solve_name, rename_shape=rename_shape) except Exception as exc: LOGGER.error('Impossible to rename "{}" to "{}" | {}'.format(obj_name, solve_name, exc)) continue if current_rule: self._naming_lib.set_active_rule(current_rule.name)
def constraint_local(source_transform, target_transform, parent=False, scale_connect=False, constraint='parentConstraint', use_duplicate=False): """ Constraints a target transform to a source one in a way that allows for setups to remain local to the origin. Useful when a control needs to move with a rig, but move something at the origin only when the control moves :param source_transform: str, name of a transform :param target_transform: str, name of a transform :param parent: bool, If False, the setup uses a local group to constraint the target transform. Otherwise, it will parent the target_transform under the local group :param scale_connect: bool, Whether to also asd a scale constraint or not :param constraint: str, the type of constraint to use ('parentConstraint', 'pointConstraint', 'orientConstraint') :param use_duplicate: bool :return: tuple(str, str), the local group that constraints the target transforms and the buffer group above the local group """ if use_duplicate: local_group = maya.cmds.duplicate( source_transform, n='local_{}'.format(source_transform))[0] attribute.remove_user_defined_attributes(local_group) children = maya.cmds.listRelatives(local_group) if children: maya.cmds.delete(children) dup_parent = maya.cmds.listRelatives(local_group, p=True) if dup_parent: maya.cmds.parent(local_group, w=True) buffer_group = transform_utils.create_buffer_group(local_group, use_duplicate=True) else: local_group = maya.cmds.group(empty=True, n=dcc.find_unique_name( 'local_{}'.format(source_transform))) transform_utils.MatchTransform(target_transform, local_group).translation_rotation() transform_utils.MatchTransform(target_transform, local_group).scale() if shape_utils.has_shape_of_type(source_transform, 'follicle'): buffer_group = maya.cmds.group(empty=True, n='buffer_{}'.format(local_group)) maya.cmds.parent(local_group, buffer_group) else: buffer_group = transform_utils.create_buffer_group(local_group, copy_scale=True) parent_world = maya.cmds.listRelatives(source_transform, p=True) if parent_world: if not shape_utils.has_shape_of_type(source_transform, 'follicle'): parent_world = parent_world[0] transform_utils.MatchTransform( parent_world, buffer_group).translation_rotation() if not local_group: return attribute.connect_translate(source_transform, local_group) attribute.connect_rotate(source_transform, local_group) if scale_connect: attribute.connect_scale(source_transform, local_group) if parent: maya.cmds.parent(target_transform, local_group) if not parent: if constraint == 'parentConstraint': maya.cmds.parentConstraint(local_group, target_transform, mo=True) if constraint == 'pointConstraint': maya.cmds.pointConstraint(local_group, target_transform, mo=True) if constraint == 'orientConstraint': maya.cmds.orientConstraint(local_group, target_transform, mo=True) if scale_connect: attribute.connect_scale(source_transform, target_transform) attribute.connect_message(local_group, source_transform, 'out_local') return local_group, buffer_group