def get_controls(**kwargs):
    """
    Returns all controls in current scene
    Checks for the following info:
        - Check if the controls start with a control prefx or ends with a control suffix
        - Check if the controls have a specific control attribute
        - Check if a transform has an attribute called tag (with value) and the transform has a nurbsCurve at least
    :param namespace: str, only controls with the given namespace will be search.
    :return: list(str), list of control names
    """

    namespace = kwargs.get('namespace', '')
    name = '{}:*'.format(namespace) if namespace else '*'

    transforms = dcc.list_nodes(name, node_type='transform', full_path=False)
    joints = dcc.list_nodes(name, node_type='joint', full_path=False)
    if joints:
        transforms += joints

    found = list()
    found_with_value = list()

    for transform_node in transforms:
        if is_control(transform_node, only_tagged=True, **kwargs):
            found_with_value.append(transform_node)
        elif is_control(transform_node, only_tagged=False, **kwargs):
            found.append(transform_node)

    return found_with_value if found_with_value else found
Example #2
0
    def _get_nodes_to_discard(self):
        """
        Internal function that returns list of nodes that should be discarded during renaming process
        """

        discard_nodes = self._default_nodes_to_discard[:] or list()

        if self._hide_default_scene_nodes_cbx and self._hide_default_scene_nodes_cbx.isChecked(
        ):
            discard_nodes.extend(dcc.default_scene_nodes(full_path=False))

        # discard_nodes.extend(dcc.list_nodes(node_type='camera'))

        for btn in self._category_buttons:
            if not btn.isChecked():
                dcc_type = btn.property('dcc_type')
                if dcc_type:
                    discard_nodes.extend(
                        dcc.list_nodes(node_type=btn.property('dcc_type')))
                else:
                    dcc_fn = btn.property('dcc_fn')
                    if dcc_fn:
                        dcc_args = btn.property('dcc_args')
                        if dcc.is_maya():
                            valid_args = dict()
                            for arg_name, arg_value in dcc_args.items():
                                valid_args[str(arg_name)] = arg_value
                            nodes = getattr(maya.cmds, dcc_fn)(**valid_args)
                            discard_nodes.extend(nodes)

        return list(set(discard_nodes))
def restore_to_bind_pose(skinned_mesh=None):

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

    skinned_meshes = skinned_mesh or dcc.selected_nodes_of_type('transform')
    skinned_meshes = python.force_list(skinned_meshes)
    if not skinned_meshes:
        skinned_meshes = list()
        meshes = dcc.list_nodes(node_type='mesh')
        for mesh in meshes:
            skinned_meshes.append(
                maya.cmds.listRelatives(mesh, parent=True)[0])
    if not skinned_meshes:
        out_dict['msg'] = 'No skinned meshes to restore bind poses of found.'
        return out_dict

    try:
        result = skin_utils.restore_to_bind_pose(skinned_mesh)
        out_dict['result'] = result
    except Exception as exc:
        out_dict[
            'msg'] = 'Was not possible to restore skinned mesh to bind pose: {}'.format(
                exc)
        return out_dict

    out_dict['success'] = True

    return out_dict
Example #4
0
 def to_short_name(self):
     names = dcc.list_nodes(node_name=self.short_name())
     if len(names) == 1:
         return Node(names[0])
     elif len(names) > 1:
         raise exceptions.MoreThanOneObjectFoundError(
             'More than one object found {}'.format(str(names)))
     else:
         raise exceptions.NoObjectFoundError('No object found {}'.format(
             self.short_name()))
Example #5
0
    def refresh(self):
        """
        Syncs view to the current state of its model
        """

        self._hierarchy_cbx.setChecked(self._model.hierarchy_check)

        self._node_types_combo.clear()
        for btn in self._buttons_grp.buttons():
            self._buttons_grp.removeButton(btn)

        node_types = self._model.node_types
        if not node_types:
            self._node_types_combo.setVisible(False)
        else:
            self._node_types_combo.setVisible(True)
            for node_type in node_types:
                self._node_types_combo.addItem(str(node_type).split('.')[-1])

        categories = self._model.categories or dict()
        nodes_to_discard = self._model.nodes_to_discard
        types_to_discard = self._model.types_to_discard
        for node_type in types_to_discard:
            nodes_to_discard.extend(dcc.list_nodes(node_type=node_type))

        for i, category in enumerate(categories):
            for category_name, category_data in category.items():
                title = category_data.get('title', category)
                icon = category_data.get('icon', None)
                types = category_data.get('types', dict())
                category_btn = buttons.BaseButton(title)
                category_btn.setCheckable(True)
                if icon:
                    category_btn.setIcon(resources.icon(icon))
                if i == 0:
                    category_btn.setChecked(True)
                self._buttons_grp.addButton(category_btn)
                self._categories_layout.addWidget(category_btn)
                category_widget = categorywidget.CategoryWidget(
                    types=types, nodes_to_discard=nodes_to_discard)
                self._stack.addWidget(category_widget)

                # category_widget.doRefresh.connect(self._on_refresh_category)
                # category_widget.doPreview.connect(self._set_preview_names)
                # category_widget.togglePreview.connect(self.update_current_items)
                # category_widget.doRename.connect(self._on_rename)
                # category_btn.clicked.connect(partial(self._on_category_selected, i + 1))

        self._auto_rename_widget.refresh()

        self._controller.update_rules()
Example #6
0
def get_valid_joints(joints=None):

    valid_joints = list()
    joints = joints or dcc.selected_nodes_of_type(node_type='joint',
                                                  full_path=False)
    joints = python.force_list(joints)
    for joint in joints:
        if not dcc.object_type(joint) == 'joint':
            continue
        valid_joints.append(joint)
    if not valid_joints:
        valid_joints = dcc.list_nodes(node_type='joint')

    return valid_joints
Example #7
0
def zero_joint_orient_all_joints():
    """
    Zeroes out the orient of all joints in current scene
    """

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

    all_joints = dcc.list_nodes(node_type='joint', full_path=False)
    if not all_joints:
        out_dict['msg'] = 'No joints to remove orient data from found.'
        return out_dict

    joint_utils.OrientJointAttributes.zero_orient_joint(all_joints)

    out_dict['success'] = True

    return out_dict
Example #8
0
def mirror_all_joints():
    """
    Mirror all joints in current scene
    """

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

    all_joints = dcc.list_nodes(node_type='joint', full_path=False)
    if not all_joints:
        out_dict['msg'] = 'No joints to mirror found.'
        return out_dict

    dcc.mirror_transform(all_joints, create_if_missing=True)

    out_dict['success'] = True

    return out_dict
Example #9
0
def add_orient_data_all_joints():
    """
    Add orient data to all joints in current scene
    """

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

    all_joints = dcc.list_nodes(node_type='joint', full_path=False)
    if not all_joints:
        out_dict['msg'] = 'No joints to add orient data to found.'
        return out_dict

    joint_utils.OrientJointAttributes.add_orient_attributes(all_joints)

    out_dict['success'] = True

    return out_dict
Example #10
0
def zero_joint_orient(joints=None):
    """
    Zeroes out the data of joints
    """

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

    valid_joints = get_valid_joints(joints)
    if not valid_joints:
        valid_joints = dcc.list_nodes(node_type='joint')
    if not valid_joints:
        out_dict['msg'] = 'No joints to zero out orient of found.'
        return out_dict

    joint_utils.OrientJointAttributes.zero_orient_joint(valid_joints)

    out_dict['success'] = True

    return out_dict
Example #11
0
def mirror_joints(joints=None):
    """
    Mirror joints
    """

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

    valid_joints = get_valid_joints(joints)
    if not valid_joints:
        valid_joints = dcc.list_nodes(node_type='joint')
    if not valid_joints:
        out_dict['msg'] = 'No joints to mirror found.'
        return out_dict

    dcc.mirror_transform(valid_joints)

    out_dict['success'] = True

    return out_dict
Example #12
0
def orient_all_joints(force_orient_attributes=True):
    """
    Orients all joints
    :param force_orient_attributes: bool, Whether to force the orientation through OrientJointAttributes or not
    """

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

    all_joints = dcc.list_nodes(node_type='joint', full_path=False)
    if not all_joints:
        out_dict['msg'] = 'No joints to orient found.'
        return out_dict

    dcc.orient_joints(joints_to_orient=all_joints,
                      force_orient_attributes=force_orient_attributes)

    out_dict['success'] = True

    return out_dict
Example #13
0
def clean_orient_data(joints=None):
    """
    Clean orient data from joints
    """

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

    valid_joints = get_valid_joints(joints)
    if not valid_joints:
        valid_joints = dcc.list_nodes(node_type='joint')
    if not valid_joints:
        out_dict['msg'] = 'No joints to remove orient data from found.'
        return out_dict

    joint_utils.OrientJointAttributes.remove_orient_attributes(valid_joints)

    out_dict['success'] = True

    return out_dict
Example #14
0
def add_orient_data(joints=None):
    """
    Add orient data to joints
    """

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

    valid_joints = get_valid_joints(joints)
    if not valid_joints:
        valid_joints = dcc.list_nodes(node_type='joint')
    if not valid_joints:
        out_dict['msg'] = 'No joints to add orient data to found.'
        return out_dict

    joint_utils.OrientJointAttributes.add_orient_attributes(valid_joints)

    out_dict['success'] = True

    return out_dict
Example #15
0
def orient_joints(joints=None, force_orient_attributes=True):
    """
    Orients all joints that have OrientJointAttributes added
    :param joints: list(str) or None
    :param force_orient_attributes: bool, Whether to force the orientation through OrientJointAttributes or not
    """

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

    valid_joints = get_valid_joints(joints)
    if not valid_joints:
        valid_joints = dcc.list_nodes(node_type='joint')
    if not valid_joints:
        out_dict['msg'] = 'No joints to orient found.'
        return out_dict

    dcc.orient_joints(joints_to_orient=valid_joints,
                      force_orient_attributes=force_orient_attributes)

    out_dict['success'] = True

    return out_dict
    def _import_skin_weights(self, data_path, mesh):
        if not dcc.node_exists(mesh) or not os.path.isdir(data_path):
            return False

        try:
            if not dcc.is_plugin_loaded('ngSkinTools2'):
                dcc.load_plugin('ngSkinTools2')
            import ngSkinTools2
            from ngSkinTools2 import api as ngst_api
        except ImportError:
            logger.warning(
                'NgSkinTools 2.0 is not installed. Impossible to import ngSkin data'
            )
            return False

        ng_skin_data_path = path_utils.join_path(data_path, 'ngdata.json')
        if not path_utils.is_file(ng_skin_data_path):
            logger.warning(
                'No Ng Skin Data file found: "{}", aborting import skin weights operation ...'
                .format(ng_skin_data_path))
            return False

        is_valid_mesh = False
        shape_types = ['mesh', 'nurbsSurface', 'nurbsCurve', 'lattice']
        for shape_type in shape_types:
            if shape_utils.has_shape_of_type(mesh, shape_type):
                is_valid_mesh = True
                break
        if not is_valid_mesh:
            logger.warning(
                'Node "{}" is not a valid mesh node! Currently supported nodes include: {}'
                .format(mesh, shape_types))
            return False

        logger.info('Importing skin clusters {} --> "{}"'.format(
            mesh, data_path))

        influence_dict = self._get_influences(data_path)
        if not influence_dict:
            logger.warning('No influences data found for: {}'.format(mesh))
            return False

        influences = influence_dict.keys()
        if not influences:
            logger.warning('No influences found for: "{}"'.format(mesh))
            return False
        influences.sort()
        logger.debug('Influences found for {}: {}'.format(mesh, influences))

        short_name = dcc.node_short_name(mesh)
        transfer_mesh = None

        if shape_utils.has_shape_of_type(mesh, 'mesh'):
            orig_mesh = self._import_mesh_obj(data_path)
            if orig_mesh:
                mesh_match = geo_utils.is_mesh_compatible(orig_mesh, mesh)
                if not mesh_match:
                    transfer_mesh = mesh
                    mesh = orig_mesh
                else:
                    dcc.delete_node(orig_mesh)

        # Check if there are duplicated influences and also for the creation of influences that does not currently
        # in the scene
        add_joints = list()
        remove_entries = list()
        for influence in influences:
            joints = dcc.list_nodes(influence, full_path=True)
            if type(joints) == list and len(joints) > 1:
                add_joints.append(joints[0])
                conflicting_count = len(joints)
                logger.warning(
                    'Found {} joints with name {}. Using only the first one: {}'
                    .format(conflicting_count, influence, joints[0]))
                remove_entries.append(influence)
                influence = joints[0]
            if not dcc.node_exists(influence):
                dcc.clear_selection()
                dcc.create_joint(
                    name=influence,
                    position=influence_dict[influence]['position'])
        for entry in remove_entries:
            influences.remove(entry)
        influences += add_joints

        settings_data = dict()
        settings_path = path_utils.join_path(data_path, 'settings.info')
        if path_utils.is_file(settings_path):
            lines = fileio.get_file_lines(settings_path)
            for line in lines:
                test_line = line.strip()
                if not test_line:
                    continue
                line_list = eval(line)
                attr_name = line_list[0]
                value = line_list[1]
                settings_data[attr_name] = value

        # Create skin cluster and removes if it already exists
        skin_cluster = deform_utils.find_deformer_by_type(mesh, 'skinCluster')
        if skin_cluster:
            dcc.delete_node(skin_cluster)

        skin_node_name = settings_data.pop('skinNodeName',
                                           'skin_{}'.format(short_name))
        skin_cluster = maya.cmds.skinCluster(
            influences, mesh, tsb=True,
            n=dcc.find_unique_name(skin_node_name))[0]
        dcc.set_attribute_value(skin_cluster, 'normalizeWeights', 0)
        skin_utils.set_skin_weights_to_zero(skin_cluster)

        # TODO: This Influence mapping configuration should be generated during export and imported here as JSON file
        # Import ng skin data
        config = ngst_api.InfluenceMappingConfig()
        config.use_distance_matching = True
        config.use_label_matching = True
        config.use_name_matching = True

        ngst_api.import_json(mesh,
                             file=ng_skin_data_path,
                             influences_mapping_config=config)

        maya.cmds.skinCluster(skin_cluster, edit=True, normalizeWeights=1)
        maya.cmds.skinCluster(skin_cluster,
                              edit=True,
                              forceNormalizeWeights=True)

        for attr_name, value in settings_data.items():
            if attr_name == 'blendWeights':
                skin_utils.set_skin_blend_weights(skin_cluster, value)
            else:
                if dcc.attribute_exists(skin_cluster, attr_name):
                    dcc.set_attribute_value(skin_cluster, attr_name, value)

        if transfer_mesh:
            logger.info(
                'Import sking weights: mesh topology does not match. Trying to transfer topology ...'
            )
            skin_utils.skin_mesh_from_mesh(mesh, transfer_mesh)
            dcc.delete_node(mesh)

        logger.info('Import skinCluster weights: {} from {}'.format(
            short_name, data_path))

        return True
def 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