Пример #1
0
 def set_attribute(self, name, attr, value, mirror_axis=None):
     if mirror_axis is not None:
         value = self.format_value(attr, value, mirror_axis)
     try:
         dcc.set_attribute_value(name, attr, value)
     except RuntimeError:
         logger.warning('Cannot mirror static attribute {}.{}'.format(name, attr))
Пример #2
0
    def _create_ik_buffer_joint(self):
        """
        Internal function that creates Ik buffer joint
        This buffer is useful when multiple rigs are attached to the same target Ik handle joint to avoid transform
        cycles and also to have clean transforms channels in the target node which helps the Ik handle to behave in
        a more solid manner
        :return: str
        """

        end_joint = self._ik_chain[self._end_index]
        buffer_name = dcc.find_unique_name('{}_ikBuffer'.format(end_joint))
        buffer_joint = dcc.duplicate_node(end_joint,
                                          new_node_name=buffer_name,
                                          only_parent=True)
        end_joint = dcc.set_parent(end_joint, buffer_joint)
        if not dcc.is_attribute_connected_to_attribute(
                buffer_joint, 'scale', end_joint, 'inverseScale'):
            dcc.connect_attribute(buffer_joint, 'scale', end_joint,
                                  'inverseScale')

        attributes = list()
        for axis in 'XYZ':
            for attr_name in ['rotate', 'jointOrient']:
                attributes.append('{}{}'.format(attr_name, axis))
        for attribute in attributes:
            dcc.set_attribute_value(end_joint, attribute, 0)

        return buffer_joint
Пример #3
0
    def create_auto(self, name=None, *args, **kwargs):
        """
        Creates an auto buffer group above the control
        :return: str
        """

        suffix = kwargs.pop('suffix', 'auto')
        name = name or 'auto'

        if self.get_auto(suffix=suffix):
            return self.get_auto(suffix=suffix)

        new_group = self._create_group(suffix, name=name, *args, **kwargs)
        node_parent = dcc.node_parent(self.get())
        if node_parent:
            new_group = dcc.set_parent(new_group, node_parent)

        root_group = self.get_root(suffix=kwargs.pop('auto_suffix', None))
        if root_group:
            if not dcc.node_short_name(dcc.node_parent(
                    new_group)) == dcc.node_short_name(root_group):
                dcc.set_parent(new_group, root_group)
            for xform in 'trs':
                for axis in 'xyz':
                    attr_value = 1.0 if xform == 's' else 0.0
                    dcc.set_attribute_value(new_group,
                                            '{}{}'.format(xform,
                                                          axis), attr_value)

        self.set_parent(new_group, parent_top=False)

        return new_group
Пример #4
0
def create_ik_on_joint(joint, name, solver=IkHandle.SOLVER_SC):
    """
    Creates a new IK on given joint. The end of the IK handle will be the last joint on the given joint hierarchy
    :param joint: str
    :param name: str
    :param solver: str
    :return: str
    """

    relatives = dcc.list_relatives(joint, relative_type='joint')
    if not relatives:
        return
    joint_end = relatives[0]

    ik_handle = IkHandle(name)
    ik_handle.set_start_joint(joint)
    ik_handle.set_end_joint(joint_end)
    ik_handle.set_solver(solver)
    ik_pole = ik_handle.create()

    if solver == IkHandle.SOLVER_RP:
        for axis in 'XYZ':
            dcc.set_attribute_value(ik_pole, 'poleVector{}'.format(axis), 0)

    return ik_pole
    def _create_nurbs_plane(self):
        """
        Internal function that creates the NURBS plane that will drive the rig system
        """

        self._nurbs_plane = dcc.create_nurbs_plane(
            name=self._get_name('flexiPlane', node_type='surface'),
            axis=(0, 1, 0), width=self._num_joints * 2, length=self._length, patches_u=self._num_joints,
            construction_history=False)
        dcc.freeze_transforms(self._nurbs_plane, translate=True, rotate=True, scale=True)
        dcc.hide_keyable_attributes(self._nurbs_plane, skip_visibility=True)

        material_name = self._get_name('flexiMat', node_type='material')
        if not dcc.node_exists(material_name):
            self._nurbs_plane_material = dcc.create_lambert_material(
                name=material_name, no_surface_shader=True, color=(0.0, 0.85, 1.0), transparency=(0.8, 0.8, 0.8))
        else:
            self._nurbs_plane_material = material_name
        dcc.apply_shader(self._nurbs_plane_material, self._nurbs_plane)

        if self._display_nurbs_plane_as_template:
            dcc.set_node_template_display(self._nurbs_plane, True)

        nurbs_plane_shape = dcc.list_shapes(self._nurbs_plane)[0]
        dcc.set_node_renderable(nurbs_plane_shape, False)
        dcc.set_attribute_value(nurbs_plane_shape, 'doubleSided', True)

        dcc.set_parent(self._nurbs_plane, self._global_move_group)
    def set_stored_attribute_value(self, data, reply):
        node = data['node']
        attribute_name = data['attribute_name']
        attribute_value = data['attribute_value']

        dcc.set_attribute_value(node, attribute_name, attribute_value)

        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
Пример #8
0
def set_skeleton_generator_attrs(skeleton_generator_node, attrs_dict):

    for attr_name, attr_value in attrs_dict.items():
        if not dcc.attribute_exists(skeleton_generator_node, attr_name):
            logger.warning(
                'Impossible to set {} because that attribute was not found in '
                'HIK Skeleton generator node "{}"'.format(attr_name, skeleton_generator_node))
            continue
        dcc.set_attribute_value(skeleton_generator_node, attr_name, attr_value)
Пример #9
0
    def match_rotation(self, target):
        """
        Matches control rotation to given target
        :param target:
        """

        maya.cmds.delete(maya.cmds.orientConstraint(target, self.get_top()))

        if dcc.name_is_right(self.side) and self.get_mirror():
            dcc.set_attribute_value(self.get(), 'rotateY', 0.0)
Пример #10
0
    def create_root(self, name=None, *args, **kwargs):
        """
        Creates a root buffer group above the control
        :return: str
        """

        suffix = kwargs.pop('suffix', 'root')
        name = name or 'root'

        if self.get_root(suffix=suffix):
            return self.get_root(suffix=suffix)

        top_parent = dcc.node_parent(self.get_top())

        new_group = self._create_group(suffix, name=name, *args, **kwargs)

        # MIRROR BEHAVIOUR
        # TODO: This should be optional
        mirror_group = None
        if self.side and dcc.name_is_right(self.side):
            mirror_group = self._create_group('mirror',
                                              name='mirror',
                                              *args,
                                              **kwargs)
            # dcc.match_translation_rotation(self.get(), mirror_group)
            dcc.set_attribute_value(mirror_group, 'scaleX', -1)
            if top_parent:
                dcc.set_parent(mirror_group, top_parent)

        auto_group = self.get_auto()
        if not auto_group:
            if mirror_group:
                dcc.set_parent(new_group, mirror_group)
                self.set_parent(new_group, parent_top=False)
                for xform in 'trs':
                    for axis in 'xyz':
                        attr_value = 1.0 if xform == 's' else 0.0
                        dcc.set_attribute_value(new_group,
                                                '{}{}'.format(xform, axis),
                                                attr_value)
            else:
                node_parent = dcc.node_parent(self.get())
                if node_parent:
                    dcc.set_parent(new_group, node_parent)
                self.set_parent(new_group, parent_top=False)
        else:
            if mirror_group:
                dcc.set_parent(new_group, mirror_group)
            else:
                auto_group_parent = dcc.node_parent(auto_group)
                if auto_group_parent:
                    new_group = dcc.set_parent(new_group, auto_group_parent)
            dcc.set_parent(auto_group, new_group)

        return new_group
    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)
Пример #12
0
def create_skeleton_generator_node(character_node):
    """
    Creates a new HIK Skeleton Generator node (HIKSkeletonGeneratorNode)
    :param character_node: str
    :return:str
    """

    skeleton_generator_node = maya.cmds.createNode('HIKSkeletonGeneratorNode')
    dcc.set_attribute_value(skeleton_generator_node, 'isHistoricallyInteresting', 0)
    dcc.connect_attribute(skeleton_generator_node, 'CharacterNode', character_node, 'SkeletonGenerator')

    return skeleton_generator_node
Пример #13
0
def set_skeleton_generator_defaults(skeleton_generator_node):
    """
    Sets given Skeleton Generator node to its defaults values
    :param skeleton_generator_node: str
    """

    for attr_name, default_value in HIK_SKELETON_GENERATOR_DEFAULTS.items():
        if not dcc.attribute_exists(skeleton_generator_node, attr_name):
            logger.warning(
                'Impossible to reset {} because that attribute was not found in '
                'HIK Skeleton generator node: "{}"'.format(attr_name, skeleton_generator_node))
            continue
        dcc.set_attribute_value(skeleton_generator_node, attr_name, default_value)
    def reset_attributes(self, data, reply):
        node = data['node']
        attributes_dict = data['attributes_dict']
        if not node or not attributes_dict:
            reply['msg'] = 'Impossible to reset node "{}" attributes!'.format(node)
            reply['success'] = False
            return

        for attr_name, _ in attributes_dict.items():
            default_value = dcc.attribute_default_value(node, attr_name)
            dcc.set_attribute_value(node, attr_name, default_value)

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

        dcc.add_title_attribute(self._global_control.get(), 'volume')
        dcc.add_bool_attribute(self._global_control.get(), 'enable')

        curve_shape = dcc.list_shapes(self._wire_curve)[0]
        curve_info = dcc.create_node('curveInfo', self._get_name('curveLength', node_type='curveInfo'))
        dcc.connect_attribute(curve_shape, 'worldSpace[0]', curve_info, 'inputCurve')
        current_length = dcc.get_attribute_value(curve_info, 'arcLength')
        squash_stretch_divide = dcc.create_node(
            'multiplyDivide', node_name=self._get_name('squashStretchDivide', node_type='multiplyDivide'))
        dcc.set_attribute_value(squash_stretch_divide, 'operation', 2)    # divide
        dcc.set_attribute_value(squash_stretch_divide, 'input1X', current_length)
        dcc.connect_attribute(curve_info, 'arcLength', squash_stretch_divide, 'input2X')
        squash_stretch_volume_multiplier = dcc.create_node(
            'multiplyDivide', node_name=self._get_name('squashStretchVolume', node_type='multiplyDivide'))
        dcc.set_attribute_value(squash_stretch_volume_multiplier, 'input1X', 1.0)
        dcc.connect_attribute(squash_stretch_divide, 'outputX', squash_stretch_volume_multiplier, 'input2X')

        squash_stretch_enabled = dcc.create_node(
            'condition', node_name=self._get_name('squashStretchEnable', node_type='condition'))
        dcc.connect_attribute(self._global_control.get(), 'enable', squash_stretch_enabled, 'firstTerm')
        dcc.set_attribute_value(squash_stretch_enabled, 'secondTerm', 1.0)
        dcc.connect_attribute(squash_stretch_volume_multiplier, 'outputX', squash_stretch_enabled, 'colorIfTrueR')

        for joint in self._joints:
            dcc.connect_attribute(squash_stretch_enabled, 'outColorR', joint, 'scaleY')
            dcc.connect_attribute(squash_stretch_enabled, 'outColorR', joint, 'scaleZ')
    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'))
    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'))
    def _connect_twist_joints(self):
        """
        Internal function that connects twist setup
        """

        # We make sure that last twist joint has the full rotation from the driver joint
        if self._reverse_orient:
            dcc.create_orient_constraint(self._twist_joints[-1],
                                         self._twist_driven,
                                         maintain_offset=False)
        else:
            dcc.create_orient_constraint(self._twist_joints[-1],
                                         self._twist_driver,
                                         maintain_offset=False)

        mid_joint = int((len(self._twist_joints) / 2) - 1)
        distance_ratio = 1.0 / (len(self._twist_joints) - 1)

        loop_joints = self._twist_joints[1:-1]
        if self._reverse_orient:
            loop_joints = list(reversed(loop_joints))

        for i, twist_joint in enumerate(loop_joints):
            point_cns = maya.cmds.pointConstraint(self._twist_joints[0],
                                                  self._twist_joints[-1],
                                                  twist_joint,
                                                  mo=False)[0]
            ori_cns = maya.cmds.orientConstraint(self._twist_joints[0],
                                                 self._twist_joints[-1],
                                                 twist_joint,
                                                 mo=False)[0]
            weight_names = constraint.Constraint().get_weight_names(point_cns)

            if len(self._twist_joints) % 2 != 0 and i == mid_joint:
                start_weight = 0.5
                end_weight = 0.5
            else:
                if self._reverse_orient:
                    end_weight = 1.0 - ((i + 1) * distance_ratio)
                    start_weight = 1.0 - end_weight
                else:
                    start_weight = 1.0 - ((i + 1) * distance_ratio)
                    end_weight = 1.0 - start_weight

            for cns in [point_cns, ori_cns]:
                dcc.set_attribute_value(cns, weight_names[0], start_weight)
                dcc.set_attribute_value(cns, weight_names[1], end_weight)
def add_control_tracker_attributes(
        control_name,
        control_type='circle',
        translate=(0.0, 0.0, 0.0),
        rotate=(0.0, 0.0, 0.0),
        scale=(1.0, 1.0, 1.0),
        color=None,
):
    """
    Add control tracker attributes
    :param control_name: str, name of the control lwe want to track
    :param control_type: str, control type of the control
    :param translate: tuple(float, float, float), initial translation value
    :param rotate: tuple(float, float, float), initial rotation value
    :param scale: tuple(float, float, float), initial scale value
    :param color: list(float), initial color as linear color
    """

    xform_utils.add_transform_tracker_attributes(control_name,
                                                 translate=translate,
                                                 rotate=rotate,
                                                 scale=scale)

    if not color:
        shapes = dcc.list_shapes_of_type(control_name, shape_type='nurbsCurve')
        if shapes:
            color = node_utils.get_rgb_color(shapes[0], linear=True)
    if not color:
        color = (0.0, 0.0, 0.0)
    color_utils.add_color_tracker_attributes(control_name, color)

    for i, attr_name in enumerate(
            consts.ALL_CONTROL_TYPE_TRACKER_ATTRIBUTE_NAMES):
        if not dcc.attribute_exists(control_name, attr_name):
            dcc.add_string_attribute(control_name, attr_name)

    dcc.set_attribute_value(control_name,
                            consts.TRACKER_CONTROL_TYPE_ATTR_NAME,
                            control_type)
    dcc.set_attribute_value(control_name,
                            consts.TRACKER_CONTROL_TYPE_DEFAULT_ATTR_NAME,
                            control_type)
Пример #20
0
    def _set_dcc_native_attribute(self, attribute_name, value):
        """
        Sets the value of the property defined by the given attribute name
        :param attribute_name: str, name of the attribute we want to set the value of
        :param value: variant, new value of the attribute
        :return: bool, True if the operation was successful; False otherwise.
        """

        node_name = node_utils.get_name(self._dcc_native_object, fullname=True)

        return dcc.set_attribute_value(node_name, attribute_name, value)
    def set_manual_orient_joints(self, data, reply):
        x_axis = data.get('x_axis', 0.0)
        y_axis = data.get('y_axis', 0.0)
        z_axis = data.get('z_axis', 0.0)
        affect_children = data.get('affect_children', False)

        childs = list()

        tweak_rot = [x_axis, y_axis, z_axis]

        joints = dcc.selected_nodes_of_type(node_type='joint', full_path=False)
        if not joints:
            return

        for jnt in joints:
            if not affect_children:
                childs = dcc.list_children(
                    jnt,
                    children_type=['transform', 'joint'],
                    full_path=False,
                    all_hierarchy=False) or list()
                for child in childs:
                    dcc.set_parent_to_world(child)

            # Set the rotation axis
            for i, axis in enumerate(['x', 'y', 'z']):
                dcc.set_attribute_value(jnt,
                                        'jointOrient{}'.format(axis.upper()),
                                        tweak_rot[i])

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

            if childs:
                for child in childs:
                    dcc.set_parent(child, jnt)

        dcc.select_node(joints, replace_selection=True)

        reply['success'] = True
Пример #22
0
def match_rotation(source_transform=None, target_transform=None):
    """
    Matches rotation of the source node to the rotation of the given target node(s)
    """

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

    selection = dcc.selected_nodes_of_type(node_type='transform')
    source_transform = source_transform or selection[
        0] if python.index_exists_in_list(selection, 0) else None
    if not source_transform:
        out_dict[
            'msg'] = 'No source transform given to match against target rotation.'
        return out_dict
    target_transform = target_transform or selection[1:] if len(
        selection) > 1 else None
    if not source_transform:
        out_dict[
            'msg'] = 'No target transform(s) given to match source rotation against.'
        return out_dict
    source_transform = python.force_list(source_transform)
    target_transform = python.force_list(target_transform)

    percentage = 100.0 / len(source_transform)

    for i, source in enumerate(source_transform):
        library.Command.progressCommand.emit(
            percentage * (i + 1), 'Matching rotation: {}'.format(source))
        try:
            maya.cmds.delete(
                maya.cmds.orientConstraint(target_transform,
                                           source,
                                           maintainOffset=False))

            # For joints, we store now rotation data in jointOrient attribute
            if dcc.node_type(source) == 'joint':
                for axis in 'XYZ':
                    joint_orient_attr = 'jointOrient{}'.format(axis)
                    joint_rotation_attr = 'rotate{}'.format(axis)
                    dcc.set_attribute_value(source, joint_orient_attr, 0.0)
                    joint_rotation = dcc.get_attribute_value(
                        source, joint_rotation_attr)
                    dcc.set_attribute_value(source, joint_orient_attr,
                                            joint_rotation)
                    dcc.set_attribute_value(source, joint_rotation_attr, 0.0)

            out_dict['result'].append(source)
        except Exception as exc:
            out_dict[
                'msg'] = 'Was not possible to match node "{}" rotation to "{}" : {}'.format(
                    source_transform, target_transform, exc)
            return out_dict

    matched_nodes = out_dict.get('result', None)
    if matched_nodes:
        dcc.select_node(matched_nodes)

    out_dict['success'] = True

    return out_dict
def create_buffer_groups(target=None, depth=1):
    """
    Creates buffer groups for the given target
    :param target: str
    :param depth: int
    :return: list(str)
    """

    result = list()

    target = python.force_list(target)
    for tgt in target:
        rotate_order = dcc.get_attribute_value(tgt, 'rotateOrder')
        for i in range(depth):
            obj_parent = maya.cmds.listRelatives(tgt,
                                                 parent=True,
                                                 fullPath=True)
            empty_group_name = 'buffer' if i == 0 else 'buffer{}'.format(i)
            empty_group = maya.cmds.group(empty=True,
                                          n=empty_group_name,
                                          world=True)
            dcc.set_attribute_value(empty_group, 'rotateOrder', rotate_order)
            if obj_parent:
                maya.cmds.parent(empty_group, obj_parent)
            obj_transform = [
                dcc.get_attribute_value(tgt, xform) for xform in 'tsr'
            ]
            tgt = maya.cmds.parent(tgt, empty_group)[0]
            for j, xform in enumerate('tsr'):
                maya.cmds.setAttr('{}.{}'.format(empty_group, xform),
                                  *obj_transform[j],
                                  type='double3')
                reset_xform = (0, 0, 0) if j != 1 else (1, 1, 1)
                maya.cmds.setAttr('{}.{}'.format(tgt, xform),
                                  *reset_xform,
                                  type='double3')
            result.append(empty_group)

    return result
Пример #24
0
def create_ik_chain(top_transform,
                    bottom_transform,
                    name,
                    solver=IkHandle.SOLVER_SC):
    """
    Creates a new two joint chain with an Ik handle
    :param top_transform: str, name of a transform
    :param bottom_transform: str, name of a transform
    :param name: str, name to give to new joints
    :param solver: str, type of Ik solver to use
    :return: tuple(str, str, str), tuple containing joint names and ik handle name
    """

    maya.cmds.select(clear=True)

    # Create joints and match to given transforms
    start_joint = maya.cmds.joint(n=name_utils.find_unique_name(name))
    end_joint = maya.cmds.joint(n=name_utils.find_unique_name(name))
    transform_utils.MatchTransform(top_transform, start_joint).translation()
    transform_utils.MatchTransform(bottom_transform, end_joint).translation()
    maya.cmds.joint(start_joint,
                    e=True,
                    oj='xyz',
                    secondaryAxisOrient='xup',
                    zso=True)
    maya.cmds.makeIdentity(end_joint, jo=True, apply=True)

    # Create IK handle
    ik_handle = IkHandle(name)
    ik_handle.set_start_joint(start_joint)
    ik_handle.set_end_joint(end_joint)
    ik_handle.set_solver(solver)
    ik_pole = ik_handle.create()

    if solver == IkHandle.SOLVER_RP:
        for axis in 'XYZ':
            dcc.set_attribute_value(ik_pole, 'poleVector{}'.format(axis), 0)

    return start_joint, end_joint, ik_pole
Пример #25
0
    def set(self, value, blend=100, key=False, clamp=True, additive=False):
        """
        Sets the value for the given attribute
        :param value: float or str or list
        :param blend: int
        :param key: bool
        :param clamp: bool
        :param additive: bool
        """

        try:
            if additive and self.type != 'bool':
                if self.attr.startswith('scale'):
                    value = self.value * (1 + (value - 1) * (blend / 100.0))
                else:
                    value = self.value + value * (blend / 100.0)
            elif int(blend) == 0:
                value = self.value
            else:
                value = (value - self.value) * (blend / 100.0)
                value = self.value + value
        except TypeError as exc:
            logger.warning('Cannot blend or add attribute "{}" | {}'.format(
                self.fullname, exc))

        try:
            if self.type in ['string']:
                dcc.set_attribute_value(self.name, self.attr, value)
            elif self.type in ['list', 'matrix']:
                dcc.set_attribute_value(self.name, self.attr, *value)
            else:
                dcc.set_attribute_value(self.name,
                                        self.attr,
                                        value,
                                        clamp=clamp)
        except (ValueError, RuntimeError) as exc:
            logger.warning('Cannot set attribute "{}" | {}'.format(
                self.fullname, exc))

        try:
            if key:
                self.set_keyframe(value=value)
        except TypeError as exc:
            logger.warning('Cannot key attribute "{}" | {}'.format(
                self.fullname, exc))
Пример #26
0
def set_render_globals_attribute(attribute_name, attribute_value):
    """
    Internal function that returns value of the given attribute of the render global Maya node
    :param attribute_name: str, name of the attribute to get
    :param attribute_value: object, value used to set attribute to
    :return: object
    """

    render_globals_node = get_render_globals_node_name()
    if not dcc.attribute_exists(render_globals_node, attribute_name):
        LOGGER.warning(
            'Attribute "{}" does not exists in RenderGlobasls node "{}"!'.
            format(attribute_name, render_globals_node))
        return False

    try:
        return dcc.set_attribute_value(render_globals_node, attribute_name,
                                       attribute_value)
    except Exception as exc:
        LOGGER.error(
            'Was impossible to set attribute "{}" in RenderGlobals node "{}" with value "{}" | "{}"'
            .format(attribute_name, render_globals_node, attribute_value, exc))
        return False
    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')
Пример #28
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 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
Пример #30
0
def create_character(character_name, character_namespace=None, lock=True):
    """
    Creates a HumanIK character and tries to use the given name to name the new character
    :param character_name: str, name of the new HumanIK character
    """

    if character_namespace and not character_namespace.endswith(':'):
        character_namespace = '{}:'.format(character_namespace)
    character_namespace = character_namespace or ''

    character_definition = maya.mel.eval('hikCreateCharacter("{0}")'.format(character_name))
    set_current_character(character_definition)

    try:
        maya.mel.eval('hikUpdateCharacterList()')
        maya.mel.eval('hikSelectDefinitionTab()')
    except Exception:
        pass

    for bone_name, bone_data in HIK_BONES.items():
        bone_full_name = '{}{}'.format(character_namespace, bone_name)
        if not dcc.node_exists(bone_full_name):
            logger.debug('HIK bone "{}" not found in scene!'.format(bone_name))
            continue
        bone_index = bone_data['index']
        set_character_object(character_definition, bone_full_name, bone_index, 0)

    property_node = get_properties_node(character_definition)

    dcc.set_attribute_value(property_node, 'ForceActorSpace', 0)
    dcc.set_attribute_value(property_node, 'ScaleCompensationMode', 1)
    dcc.set_attribute_value(property_node, 'Mirror', 0)
    dcc.set_attribute_value(property_node, 'HipsHeightCompensationMode', 1)
    dcc.set_attribute_value(property_node, 'AnkleProximityCompensationMode', 1)
    dcc.set_attribute_value(property_node, 'AnkleHeightCompensationMode', 0)
    dcc.set_attribute_value(property_node, 'MassCenterCompensationMode', 1)

    if lock:
        maya.mel.eval('hikToggleLockDefinition')
    # else:
    #     generator_node = maya.cmds.createNode('HIKSkeletonGeneratorNode')
        # dcc.connect_attribute(
        #     generator_node, 'CharacterNode', character_definition, 'SkeletonGenerator', force=True)

    return character_definition