Example #1
0
    def search_and_replace(self, data, reply):
        search_str = data.get('search', '')
        replace_str = data.get('replace', '')
        nodes = data.get('nodes', list())
        if not nodes:
            nodes = dcc.selected_nodes()

        handles_list = list()
        for obj in nodes:
            sel = api.SelectionList()
            sel.add(obj)
            mobj = sel.get_depend_node(0)
            handle = maya.api.OpenMaya.MObjectHandle(mobj)
            handles_list.append(handle)

        new_name = None
        for node_handle in handles_list:
            node = node_handle
            try:
                mobj = node_handle.object()
                dag_path = maya.api.OpenMaya.MDagPath.getAPathTo(mobj)
                node = dag_path.partialPathName()
                obj_short_name = dag_path.partialPathName()
                new_name = obj_short_name.replace(search_str, replace_str)
                dcc.rename_node(node, new_name)
            except Exception as exc:
                LOGGER.warning('Impossible to rename {} >> {} | {}'.format(
                    node, new_name, exc))

        reply['success'] = True
    def _create_connector_controls(self):

        self._global_control = control.RigControl(name=self._get_name('global', node_type='control'))
        global_circle1 = maya.cmds.circle(normal=(0, 1, 0), radius=0.3)[0]
        dcc.move_node(global_circle1, 0, 0, -self._length)
        global_circle2 = maya.cmds.circle(normal=(0, 1, 0), radius=0.3)[0]
        dcc.move_node(global_circle2, 0, 0, self._length)
        dcc.freeze_transforms(global_circle1)
        dcc.freeze_transforms(global_circle2)
        self._global_control.set_shape([global_circle1, global_circle2])
        self._global_control.set_color_rgb(255, 255, 0)
        dcc.delete_node([global_circle1, global_circle2])
        for shape in dcc.list_shapes(self._global_control.get()):
            dcc.rename_node(shape, '{}Shape'.format(self._global_control.get()))
        self._global_control.create_root_group()
        dcc.set_parent(self._global_control.get_top(), self._top_group)
        dcc.set_parent(self._global_move_group, self._global_control.get())

        top_end_distance = self._num_joints
        self._start_control = control.RigControl(name=self._get_name('startConnector', node_type='control'))
        self._start_control.set_curve_type(
            'square', color=(255, 255, 0), axis_order='YXZ', control_size=self._control_size)
        dcc.move_node(self._start_control.get_top(), -top_end_distance, 0, 0)

        self._end_control = control.RigControl(name=self._get_name('endConnector', node_type='control'))
        self._end_control.set_curve_type(
            'square', color=(255, 255, 0), axis_order='YXZ', control_size=self._control_size)
        dcc.move_node(self._end_control.get_top(), top_end_distance, 0, 0)

        sphere_control = maya.cmds.polySphere(subdivisionsX=12, subdivisionsY=12, radius=0.3)
        sphere_shape = dcc.list_shapes(sphere_control)[0]
        sphere_material = self._get_name('flexiBendControlMat', node_type='material')
        if not dcc.node_exists(sphere_material):
            self._mid_control_material = dcc.create_surface_shader(shader_name=sphere_material)
            dcc.set_attribute_value(self._mid_control_material, 'outColor', (1, 1, 0))
        else:
            self._mid_control_material = sphere_material
        dcc.apply_shader(self._mid_control_material, sphere_shape)
        dcc.set_node_renderable(sphere_shape, False)
        self._mid_control = control.RigControl(name=self._get_name('midBend', node_type='control'))
        self._mid_control.set_shape(sphere_control)
        maya.cmds.delete(sphere_control)
        mid_control_shape = dcc.list_shapes(self._mid_control.get())[0]
        dcc.rename_node(mid_control_shape, '{}Shape'.format(self._mid_control.get()))

        for connector_control in [self._start_control, self._mid_control, self._end_control]:
            connector_control.create_root_group()
            connector_control.create_auto_group()
            dcc.set_parent(connector_control.get_top(), self._controls_group)

        # Mid control will be positioned in the mid position between start and end controls
        dcc.create_point_constraint(
            self._mid_control.get_buffer_group('auto'), (self._start_control.get(), self._end_control.get()),
            maintain_offset=False)
    def _create_wire_setup(self):
        # NOTE: We use wire deform to deform the blendShape plane because allow us to maintain the uniform spacing
        # NOTE: between surface patches while deforming the wired curve

        points_list = [(-self._num_joints, 0, -self._num_joints),
                       (0, 0, -self._num_joints),
                       (self._num_joints, 0, -self._num_joints)]
        self._wire_curve = curve.create_from_point_list(
            points_list, degree=2, name=self._get_name('flexiPlaneWire', node_type='curve'))
        dcc.hide_node(self._wire_curve)
        dcc.center_pivot(self._wire_curve)
        dcc.set_parent(self._wire_curve, self._extras_group)

        # NOTE: We create clusters in relative mode so the transforms in their above groups does not affect them
        start_cluster, start_handle = cluster.create_cluster(
            ['{}.cv[{}]'.format(self._wire_curve, i) for i in range(2)],
            name=self._get_name('wireStart', node_type='cluster'), relative=True, exclusive=False)
        dcc.set_attribute_value(start_handle, 'originX', -(self._num_joints + 1))
        dcc.move_pivot_in_object_space(start_handle, -self._num_joints / 2, 0, 0)

        end_cluster, end_handle = cluster.create_cluster(
            ['{}.cv[{}]'.format(self._wire_curve, i) for i in range(1, 3)],
            name=self._get_name('wireEnd', node_type='cluster'), relative=True, exclusive=False)
        dcc.set_attribute_value(end_handle, 'originX', self._num_joints + 1)
        dcc.move_pivot_in_object_space(end_handle, self._num_joints / 2, 0, 0)

        mid_cluster, mid_handle = cluster.create_cluster(
            '{}.cv[1]'.format(self._wire_curve), name=self._get_name('wireMid', node_type='cluster'),
            relative=True, exclusive=False)
        for cls, handle in zip([start_cluster, mid_cluster, end_cluster], [start_handle, mid_handle, end_handle]):
            self._clusters.append({'node': cls, 'handle': handle})
            dcc.set_parent(handle, self._clusters_group)

        # Make sure that mid CV is only deformer 0.5 by start/end clusters
        # This will give us a linear deformation
        maya.cmds.percent(start_cluster, '{}.cv[1]'.format(self._wire_curve), value=0.5)
        maya.cmds.percent(end_cluster, '{}.cv[1]'.format(self._wire_curve), value=0.5)

        wire_curve_shape = dcc.list_shapes(self._wire_curve)[0]
        wire_tweak = maya.cmds.listConnections(wire_curve_shape, type='tweak')[0]
        dcc.rename_node(wire_tweak, self._get_name('wireCurveClusters', node_type='tweak'))

        # TODO: Dropoff distance should be multiplied by global scale
        blendshape_curve_shape = dcc.list_shapes(self._nurbs_blendshape_plane)[0]
        self._wire_node = maya.cmds.wire(
            self._nurbs_blendshape_plane, wire=self._wire_curve,
            name=self._get_name('wireDeformer', node_type='wire'), dropoffDistance=[0, 20])
        wire_plane_tweak = maya.cmds.listConnections(blendshape_curve_shape, type='tweak')[0]
        dcc.rename_node(wire_plane_tweak, self._get_name('flexiPlaneBshpWire', node_type='tweak'))
Example #4
0
def separate_meshes(meshes=None, new_mesh_name=None):
    """
    Separates given meshes into one transform
    """

    out_dict = {'success': False, 'result': None}

    meshes = meshes or dcc.selected_nodes_of_type(node_type='transform')
    meshes = python.force_list(meshes)
    if not meshes:
        out_dict['msg'] = 'No meshes to separate selected.'
        return out_dict
    new_mesh_name = new_mesh_name or dcc.node_short_name(meshes[0])

    try:
        result_meshes = list()
        separated_meshes = dcc.separate_meshes(construction_history=False)
        if not separated_meshes:
            out_dict[
                'msg'] = 'Separate operation was done but not separated mesh was generated'
            return out_dict
        for separated_mesh in separated_meshes:
            separated_mesh = dcc.rename_node(separated_mesh, new_mesh_name)
            result_meshes.append(separated_mesh)

        out_dict['result'] = result_meshes
    except Exception as exc:
        out_dict[
            'msg'] = 'Was not possible to separate meshes "{}" : {}'.format(
                meshes, exc)
        return out_dict

    out_dict['success'] = True

    return out_dict
    def _create_blendshape_setup(self):
        if not self._nurbs_plane:
            return

        self._nurbs_blendshape_plane = dcc.duplicate_node(
            self._nurbs_plane, new_node_name=self._get_name('flexiPlaneBshp', node_type='surface'))[0]
        dcc.move_node(self._nurbs_blendshape_plane, 0, 0, -self._num_joints)

        self._nurbs_blendshape_node = blendshape.create(
            self._nurbs_plane, self._nurbs_blendshape_plane, name=self._get_name('flexiPlane', node_type='blendShape'))
        dcc.set_attribute_value(self._nurbs_blendshape_node, self._nurbs_blendshape_plane, 1.0)

        # Rename blendshape tweak node
        nurbs_plane_shape = dcc.list_shapes(self._nurbs_plane)[0]
        bs_tweak = maya.cmds.listConnections(nurbs_plane_shape, type='tweak')[0]
        dcc.rename_node(bs_tweak, self._get_name('flexiPlaneBshp', node_type='tweak'))
Example #6
0
    def rename(self, **kwargs):
        hierarchy_check = self._model.hierarchy_check
        selection_type = self._model.selection_type

        nodes = utils.get_objects_to_rename(hierarchy_check=hierarchy_check, selection_type=selection_type, uuid=True)
        generated_names = self.generate_names(items=nodes, **kwargs)

        if not generated_names or len(nodes) != len(generated_names):
            LOGGER.warning('Impossible to rename because was impossible to generate some of the names ...')
            return

        if dcc.is_maya():
            import maya.api.OpenMaya

        for item, new_name in zip(nodes, generated_names):
            if dcc.is_maya():
                mobj = None
                if hasattr(item, 'handle'):
                    mobj = item.handle.object()
                elif hasattr(item, 'object'):
                    mobj = item.object()
                if mobj:
                    try:
                        dag_path = maya.api.OpenMaya.MDagPath.getAPathTo(mobj)
                        full_name = dag_path.fullPathName()
                    except Exception as exc:
                        if hasattr(item, 'full_name'):
                            full_name = item.full_name
                        else:
                            LOGGER.warning('Impossible to retrieve Maya node full path: {}'.format(item))
                            continue
                else:
                    full_name = item
            else:
                if hasattr(item, 'full_name'):
                    full_name = item.full_name
                else:
                    full_name = item

            try:
                dcc.rename_node(full_name, new_name)
                if hasattr(item, 'obj') and hasattr(item, 'preview_name'):
                    item.obj = item.preview_name
                    item.preview_name = ''
            except Exception:
                LOGGER.error('Impossible to rename: {} to {} | {}'.format(full_name, new_name, traceback.format_exc()))
Example #7
0
    def simple_rename(self, data, reply):

        new_name = data.get('new_name', '')
        if not new_name:
            reply[
                'msg'] = 'Please type a new name and try the operation again!'
            reply['success'] = False
            return

        rename_shape = data.get('rename_shape', True)
        nodes = data.get('nodes', list())
        if not nodes:
            nodes = dcc.selected_nodes()
        for node in nodes:
            dcc.rename_node(node, new_name, rename_shape=rename_shape)

        reply['success'] = True
    def _create_twist_setup(self):

        # Update rotate order for start and end controls to improve twist axis stability
        dcc.set_attribute_value(self._start_control.get(), 'rotateOrder', 3)    # xyz
        dcc.set_attribute_value(self._end_control.get(), 'rotateOrder', 3)      # xyz

        # NOTE: It's important to create the twist deform in front of the deformation chain (so its evaluated before
        # the wire deformer)
        self._twist_node, self._twist_handle = maya.cmds.nonLinear(
            self._nurbs_blendshape_plane, type='twist', frontOfChain=True)
        self._twist_node = dcc.rename_node(self._twist_node, self._get_name('twistDeformer', node_type='twist'))
        self._twist_handle = dcc.rename_node(self._twist_handle, self._get_name('twistHandle', node_type='twist'))
        dcc.set_attribute_value(self._twist_handle, 'rotateZ', 90)
        dcc.hide_node(self._twist_handle)
        dcc.set_parent(self._twist_handle, self._extras_group)

        dcc.connect_attribute(self._start_control.get(), 'rotateX', self._twist_node, 'endAngle')
        dcc.connect_attribute(self._end_control.get(), 'rotateX', self._twist_node, 'startAngle')
Example #9
0
    def remove_last(self, data, reply):
        num_to_remove = data.get('count', 0)
        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)

        if not num_to_remove > 0:
            msg = 'Specify a number of characters to remove greater than zero ({})'.format(
                num_to_remove)
            LOGGER.warning(msg)
            reply['success'] = False
            reply['msg'] = msg
            return

        if not search_hierarchy and not selection_only:
            msg = 'Remove last must be used with "Selected" options not with "All"'
            LOGGER.warning(msg)
            reply['success'] = False
            reply['msg'] = msg
            return

        filtered_obj_list = dcc.filter_nodes_by_type(
            filter_type=filter_type,
            search_hierarchy=search_hierarchy,
            selection_only=selection_only)

        for obj in filtered_obj_list:
            original_name = dcc.node_short_name(obj)
            new_name = obj[:-num_to_remove]
            if not new_name:
                LOGGER.warning(
                    'Impossible to rename {}. Total characters to remove is greater or equal than '
                    'the original name length: {} >= {}'.format(
                        original_name, num_to_remove, len(original_name)))
                continue
            dcc.rename_node(obj, new_name, rename_shape=rename_shape)

        reply['success'] = True
def set_shape(crv,
              crv_shape_list,
              size=None,
              select_new_shape=False,
              keep_color=False):
    """
    Creates a new shape on the given curve
    :param crv:
    :param crv_shape_list:
    :param size:
    :param select_new_shape: bool
    :param keep_color: bool
    """

    crv_shapes = controlutils.validate_curve(crv)

    orig_size = None
    orig_color = None
    if crv_shapes:
        orig_size = dcc.node_bounding_box_size(crv)

        # If there are multiple shapes, we only take into account the color of the first shape
        orig_color = dcc.node_color(crv_shapes[0])

    if crv_shapes:
        dcc.delete_node(crv_shapes)

    for i, c in enumerate(crv_shape_list):
        new_shape = dcc.list_shapes(c)[0]
        new_shape = dcc.rename_node(
            new_shape,
            dcc.node_short_name(crv) + 'Shape' + str(i + 1).zfill(2))
        dcc.enable_overrides(new_shape)
        if orig_color is not None and keep_color:
            dcc.set_node_color(new_shape, orig_color)
        dcc.combine_shapes(crv, new_shape, delete_after_combine=True)

    new_size = dcc.node_bounding_box_size(crv)

    if orig_size and new_size:
        scale_size = orig_size / new_size
        dcc.scale_shapes(crv, scale_size, relative=False)

    if size:
        dcc.scale_shapes(crv, size, relative=True)

    if select_new_shape:
        dcc.select_node(crv)

    return crv
Example #11
0
def combine_meshes(meshes=None, new_mesh_name=None):
    """
    Combines given meshes into one transform
    """

    out_dict = {'success': False, 'result': None}

    meshes = meshes or dcc.selected_nodes_of_type(node_type='transform')
    meshes = python.force_list(meshes)
    if not meshes:
        out_dict['msg'] = 'No meshes to combine selected.'
        return out_dict
    if len(meshes) < 2:
        out_dict['msg'] = 'You need to select at least two meshes to combine.'
        return out_dict
    new_mesh_name = new_mesh_name or dcc.node_short_name(meshes[0])

    parent_node = None
    node_parents = list(set([dcc.node_parent(mesh) for mesh in meshes]))
    if all(parent == node_parents[0] for parent in node_parents):
        parent_node = node_parents[0]

    try:
        combined_mesh = dcc.combine_meshes(construction_history=False)
        if not combined_mesh:
            out_dict[
                'msg'] = 'Combine operation was done but not combined mesh was generated'
            return out_dict
        combined_mesh = dcc.rename_node(combined_mesh, new_mesh_name)
        if parent_node:
            dcc.set_parent(combined_mesh, parent_node)

        out_dict['result'] = combined_mesh
    except Exception as exc:
        out_dict[
            'msg'] = 'Was not possible to combine meshes "{}" : {}'.format(
                meshes, exc)
        return out_dict

    out_dict['success'] = True

    return out_dict
def mirror_control(source_control,
                   target_control=None,
                   mirror_axis='X',
                   mirror_mode=0,
                   mirror_color=None,
                   mirror_replace=False,
                   keep_color=True,
                   from_name=None,
                   to_name=None):
    """
    Find the right side control of a left side control and mirrors the control following next rules:
        - Mirror only will be applied if corresponding right side name exists
        - Replace left prefix and suffixes checking for validity
    :param mirror_axis: str
    :param mirror_mode: int or None
    :param mirror_color: int or list(float, float, float)
    :param mirror_replace: bool
    :param keep_color: bool
    :return: str, mirrored control
    """

    if keep_color:
        target_control_color = get_control_color(source_control)
    else:
        target_control_color = get_control_color(
            source_control
        ) if not mirror_color and keep_color else mirror_color

    source_shapes = dcc.list_shapes_of_type(source_control, 'nurbsCurve')
    if not source_shapes:
        return None

    duplicated_control = duplicate_control(source_control)
    mirror_pivot_grp = dcc.create_empty_group(name='temp_mirrorPivot')
    duplicated_control = dcc.set_parent(duplicated_control, mirror_pivot_grp)

    dcc.set_attribute_value(mirror_pivot_grp,
                            'scale{}'.format(mirror_axis.upper()), -1)

    target_control = target_control or source_control.replace(
        from_name, to_name)

    # We force this conversion. This is something that we should remove in the future
    if target_control and not dcc.node_exists(target_control):
        target_control = target_control.replace('Left', 'Right')

    if target_control and not dcc.node_exists(target_control):
        target_control = dcc.node_short_name(target_control)

    if target_control and dcc.node_exists(target_control) and mirror_replace:
        if keep_color:
            target_control_color = get_control_color(target_control)
        mirrored_control = xform_utils.parent_transforms_shapes(
            target_control, duplicated_control, delete_original=True)
    else:
        mirrored_control = dcc.set_parent_to_world(duplicated_control)

    maya.cmds.delete(mirror_pivot_grp)

    if mirror_mode == 0:
        dcc.move_node(mirrored_control, 0, 0, 0, world_space=True)
    elif mirror_mode == 1:
        orig_pos = dcc.node_world_space_pivot(source_control)
        dcc.move_node(mirrored_control,
                      orig_pos[0],
                      orig_pos[1],
                      orig_pos[2],
                      world_space=True)

    if target_control_color:
        target_shapes = dcc.list_shapes_of_type(mirrored_control,
                                                shape_type='nurbsCurve')
        for target_shape in target_shapes:
            dcc.set_node_color(target_shape, target_control_color)

    if from_name and to_name and from_name != to_name:
        if from_name in mirrored_control:
            mirrored_control = dcc.rename_node(
                mirrored_control, source_control.replace(from_name, to_name))

    return mirrored_control
Example #13
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)