545 lines
18 KiB
C++
545 lines
18 KiB
C++
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup editors
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "BLI_array.hh"
|
|
#include "BLI_math_vector_types.hh"
|
|
|
|
#include "ED_anim_api.hh" /* for enum eAnimFilter_Flags */
|
|
|
|
struct BezTriple;
|
|
struct ButterworthCoefficients;
|
|
struct FCurve;
|
|
struct Scene;
|
|
struct bAnimContext;
|
|
struct bAnimListElem;
|
|
struct bDopeSheet;
|
|
|
|
/* ************************************************ */
|
|
/* Common Macros and Defines */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Tool Flags
|
|
* \{ */
|
|
|
|
/** bezt validation. */
|
|
enum eEditKeyframes_Validate {
|
|
/* Frame range */
|
|
BEZT_OK_FRAME = 1,
|
|
BEZT_OK_FRAMERANGE,
|
|
/* Selection status */
|
|
BEZT_OK_SELECTED,
|
|
/* Values (y-val) only */
|
|
BEZT_OK_VALUE,
|
|
BEZT_OK_VALUERANGE,
|
|
/* For graph editor keyframes (2D tests) */
|
|
BEZT_OK_REGION,
|
|
BEZT_OK_REGION_LASSO,
|
|
BEZT_OK_REGION_CIRCLE,
|
|
/* Only for keyframes a certain Dopesheet channel */
|
|
BEZT_OK_CHANNEL_LASSO,
|
|
BEZT_OK_CHANNEL_CIRCLE,
|
|
};
|
|
|
|
/** \} */
|
|
|
|
/* select modes */
|
|
enum eEditKeyframes_Select {
|
|
/* SELECT_SUBTRACT for all, followed by SELECT_ADD for some */
|
|
SELECT_REPLACE = (1 << 0),
|
|
/* add ok keyframes to selection */
|
|
SELECT_ADD = (1 << 1),
|
|
/* remove ok keyframes from selection */
|
|
SELECT_SUBTRACT = (1 << 2),
|
|
/* flip ok status of keyframes based on key status */
|
|
SELECT_INVERT = (1 << 3),
|
|
SELECT_EXTEND_RANGE = (1 << 4),
|
|
};
|
|
|
|
/* "selection map" building modes. */
|
|
enum eEditKeyframes_SelMap {
|
|
SELMAP_MORE = 0,
|
|
SELMAP_LESS,
|
|
};
|
|
|
|
/* snapping tools */
|
|
enum eEditKeyframes_Snap {
|
|
SNAP_KEYS_CURFRAME = 1,
|
|
SNAP_KEYS_NEARFRAME,
|
|
SNAP_KEYS_NEARSEC,
|
|
SNAP_KEYS_NEARMARKER,
|
|
SNAP_KEYS_HORIZONTAL,
|
|
SNAP_KEYS_VALUE,
|
|
SNAP_KEYS_TIME,
|
|
};
|
|
|
|
/* equalizing tools */
|
|
enum eEditKeyframes_Equalize {
|
|
EQUALIZE_HANDLES_LEFT = (1 << 0),
|
|
EQUALIZE_HANDLES_RIGHT = (1 << 1),
|
|
EQUALIZE_HANDLES_BOTH = (EQUALIZE_HANDLES_LEFT | EQUALIZE_HANDLES_RIGHT),
|
|
};
|
|
|
|
/* mirroring tools */
|
|
enum eEditKeyframes_Mirror {
|
|
MIRROR_KEYS_CURFRAME = 1,
|
|
MIRROR_KEYS_YAXIS,
|
|
MIRROR_KEYS_XAXIS,
|
|
MIRROR_KEYS_MARKER,
|
|
MIRROR_KEYS_VALUE,
|
|
MIRROR_KEYS_TIME,
|
|
};
|
|
|
|
/* use with BEZT_OK_REGION_LASSO */
|
|
struct KeyframeEdit_LassoData {
|
|
rctf *rectf_scaled;
|
|
const rctf *rectf_view;
|
|
blender::Array<blender::int2> mcoords;
|
|
};
|
|
|
|
/* use with BEZT_OK_REGION_CIRCLE */
|
|
struct KeyframeEdit_CircleData {
|
|
rctf *rectf_scaled;
|
|
const rctf *rectf_view;
|
|
float mval[2];
|
|
float radius_squared;
|
|
};
|
|
|
|
/* ************************************************ */
|
|
/* Non-Destructive Editing API (keyframes_edit.cc) */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Defines for 'OK' polls + KeyframeEditData Flags
|
|
* \{ */
|
|
|
|
/* which verts of a keyframe is active (after polling) */
|
|
enum eKeyframeVertOk {
|
|
KEYFRAME_NONE = 0,
|
|
/* 'key' itself is ok */
|
|
KEYFRAME_OK_KEY = (1 << 0),
|
|
/* 'handle 1' is ok */
|
|
KEYFRAME_OK_H1 = (1 << 1),
|
|
/* 'handle 2' is ok */
|
|
KEYFRAME_OK_H2 = (1 << 2),
|
|
/* all flags */
|
|
KEYFRAME_OK_ALL = (KEYFRAME_OK_KEY | KEYFRAME_OK_H1 | KEYFRAME_OK_H2),
|
|
};
|
|
|
|
/* Flags for use during iteration */
|
|
enum eKeyframeIterFlags {
|
|
/* consider handles in addition to key itself */
|
|
KEYFRAME_ITER_INCL_HANDLES = (1 << 0),
|
|
|
|
/* Perform NLA time remapping (global -> strip) for the "f1" parameter
|
|
* (e.g. used for selection tools on summary tracks)
|
|
*/
|
|
KED_F1_NLA_UNMAP = (1 << 1),
|
|
|
|
/* Perform NLA time remapping (global -> strip) for the "f2" parameter */
|
|
KED_F2_NLA_UNMAP = (1 << 2),
|
|
|
|
/* Set this when handles aren't visible by default and you want to perform additional checks to
|
|
* get the actual visibility state. E.g. in some cases handles are only drawn if either a handle
|
|
* or their control point is selected. The selection state will have to be checked in the
|
|
* iterator callbacks then. */
|
|
KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE = (1 << 3),
|
|
};
|
|
ENUM_OPERATORS(eKeyframeIterFlags, KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE)
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Generic Properties for Keyframe Edit Tools
|
|
* \{ */
|
|
|
|
/**
|
|
* Temporary struct used to store frame time and selection status.
|
|
* Used for example by `columnselect_action_keys` to select all keyframes in a column.
|
|
*/
|
|
struct CfraElem {
|
|
CfraElem *next, *prev;
|
|
float cfra;
|
|
int sel;
|
|
};
|
|
|
|
struct KeyframeEditData {
|
|
/* generic properties/data access */
|
|
/** temp list for storing custom list of data to check */
|
|
ListBase list;
|
|
/** pointer to current scene - many tools need access to cfra/etc. */
|
|
Scene *scene;
|
|
/** pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */
|
|
void *data;
|
|
/** storage of times/values as 'decimals' */
|
|
float f1, f2;
|
|
/** storage of times/values/flags as 'whole' numbers */
|
|
int i1, i2;
|
|
|
|
/* current iteration data */
|
|
/** F-Curve that is being iterated over */
|
|
FCurve *fcu;
|
|
/** index of current keyframe being iterated over */
|
|
int curIndex;
|
|
/** y-position of midpoint of the channel (for the dopesheet) */
|
|
float channel_y;
|
|
|
|
/* flags */
|
|
/** current flags for the keyframe we're reached in the iteration process */
|
|
eKeyframeVertOk curflags;
|
|
/** settings for iteration process */
|
|
eKeyframeIterFlags iterflags;
|
|
};
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Function Pointer Typedefs
|
|
* \{ */
|
|
|
|
/** Callback function that refreshes the F-Curve after use. */
|
|
using FcuEditFunc = void (*)(FCurve *fcu);
|
|
/** Callback function that operates on the given #BezTriple. */
|
|
using KeyframeEditFunc = short (*)(KeyframeEditData *ked, BezTriple *bezt);
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Custom Data Type Defines
|
|
* \{ */
|
|
|
|
/** Custom data for remapping one range to another in a fixed way. */
|
|
struct KeyframeEditCD_Remap {
|
|
float oldMin, oldMax; /* old range */
|
|
float newMin, newMax; /* new range */
|
|
};
|
|
|
|
/** Paste options. */
|
|
enum eKeyPasteOffset {
|
|
/** Paste keys starting at current frame. */
|
|
KEYFRAME_PASTE_OFFSET_CFRA_START,
|
|
/** Paste keys ending at current frame. */
|
|
KEYFRAME_PASTE_OFFSET_CFRA_END,
|
|
/** Paste keys relative to the current frame when copying. */
|
|
KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE,
|
|
/** Paste keys from original time. */
|
|
KEYFRAME_PASTE_OFFSET_NONE,
|
|
};
|
|
|
|
enum eKeyPasteValueOffset {
|
|
/** Paste keys with the first key matching the key left of the cursor. */
|
|
KEYFRAME_PASTE_VALUE_OFFSET_LEFT_KEY,
|
|
/** Paste keys with the last key matching the key right of the cursor. */
|
|
KEYFRAME_PASTE_VALUE_OFFSET_RIGHT_KEY,
|
|
/** Paste keys relative to the value of the curve under the cursor. */
|
|
KEYFRAME_PASTE_VALUE_OFFSET_CFRA,
|
|
/** Paste values relative to the cursor position. */
|
|
KEYFRAME_PASTE_VALUE_OFFSET_CURSOR,
|
|
/** Paste keys with the exact copied value. */
|
|
KEYFRAME_PASTE_VALUE_OFFSET_NONE,
|
|
};
|
|
|
|
enum eKeyMergeMode {
|
|
/** Overlay existing with new keys. */
|
|
KEYFRAME_PASTE_MERGE_MIX,
|
|
/** Replace entire fcurve. */
|
|
KEYFRAME_PASTE_MERGE_OVER,
|
|
/** Overwrite keys in pasted range. */
|
|
KEYFRAME_PASTE_MERGE_OVER_RANGE,
|
|
/** Overwrite keys in pasted range (use all keyframe start & end for range). */
|
|
KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL,
|
|
};
|
|
|
|
/** Possible errors occurring while pasting keys. */
|
|
enum eKeyPasteError {
|
|
/** No errors occurred. */
|
|
KEYFRAME_PASTE_OK,
|
|
/** Nothing was copied. */
|
|
KEYFRAME_PASTE_NOTHING_TO_PASTE,
|
|
/** No F-curves was selected to paste into. */
|
|
KEYFRAME_PASTE_NOWHERE_TO_PASTE
|
|
};
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Looping API
|
|
*
|
|
* Functions for looping over keyframes.
|
|
* \{ */
|
|
|
|
/**
|
|
* This function is used to loop over BezTriples in the given F-Curve, applying a given
|
|
* operation on them, and optionally applies an F-Curve validation function afterwards.
|
|
*
|
|
* function for working with F-Curve data only
|
|
* (i.e. when filters have been chosen to explicitly use this).
|
|
*/
|
|
short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked,
|
|
FCurve *fcu,
|
|
KeyframeEditFunc key_ok,
|
|
KeyframeEditFunc key_cb,
|
|
FcuEditFunc fcu_cb);
|
|
/**
|
|
* Sets selected keyframes' bezier handles to an equal length and optionally makes
|
|
* the keyframes' handles horizontal.
|
|
* \param handle_length: Desired handle length, must be positive.
|
|
* \param flatten: Makes the keyframes' handles the same value as the keyframe,
|
|
* flattening the curve at that point.
|
|
*/
|
|
void ANIM_fcurve_equalize_keyframes_loop(FCurve *fcu,
|
|
eEditKeyframes_Equalize mode,
|
|
float handle_length,
|
|
bool flatten);
|
|
|
|
/**
|
|
* Function for working with any type (i.e. one of the known types) of animation channel.
|
|
*/
|
|
short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked,
|
|
bDopeSheet *ads,
|
|
bAnimListElem *ale,
|
|
KeyframeEditFunc key_ok,
|
|
KeyframeEditFunc key_cb,
|
|
FcuEditFunc fcu_cb);
|
|
/**
|
|
* Same as above, except bAnimListElem wrapper is not needed.
|
|
* \param keytype: is #eAnim_KeyType.
|
|
*/
|
|
short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked,
|
|
bDopeSheet *ads,
|
|
void *data,
|
|
int keytype,
|
|
KeyframeEditFunc key_ok,
|
|
KeyframeEditFunc key_cb,
|
|
FcuEditFunc fcu_cb);
|
|
|
|
/**
|
|
* Calls callback_fn() for each keyframe in each fcurve in the filtered animation context.
|
|
* Assumes the callback updates keys.
|
|
*/
|
|
void ANIM_animdata_keyframe_callback(bAnimContext *ac,
|
|
eAnimFilter_Flags filter,
|
|
KeyframeEditFunc callback_fn);
|
|
|
|
/**
|
|
* Functions for making sure all keyframes are in good order.
|
|
*/
|
|
void ANIM_editkeyframes_refresh(bAnimContext *ac);
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name BezTriple Callback Getters
|
|
* \{ */
|
|
|
|
/* accessories */
|
|
KeyframeEditFunc ANIM_editkeyframes_ok(short mode);
|
|
|
|
/* edit */
|
|
KeyframeEditFunc ANIM_editkeyframes_snap(short mode);
|
|
/**
|
|
* \note for markers and 'value', the values to use must be supplied as the first float value.
|
|
*/
|
|
KeyframeEditFunc ANIM_editkeyframes_mirror(short mode);
|
|
KeyframeEditFunc ANIM_editkeyframes_select(short mode);
|
|
/**
|
|
* Set all selected Bezier Handles to a single type.
|
|
*/
|
|
KeyframeEditFunc ANIM_editkeyframes_handles(short mode);
|
|
/**
|
|
* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one.
|
|
*/
|
|
KeyframeEditFunc ANIM_editkeyframes_ipo(short mode);
|
|
KeyframeEditFunc ANIM_editkeyframes_keytype(short mode);
|
|
KeyframeEditFunc ANIM_editkeyframes_easing(short mode);
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name BezTriple Callbacks (Selection Map)
|
|
* \{ */
|
|
|
|
/**
|
|
* Get a callback to populate the selection settings map
|
|
* requires: `ked->custom = char[]` of length `fcurve->totvert`.
|
|
*/
|
|
KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode);
|
|
|
|
/**
|
|
* Change the selection status of the keyframe based on the map entry for this vert
|
|
* requires: `ked->custom = char[]` of length `fcurve->totvert`.
|
|
*/
|
|
short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt);
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name BezTriple Callback (Assorted Utilities)
|
|
* \{ */
|
|
|
|
/**
|
|
* Used to calculate the average location of all relevant BezTriples by summing their locations.
|
|
*/
|
|
short bezt_calc_average(KeyframeEditData *ked, BezTriple *bezt);
|
|
|
|
/**
|
|
* Used to extract a set of cfra-elems from the keyframes.
|
|
*/
|
|
short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt);
|
|
|
|
/**
|
|
* Used to remap times from one range to another.
|
|
* requires: `ked->custom = KeyframeEditCD_Remap`.
|
|
*/
|
|
void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt);
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name 1.5-D Region Testing Utilities (Lasso/Circle Select)
|
|
* \{ */
|
|
|
|
/* XXX: These are temporary,
|
|
* until we can unify GP/Mask Keyframe handling and standard FCurve Keyframe handling */
|
|
|
|
bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const float xy[2]);
|
|
|
|
bool keyframe_region_circle_test(const KeyframeEdit_CircleData *data_circle, const float xy[2]);
|
|
|
|
/* ************************************************ */
|
|
/* Destructive Editing API `keyframes_general.cc`. */
|
|
|
|
bool duplicate_fcurve_keys(FCurve *fcu);
|
|
float get_default_rna_value(FCurve *fcu, PropertyRNA *prop, PointerRNA *ptr);
|
|
|
|
struct FCurveSegment {
|
|
FCurveSegment *next, *prev;
|
|
int start_index, length;
|
|
};
|
|
|
|
/**
|
|
* Return a list of #FCurveSegment with a start index and a length.
|
|
* A segment is a continuous selection of keyframes.
|
|
* Keys that have BEZT_FLAG_IGNORE_TAG set are treated as unselected.
|
|
* The caller is responsible for freeing the memory.
|
|
*/
|
|
ListBase find_fcurve_segments(FCurve *fcu);
|
|
void clean_fcurve(bAnimContext *ac,
|
|
bAnimListElem *ale,
|
|
float thresh,
|
|
bool cleardefault,
|
|
bool only_selected_keys);
|
|
void blend_to_neighbor_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
|
|
void breakdown_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
|
|
void scale_average_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
|
|
void push_pull_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
|
|
/** Used for operators that need a reference key of the segment to work. */
|
|
enum class FCurveSegmentAnchor { LEFT, RIGHT };
|
|
void scale_from_fcurve_segment_neighbor(FCurve *fcu,
|
|
FCurveSegment *segment,
|
|
float factor,
|
|
FCurveSegmentAnchor anchor);
|
|
/**
|
|
* Get a 1D gauss kernel. Since the kernel is symmetrical, only calculates the positive side.
|
|
* \param sigma: The shape of the gauss distribution.
|
|
* \param kernel_size: How long the kernel array is.
|
|
*/
|
|
void ED_ANIM_get_1d_gauss_kernel(const float sigma, int kernel_size, double *r_kernel);
|
|
|
|
ButterworthCoefficients *ED_anim_allocate_butterworth_coefficients(const int filter_order);
|
|
void ED_anim_free_butterworth_coefficients(ButterworthCoefficients *bw_coeff);
|
|
void ED_anim_calculate_butterworth_coefficients(float cutoff,
|
|
float sampling_frequency,
|
|
ButterworthCoefficients *bw_coeff);
|
|
/**
|
|
* \param samples: Are expected to start at the first frame of the segment with a buffer of size
|
|
* `segment->filter_order` at the left.
|
|
*/
|
|
void butterworth_smooth_fcurve_segment(FCurve *fcu,
|
|
FCurveSegment *segment,
|
|
float *samples,
|
|
int sample_count,
|
|
float factor,
|
|
int blend_in_out,
|
|
int sample_rate,
|
|
ButterworthCoefficients *bw_coeff);
|
|
void smooth_fcurve_segment(FCurve *fcu,
|
|
FCurveSegment *segment,
|
|
float *samples,
|
|
float factor,
|
|
int kernel_size,
|
|
double *kernel);
|
|
/**
|
|
* Snap the keys on the given FCurve segment to an S-Curve. By modifying the `factor` the part of
|
|
* the S-Curve that the keys are snapped to is moved on the x-axis.
|
|
*/
|
|
void ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor, float width);
|
|
|
|
enum tShearDirection {
|
|
SHEAR_FROM_LEFT = 1,
|
|
SHEAR_FROM_RIGHT,
|
|
};
|
|
void shear_fcurve_segment(FCurve *fcu,
|
|
FCurveSegment *segment,
|
|
float factor,
|
|
tShearDirection direction);
|
|
/**
|
|
* Shift the FCurve segment up/down so that it aligns with the key before/after
|
|
* the segment.
|
|
*
|
|
* \param factor: blend factor from -1.0 to 1.0. The sign determines whether the
|
|
* segment is aligned with the key before or after the segment.
|
|
*/
|
|
void blend_offset_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
|
|
void blend_to_ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
|
|
void time_offset_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float frame_offset);
|
|
bool decimate_fcurve(bAnimListElem *ale, float remove_ratio, float error_sq_max);
|
|
bool match_slope_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
|
|
|
|
/**
|
|
* Blends the selected keyframes to the default value of the property the F-curve drives.
|
|
*/
|
|
void blend_to_default_fcurve(PointerRNA *id_ptr, FCurve *fcu, float factor);
|
|
/**
|
|
* Use a weighted moving-means method to reduce intensity of fluctuations.
|
|
*/
|
|
void smooth_fcurve(FCurve *fcu);
|
|
void bake_fcurve_segments(FCurve *fcu);
|
|
/**
|
|
* \param sample_rate: indicates how many samples per frame should be generated.
|
|
*/
|
|
void sample_fcurve_segment(
|
|
FCurve *fcu, float start_frame, float sample_rate, float *r_samples, int sample_count);
|
|
|
|
enum class BakeCurveRemove {
|
|
REMOVE_NONE = 0,
|
|
REMOVE_IN_RANGE = 1,
|
|
REMOVE_OUT_RANGE = 2,
|
|
REMOVE_ALL = 3,
|
|
};
|
|
/** Creates keyframes in the given range at the given step interval.
|
|
* \param range: start and end frame to bake. Is inclusive on both ends.
|
|
* \param remove_existing: choice which keys to remove in relation to the given range.
|
|
*/
|
|
void bake_fcurve(FCurve *fcu, blender::int2 range, float step, BakeCurveRemove remove_existing);
|
|
|
|
/* ----------- */
|
|
|
|
void ANIM_fcurves_copybuf_free();
|
|
short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data);
|
|
eKeyPasteError paste_animedit_keys(bAnimContext *ac,
|
|
ListBase *anim_data,
|
|
eKeyPasteOffset offset_mode,
|
|
eKeyPasteValueOffset value_offset_mode,
|
|
eKeyMergeMode merge_mode,
|
|
bool flip);
|
|
|
|
/* ************************************************ */
|
|
|
|
/** \} */
|