예제 #1
0
def __set_attr_keyframes(node,
                         attr_name,
                         keyframes,
                         before_value=None,
                         after_value=None,
                         reduce_keys=None):
    """
    Set keyframes on a node.attribute, from a KeyframeData instance.

    :param node: Node to set data on.
    :type node: str

    :param attr_name: Attribute (on 'node') to set keyframes.
    :type attr_name: str

    :param keyframes: The keyframe information.
    :type keyframes: KeyframeData

    :param before_value: Value to set before the first keyframe.
    :type before_value: int, float or bool

    :param after_value: Value to set after the first keyframe.
    :type after_value: int, float or bool

    :param reduce_keys: Allow reducing the keyframes, potentially
                        deleting all keyframes. Values will NEVER be
                        changed, only duplicate keyframe data is
                        removed.
    :type reduce_keys: bool

    :returns: Maya API (version 1) MFnAnimCurve object.
    :rtype: maya.OpenMaya.MFnAnimCurve
    """
    if isinstance(keyframes, interface.KeyframeData) is False:
        msg = 'keyframes must be type %r'
        raise TypeError(msg % interface.KeyframeData.__name__)
    if reduce_keys is None:
        reduce_keys = False
    if isinstance(reduce_keys, bool) is False:
        msg = "reduce_keys must be type 'bool'"
        raise TypeError(msg)
    times, values = keyframes.get_times_and_values()
    assert len(times) == len(values)

    # Set an extra value before/after the first/last keyframe.
    if len(times) > 0:
        if before_value is not None:
            start_time = times[0]
            times = [start_time - 1] + times
            values = [before_value] + values
        if after_value is not None:
            end_time = times[-1]
            times = times + [end_time + 1]
            values = values + [after_value]

    # Reduce keyframes, we don't need per-frame keyframes if the data
    # is the same. Change the times/values just before we set the
    # keyframes
    if reduce_keys is True:
        tmp_times = list(times)
        tmp_values = list(values)
        times = []
        values = []
        prev_t = None
        prev_v = None
        for t, v in zip(tmp_times, tmp_values):
            if prev_v is None:
                times.append(t)
                values.append(v)
            elif interface.float_is_equal(prev_v, v) is False:
                times.append(prev_t)
                values.append(prev_v)
                times.append(t)
                values.append(v)
            prev_t = t
            prev_v = v

    node_attr = node + '.' + attr_name
    anim_fn = anim_utils.create_anim_curve_node_apione(times, values,
                                                       node_attr)

    if reduce_keys is True:
        locked = maya.cmds.getAttr(node_attr, lock=True)
        maya.cmds.setAttr(node_attr, lock=False)
        maya.cmds.delete(node_attr, staticChannels=True)
        maya.cmds.setAttr(node_attr, lock=locked)
    return anim_fn
예제 #2
0
def calculate_overscan_ratio(cam, mkr_grp, camera_fov):
    """Calculate overscan with camera and FOV.

    Query the overscan of cam by comparing to the camera_fov
    field of view.

    :param cam:
        The mmSolver.api.Camera object to query field of view from.
    :type cam: Camera

    :param camera_fov:
        Tuple of camera field of view per-frame values X and Y.
    :type camera_fov: [(int, float, float), ..]

    :param mkr_grp:
        The mmapi MarkerGroup object, to be used additionally to the
        provided camera to calculate the overscan.
    :type mkr_grp: MarkerGroup or None

    :returns: Overscan X and Y values.
    :rtype: (float, float)

    """
    assert isinstance(cam, mmapi.Camera)
    assert isinstance(camera_fov, list)
    assert mkr_grp is None or isinstance(mkr_grp, mmapi.MarkerGroup)

    cam_shp = cam.get_shape_node()
    frames = [f for f, _, _ in camera_fov]
    maya_camera_fov = get_camera_field_of_view(cam_shp, frames)

    x = 1.0
    y = 1.0
    all_same_ratio_x = True
    all_same_ratio_y = True
    last_ratio_x = None
    last_ratio_y = None
    for file_fov, maya_fov in zip(camera_fov, maya_camera_fov):
        file_frame, file_angle_x, file_angle_y = file_fov
        maya_frame, maya_angle_x, maya_angle_y = maya_fov

        file_fov_x = math.tan(math.radians(file_angle_x * 0.5))
        file_fov_y = math.tan(math.radians(file_angle_y * 0.5))
        maya_fov_x = math.tan(math.radians(maya_angle_x * 0.5))
        maya_fov_y = math.tan(math.radians(maya_angle_y * 0.5))

        ratio_x = maya_fov_x / file_fov_x
        ratio_y = maya_fov_y / file_fov_y
        if last_ratio_x is None and last_ratio_y is None:
            last_ratio_x = ratio_x
            last_ratio_y = ratio_y

        ratio_same_x = interface.float_is_equal(ratio_x, last_ratio_x)
        ratio_same_y = interface.float_is_equal(ratio_y, last_ratio_y)
        if not ratio_same_x:
            all_same_ratio_x = False
        if not ratio_same_y:
            all_same_ratio_y = False
        if all_same_ratio_x is True or all_same_ratio_y is True:
            x = ratio_x
            y = ratio_y
        else:
            x = 1.0
            y = 1.0
            break

    # Account for MarkerGroup overscan.
    #
    # NOTE: We assume that the overscanX/Y values are NOT changing
    # over time.
    mkr_grp_overscan_x = 1.0
    mkr_grp_overscan_y = 1.0
    if mkr_grp is not None:
        mkr_grp_node = mkr_grp.get_node()
        if mkr_grp_node is not None:
            attr_x = mkr_grp_node + '.overscanX'
            attr_y = mkr_grp_node + '.overscanY'
            mkr_grp_overscan_x = maya.cmds.getAttr(attr_x)
            mkr_grp_overscan_y = maya.cmds.getAttr(attr_y)
    x = mkr_grp_overscan_x / x
    y = mkr_grp_overscan_y / y
    return x, y