Exemplo n.º 1
0
    def get_selected_info(self, data, reply):
        """
        Function that returns selected geometry info (its name and its vertices)
        :return: tuple(str, list(list(float, float, float))
        """

        nodes = dcc.selected_nodes(flatten=True)
        selected_geo = dcc.filter_nodes_by_selected_components(filter_type=12,
                                                               nodes=nodes,
                                                               full_path=True)
        selected_vertices = None
        if selected_geo:
            selected_geo = selected_geo[0]
        if not selected_geo:
            hilited_geo = dcc.selected_hilited_nodes(full_path=True)
            if len(hilited_geo) == 1:
                selected_geo = hilited_geo[0]
                selected_vertices = dcc.filter_nodes_by_selected_components(
                    filter_type=31, nodes=nodes, full_path=False)
            elif len(hilited_geo) > 1:
                logger.warning(
                    'Only one object can be hilited in component mode!')

        if selected_geo:
            if dcc.node_is_a_shape(selected_geo):
                selected_geo = dcc.node_parent(selected_geo, full_path=True)

        if not selected_geo or not dcc.node_exists(selected_geo):
            reply['success'] = False
            reply['result'] = '', list()
            return

        reply['success'] = True
        reply['result'] = selected_geo, selected_vertices
Exemplo n.º 2
0
    def _save(self):
        if not self.library_window():
            return

        try:
            path = self.folder_path()
            options = self._options_widget.values()
            name = options.get('name')
            objects = dcc.selected_nodes(full_path=True) or list()
            if not path:
                raise Exception(
                    'No folder selected. Please select a destination folder')
            if not name:
                raise Exception(
                    'No name specified. Please set a name before saving')

            if not os.path.exists(self.icon_path()):
                btn = self.show_thumbnail_capture_dialog()
                if btn == QDialogButtonBox.Cancel:
                    return

            path += '/{}'.format(name)
            icon_path = self.icon_path()

            self.save(path=path, icon_path=icon_path, objects=objects)

        except Exception as e:
            messagebox.MessageBox.critical(self.library_window(),
                                           'Error while saving', str(e))
            LOGGER.error(traceback.format_exc())
            raise

        self.library_window().stack.slide_in_index(0)
def swap_skin_weights(source_joint=None, target_joint=None, mesh=None):

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

    selection = dcc.selected_nodes()
    source_joint = source_joint or (
        selection[0] if python.index_exists_in_list(selection, 0) else None)
    if not source_joint:
        out_dict['msg'] = 'No source joint found to swap skin weights from.'
        return out_dict

    target_joint = target_joint or (
        selection[1] if python.index_exists_in_list(selection, 1) else None)
    if not target_joint:
        out_dict['msg'] = 'No target joint found to swap skin weights to.'
        return out_dict

    mesh = mesh or (selection[2]
                    if python.index_exists_in_list(selection, 2) else None)
    if not mesh:
        out_dict['msg'] = 'No mesh with skinning information found'
        return out_dict

    try:
        result = skin_utils.swap_skin_weights(source_joint, target_joint, mesh)
        out_dict['result'] = result
    except Exception as exc:
        out_dict['msg'] = 'Was not possible to swap skin weights: {}'.format(
            exc)
        return out_dict

    out_dict['success'] = True

    return out_dict
Exemplo n.º 4
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
Exemplo n.º 5
0
def rename_shapes(transform_node=None):
    """
    Rename all shapes under the given transform to match the name of the transform
    :param transform_node: str, name of a transform
    """

    renamed_shapes = list()

    transform_node = python.force_list(transform_node or dcc.selected_nodes())
    for node in transform_node:
        node_shapes = list()
        short_name = name_utils.get_short_name(node)
        shapes = get_shapes(node)
        if shapes:
            node_shapes.append(
                maya.cmds.rename(shapes[0], '{}Shape'.format(short_name)))
            if len(shapes) > 1:
                i = 1
                for s in shapes[1:]:
                    node_shapes.append(
                        maya.cmds.rename(s, '{}Shape{}'.format(short_name, i)))
                    i += 1
            renamed_shapes.append(node_shapes)

    return renamed_shapes
    def select_hierarchy(data, reply):

        sel = dcc.selected_nodes()

        for obj in sel:
            dcc.select_hierarchy(obj, add=True)

        reply['success'] = True
    def set_local_rotation_axis(data, reply):
        state = data.get('state', False)

        sel = dcc.selected_nodes()
        for obj in sel:
            if dcc.attribute_exists(obj, 'displayLocalAxis'):
                dcc.set_attribute_value(obj, 'displayLocalAxis', state)

        reply['success'] = True
Exemplo n.º 8
0
    def ls(cls, objects=None, selection=False):
        if objects is None and not selection:
            objects = dcc.all_scene_nodes(full_path=False)
        else:
            objects = objects or list()
            if selection:
                objects.extend(dcc.selected_nodes(full_path=False) or [])

        return [cls(name) for name in objects]
def delete_unused_influences(skinned_objects=None):

    out_dict = {'success': False, 'result': list()}

    skinned_objects = skinned_objects or dcc.selected_nodes()
    skinned_objects = python.force_list(skinned_objects)
    if not skinned_objects:
        out_dict['msg'] = 'No components to extract from found.'
        return out_dict

    percentage = 100.0 / len(skinned_objects)

    for i, mesh in enumerate(skinned_objects):
        try:
            library.Command.progressCommand.emit(
                percentage * (i + 1),
                'Deleting unused influences: {}'.format(mesh))
            skin_cluster_name = skin_utils.find_related_skin_cluster(mesh)
            if not skin_cluster_name:
                shape = maya.cmds.listRelatives(mesh, shapes=True) or None
                if shape:
                    LOGGER.warning(
                        'Impossible to delete unused influences because mesh "{}" '
                        'has no skin cluster attached to it!'.format(mesh))
                continue

            attached_joints = maya.cmds.skinCluster(skin_cluster_name,
                                                    query=True,
                                                    influence=True)
            weighted_joints = maya.cmds.skinCluster(skin_cluster_name,
                                                    query=True,
                                                    weightedInfluence=True)

            non_influenced = list()
            for attached in attached_joints:
                if attached in weighted_joints:
                    continue
                non_influenced.append(attached)

            for joint in non_influenced:
                maya.cmds.skinCluster(skin_cluster_name,
                                      edit=True,
                                      removeInfluence=joint)
            out_dict['result'].append(mesh)
        except Exception as exc:
            out_dict[
                'msg'] = 'Was not possible to delete unused influences: "{}" | {}'.format(
                    skinned_objects, exc)
            return out_dict

    return out_dict
Exemplo n.º 10
0
    def _before_load(self, clear_selection=True):
        """
        Internal function that is called before loading the pose
        :param clear_selection:
        """

        logger.debug('Before Load Pose "{}"'.format(self.path))

        if not self._is_loading:
            self._is_loading = True
            dcc.enable_undo()
            self._selection = dcc.selected_nodes() or list()
            self._auto_key_frame = dcc.is_auto_keyframe_enabled()
            dcc.set_auto_keyframe_enabled(False)
            if clear_selection:
                dcc.clear_selection()
Exemplo n.º 11
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
Exemplo n.º 12
0
def get_objects_to_rename(hierarchy_check, selection_type, uuid=False):
    search_hierarchy = hierarchy_check
    search_selection = True if selection_type == 0 else False

    if not search_selection:
        objs_to_rename = dcc.all_scene_nodes(full_path=True)
    else:
        objs_to_rename = dcc.selected_nodes(full_path=True)

    if not objs_to_rename:
        LOGGER.warning('No objects to rename!')
        return

    if search_hierarchy:
        children_list = list()
        for obj in objs_to_rename:
            children = dcc.list_children(obj,
                                         all_hierarchy=True,
                                         full_path=True)
            if children:
                children_list.extend(children)
        children_list = list(set(children_list))
        objs_to_rename.extend(children_list)

    if uuid and dcc.is_maya():
        import tpDcc.dccs.maya as maya

        handles_list = list()
        # objs_to_rename = [obj for obj in objs_to_rename if dcc.node_type(obj) == 'transform']
        for obj in objs_to_rename:
            mobj = maya.OpenMaya.MObject()
            sel = maya.OpenMaya.MSelectionList()
            sel.add(obj)
            sel.getDependNode(0, mobj)
            handle = maya.OpenMaya.MObjectHandle(mobj)
            handles_list.append(handle)
        return handles_list
    else:
        # We reverse the list so we update first children and later parents, otherwise we will have
        # problems during renaming if we use full paths
        objs_to_rename.reverse()

    return objs_to_rename
Exemplo n.º 13
0
    def save(self, thumbnail='', **kwargs):
        """
        Saves all the given data to the item path on disk
        :param thumbnail: str
        :param kwargs: dict
        """

        LOGGER.debug('Saving {} | {}'.format(self.path, kwargs))

        super(SkeletonFileData, self).save(thumbnail=thumbnail, **kwargs)

        objects = kwargs.get('objects', None)
        if not objects:
            objects = dcc.selected_nodes(full_path=True)
            if not objects:
                LOGGER.warning(
                    'Select root node of the skeleton to export or the list of skeleton nodes to export'
                )
                return False
Exemplo n.º 14
0
def detach_edges(edges=None):
    """
    Detach selected edges in different groups
    """

    # make list of edges, that belong to certain object
    def _group_edges(obj, edges_list):
        return [item for item in edges_list if re.match(obj, item)]

    out_dict = {'success': False, 'result': list()}

    valid_edges = list()
    selection = edges or dcc.selected_nodes()
    selection = python.force_list(selection)
    for obj in selection:
        obj_type = maya.cmds.nodeType(obj)
        if obj_type == 'transform':
            continue
        is_edge = maya.cmds.filterExpand(sm=32)
        if is_edge is None:
            continue
        valid_edges.append(obj)

    if not valid_edges:
        out_dict['msg'] = 'No edges to detach selected.'
        return out_dict

    obj_list = [edge.split('.')[0] for edge in valid_edges]
    edge_list = [_group_edges(obj, valid_edges) for obj in obj_list]

    try:
        for edge_group in edge_list:
            maya.cmds.select(edge_group)
            maya.cmds.polySplitEdge()
            out_dict['result'].append(edge_group)
    except Exception as exc:
        out_dict['msg'] = 'Was not possible to detach edges "{}" : '.format(
            valid_edges, exc)
        return out_dict

    out_dict['success'] = True

    return out_dict
Exemplo n.º 15
0
def detach_components(components=None):
    """
    Detach selected components
    """

    out_dict = {'success': False, 'result': list()}

    selection = components or dcc.selected_nodes()
    if not selection:
        out_dict['msg'] = 'No components to detach selected.'
        return out_dict

    try:
        maya.cmds.DetachComponent()
    except Exception as exc:
        out_dict[
            'msg'] = 'Was not possible to detach components "{}" : '.format(
                selection, exc)
        return out_dict

    out_dict['success'] = True

    return out_dict
def extract_skinned_selected_components(selected_components=None, **kwargs):

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

    components = selected_components or dcc.selected_nodes(flatten=True)
    components = python.force_list(components)
    if not components:
        out_dict['msg'] = 'No components to extract from found.'
        return out_dict

    try:
        result = skin_utils.extract_skinned_selected_components(
            components, **kwargs)
        out_dict['result'] = result
    except Exception as exc:
        out_dict[
            'msg'] = 'Was not possible to transfers UVs to skinned geometry: {}'.format(
                exc)
        return out_dict

    out_dict['success'] = True

    return out_dict
Exemplo n.º 17
0
    def refresh(self, selected_objects=False, hierarchy=False):
        self._names_list.clear()
        self._names_list.setSortingEnabled(True)

        try:
            objs_names = list()
            if not selected_objects:
                objs_names.extend(dcc.all_scene_nodes(full_path=True))
            else:
                objs_names.extend(dcc.selected_nodes(full_path=True))
                if objs_names and hierarchy:
                    children_list = list()
                    for obj in objs_names:
                        children = dcc.list_children(obj,
                                                     all_hierarchy=True,
                                                     full_path=True)
                        if children:
                            children_list.extend(children)
                    children_list = list(set(children_list))
                    objs_names.extend(children_list)
            self._update_names_list(objs_names)
            self._on_filter_names_changed(self._names_filter.get_text())
        finally:
            self._names_list.setSortingEnabled(False)
def create_control_curve(control_name='new_ctrl',
                         control_type='circle',
                         controls_path=None,
                         control_size=1.0,
                         translate_offset=(0.0, 0.0, 0.0),
                         rotate_offset=(0.0, 0.0, 0.0),
                         scale=(1.0, 1.0, 1.0),
                         axis_order='XYZ',
                         mirror=None,
                         color=None,
                         line_width=-1,
                         create_buffers=False,
                         buffers_depth=0,
                         match_translate=False,
                         match_rotate=False,
                         match_scale=False,
                         parent=None,
                         **kwargs):
    """
    Creates a new curve based control
    :param control_name: str, name of the new control to create
    :param control_type: str, curve types used by the new control
    :param controls_path: str or None, path were control curve types can be located
    :param control_size: float, global size of the control
    :param translate_offset: tuple(float, float, float), XYZ translation offset to apply to the control curves
    :param rotate_offset: tuple(float, float, float), XYZ rotation offset to apply to the control curves
    :param scale: tuple(float, float, float), scale of the control.
    :param axis_order: str, axis order of the control. Default is XYZ.
    :param mirror: str or None, axis mirror to apply to the control curves (None, 'X', 'Y' or 'Z')
    :param color: list(float, float, float), RGB or index color to apply to the control
    :param line_width: str, If given, the new shapes will be parented to given node
    :param create_buffers: bool, Whether or not control buffer groups should be created.
    :param buffers_depth: int, Number of buffers groups to create.
    :param parent: str, If given, the new shapes will be parented to given node
    :param match_translate: bool, Whether or not new control root node should match the translate with the
        translation of the current DCC selected node
    :param match_translate: bool, Whether or not new control root node should match the rotate with the
        rotation of the current DCC selected node
    :param match_scale: bool, Whether or not new control root node should match the scale with the
        scale of the current DCC selected node
    :return:
    """

    current_selection = dcc.selected_nodes()

    parent_mobj = None
    if parent:
        parent_mobj = api_node.as_mobject(parent)

    runner = command.CommandRunner()

    control_data = kwargs.pop('control_data', None)
    if control_data:
        parent_mobj, shape_mobjs = runner.run(
            'tpDcc-libs-curves-dccs-maya-createCurveFromData',
            curve_data=control_data,
            curve_size=control_size,
            translate_offset=translate_offset,
            scale=scale,
            axis_order=axis_order,
            mirror=mirror,
            parent=parent_mobj)
    else:
        parent_mobj, shape_mobjs = runner.run(
            'tpDcc-libs-curves-dccs-maya-createCurveFromPath',
            curve_type=control_type,
            curves_path=controls_path,
            curve_size=control_size,
            translate_offset=translate_offset,
            scale=scale,
            axis_order=axis_order,
            mirror=mirror,
            parent=parent_mobj)

    if parent_mobj:
        for shape in shape_mobjs:
            api_node.rename_mobject(shape, control_name)
        curve_long_name_list = api_node.names_from_mobject_handles(shape_mobjs)
    else:
        api_node.rename_mobject(shape_mobjs[0], control_name)
        curve_long_name = api_node.names_from_mobject_handles(shape_mobjs)[0]
        curve_long_name_list = [curve_long_name]

    if rotate_offset != (0.0, 0.0, 0.0):
        shape_utils.rotate_node_shape_cvs(curve_long_name_list, rotate_offset)
    if line_width != -1:
        curve.set_curve_line_thickness(curve_long_name_list,
                                       line_width=line_width)

    # TODO: Support index based color
    if color is not None:
        if isinstance(color, int):
            node_utils.set_color(curve_long_name_list, color)
        else:
            node_utils.set_rgb_color(curve_long_name_list,
                                     color,
                                     linear=True,
                                     color_shapes=True)

    transforms = list()
    for curve_shape in curve_long_name_list:
        parent = dcc.node_parent(curve_shape)
        if parent:
            if parent not in transforms:
                transforms.append(parent)
        else:
            if curve_shape not in transforms:
                transforms.append(curve_shape)

    if not parent and transforms:
        if create_buffers and buffers_depth > 0:
            transforms = create_buffer_groups(transforms, buffers_depth)
        if current_selection:
            match_transform = current_selection[0]
            if match_transform and dcc.node_exists(match_transform):
                for transform in transforms:
                    if match_translate:
                        dcc.match_translation(match_transform, transform)
                    if match_rotate:
                        dcc.match_rotation(match_transform, transform)
                    if match_scale:
                        dcc.match_scale(match_transform, transform)

    return transforms
Exemplo n.º 19
0
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 replace_control_curves(control_name,
                           control_type='circle',
                           controls_path=None,
                           auto_scale=True,
                           maintain_line_width=True,
                           keep_color=True,
                           **kwargs):
    """
    Replaces the given control with the given control type deleting the existing control curve shape nodes
    :param control_name:
    :param control_type:
    :param controls_path:
    :param auto_scale: bool
    :param maintain_line_width: bool
    :param keep_color: bool
    :return:
    """

    orig_sel = dcc.selected_nodes()

    line_width = -1
    orig_size = None
    orig_color = kwargs.pop('color', None)
    if auto_scale:
        orig_size = get_control_size(control_name)
    if maintain_line_width:
        line_width = curve.get_curve_line_thickness(control_name)
    if keep_color:
        orig_color = get_control_color(control_name)

    new_control = create_control_curve(control_name='new_ctrl',
                                       control_type=control_type,
                                       controls_path=controls_path,
                                       color=orig_color,
                                       **kwargs)[0]
    if auto_scale and orig_size is not None:
        new_scale = get_control_size(new_control)
        scale_factor = orig_size / new_scale
        dcc.scale_shapes(new_control, scale_factor, relative=False)

    # We need to make sure that transforms are reset in all scenarios
    # Previous implementation was failing if the target hierarchy had a mirror behaviour (group scaled negative in
    # one of the axises)
    # maya.cmds.matchTransform([new_control, target], pos=True, rot=True, scl=True, piv=True)
    target = dcc.list_nodes(control_name, node_type='transform')[0]
    dcc.delete_node(
        dcc.create_parent_constraint(new_control,
                                     target,
                                     maintain_offset=False))
    dcc.delete_node(
        dcc.create_scale_constraint(new_control, target,
                                    maintain_offset=False))
    target_parent = dcc.node_parent(target)
    if target_parent:
        new_control = dcc.set_parent(new_control, target_parent)
        for axis in 'XYZ':
            dcc.set_attribute_value(new_control, 'translate{}'.format(axis),
                                    0.0)
            dcc.set_attribute_value(new_control, 'rotate{}'.format(axis), 0.0)
            dcc.set_attribute_value(new_control, 'scale{}'.format(axis), 1.0)
        new_control = dcc.set_parent_to_world(new_control)

    if target != new_control:
        xform_utils.parent_transforms_shapes(target, [new_control],
                                             delete_original=True,
                                             delete_shape_type='nurbsCurve')

    if maintain_line_width:
        curve.set_curve_line_thickness(target, line_width=line_width)

    dcc.select_node(orig_sel)

    return target