Exemple #1
0
 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)))
Exemple #2
0
 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)))
Exemple #3
0
 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
Exemple #4
0
    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
Exemple #5
0
    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
Exemple #6
0
    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
Exemple #8
0
 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])
Exemple #9
0
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
Exemple #10
0
 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')
Exemple #11
0
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
Exemple #13
0
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
Exemple #14
0
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
Exemple #16
0
    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)
Exemple #17
0
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