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 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
Пример #3
0
    def transfer_animation(self, source_object, target_object, mirror_axis=None, option=None, time=None):
        option = option or MirrorOptions.Swap

        source_valid = self.is_valid_mirror(source_object, option)
        target_valid = self.is_valid_mirror(target_object, option)

        temp_obj = dcc.duplicate_node(source_object, new_node_name='DELETE_ME', only_parent=True)
        try:
            if target_valid:
                self._transfer_animation(source_object, temp_obj, time=time)
            if source_valid:
                self._transfer_animation(target_object, source_object, mirror_axis=mirror_axis, time=time)
            if target_valid:
                self._transfer_animation(temp_obj, target_object, mirror_axis=mirror_axis, time=time)
        finally:
            dcc.delete_node(temp_obj)
Пример #4
0
    def _remove_dcc_objects(self, dcc_native_objects):
        """
        Internal function that removes given DCC objects from current scene
        :param dcc_native_objects: variant or list(variant)
        :return: bool, True if the operation is successful; False otherwise
        """

        return dcc.delete_node(dcc_native_objects)
Пример #5
0
    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
    def orient_joints(self, data, reply):
        aim_axis_index = data.get('aim_axis_index', 0.0)
        aim_axis_reverse = data.get('aim_axis_reverse', False)
        up_axis_index = data.get('up_axis_index', 0.0)
        up_axis_reverse = data.get('up_axis_reverse', False)
        up_world_axis_x = data.get('up_world_axis_x', 0.0)
        up_world_axis_y = data.get('up_world_axis_y', 0.0)
        up_world_axis_z = data.get('up_world_axis_z', 0.0)
        apply_to_hierarchy = data.get('apply_to_hierarchy', False)

        reset_joints = list()

        # Get up and aim axis
        aim_axis = [0, 0, 0]
        up_axis = [0, 0, 0]
        world_up_axis = [up_world_axis_x, up_world_axis_y, up_world_axis_z]

        if aim_axis_index == up_axis_index:
            LOGGER.warning(
                'aim and up axis are the same, maybe orientation wont work correctly!'
            )

        aim_axis_reverse_value = 1.0 if not aim_axis_reverse else -1.0
        up_axis_reverse_value = 1.0 if not up_axis_reverse else -1.0

        aim_axis[aim_axis_index] = aim_axis_reverse_value
        up_axis[up_axis_index] = up_axis_reverse_value

        # Get selected joints
        if apply_to_hierarchy:
            dcc.select_hierarchy()

        joints = dcc.selected_nodes_of_type(node_type='joint', full_path=False)
        if not joints:
            reply['msg'] = 'No joints selected'
            reply['success'] = False
            return

        for jnt in reversed(joints):
            childs = dcc.list_children(jnt,
                                       all_hierarchy=False,
                                       children_type=['transform', 'joint'])

            # If the joints has direct childs, unparent that childs and store names
            if childs:
                if len(childs) > 0:
                    childs = dcc.set_parent_to_world(childs)
            childs = python.force_list(childs)

            # Get parent of this joints for later use
            parent = ''
            parents = dcc.node_parent(jnt)
            if parents:
                parent = parents[0]

            # Aim to the child
            aim_target = ''
            if childs:
                for child in childs:
                    if dcc.node_type(child) == 'joint':
                        aim_target = child
                        break

            if aim_target != '':

                # Apply an aim constraint from the joint to its child (target)
                dcc.delete_node(
                    dcc.create_aim_constraint(jnt,
                                              aim_target,
                                              aim_axis=aim_axis,
                                              up_axis=up_axis,
                                              world_up_axis=world_up_axis,
                                              world_up_type='vector',
                                              weight=1.0))

                # Clear joint axis
                dcc.zero_scale_joint(jnt)
                dcc.freeze_transforms(jnt, preserve_pivot_transforms=True)

            elif parent != '':
                reset_joints.append(jnt)

            # Reparent child
            if childs:
                if len(childs) > 0:
                    dcc.set_parent(childs, jnt)

        for jnt in reset_joints:
            # If there is no target, the joint will take its parent orientation
            for axis in ['x', 'y', 'z']:
                dcc.set_attribute_value(
                    jnt, 'jointOrient{}'.format(axis.upper()),
                    dcc.get_attribute_value(jnt, 'r{}'.format(axis)))
                dcc.set_attribute_value(jnt, 'r{}'.format(axis), 0)

        dcc.select_node(joints, replace_selection=True)

        reply['success'] = True