Esempio n. 1
0
 def __get_times_and_nodes(self):
     """Get times and nodes."""
     times = []
     map_uuid_to_node = dict()
     for uuid in self._data.keys():
         node = maya.cmds.ls(uuid, long=True)[0]
         map_uuid_to_node[uuid] = dict()
         for attr_name in self._data[uuid].keys():
             plug_name = node + '.' + attr_name
             plug = node_utils.get_as_plug_apitwo(plug_name)
             assert plug is not None
             map_uuid_to_node[uuid][attr_name] = plug
             data = self._data.get(uuid, dict())
             data = data.get(attr_name, dict())
             times += data
     times = list(set(times))
     times = list(sorted(times))
     return times, map_uuid_to_node
Esempio n. 2
0
 def test_get_double_from_plug_apitwo(self):
     start_frame = 1001
     end_frame = 1101
     node = maya.cmds.createNode('transform')
     attr_names = [
         'translateX',
         'rotateY',
         'scaleZ',
     ]
     for attr_name in attr_names:
         plug_name = '{}.{}'.format(node, attr_name)
         plug = node_utils.get_as_plug_apitwo(plug_name)
         times = [1.0, 2, -1.0, -1, 42, 9999, -9999]
         times += list(range(start_frame, end_frame))
         for time in times:
             ctx = mod.create_dg_context_apitwo(time)
             value = mod.get_double_from_plug_apitwo(plug, ctx)
             assert isinstance(value, float)
     return
Esempio n. 3
0
 def test_get_matrix_from_plug_apitwo(self):
     start_frame = 1001
     end_frame = 1101
     node = maya.cmds.createNode('transform')
     attr_names = [
         'matrix',
         'worldMatrix[0]',
         'parentMatrix[0]',
     ]
     for attr_name in attr_names:
         plug_name = '{}.{}'.format(node, attr_name)
         plug = node_utils.get_as_plug_apitwo(plug_name)
         times = [1.0, 2, -1.0, -1, 42, 9999, -9999]
         times += list(range(start_frame, end_frame))
         for time in times:
             ctx = mod.create_dg_context_apitwo(time)
             matrix = mod.get_matrix_from_plug_apitwo(plug, ctx)
             assert isinstance(matrix, OpenMaya2.MMatrix)
     return
Esempio n. 4
0
def get_world_matrix_apitwo(node, ctx):
    """
    Get the matrix value of attribute 'worldMatrix[0]' at a
    given DG Context.

    :param node: Node path to query values on.
    :type node: str

    :param ctx: The (time) context to query the attribute at.
    :type ctx: maya.api.OpenMaya.MDGContext

    :returns: The 4x4 matrix value at the given DG context.
    :rtype: maya.api.OpenMaya.MMatrix
    """
    assert isinstance(node, (str, unicode))
    assert isinstance(ctx, OpenMaya2.MDGContext)
    name = node + '.worldMatrix[0]'
    plug = node_utils.get_as_plug_apitwo(name)
    return get_matrix_from_plug_apitwo(plug, ctx)
Esempio n. 5
0
def get_parent_inverse_matrix_apitwo(node, ctx):
    """
    Get the matrix value of attribute 'parentInverseMatrix[0]' at a
    given DG Context.

    :param node: Node path to query values on.
    :type node: str

    :param ctx: The (time) context to query the attribute at.
    :type ctx: maya.api.OpenMaya.MDGContext

    :returns: The 4x4 matrix value at the given DG context.
    :rtype: maya.api.OpenMaya.MMatrix
    """
    assert isinstance(node, pycompat.TEXT_TYPE)
    assert isinstance(ctx, OpenMaya2.MDGContext)
    name = node + '.parentInverseMatrix[0]'
    plug = node_utils.get_as_plug_apitwo(name)
    return get_matrix_from_plug_apitwo(plug, ctx)
Esempio n. 6
0
    def process(self):
        """
        Evaluate all the node attributes at times.

        :rtype: None
        """
        # Get times and nodes.
        times = []
        map_uuid_to_node = dict()
        for uuid in self._data.keys():
            node = maya.cmds.ls(uuid, long=True)[0]
            map_uuid_to_node[uuid] = dict()
            for attr_name in self._data[uuid].keys():
                plug_name = node + '.' + attr_name
                plug = node_utils.get_as_plug_apitwo(plug_name)
                assert plug is not None
                map_uuid_to_node[uuid][attr_name] = plug
                data = self._data.get(uuid, dict())
                data = data.get(attr_name, dict())
                times += data
        times = list(set(times))
        times = list(sorted(times))

        # Query the matrices, looping over time sequentially.
        for t in times:
            ctx = create_dg_context_apitwo(t)
            for uuid in self._data.keys():
                d = self._data.get(uuid, dict())
                for attr_name in d.keys():
                    d2 = map_uuid_to_node.get(uuid, dict())
                    plug = d2.get(attr_name, dict())
                    if 'matrix' in attr_name.lower():
                        matrix = get_matrix_from_plug_apitwo(plug, ctx)
                        self._data[uuid][attr_name][t] = matrix
                    elif 'rotatepivot' in attr_name.lower():
                        value = get_double_from_plug_apitwo(plug, ctx)
                        self._data[uuid][attr_name][t] = value
                    else:
                        msg = 'Attribute name is not supported; attr_name=%r'
                        raise ValueError(msg % attr_name)
        return
Esempio n. 7
0
def set_transform_values(tfm_matrix_cache,
                         times,
                         src_tfm_node,
                         dst_tfm_node,
                         rotate_order=None,
                         delete_static_anim_curves=False,
                         eval_mode=None):
    """
    Set transform node values on a destination node at times,
    using previously evaluated cached values.

    src_tfm_node is used to look-up into the cache for values.
    dst_tfm_node is the node that will be set values on. It is
    possible to have src_tfm_node and dst_tfm_node reference the same
    Maya node, or even the same object.

    .. note::
       The function assumes the given destination node has no locked
       attributes.

    :param tfm_matrix_cache: A cache holding queried matrix values.
    :type tfm_matrix_cache: TransformMatrixCache

    :param times: The times to set transforms values on.
    :type times: [int or float, ...]

    :param src_tfm_node: Source node to get cached transform values from.
    :type src_tfm_node: TransformNode

    :param dst_tfm_node: Destination node set transform values on.
    :type dst_tfm_node: TransformNode

    :param rotate_order: The rotation order to set on the dst_node,
                         or use the existing rotation on the dst_node
                         if rotate_order is None.
    :type rotate_order: str

    :param delete_static_anim_curves: If an animation curve is static,
                                      it will be deleted.
    :type delete_static_anim_curves: bool

    :param eval_mode: What type of evaluation method to use?
    :type eval_mode: mmSolver.utils.constant.EVAL_MODE_*

    :rtype: None
    """
    assert isinstance(tfm_matrix_cache, TransformMatrixCache)
    assert isinstance(times, (list, tuple))
    assert isinstance(src_tfm_node, TransformNode)
    assert isinstance(dst_tfm_node, TransformNode)
    assert rotate_order is None or isinstance(rotate_order, (str, unicode))
    if eval_mode is None:
        eval_mode = const.EVAL_MODE_DEFAULT
    assert eval_mode in const.EVAL_MODE_LIST

    current_frame = maya.cmds.currentTime(query=True)
    space = OpenMaya2.MSpace.kWorld
    attrs = [
        'translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY',
        'rotateZ', 'scaleX', 'scaleY', 'scaleZ'
    ]

    dst_node = dst_tfm_node.get_node()
    if rotate_order is None:
        rotate_order = maya.cmds.xform(dst_node, query=True, rotateOrder=True)
    else:
        maya.cmds.xform(dst_node, edit=True, rotateOrder=rotate_order)
    assert rotate_order in const.ROTATE_ORDER_STR_LIST
    rotate_order_api = ROTATE_ORDER_STR_TO_APITWO_CONSTANT[rotate_order]

    # Get destination node plug.
    dst_node = dst_tfm_node.get_node()
    dst_name = dst_node + '.parentInverseMatrix[0]'
    parent_inv_matrix_plug = node_utils.get_as_plug_apitwo(dst_name)

    # Query the matrix of nodes.
    world_mat_list = get_transform_matrix_list(tfm_matrix_cache,
                                               times,
                                               src_tfm_node,
                                               rotate_order=rotate_order)
    assert len(world_mat_list) == len(times)

    # Set transform
    dst_node = dst_tfm_node.get_node()
    prv_rot = None
    for t, world_mat in zip(times, world_mat_list):
        assert t is not None
        assert world_mat is not None

        parent_inv_mat = None
        if eval_mode == const.EVAL_MODE_API_DG_CONTEXT:
            ctx = create_dg_context_apitwo(t)
            parent_inv_mat = get_matrix_from_plug_apitwo(
                parent_inv_matrix_plug, ctx)
        elif eval_mode == const.EVAL_MODE_TIME_SWITCH_GET_ATTR:
            maya.cmds.currentTime(t, update=True)
            plug_name = parent_inv_matrix_plug.name()
            parent_inv_mat = maya.cmds.getAttr(plug_name)
            parent_inv_mat = OpenMaya2.MMatrix(parent_inv_mat)
        else:
            msg = 'eval_mode does not have a valid value'
            raise ValueError(msg % eval_mode)

        local_mat = world_mat.asMatrix() * parent_inv_mat
        local_mat = OpenMaya2.MTransformationMatrix(local_mat)
        local_mat.reorderRotation(rotate_order_api)

        # Decompose matrix into components
        trans = local_mat.translation(space)
        scl = local_mat.scale(space)
        rot = local_mat.rotation(asQuaternion=False)

        # Convert and clean rotation values
        trans = (trans[0], trans[1], trans[2])
        scl = (scl[0], scl[1], scl[2])
        rot = (math.degrees(rot[0]), math.degrees(rot[1]),
               math.degrees(rot[2]))
        if prv_rot is not None:
            rot = (animcurve_utils.euler_filter_value(prv_rot[0], rot[0]),
                   animcurve_utils.euler_filter_value(prv_rot[1], rot[1]),
                   animcurve_utils.euler_filter_value(prv_rot[2], rot[2]))
        prv_rot = rot

        # Set Keyframes
        values = trans + rot + scl
        assert len(attrs) == len(values)
        for attr, v in zip(attrs, values):
            maya.cmds.setKeyframe(dst_node, attribute=attr, time=t, value=v)

    if delete_static_anim_curves is True:
        maya.cmds.delete(dst_node, staticChannels=True)

    if eval_mode == const.EVAL_MODE_TIME_SWITCH_GET_ATTR:
        maya.cmds.currentTime(current_frame, update=True)
    return
Esempio n. 8
0
def get_transform_matrix_list(tfm_matrix_cache,
                              times,
                              src_tfm_node,
                              rotate_order=None):
    """
    Get the transform values, as raw MTransformationMatrix.

    This function does not modify the original node in any way.

    src_tfm_node is used to look-up into the cache for values.

    :param tfm_matrix_cache: A cache holding queried matrix values.
    :type tfm_matrix_cache: TransformMatrixCache

    :param times: The times to set transforms values on.
    :type times: [int or float, ...]

    :param src_tfm_node: Source node to get cached transform values from.
    :type src_tfm_node: TransformNode

    :param rotate_order: The rotation order to set on the dst_node,
                         or use the existing rotation on the dst_node
                         if rotate_order is None.
    :type rotate_order: str

    :rtype: [maya.api.OpenMaya.MTransformationMatrix, ..]
    """
    assert isinstance(tfm_matrix_cache, TransformMatrixCache)
    assert isinstance(times, (list, tuple))
    assert isinstance(src_tfm_node, TransformNode)
    assert rotate_order is None or isinstance(rotate_order, (str, unicode))

    space = OpenMaya2.MSpace.kWorld
    attrs = [
        'translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY',
        'rotateZ', 'scaleX', 'scaleY', 'scaleZ'
    ]

    if rotate_order is None:
        rotate_order = 'xyz'
    assert rotate_order in const.ROTATE_ORDER_STR_LIST
    rotate_order = ROTATE_ORDER_STR_TO_APITWO_CONSTANT[rotate_order]

    # Query the matrix node.
    src_node_uuid = src_tfm_node.get_node_uuid()
    src_node_attrs = tfm_matrix_cache.get_attrs_for_node(src_node_uuid)
    with_pivot = len(src_node_attrs) > 1
    world_mat_list = []
    if with_pivot is False:
        world_mat_list = tfm_matrix_cache.get_node_attr(
            src_node_uuid,
            'worldMatrix[0]',
            times,
        )
    else:
        mat_list = tfm_matrix_cache.get_node_attr(
            src_node_uuid,
            'matrix',
            times,
        )
        assert len(mat_list) == len(times)

        par_inv_mat_list = tfm_matrix_cache.get_node_attr(
            src_node_uuid,
            'parentInverseMatrix[0]',
            times,
        )
        assert len(par_inv_mat_list) == len(times)

        rot_piv_x_list = tfm_matrix_cache.get_node_attr(
            src_node_uuid,
            'rotatePivotX',
            times,
        )
        assert len(rot_piv_x_list) == len(times)

        rot_piv_y_list = tfm_matrix_cache.get_node_attr(
            src_node_uuid,
            'rotatePivotY',
            times,
        )
        assert len(rot_piv_y_list) == len(times)

        rot_piv_z_list = tfm_matrix_cache.get_node_attr(
            src_node_uuid,
            'rotatePivotZ',
            times,
        )
        assert len(rot_piv_z_list) == len(times)

        # Reconstruct World-Matrix, accounting for pivot point.
        space = OpenMaya2.MSpace.kWorld
        loop_iter = zip(mat_list, par_inv_mat_list, rot_piv_x_list,
                        rot_piv_y_list, rot_piv_z_list)
        for mat, par_inv_mat, rot_piv_x, rot_piv_y, rot_piv_z in loop_iter:
            assert mat is not None
            assert par_inv_mat is not None
            assert rot_piv_x is not None
            assert rot_piv_y is not None
            assert rot_piv_z is not None
            mat = OpenMaya2.MTransformationMatrix(mat)
            pivot = OpenMaya2.MVector(rot_piv_x, rot_piv_y, rot_piv_z)
            trans = mat.translation(space)
            mat.setTranslation(trans + pivot, space)
            world_mat = par_inv_mat * mat.asMatrix()
            world_mat_list.append(world_mat)
    assert len(world_mat_list) == len(times)

    # Get destination node plug.
    src_node = src_tfm_node.get_node()
    src_name = src_node + '.parentInverseMatrix[0]'
    parent_inv_matrix_plug = node_utils.get_as_plug_apitwo(src_name)

    # Get transform
    matrix_list = []
    for t, world_mat in zip(times, world_mat_list):
        assert world_mat is not None
        par_inv_mat = None
        if True:
            maya.cmds.currentTime(t, update=True)
            plug_name = parent_inv_matrix_plug.name()
            par_inv_mat = maya.cmds.getAttr(plug_name)
            par_inv_mat = OpenMaya2.MMatrix(par_inv_mat)
        else:
            ctx = create_dg_context_apitwo(t)
            par_inv_mat = get_matrix_from_plug_apitwo(parent_inv_matrix_plug,
                                                      ctx)
        local_mat = OpenMaya2.MTransformationMatrix(world_mat)
        local_mat.reorderRotation(rotate_order)
        matrix_list.append(local_mat)

    return matrix_list
Esempio n. 9
0
def set_transform_values(tfm_matrix_cache,
                         times,
                         src_tfm_node,
                         dst_tfm_node,
                         rotate_order=None,
                         delete_static_anim_curves=True):
    """
    Set transform node values on a destination node at times,
    using previously evaluated cached values.

    src_tfm_node is used to look-up into the cache for values.
    dst_tfm_node is the node that will be set values on. It is
    possible to have src_tfm_node and dst_tfm_node reference the same
    Maya node, or even the same object.

    .. note::
       The function assumes the given destination node has no locked
       attributes.

    :param tfm_matrix_cache: A cache holding queried matrix values.
    :type tfm_matrix_cache: TransformMatrixCache

    :param times: The times to set transforms values on.
    :type times: [int or float, ...]

    :param src_tfm_node: Source node to get cached transform values from.
    :type src_tfm_node: TransformNode

    :param dst_tfm_node: Destination node set transform values on.
    :type dst_tfm_node: TransformNode

    :param rotate_order: The rotation order to set on the dst_node,
                         or use the existing rotation on the dst_node
                         if rotate_order is None.
    :type rotate_order: str

    :param delete_static_anim_curves: If an animation curve is static,
                                      it will be deleted.
    :type delete_static_anim_curves: bool

    :rtype: None
    """
    assert isinstance(tfm_matrix_cache, TransformMatrixCache)
    assert isinstance(times, (list, tuple))
    assert isinstance(src_tfm_node, TransformNode)
    assert isinstance(dst_tfm_node, TransformNode)
    assert rotate_order is None or isinstance(rotate_order, (str, unicode))

    space = OpenMaya2.MSpace.kWorld
    attrs = [
        'translateX', 'translateY', 'translateZ',
        'rotateX', 'rotateY', 'rotateZ',
        'scaleX', 'scaleY', 'scaleZ'
    ]

    dst_node = dst_tfm_node.get_node()
    if rotate_order is None:
        rotate_order = maya.cmds.xform(
            dst_node,
            query=True,
            rotateOrder=True)
    else:
        maya.cmds.xform(
            dst_node,
            edit=True,
            rotateOrder=rotate_order)
    assert rotate_order in const.ROTATE_ORDER_STR_LIST
    rotate_order = ROTATE_ORDER_STR_TO_APITWO_CONSTANT[rotate_order]

    # Get destination node plug.
    src_node = src_tfm_node.get_node()
    src_name = src_node + '.parentInverseMatrix[0]'
    parent_inv_matrix_plug = node_utils.get_as_plug_apitwo(src_name)

    # Query the matrix node.
    src_node_uuid = src_tfm_node.get_node_uuid()
    src_node_attrs = tfm_matrix_cache.get_attrs_for_node(src_node_uuid)
    with_pivot = len(src_node_attrs) > 1
    world_mat_list = []
    if with_pivot is False:
        world_mat_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'worldMatrix[0]',
            times,
        )
    else:
        mat_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'matrix',
            times,
        )
        assert len(mat_list) == len(times)

        par_inv_mat_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'parentInverseMatrix[0]',
            times,
        )
        assert len(par_inv_mat_list) == len(times)

        rot_piv_x_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'rotatePivotX',
            times,
        )
        assert len(rot_piv_x_list) == len(times)

        rot_piv_y_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'rotatePivotY',
            times,
        )
        assert len(rot_piv_y_list) == len(times)

        rot_piv_z_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'rotatePivotZ',
            times,
        )
        assert len(rot_piv_z_list) == len(times)

        # Reconstruct World-Matrix, accounting for pivot point.
        space = OpenMaya2.MSpace.kWorld
        loop_iter = zip(mat_list,
                        par_inv_mat_list,
                        rot_piv_x_list,
                        rot_piv_y_list,
                        rot_piv_z_list)
        for mat, par_inv_mat, rot_piv_x, rot_piv_y, rot_piv_z in loop_iter:
            assert mat is not None
            assert par_inv_mat is not None
            assert rot_piv_x is not None
            assert rot_piv_y is not None
            assert rot_piv_z is not None
            mat = OpenMaya2.MTransformationMatrix(mat)
            pivot = OpenMaya2.MVector(rot_piv_x, rot_piv_y, rot_piv_z)
            trans = mat.translation(space)
            mat.setTranslation(trans + pivot, space)
            mat = mat.asMatrix()
            world_mat = par_inv_mat * mat
            world_mat_list.append(world_mat)
    assert len(world_mat_list) == len(times)

    # Set transform
    dst_node = dst_tfm_node.get_node()
    prv_rot = None
    for t, world_mat in zip(times, world_mat_list):
        assert world_mat is not None
        ctx = create_dg_context_apitwo(t)
        parent_mat = get_matrix_from_plug_apitwo(
            parent_inv_matrix_plug,
            ctx
        )

        local_mat = parent_mat * world_mat
        local_mat = OpenMaya2.MTransformationMatrix(local_mat)
        local_mat.reorderRotation(rotate_order)

        # Decompose matrix into components
        trans = local_mat.translation(space)
        scl = local_mat.scale(space)
        rot = local_mat.rotation(asQuaternion=False)

        # Convert and clean rotation values
        trans = (trans[0], trans[1], trans[2])
        scl = (scl[0], scl[1], scl[2])
        rot = (
            math.degrees(rot[0]),
            math.degrees(rot[1]),
            math.degrees(rot[2])
        )
        if prv_rot is not None:
            rot = (
                animcurve_utils.euler_filter_value(prv_rot[0], rot[0]),
                animcurve_utils.euler_filter_value(prv_rot[1], rot[1]),
                animcurve_utils.euler_filter_value(prv_rot[2], rot[2])
            )
        prv_rot = rot

        # Set Keyframes
        values = trans + rot + scl
        assert len(attrs) == len(values)
        for attr, v in zip(attrs, values):
            maya.cmds.setKeyframe(dst_node, attribute=attr, time=t, value=v)

    if delete_static_anim_curves is True:
        maya.cmds.delete(dst_node, staticChannels=True)
    return