Animation: Add GP layers in regular Dopesheet

Grease Pencil animation channels are now also shown in the Dopesheet
mode of the Dopesheet editor and in the Timeline.

Grease pencil related events are now listened not only by container
`SACTCONT_GPENCIL` (Grease Pencil Dopesheet), but also
`SACTCONT_DOPESHEET` (main Dopesheet), and `SACTCONT_TIMELINE`
(timeline).

A new Animation Filter flag was added: `ANIMFILTER_FCURVESONLY`. For now
this only filters out Grease Pencil Layer channels.

**Implemented:**

- Preview range set: now only considers selected Grease Pencil keyframes
  when `onlySel` parameter is true. Not only this allows the operator to
  work with grease pencil keyframes in main dopesheet, but it also fixes
  the operator in the Grease Pencil dopesheet.
- Translation: allocation (and freeing) of specific memory for
  translation of Grease Pencil keyframes.
- Copy/Paste: call to both Fcurve and GPencil operators, to allow for
  mixed selection. Errors are only reported when both the FCurve and
  GPencil functions fail to paste anything.
- Keyframe Type change and Insert Keyframe: removed some code here to
  unify Grease Pencil dopesheet and main dopesheet code.

- Jump, Snap, Mirror, Select all/box/lasso/circle, Select left/right,
  Clickselect: account for Grease Pencil channels within the channels
  loop, no need for `ANIMFILTER_FCURVESONLY` there.

**Not Implemented:**

- Graph-related operators. The filter `ANIMFILTER_FCURVESONLY` is
  naively added to all graph-related operators, meaning more-or-less all
  operators that used `ANIMFILTER_CURVE_VISIBLE`.
- Select linked: is for F-curves channel only
- Select more/less: not yet implemented for grease pencil layers.
- Clean Keys, Sample, Extrapolation, Interpolation, Easing, and Handle
  type change: work on Fcurve-channels only, so the
  `ANIMFILTER_FCURVESONLY` filter is activated

Graying out these operators (when no fcurve keyframe is selected) can be
done with custom poll functions BUT may affect performance. This is NOT
done in this patch.

**Dopesheet Summary Selection:**

The main summary of the dopesheet now also takes into account Grease
Pencil keyframes, using some nasty copy/pasting of code, as explained
[on devtalk](https://devtalk.blender.org/t/gpencil-layers-integration-in-main-dopesheet-selection-issue/24527).
It works, but may be improved, providing some deeper changes.

Reviewed By: mendio, pepeland, sybren

Maniphest Tasks: T97477

Differential Revision: https://developer.blender.org/D15003
This commit is contained in:
Amélie Fondevilla 2022-06-30 15:16:05 +02:00 committed by Sybren A. Stüvel
parent 416aef4e13
commit 92d7f9ac56
Notes: blender-bot 2024-02-15 12:44:01 +01:00
Referenced by commit d1810d11f4, Fix T103303: Dbl-click in the Graph Editor wont select all keyframes
Referenced by commit 051a341cf0, Fix T99491: Crash when opening modifiers panel
Referenced by issue #99505, Regression: Crash when hit Tab key in Non Linear Animation panel
Referenced by issue #98661, 3.2: Potential candidates for corrective releases
Referenced by issue #97477, Dope Sheet standard mode does not show Grease Pencil keyframes
Referenced by pull request #118251, Fix #118225 possible crash double clicking on certain anim channels
22 changed files with 553 additions and 462 deletions

View File

@ -3123,7 +3123,7 @@ static bAnimChannelType ACF_DSSIMULATION = {
/* TODO: just get this from RNA? */
static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
{
return ICON_GREASEPENCIL;
return ICON_OUTLINER_DATA_GREASEPENCIL;
}
/* Get the appropriate flag(s) for the setting when it is valid. */

View File

@ -2033,7 +2033,7 @@ static void setflag_anim_channels(bAnimContext *ac,
if ((ac->spacetype == SPACE_GRAPH) && (ac->regiontype != RGN_TYPE_CHANNELS)) {
/* graph editor (case 2) */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_NODUPLIS);
ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
}
else {
/* standard case */

View File

@ -1925,6 +1925,9 @@ static size_t animdata_filter_ds_gpencil(
tmp_items += animfilter_block_data(ac, &tmp_data, ads, &gpd->id, filter_mode);
/* add Grease Pencil layers */
if (!(filter_mode & ANIMFILTER_FCURVESONLY)) {
tmp_items += animdata_filter_gpencil_layers_data(&tmp_data, ads, gpd, filter_mode);
}
/* TODO: do these need a separate expander?
* XXX: what order should these go in? */

View File

@ -1217,11 +1217,11 @@ const EnumPropertyItem rna_enum_keyframe_paste_merge_items[] = {
{0, NULL, 0, NULL, NULL},
};
short paste_animedit_keys(bAnimContext *ac,
ListBase *anim_data,
const eKeyPasteOffset offset_mode,
const eKeyMergeMode merge_mode,
bool flip)
eKeyPasteError paste_animedit_keys(bAnimContext *ac,
ListBase *anim_data,
const eKeyPasteOffset offset_mode,
const eKeyMergeMode merge_mode,
bool flip)
{
bAnimListElem *ale;
@ -1235,13 +1235,11 @@ short paste_animedit_keys(bAnimContext *ac,
/* check if buffer is empty */
if (BLI_listbase_is_empty(&animcopybuf)) {
BKE_report(ac->reports, RPT_ERROR, "No animation data in buffer to paste");
return -1;
return KEYFRAME_PASTE_NOTHING_TO_PASTE;
}
if (BLI_listbase_is_empty(anim_data)) {
BKE_report(ac->reports, RPT_ERROR, "No selected F-Curves to paste into");
return -1;
return KEYFRAME_PASTE_NOWHERE_TO_PASTE;
}
/* methods of offset */
@ -1335,7 +1333,7 @@ short paste_animedit_keys(bAnimContext *ac,
ANIM_animdata_update(ac, anim_data);
return 0;
return KEYFRAME_PASTE_OK;
}
/* **************************************************** */

View File

@ -214,6 +214,18 @@ void ED_gpencil_layer_frames_select_region(KeyframeEditData *ked,
}
}
void ED_gpencil_set_active_channel(bGPdata *gpd, bGPDlayer *gpl)
{
gpl->flag |= GP_LAYER_SELECT;
/* Update other layer status. */
if (BKE_gpencil_layer_active_get(gpd) != gpl) {
BKE_gpencil_layer_active_set(gpd, gpl);
BKE_gpencil_layer_autolock_set(gpd, false);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
}
/* ***************************************** */
/* Frame Editing Tools */
@ -316,8 +328,13 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* assume that each of these is a GP layer */
for (ale = anim_data.first; ale; ale = ale->next) {
/* This function only deals with grease pencil layer frames.
* This check is needed in the case of a call from the main dopesheet. */
if (ale->type != ANIMTYPE_GPLAYER) {
continue;
}
ListBase copied_frames = {NULL, NULL};
bGPDlayer *gpl = (bGPDlayer *)ale->data;
@ -359,14 +376,8 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
/* clean up */
ANIM_animdata_freelist(&anim_data);
/* check if anything ended up in the buffer */
if (ELEM(NULL, gpencil_anim_copybuf.first, gpencil_anim_copybuf.last)) {
BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
return false;
}
/* report success */
return true;
return !BLI_listbase_is_empty(&gpencil_anim_copybuf);
}
bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
@ -381,7 +392,6 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
/* check if buffer is empty */
if (BLI_listbase_is_empty(&gpencil_anim_copybuf)) {
BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste");
return false;
}
@ -414,6 +424,11 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
/* from selected channels */
for (ale = anim_data.first; ale; ale = ale->next) {
/* only deal with GPlayers (case of calls from general dopesheet) */
if (ale->type != ANIMTYPE_GPLAYER) {
continue;
}
bGPDlayer *gpld = (bGPDlayer *)ale->data;
bGPDlayer *gpls = NULL;
bGPDframe *gpfs, *gpf;

View File

@ -324,11 +324,15 @@ typedef enum eAnimFilter_Flags {
/** duplicate entries for animation data attached to multi-user blocks must not occur */
ANIMFILTER_NODUPLIS = (1 << 11),
/** avoid channel that does not have any F-curve data */
ANIMFILTER_FCURVESONLY = (1 << 12),
/** for checking if we should keep some collapsed channel around (internal use only!) */
ANIMFILTER_TMP_PEEK = (1 << 30),
/** Ignore ONLYSEL flag from #bDopeSheet.filterflag (internal use only!) */
ANIMFILTER_TMP_IGNORE_ONLYSEL = (1u << 31),
} eAnimFilter_Flags;
/** \} */

View File

@ -280,6 +280,11 @@ void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode);
*/
void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode);
/**
* Set the layer's channel as active
*/
void ED_gpencil_set_active_channel(struct bGPdata *gpd, struct bGPDlayer *gpl);
/**
* Delete selected frames.
*/

View File

@ -229,6 +229,16 @@ typedef enum eKeyMergeMode {
KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL,
} eKeyMergeMode;
/* Possible errors occurring while pasting keys. */
typedef 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
} eKeyPasteError;
/** \} */
/* -------------------------------------------------------------------- */
@ -416,11 +426,11 @@ void sample_fcurve(struct FCurve *fcu);
void ANIM_fcurves_copybuf_free(void);
short copy_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
short paste_animedit_keys(struct bAnimContext *ac,
ListBase *anim_data,
eKeyPasteOffset offset_mode,
eKeyMergeMode merge_mode,
bool flip);
eKeyPasteError paste_animedit_keys(struct bAnimContext *ac,
ListBase *anim_data,
eKeyPasteOffset offset_mode,
eKeyMergeMode merge_mode,
bool flip);
/* ************************************************ */

View File

@ -995,7 +995,7 @@ static eContextResult screen_ctx_sel_actions_impl(const bContext *C,
switch (ac.spacetype) {
case SPACE_GRAPH:
filter |= ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL;
filter |= ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL;
break;
case SPACE_ACTION:
@ -1059,8 +1059,9 @@ static eContextResult screen_ctx_sel_edit_fcurves_(const bContext *C,
ListBase anim_data = {NULL, NULL};
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS) |
(ac.spacetype == SPACE_GRAPH ? ANIMFILTER_CURVE_VISIBLE :
ANIMFILTER_LIST_VISIBLE) |
(ac.spacetype == SPACE_GRAPH ?
(ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY) :
ANIMFILTER_LIST_VISIBLE) |
extra_filter;
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@ -1104,7 +1105,7 @@ static eContextResult screen_ctx_active_editable_fcurve(const bContext *C,
ListBase anim_data = {NULL, NULL};
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT |
ANIMFILTER_CURVE_VISIBLE);
ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@ -1130,8 +1131,9 @@ static eContextResult screen_ctx_selected_editable_keyframes(const bContext *C,
/* Use keyframes from editable selected FCurves. */
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS | ANIMFILTER_FOREDIT |
ANIMFILTER_SEL) |
(ac.spacetype == SPACE_GRAPH ? ANIMFILTER_CURVE_VISIBLE :
ANIMFILTER_LIST_VISIBLE);
(ac.spacetype == SPACE_GRAPH ?
(ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY) :
ANIMFILTER_LIST_VISIBLE);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);

View File

@ -158,8 +158,7 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
/* get data to filter, from Action or Dopesheet */
/* XXX: what is sel doing here?!
* Commented it, was breaking things (eg. the "auto preview range" tool). */
filter = (ANIMFILTER_DATA_VISIBLE |
ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL */ /*| ANIMFILTER_CURVESONLY*/ |
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL */ |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -178,10 +177,12 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
/* Find gp-frame which is less than or equal to current-frame. */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
const float framenum = (float)gpf->framenum;
*min = min_ff(*min, framenum);
*max = max_ff(*max, framenum);
found = true;
if (!onlySel || (gpf->flag & GP_FRAME_SELECT)) {
const float framenum = (float)gpf->framenum;
*min = min_ff(*min, framenum);
*max = max_ff(*max, framenum);
found = true;
}
}
}
else if (ale->datatype == ALE_MASKLAY) {
@ -498,7 +499,7 @@ static short copy_action_keys(bAnimContext *ac)
ANIM_fcurves_copybuf_free();
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -511,13 +512,13 @@ static short copy_action_keys(bAnimContext *ac)
return ok;
}
static short paste_action_keys(bAnimContext *ac,
const eKeyPasteOffset offset_mode,
const eKeyMergeMode merge_mode,
bool flip)
static eKeyPasteError paste_action_keys(bAnimContext *ac,
const eKeyPasteOffset offset_mode,
const eKeyMergeMode merge_mode,
bool flip)
{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
int filter;
/* filter data
* - First time we try to filter more strictly, allowing only selected channels
@ -525,15 +526,15 @@ static short paste_action_keys(bAnimContext *ac,
* - Second time, we loosen things up if nothing was found the first time, allowing
* users to just paste keyframes back into the original curve again T31670.
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
}
/* paste keyframes */
ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
const eKeyPasteError ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
/* clean up */
ANIM_animdata_freelist(&anim_data);
@ -555,7 +556,8 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
/* copy keyframes */
if (ac.datatype == ANIMCONT_GPENCIL) {
if (ED_gpencil_anim_copybuf_copy(&ac) == false) {
/* Nothing got copied - An error about this should be been logged already */
/* check if anything ended up in the buffer */
BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
return OPERATOR_CANCELLED;
}
}
@ -565,7 +567,11 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else {
if (copy_action_keys(&ac)) {
/* Both copy function needs to be evaluated to account for mixed selection */
const short kf_empty = copy_action_keys(&ac);
const bool gpf_ok = ED_gpencil_anim_copybuf_copy(&ac);
if (kf_empty && !gpf_ok) {
BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
return OPERATOR_CANCELLED;
}
@ -597,6 +603,8 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
const bool flipped = RNA_boolean_get(op->ptr, "flipped");
bool gpframes_inbuf = false;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
@ -608,7 +616,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
/* paste keyframes */
if (ac.datatype == ANIMCONT_GPENCIL) {
if (ED_gpencil_anim_copybuf_paste(&ac, offset_mode) == false) {
/* An error occurred - Reports should have been fired already */
BKE_report(op->reports, RPT_ERROR, "No data in buffer to paste");
return OPERATOR_CANCELLED;
}
}
@ -620,14 +628,31 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else {
/* Both paste function needs to be evaluated to account for mixed selection */
const eKeyPasteError kf_empty = paste_action_keys(&ac, offset_mode, merge_mode, flipped);
/* non-zero return means an error occurred while trying to paste */
if (paste_action_keys(&ac, offset_mode, merge_mode, flipped)) {
return OPERATOR_CANCELLED;
gpframes_inbuf = ED_gpencil_anim_copybuf_paste(&ac, offset_mode);
/* Only report an error if nothing was pasted, i.e. when both FCurve and GPencil failed. */
if (!gpframes_inbuf) {
switch (kf_empty) {
case KEYFRAME_PASTE_OK:
/* FCurve paste was ok, so it's all good. */
break;
case KEYFRAME_PASTE_NOWHERE_TO_PASTE:
BKE_report(op->reports, RPT_ERROR, "No selected F-Curves to paste into");
return OPERATOR_CANCELLED;
case KEYFRAME_PASTE_NOTHING_TO_PASTE:
BKE_report(op->reports, RPT_ERROR, "No data in buffer to paste");
return OPERATOR_CANCELLED;
}
}
}
/* Grease Pencil needs extra update to refresh the added keyframes. */
if (ac.datatype == ANIMCONT_GPENCIL) {
if (ac.datatype == ANIMCONT_GPENCIL || gpframes_inbuf) {
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
}
/* set notifier that keyframes have changed */
@ -697,6 +722,72 @@ static const EnumPropertyItem prop_actkeys_insertkey_types[] = {
{0, NULL, 0, NULL, NULL},
};
static void insert_gpencil_key(bAnimContext *ac,
bAnimListElem *ale,
const eGP_GetFrame_Mode add_frame_mode,
bGPdata **gpd_old)
{
Scene *scene = ac->scene;
bGPdata *gpd = (bGPdata *)ale->id;
bGPDlayer *gpl = (bGPDlayer *)ale->data;
BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
/* Check if the gpd changes to tag only once. */
if (gpd != *gpd_old) {
BKE_gpencil_tag(gpd);
*gpd_old = gpd;
}
}
static void insert_fcurve_key(bAnimContext *ac,
bAnimListElem *ale,
const AnimationEvalContext anim_eval_context,
eInsertKeyFlags flag,
ListBase *nla_cache)
{
FCurve *fcu = (FCurve *)ale->key_data;
ReportList *reports = ac->reports;
Scene *scene = ac->scene;
ToolSettings *ts = scene->toolsettings;
/* Read value from property the F-Curve represents, or from the curve only?
* - ale->id != NULL:
* Typically, this means that we have enough info to try resolving the path.
*
* - ale->owner != NULL:
* If this is set, then the path may not be resolvable from the ID alone,
* so it's easier for now to just read the F-Curve directly.
* (TODO: add the full-blown PointerRNA relative parsing case here...)
*/
if (ale->id && !ale->owner) {
insert_keyframe(ac->bmain,
reports,
ale->id,
NULL,
((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path,
fcu->array_index,
&anim_eval_context,
ts->keyframe_type,
nla_cache,
flag);
}
else {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* adjust current frame for NLA-scaling */
float cfra = anim_eval_context.eval_time;
if (adt) {
cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
}
const float curval = evaluate_fcurve(fcu, cfra);
insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
}
ale->update |= ANIM_UPDATE_DEFAULT;
}
/* this function is responsible for inserting new keyframes */
static void insert_action_keys(bAnimContext *ac, short mode)
{
@ -705,14 +796,16 @@ static void insert_action_keys(bAnimContext *ac, short mode)
bAnimListElem *ale;
int filter;
ReportList *reports = ac->reports;
Scene *scene = ac->scene;
ToolSettings *ts = scene->toolsettings;
eInsertKeyFlags flag;
eGP_GetFrame_Mode add_frame_mode;
bGPdata *gpd_old = NULL;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
if (mode == 2) {
filter |= ANIMFILTER_SEL;
}
@ -725,97 +818,34 @@ static void insert_action_keys(bAnimContext *ac, short mode)
/* Init keyframing flag. */
flag = ANIM_get_keyframing_flags(scene, true);
/* insert keyframes */
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(ac->depsgraph,
(float)CFRA);
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu = (FCurve *)ale->key_data;
/* Read value from property the F-Curve represents, or from the curve only?
* - ale->id != NULL:
* Typically, this means that we have enough info to try resolving the path.
*
* - ale->owner != NULL:
* If this is set, then the path may not be resolvable from the ID alone,
* so it's easier for now to just read the F-Curve directly.
* (TODO: add the full-blown PointerRNA relative parsing case here...)
*/
if (ale->id && !ale->owner) {
insert_keyframe(ac->bmain,
reports,
ale->id,
NULL,
((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path,
fcu->array_index,
&anim_eval_context,
ts->keyframe_type,
&nla_cache,
flag);
}
else {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* adjust current frame for NLA-scaling */
float cfra = anim_eval_context.eval_time;
if (adt) {
cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
}
const float curval = evaluate_fcurve(fcu, cfra);
insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
}
ale->update |= ANIM_UPDATE_DEFAULT;
}
BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
/* this function is for inserting new grease pencil frames */
static void insert_gpencil_keys(bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
Scene *scene = ac->scene;
ToolSettings *ts = scene->toolsettings;
eGP_GetFrame_Mode add_frame_mode;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
if (mode == 2) {
filter |= ANIMFILTER_SEL;
}
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* add a copy or a blank frame? */
/* GPLayers specific flags */
if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
add_frame_mode = GP_GETFRAME_ADD_COPY; /* XXX: actframe may not be what we want? */
add_frame_mode = GP_GETFRAME_ADD_COPY;
}
else {
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
/* Insert gp frames. */
bGPdata *gpd_old = NULL;
/* insert keyframes */
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(ac->depsgraph,
(float)CFRA);
for (ale = anim_data.first; ale; ale = ale->next) {
bGPdata *gpd = (bGPdata *)ale->id;
bGPDlayer *gpl = (bGPDlayer *)ale->data;
BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
/* Check if the gpd changes to tag only once. */
if (gpd != gpd_old) {
BKE_gpencil_tag(gpd);
gpd_old = gpd;
switch (ale->type) {
case ANIMTYPE_GPLAYER:
insert_gpencil_key(ac, ale, add_frame_mode, &gpd_old);
break;
case ANIMTYPE_FCURVE:
insert_fcurve_key(ac, ale, anim_eval_context, flag, &nla_cache);
break;
default:
BLI_assert_msg(false, "Keys cannot be inserted into this animation type.");
}
}
BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@ -841,12 +871,7 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
mode = RNA_enum_get(op->ptr, "type");
/* insert keyframes */
if (ac.datatype == ANIMCONT_GPENCIL) {
insert_gpencil_keys(&ac, mode);
}
else {
insert_action_keys(&ac, mode);
}
insert_action_keys(&ac, mode);
/* set notifier that keyframes have changed */
if (ac.datatype == ANIMCONT_GPENCIL) {
@ -886,14 +911,8 @@ static bool duplicate_action_keys(bAnimContext *ac)
bool changed = false;
/* filter data */
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through filtered data and delete selected keys */
@ -968,14 +987,8 @@ static bool delete_action_keys(bAnimContext *ac)
bool changed_final = false;
/* filter data */
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through filtered data and delete selected keys */
@ -1063,7 +1076,7 @@ static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
ANIMFILTER_SEL | ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through filtered data and clean curves */
@ -1139,8 +1152,8 @@ static void sample_action_keys(bAnimContext *ac)
int filter;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and add keys between selected keyframes on every frame. */
@ -1238,7 +1251,7 @@ static void setexpo_action_keys(bAnimContext *ac, short mode)
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
ANIMFILTER_SEL | ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through setting mode per F-Curve */
@ -1352,7 +1365,8 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
/* set handle type */
ANIM_animdata_keyframe_callback(&ac,
(ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS),
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS |
ANIMFILTER_FCURVESONLY),
ANIM_editkeyframes_ipo(mode));
/* set notifier that keyframe properties have changed */
@ -1401,7 +1415,8 @@ static int actkeys_easing_exec(bContext *C, wmOperator *op)
/* set handle type */
ANIM_animdata_keyframe_callback(&ac,
(ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS),
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS |
ANIMFILTER_FCURVESONLY),
ANIM_editkeyframes_easing(mode));
/* set notifier that keyframe properties have changed */
@ -1444,8 +1459,8 @@ static void sethandles_action_keys(bAnimContext *ac, short mode)
KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting flags for handles
@ -1527,8 +1542,8 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode)
KeyframeEditFunc set_cb = ANIM_editkeyframes_keytype(mode);
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting BezTriple interpolation
@ -1536,32 +1551,19 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode)
* Currently that's not necessary here.
*/
for (ale = anim_data.first; ale; ale = ale->next) {
ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, NULL);
switch (ale->type) {
case ANIMTYPE_GPLAYER:
ED_gpencil_layer_frames_keytype_set(ale->data, mode);
ale->update |= ANIM_UPDATE_DEPS;
break;
ale->update |= ANIM_UPDATE_DEPS | ANIM_UPDATE_HANDLES;
}
case ANIMTYPE_FCURVE:
ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, NULL);
ale->update |= ANIM_UPDATE_DEPS | ANIM_UPDATE_HANDLES;
break;
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
/* this function is responsible for setting the keyframe type for Grease Pencil frames */
static void setkeytype_gpencil_keys(bAnimContext *ac, short mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through each layer */
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_layer_frames_keytype_set(ale->data, mode);
ale->update |= ANIM_UPDATE_DEPS;
default:
BLI_assert_msg(false, "Keytype cannot be set into this animation type.");
}
}
@ -1590,12 +1592,7 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
mode = RNA_enum_get(op->ptr, "type");
/* set handle type */
if (ac.datatype == ANIMCONT_GPENCIL) {
setkeytype_gpencil_keys(&ac, mode);
}
else {
setkeytype_action_keys(&ac, mode);
}
setkeytype_action_keys(&ac, mode);
/* set notifier that keyframe properties have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
@ -1653,19 +1650,44 @@ static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
/* init edit data */
/* loop over action data, averaging values */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
switch (ale->datatype) {
case ALE_GPFRAME: {
bGPDlayer *gpl = ale->data;
bGPDframe *gpf;
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
/* only if selected */
if (!(gpf->flag & GP_FRAME_SELECT)) {
continue;
}
/* store average time in float 1 (only do rounding at last step) */
ked.f1 += gpf->framenum;
/* increment number of items */
ked.i1++;
}
break;
}
case ALE_FCURVE: {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
}
break;
}
default:
BLI_assert_msg(false, "Cannot jump to keyframe into this animation type.");
}
}
@ -1742,8 +1764,8 @@ static void snap_action_keys(bAnimContext *ac, short mode)
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
}
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -1876,14 +1898,8 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
}
/* filter data */
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* mirror keyframes */

View File

@ -235,13 +235,7 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
KeyframeEditFunc test_cb, sel_cb;
/* determine type-based settings */
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
ANIMFILTER_NODUPLIS);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
/* filter data */
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -416,7 +410,7 @@ static void box_select_elem(
break;
}
if (ale->type == ANIMTYPE_SUMMARY && ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
if (ale->type == ANIMTYPE_SUMMARY) {
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
@ -428,8 +422,10 @@ static void box_select_elem(
ANIM_animdata_freelist(&anim_data);
}
ANIM_animchannel_keyframes_loop(
&sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
if (!ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
ANIM_animchannel_keyframes_loop(
&sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
}
}
}
}
@ -658,7 +654,7 @@ static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, b
break;
}
if (ale->type == ANIMTYPE_SUMMARY && ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
if (ale->type == ANIMTYPE_SUMMARY) {
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(ac, &anim_data, ANIMFILTER_DATA_VISIBLE, ac->data, ac->datatype);
@ -670,8 +666,10 @@ static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, b
ANIM_animdata_freelist(&anim_data);
}
ANIM_animchannel_keyframes_loop(
&sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
if (!ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
ANIM_animchannel_keyframes_loop(
&sel_data->ked, ac->ads, ale, sel_data->ok_cb, sel_data->select_cb, NULL);
}
}
}
}
@ -946,28 +944,36 @@ static void markers_selectkeys_between(bAnimContext *ac)
ked.f2 = max;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* select keys in-between */
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
switch (ale->type) {
case ANIMTYPE_GPLAYER:
ED_gpencil_layer_frames_select_box(ale->data, min, max, SELECT_ADD);
ale->update |= ANIM_UPDATE_DEPS;
break;
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
else if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_layer_frames_select_box(ale->data, min, max, SELECT_ADD);
ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_masklayer_frames_select_box(ale->data, min, max, SELECT_ADD);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
case ANIMTYPE_MASKLAYER:
ED_masklayer_frames_select_box(ale->data, min, max, SELECT_ADD);
break;
case ANIMTYPE_FCURVE: {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
break;
}
default:
BLI_assert_msg(false, "Keys cannot be selected into this animation type.");
}
}
@ -1000,11 +1006,16 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
}
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
if (ale->datatype == ALE_GPFRAME) {
ED_gpencil_layer_make_cfra_list(ale->data, &ked.list, 1);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
}
}
}
ANIM_animdata_freelist(&anim_data);
@ -1033,12 +1044,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
/* loop through all of the keys and select additional keyframes
* based on the keys found to be selected above
*/
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@ -1144,7 +1150,7 @@ static int actkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
}
/* loop through all of the keys and select additional keyframes based on these */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@ -1200,7 +1206,7 @@ static void select_moreless_action_keys(bAnimContext *ac, short mode)
build_cb = ANIM_editkeyframes_buildselmap(mode);
/* loop through all of the keys and select additional keyframes based on these */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -1354,33 +1360,36 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
}
/* filter data */
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ |
ANIMFILTER_NODUPLIS);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* select keys */
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
switch (ale->type) {
case ANIMTYPE_GPLAYER:
ED_gpencil_layer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
ale->update |= ANIM_UPDATE_DEPS;
break;
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
else if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_layer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_masklayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
case ANIMTYPE_MASKLAYER:
ED_masklayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
break;
case ANIMTYPE_FCURVE: {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
break;
}
default:
BLI_assert_msg(false, "Keys cannot be selected into this animation type.");
}
}
@ -1539,29 +1548,29 @@ static void actkeys_mselect_single(bAnimContext *ac,
ED_mask_select_frame(ale->data, selx, select_mode);
}
else {
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) && (ale->type == ANIMTYPE_SUMMARY) &&
(ale->datatype == ALE_ALL)) {
if (ale->type == ANIMTYPE_SUMMARY && ale->datatype == ALE_ALL) {
ListBase anim_data = {NULL, NULL};
int filter;
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->data, selx, select_mode);
ale->update |= ANIM_UPDATE_DEPS;
/* Loop over all keys that are represented by this summary key. */
LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
if (ale2->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale2->data, selx, select_mode);
ale2->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->data, selx, select_mode);
else if (ale2->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale2->data, selx, select_mode);
}
}
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
else {
if (!ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
}
}
@ -1588,35 +1597,29 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
/* loop through all of the keys and select additional keyframes
* based on the keys found to be selected above
*/
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
ANIMFILTER_NODUPLIS);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* set frame for validation callback to refer to */
if (adt) {
ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
}
else {
ked.f1 = selx;
}
/* select elements with frame number matching cfra */
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->key_data, selx, select_mode);
ED_gpencil_select_frame(ale->data, selx, select_mode);
ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->key_data, selx, select_mode);
ED_mask_select_frame(ale->data, selx, select_mode);
}
else {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* set frame for validation callback to refer to */
if (adt) {
ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
}
else {
ked.f1 = selx;
}
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
}
}
@ -1645,29 +1648,28 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
ED_mask_select_frames(ale->data, select_mode);
}
else {
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) && (ale->type == ANIMTYPE_SUMMARY) &&
(ale->datatype == ALE_ALL)) {
if (ale->type == ANIMTYPE_SUMMARY && ale->datatype == ALE_ALL) {
ListBase anim_data = {NULL, NULL};
int filter;
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frames(ale->data, select_mode);
ale->update |= ANIM_UPDATE_DEPS;
LISTBASE_FOREACH (bAnimListElem *, ale2, &anim_data) {
if (ale2->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frames(ale2->data, select_mode);
ale2->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frames(ale->data, select_mode);
else if (ale2->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frames(ale2->data, select_mode);
}
}
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
else {
if (!ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
ANIM_animchannel_keyframes_loop(NULL, ac->ads, ale, NULL, select_cb, NULL);
}
}
@ -1734,6 +1736,12 @@ static int mouse_action_keys(bAnimContext *ac,
fcu->flag |= FCURVE_SELECTED;
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
}
else if (ale->type == ANIMTYPE_GPLAYER) {
bGPdata *gpd = (bGPdata *)ale->id;
bGPDlayer *gpl = ale->data;
ED_gpencil_set_active_channel(gpd, gpl);
}
}
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
@ -1745,13 +1753,7 @@ static int mouse_action_keys(bAnimContext *ac,
bGPdata *gpd = (bGPdata *)ale->id;
bGPDlayer *gpl = ale->data;
gpl->flag |= GP_LAYER_SELECT;
/* Update other layer status. */
if (BKE_gpencil_layer_active_get(gpd) != gpl) {
BKE_gpencil_layer_active_set(gpd, gpl);
BKE_gpencil_layer_autolock_set(gpd, false);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
ED_gpencil_set_active_channel(gpd, gpl);
}
}
else if (ac->datatype == ANIMCONT_MASK) {

View File

@ -506,8 +506,8 @@ static void action_listener(const wmSpaceTypeListenerParams *params)
/* context changes */
switch (wmn->category) {
case NC_GPENCIL:
/* only handle these events in GPencil mode for performance considerations */
if (saction->mode == SACTCONT_GPENCIL) {
/* only handle these events for containers in which GPencil frames are displayed */
if (ELEM(saction->mode, SACTCONT_GPENCIL, SACTCONT_DOPESHEET, SACTCONT_TIMELINE)) {
if (wmn->action == NA_EDITED) {
ED_area_tag_redraw(area);
}

View File

@ -1348,7 +1348,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, shor
int filter;
/* build list of curves to draw */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY);
filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL));
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -1393,7 +1393,8 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
size_t items;
/* build list of channels to draw */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS |
ANIMFILTER_FCURVESONLY);
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Update max-extent of channels here (taking into account scrollers):

View File

@ -109,8 +109,8 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
eInsertKeyFlags flag = 0;
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
if (mode & GRAPHKEYS_INSERTKEY_SEL) {
filter |= ANIMFILTER_SEL;
}
@ -457,7 +457,8 @@ static short copy_graph_keys(bAnimContext *ac)
* - First time we try to filter more strictly, allowing only selected channels
* to allow copying animation between channels.
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -472,13 +473,13 @@ static short copy_graph_keys(bAnimContext *ac)
return ok;
}
static short paste_graph_keys(bAnimContext *ac,
const eKeyPasteOffset offset_mode,
const eKeyMergeMode merge_mode,
bool flip)
static eKeyPasteError paste_graph_keys(bAnimContext *ac,
const eKeyPasteOffset offset_mode,
const eKeyMergeMode merge_mode,
bool flip)
{
ListBase anim_data = {NULL, NULL};
int filter, ok = 0;
int filter;
/* Filter data
* - First time we try to filter more strictly, allowing only selected channels
@ -486,15 +487,15 @@ static short paste_graph_keys(bAnimContext *ac,
* - Second time, we loosen things up if nothing was found the first time, allowing
* users to just paste keyframes back into the original curve again T31670.
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0) {
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
}
/* Paste keyframes. */
ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
const eKeyPasteError ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode, flip);
/* Clean up. */
ANIM_animdata_freelist(&anim_data);
@ -554,9 +555,18 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
/* Ac.reports by default will be the global reports list, which won't show warnings. */
ac.reports = op->reports;
/* Paste keyframes - non-zero return means an error occurred while trying to paste. */
if (paste_graph_keys(&ac, offset_mode, merge_mode, flipped)) {
return OPERATOR_CANCELLED;
const eKeyPasteError kf_empty = paste_graph_keys(&ac, offset_mode, merge_mode, flipped);
switch (kf_empty) {
case KEYFRAME_PASTE_OK:
break;
case KEYFRAME_PASTE_NOWHERE_TO_PASTE:
BKE_report(op->reports, RPT_ERROR, "No selected F-Curves to paste into");
return OPERATOR_CANCELLED;
case KEYFRAME_PASTE_NOTHING_TO_PASTE:
BKE_report(op->reports, RPT_ERROR, "No data in buffer to paste");
return OPERATOR_CANCELLED;
}
/* Set notifier that keyframes have changed. */
@ -631,8 +641,8 @@ static bool duplicate_graph_keys(bAnimContext *ac)
bool changed = false;
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and delete selected keys. */
@ -702,8 +712,8 @@ static bool delete_graph_keys(bAnimContext *ac)
bool changed_final = false;
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and delete selected keys. */
@ -785,8 +795,8 @@ static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan)
int filter;
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and clean curves. */
@ -862,8 +872,8 @@ static void bake_graph_curves(bAnimContext *ac, int start, int end)
int filter;
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and add keys between selected keyframes on every frame. */
@ -949,8 +959,8 @@ static void unbake_graph_curves(bAnimContext *ac, int start, int end)
bAnimListElem *ale;
/* Filter data. */
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and add keys between selected keyframes on every frame. */
@ -1100,8 +1110,8 @@ static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op)
end = CFRA + sbi.length - 1;
/* Filter anim channels. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* Loop through all selected F-Curves, replacing its data with the sound samples. */
@ -1267,8 +1277,8 @@ static void sample_graph_keys(bAnimContext *ac)
int filter;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and add keys between selected keyframes on every frame. */
@ -1364,8 +1374,8 @@ static void setexpo_graph_keys(bAnimContext *ac, short mode)
int filter;
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting mode per F-Curve. */
@ -1469,8 +1479,8 @@ static void setipo_graph_keys(bAnimContext *ac, short mode)
KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo(mode);
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting BezTriple interpolation
@ -1547,8 +1557,8 @@ static void seteasing_graph_keys(bAnimContext *ac, short mode)
KeyframeEditFunc set_cb = ANIM_editkeyframes_easing(mode);
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting BezTriple easing.
@ -1625,8 +1635,8 @@ static void sethandles_graph_keys(bAnimContext *ac, short mode)
KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through setting flags for handles.
@ -1945,7 +1955,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
/* Step 1: extract only the rotation f-curves. */
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIMFILTER_FCURVESONLY | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@ -2056,7 +2066,8 @@ static KeyframeEditData sum_selected_keyframes(bAnimContext *ac)
memset(&ked, 0, sizeof(KeyframeEditData));
/* Loop over action data, averaging values. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@ -2240,8 +2251,8 @@ static void snap_graph_keys(bAnimContext *ac, short mode)
float cursor_value = 0.0f;
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Init custom data for iterating over keyframes. */
@ -2361,8 +2372,8 @@ static const EnumPropertyItem prop_graphkeys_equalize_handles_sides[] = {
static void equalize_graph_keys(bAnimContext *ac, int mode, float handle_length, bool flatten)
{
/* Filter data. */
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -2523,8 +2534,8 @@ static void mirror_graph_keys(bAnimContext *ac, short mode)
edit_cb = ANIM_editkeyframes_mirror(mode);
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Mirror keyframes. */
@ -2620,8 +2631,8 @@ static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op))
}
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* Smooth keyframes. */
@ -2720,7 +2731,8 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
type = RNA_enum_get(op->ptr, "type");
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS |
ANIMFILTER_FCURVESONLY);
if (RNA_boolean_get(op->ptr, "only_active")) {
/* FIXME: enforce in this case only a single channel to get handled? */
filter |= ANIMFILTER_ACTIVE;
@ -2875,14 +2887,14 @@ static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
/* Filter data. */
if (RNA_boolean_get(op->ptr, "only_active")) {
/* This should be the default (for buttons) - Just paste to the active FCurve. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FCURVESONLY | ANIMFILTER_ACTIVE |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
}
else {
/* This is only if the operator gets called from a hotkey or search -
* Paste to all visible curves. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
}
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@ -3065,7 +3077,8 @@ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op)
/* NOTE: We might need a scene update to evaluate the driver flags. */
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* Find invalid drivers. */

View File

@ -234,14 +234,16 @@ static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
/* get list of all channels that selection may need to be flushed to
* - hierarchy must not affect what we have access to here...
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FCURVESONLY | ANIMFILTER_LIST_CHANNELS |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
/* filter data
* - of the remaining visible curves, we want to hide the ones that are
* selected/unselected (depending on "unselected" prop)
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FCURVESONLY | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_NODUPLIS);
if (unselected) {
filter |= ANIMFILTER_UNSEL;
}
@ -275,7 +277,8 @@ static int graphview_curves_hide_exec(bContext *C, wmOperator *op)
/* unhide selected */
if (unselected) {
/* turn off requirement for visible */
filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS;
filter = ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_LIST_CHANNELS |
ANIMFILTER_FCURVESONLY;
/* flushing has been done */
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@ -344,13 +347,15 @@ static int graphview_curves_reveal_exec(bContext *C, wmOperator *op)
/* get list of all channels that selection may need to be flushed to
* - hierarchy must not affect what we have access to here...
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS |
ANIMFILTER_FCURVESONLY);
ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
/* filter data
* - just go through all visible channels, ensuring that everything is set to be curve-visible
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS |
ANIMFILTER_FCURVESONLY);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale = anim_data.first; ale; ale = ale->next) {

View File

@ -172,7 +172,8 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
* - if the option to only show keyframes that belong to selected F-Curves is enabled,
* include the 'only selected' flag...
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY);
if (sipo->flag &
SIPO_SELCUVERTSONLY) { /* FIXME: this should really be check for by the filtering code... */
filter |= ANIMFILTER_SEL;
@ -342,7 +343,8 @@ void deselect_graph_keys(bAnimContext *ac, bool test, short sel, bool do_channel
KeyframeEditFunc test_cb, sel_cb;
/* determine type-based settings */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
/* filter data */
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@ -498,7 +500,8 @@ static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rec
static int initialize_animdata_selection_filter(const SpaceGraph *sipo)
{
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
if (sipo->flag & SIPO_SELCUVERTSONLY) {
filter |= ANIMFILTER_FOREDIT | ANIMFILTER_SELEDIT;
}
@ -1150,7 +1153,8 @@ static void markers_selectkeys_between(bAnimContext *ac)
ked.f2 = max;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* select keys in-between */
@ -1189,7 +1193,8 @@ static void columnselect_graph_keys(bAnimContext *ac, short mode)
/* build list of columns */
switch (mode) {
case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@ -1222,7 +1227,8 @@ static void columnselect_graph_keys(bAnimContext *ac, short mode)
/* loop through all of the keys and select additional keyframes
* based on the keys found to be selected above
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@ -1314,7 +1320,8 @@ static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
}
/* loop through all of the keys and select additional keyframes based on these */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@ -1372,7 +1379,8 @@ static void select_moreless_graph_keys(bAnimContext *ac, short mode)
memset(&ked, 0, sizeof(KeyframeEditData));
/* loop through all of the keys and select additional keyframes based on these */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@ -1521,7 +1529,7 @@ static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short
}
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* select keys */
@ -1797,7 +1805,8 @@ static int mouse_graph_keys(bAnimContext *ac,
* otherwise the active flag won't be set T26452. */
if (!run_modal && (nvi->fcu->flag & FCURVE_SELECTED) && something_was_selected) {
/* NOTE: Sync the filter flags with findnearest_fcurve_vert. */
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
}
@ -1873,7 +1882,8 @@ static int graphkeys_mselect_column(bAnimContext *ac,
/* loop through all of the keys and select additional keyframes
* based on the keys found to be selected above
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
for (ale = anim_data.first; ale; ale = ale->next) {

View File

@ -48,8 +48,8 @@
/* Used to obtain a list of animation channels for the operators to work on. */
#define OPERATOR_DATA_FILTER \
(ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | \
ANIMFILTER_NODUPLIS)
(ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY | \
ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS)
/* This data type is only used for modal operation. */
typedef struct tGraphSliderOp {

View File

@ -131,7 +131,7 @@ bool graphop_visible_keyframes_poll(bContext *C)
/* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable
* stopping on the first successful match
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY);
items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
if (items == 0) {
return found;
@ -183,7 +183,8 @@ bool graphop_editable_keyframes_poll(bContext *C)
/* loop over the editable F-Curves, and see if they're suitable
* stopping on the first successful match
*/
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_FCURVESONLY);
items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
if (items == 0) {
CTX_wm_operator_poll_msg_set(C, "There is no animation data to operate on");
@ -286,7 +287,8 @@ bool graphop_selected_fcurve_poll(bContext *C)
/* Get the editable + selected F-Curves, and as long as we got some, we can return.
* NOTE: curve-visible flag isn't included,
* otherwise selecting a curve via list to edit is too cumbersome. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT |
ANIMFILTER_FCURVESONLY);
items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
if (items == 0) {
return false;

View File

@ -56,7 +56,8 @@ void get_graph_keyframe_extents(bAnimContext *ac,
int filter;
/* Get data to filter, from Dopesheet. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_NODUPLIS);
if (sipo->flag & SIPO_SELCUVERTSONLY) {
filter |= ANIMFILTER_SEL;
}
@ -398,8 +399,8 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
}
/* Filter data. */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL |
ANIMFILTER_NODUPLIS);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* Loop through filtered data and add keys between selected keyframes on every frame. */

View File

@ -463,6 +463,8 @@ typedef struct TransDataContainer {
int data_len;
/** Total number of transformed data_mirror. */
int data_mirror_len;
/** Total number of transformed gp-frames. */
int data_gpf_len;
struct Object *obedit;

View File

@ -311,6 +311,7 @@ void createTransActionData(bContext *C, TransInfo *t)
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
int count = 0;
int gpf_count = 0;
float cfra;
float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->region->v2d.cur);
@ -320,12 +321,7 @@ void createTransActionData(bContext *C, TransInfo *t)
}
/* filter data */
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
}
else {
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
}
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* which side of the current frame should be allowed */
@ -365,13 +361,16 @@ void createTransActionData(bContext *C, TransInfo *t)
}
if (adt_count > 0) {
if (ELEM(ale->type, ANIMTYPE_GPLAYER, ANIMTYPE_MASKLAYER)) {
gpf_count += adt_count;
}
count += adt_count;
ale->tag = true;
}
}
/* stop if trying to build list if nothing selected */
if (count == 0) {
if (count == 0 && gpf_count == 0) {
/* cleanup temp list */
ANIM_animdata_freelist(&anim_data);
return;
@ -387,8 +386,9 @@ void createTransActionData(bContext *C, TransInfo *t)
td = tc->data;
td2d = tc->data_2d;
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
tc->data_gpf_len = gpf_count;
tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * gpf_count, "tGPFtransdata");
tc->custom.type.use_free = true;
}
@ -558,8 +558,9 @@ static void flushTransIntFrameActionData(TransInfo *t)
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
tGPFtransdata *tfd = tc->custom.type.data;
/* flush data! */
for (int i = 0; i < tc->data_len; i++, tfd++) {
/* flush data!
* Expects data_gpf_len to be set in the data container. */
for (int i = 0; i < tc->data_gpf_len; i++, tfd++) {
*(tfd->sdata) = round_fl_to_int(tfd->val);
}
}
@ -589,7 +590,7 @@ void recalcData_actedit(TransInfo *t)
ANIM_animdata_context_getdata(&ac);
/* perform flush */
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
/* flush transform values back to actual coordinates */
flushTransIntFrameActionData(t);
}
@ -735,7 +736,7 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act)
int filter;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_FCURVESONLY);
ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION);
/* loop through relevant data, removing keyframes as appropriate
@ -776,32 +777,44 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t)
if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY, ANIMCONT_TIMELINE)) {
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
/* get channels to work on */
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* these should all be F-Curves */
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
switch (ale->datatype) {
case ALE_GPFRAME:
ale->id->tag &= ~LIB_TAG_DOIT;
posttrans_gpd_clean((bGPdata *)ale->id);
break;
/* 3 cases here for curve cleanups:
* 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
* 2) canceled == 0 -> user confirmed the transform,
* so duplicates should be removed
* 3) canceled + duplicate -> user canceled the transform,
* but we made duplicates, so get rid of these
*/
if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
}
else {
posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */
case ALE_FCURVE: {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
/* 3 cases here for curve cleanups:
* 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
* 2) canceled == 0 -> user confirmed the transform,
* so duplicates should be removed
* 3) canceled + duplicate -> user canceled the transform,
* but we made duplicates, so get rid of these
*/
if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
}
else {
posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */
}
}
break;
}
default:
BLI_assert_msg(false, "Keys cannot be transformed into this animation type.");
}
}
@ -847,15 +860,8 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t)
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ale->datatype == ALE_GPFRAME) {
ale->id->tag |= LIB_TAG_DOIT;
}
}
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ale->datatype == ALE_GPFRAME) {
if (ale->id->tag & LIB_TAG_DOIT) {
ale->id->tag &= ~LIB_TAG_DOIT;
posttrans_gpd_clean((bGPdata *)ale->id);
}
ale->id->tag &= ~LIB_TAG_DOIT;
posttrans_gpd_clean((bGPdata *)ale->id);
}
}
ANIM_animdata_freelist(&anim_data);
@ -878,15 +884,8 @@ void special_aftertrans_update__actedit(bContext *C, TransInfo *t)
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ale->datatype == ALE_MASKLAY) {
ale->id->tag |= LIB_TAG_DOIT;
}
}
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
if (ale->datatype == ALE_MASKLAY) {
if (ale->id->tag & LIB_TAG_DOIT) {
ale->id->tag &= ~LIB_TAG_DOIT;
posttrans_mask_clean((Mask *)ale->id);
}
ale->id->tag &= ~LIB_TAG_DOIT;
posttrans_mask_clean((Mask *)ale->id);
}
}
ANIM_animdata_freelist(&anim_data);

View File

@ -232,7 +232,8 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
anim_map_flag |= ANIM_get_normalization_flags(&ac);
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_FCURVESONLY);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* which side of the current frame should be allowed */
@ -915,7 +916,8 @@ void recalcData_graphedit(TransInfo *t)
flushTransGraphData(t);
/* get curves to check if a re-sort is needed */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_FCURVESONLY);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* now test if there is a need to re-sort */
@ -975,7 +977,8 @@ void special_aftertrans_update__graph(bContext *C, TransInfo *t)
if (ac.datatype) {
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE |
ANIMFILTER_FCURVESONLY);
/* get channels to work on */
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);