Anim: Baklava, add Animation data-block to anim filtering code #120654

Merged
Sybren A. Stüvel merged 7 commits from dr.sybren/blender:pr/baklava-animation-filtering into main 2024-04-20 12:19:25 +02:00
16 changed files with 354 additions and 13 deletions

View File

@ -123,6 +123,13 @@ void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu)
*/
animdata_remove_empty_action(adt);
}
else if (adt->animation) {
/* TODO: support deleting FCurves from Animation data-blocks. */
return;
}
else {
BLI_assert_unreachable();
}
BKE_fcurve_free(fcu);
}

View File

@ -57,6 +57,7 @@ endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_GREASE_PENCIL_V3)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -9,6 +9,7 @@
#include <cstdio>
#include "ANIM_action.hh"
#include "ANIM_animation.hh"
#include "ANIM_animdata.hh"
#include "ANIM_keyframing.hh"
@ -76,6 +77,8 @@
#include "WM_api.hh"
#include "WM_types.hh"
using namespace blender;
/* *********************************************** */
/* XXX constant defines to be moved elsewhere? */
@ -1246,6 +1249,94 @@ static bAnimChannelType ACF_NLACURVE = {
/*setting_ptr*/ acf_fcurve_setting_ptr,
};
/* Object Animation Expander ------------------------------------------- */
#ifdef WITH_ANIM_BAKLAVA
/* TODO: just get this from RNA? */
static int acf_fillanim_icon(bAnimListElem * /*ale*/)
{
return ICON_ACTION; /* TODO: give Animation its own icon? */
}
/* check if some setting exists for this channel */
static bool acf_fillanim_setting_valid(bAnimContext * /*ac*/,
bAnimListElem * /*ale*/,
eAnimChannel_Settings setting)
{
switch (setting) {
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
return true;
default:
return false;
}
}
/* Get the appropriate flag(s) for the setting when it is valid. */
static int acf_fillanim_setting_flag(bAnimContext * /*ac*/,
eAnimChannel_Settings setting,
bool *r_neg)
{
*r_neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT:
return ADT_UI_SELECTED;
case ACHANNEL_SETTING_EXPAND:
return ADT_UI_EXPANDED;
default:
return 0;
}
}
/* get pointer to the setting */
static void *acf_fillanim_setting_ptr(bAnimListElem *ale,
eAnimChannel_Settings setting,
short *r_type)
{
AnimData *adt = ale->adt;
BLI_assert(adt);
*r_type = 0;
switch (setting) {
case ACHANNEL_SETTING_SELECT:
return GET_ACF_FLAG_PTR(adt->flag, r_type);
case ACHANNEL_SETTING_EXPAND:
return GET_ACF_FLAG_PTR(adt->flag, r_type);
default:
return nullptr;
}
}
/** Object Animation expander type define. */
static bAnimChannelType ACF_FILLANIM = {
/*channel_type_name*/ "Ob-Animation Filler",
/*channel_role*/ ACHANNEL_ROLE_EXPANDER,
/*get_backdrop_color*/ acf_generic_dataexpand_color,
/*get_channel_color*/ nullptr,
/*draw_backdrop*/ acf_generic_dataexpand_backdrop,
/*get_indent_level*/ acf_generic_indentation_1,
/*get_offset*/ acf_generic_basic_offset,
/*name*/ acf_generic_idblock_name,
/*name_prop*/ acf_generic_idfill_name_prop,
/*icon*/ acf_fillanim_icon,
/*has_setting*/ acf_fillanim_setting_valid,
/*setting_flag*/ acf_fillanim_setting_flag,
/*setting_ptr*/ acf_fillanim_setting_ptr,
};
#endif
/* Object Action Expander ------------------------------------------- */
/* TODO: just get this from RNA? */
@ -4280,6 +4371,11 @@ static void ANIM_init_channel_typeinfo_data()
animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */
#ifdef WITH_ANIM_BAKLAVA
animchannelTypeInfo[type++] = &ACF_FILLANIM; /* Object Animation Expander */
#else
animchannelTypeInfo[type++] = nullptr;
#endif
animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */
animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
@ -4325,6 +4421,11 @@ static void ANIM_init_channel_typeinfo_data()
animchannelTypeInfo[type++] = &ACF_NLATRACK; /* NLA Track */
animchannelTypeInfo[type++] = &ACF_NLAACTION; /* NLA Action */
#ifdef WITH_ANIM_BAKLAVA
BLI_assert_msg(animchannelTypeInfo[ANIMTYPE_FILLANIM] == &ACF_FILLANIM,
"ANIMTYPE_FILLANIM does not match ACF_FILLANIM");
#endif
}
}

View File

@ -256,6 +256,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
break;
}
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_FILLANIM: /* Animation Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
@ -312,6 +313,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
break;
}
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_FILLANIM: /* Animation Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
@ -365,6 +367,7 @@ bool ANIM_is_active_channel(bAnimListElem *ale)
{
switch (ale->type) {
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_FILLANIM: /* Animation Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
@ -501,6 +504,7 @@ static eAnimChannels_SetFlag anim_channels_selection_flag_for_toggle(const ListB
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_FILLANIM: /* Animation Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
@ -615,6 +619,7 @@ static void anim_channels_select_set(bAnimContext *ac,
break;
}
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_FILLANIM: /* Animation Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
@ -3832,6 +3837,7 @@ static int mouse_anim_channels(bContext *C,
notifierFlags |= click_select_channel_object(C, ac, ale, selectmode);
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_FILLANIM: /* Animation Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:

View File

@ -55,7 +55,10 @@ void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale)
adt = BKE_animdata_from_id(id);
if (adt) {
DEG_id_tag_update(id, ID_RECALC_ANIMATION);
if (adt->action != nullptr) {
if (adt->animation != nullptr) {
DEG_id_tag_update(&adt->animation->id, ID_RECALC_ANIMATION);
}
else if (adt->action != nullptr) {
DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
}
}

View File

@ -88,8 +88,11 @@
#include "SEQ_sequencer.hh"
#include "SEQ_utils.hh"
#include "ANIM_animation.hh"
#include "ANIM_bone_collections.hh"
using namespace blender;
/* ************************************************************ */
/* Blender Context <-> Animation Context mapping */
@ -446,14 +449,14 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
/* ............................... */
/* quick macro to test if AnimData is usable */
#define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
/* Test whether AnimData has a usable Action. */
#define ANIMDATA_HAS_ACTION(id) ((id)->adt && !(id)->adt->animation && (id)->adt->action)
/* quick macro to test if AnimData is usable for drivers */
#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
/* quick macro to test if AnimData is usable for NLA */
#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
#define ANIMDATA_HAS_NLA(id) ((id)->adt && !(id)->adt->animation && (id)->adt->nla_tracks.first)
/**
* Quick macro to test for all three above usability tests, performing the appropriate provided
@ -478,6 +481,7 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
* - driversOk: line or block of code to execute for Drivers case
* - nlaKeysOk: line or block of code for NLA Strip Keyframes case
* - keysOk: line or block of code for Keyframes case
* - animOk: line or block of code for Keyframes from Animation data blocks case
*
* The checks for the various cases are as follows:
* 0) top level: checks for animdata and also that all the F-Curves for the block will be visible
@ -489,8 +493,9 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
* 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
* 4A) nla strip keyframes: these are the per-strip controls for time and influence
* 4B) normal keyframes: only when there is an active action
* 4C) normal keyframes: only when there is an Animation assigned
*/
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk) \
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk, animOk) \
{ \
if ((id)->adt) { \
if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || \
@ -502,7 +507,7 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
if (ANIMDATA_HAS_NLA(id)) { \
nlaOk \
} \
else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_KEYS(id)) { \
else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_ACTION(id)) { \
nlaOk \
} \
} \
@ -511,11 +516,14 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
driversOk \
} \
} \
else if ((id)->adt->animation) { \
animOk \
} \
else { \
if (ANIMDATA_HAS_NLA(id)) { \
nlaKeysOk \
} \
if (ANIMDATA_HAS_KEYS(id)) { \
if (ANIMDATA_HAS_ACTION(id)) { \
keysOk \
} \
} \
@ -594,6 +602,12 @@ static void key_data_from_adt(bAnimListElem &ale, AnimData *adt)
return;
}
if (adt->animation) {
ale.key_data = adt->animation;
ale.datatype = ALE_ANIM;
return;
}
if (adt->action) {
ale.key_data = adt->action;
ale.datatype = ALE_ACT;
@ -658,6 +672,15 @@ static bAnimListElem *make_new_animlistelem(void *data,
ale->adt = BKE_animdata_from_id(&ob->id);
break;
}
case ANIMTYPE_FILLANIM: {
Animation *anim = (Animation *)data;
ale->flag = anim->flag;
ale->key_data = anim;
ale->datatype = ALE_ANIM;
break;
}
case ANIMTYPE_FILLACTD: {
bAction *act = (bAction *)data;
@ -1271,6 +1294,37 @@ static size_t animfilter_fcurves(ListBase *anim_data,
return items;
}
static size_t animfilter_fcurves_span(ListBase * /*bAnimListElem*/ anim_data,
bDopeSheet * /*ads*/,
Span<FCurve *> fcurves,
const int filter_mode,
ID *owner_id,
ID *fcurve_owner_id)
{
size_t num_items = 0;
BLI_assert(owner_id);
for (FCurve *fcu : fcurves) {
/* make_new_animlistelem will return nullptr when fcu == nullptr, and that's
* going to cause problems. */
BLI_assert(fcu);
/* TODO: deal with `filter_mode` and `ads->filterflag`.
* See `animfilter_fcurve_next()`. */
if (filter_mode & ANIMFILTER_TMP_PEEK) {
/* Found an animation channel, which is good enough for the 'TMP_PEEK' mode. */
return 1;
}
bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner_id, fcurve_owner_id);
BLI_addtail(anim_data, ale);
num_items++;
}
return num_items;
}
static size_t animfilter_act_group(bAnimContext *ac,
ListBase *anim_data,
bDopeSheet *ads,
@ -1406,6 +1460,32 @@ static size_t animfilter_action(bAnimContext *ac,
return items;
}
/**
* Add animation list elements for FCurves in an Animation data-block.
*/
static size_t animfilter_animation_fcurves(
ListBase *anim_data, bDopeSheet *ads, AnimData *adt, const int filter_mode, ID *owner_id)
{
/* If this ID is not bound, there is nothing to show. */
if (adt->binding_handle == 0) {
return 0;
}
BLI_assert(adt->animation); /* Otherwise this function wouldn't be called. */
animrig::Animation &anim = adt->animation->wrap();
/* Don't include anything from this animation if it is linked in from another
* file, and we're getting stuff for editing... */
if ((filter_mode & ANIMFILTER_FOREDIT) && (ID_IS_LINKED(&anim) || ID_IS_OVERRIDE_LIBRARY(&anim)))
{
return 0;
}
/* For now we don't show layers anywhere, just the contained F-Curves. */
Span<FCurve *> fcurves = animrig::fcurves_for_animation(anim, adt->binding_handle);
return animfilter_fcurves_span(anim_data, ads, fcurves, filter_mode, owner_id, &anim.id);
}
/* Include NLA-Data for NLA-Editor:
* - When ANIMFILTER_LIST_CHANNELS is used, that means we should be filtering the list for display
* Although the evaluation order is from the first track to the last and then apply the
@ -1597,8 +1677,11 @@ static size_t animfilter_block_data(
{ /* NLA Control Keyframes */
items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id);
},
{ /* Keyframes */
{ /* Keyframes from Action. */
items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id);
},
{ /* Keyframes from Animation. */
items += animfilter_animation_fcurves(anim_data, ads, adt, filter_mode, id);
});
}
@ -2873,10 +2956,15 @@ static size_t animdata_filter_ds_obanim(
expanded = EXPANDED_DRVD(adt);
},
{/* NLA Strip Controls - no dedicated channel for now (XXX) */},
{ /* Keyframes */
{ /* Keyframes from Action. */
type = ANIMTYPE_FILLACTD;
cdata = adt->action;
expanded = EXPANDED_ACTC(adt->action);
},
{ /* Keyframes from Animation. */
type = ANIMTYPE_FILLANIM;
cdata = adt->animation;
expanded = EXPANDED_ADT(adt);
});
/* add object-level animation channels */
@ -3052,10 +3140,15 @@ static size_t animdata_filter_ds_scene(
expanded = EXPANDED_DRVD(adt);
},
{/* NLA Strip Controls - no dedicated channel for now (XXX) */},
{ /* Keyframes */
{ /* Keyframes from Action. */
type = ANIMTYPE_FILLACTD;
cdata = adt->action;
expanded = EXPANDED_ACTC(adt->action);
},
{ /* Keyframes from Animation. */
type = ANIMTYPE_FILLANIM;
cdata = adt->animation;
expanded = EXPANDED_ADT(adt);
});
/* add scene-level animation channels */

View File

@ -384,6 +384,7 @@ enum class ChannelType {
SCENE,
OBJECT,
FCURVE,
ANIMATION,
ACTION,
ACTION_GROUP,
GREASE_PENCIL_CELS,
@ -409,6 +410,7 @@ struct ChannelListElement {
Object *ob;
AnimData *adt;
FCurve *fcu;
Animation *anim;
bAction *act;
bActionGroup *agrp;
bGPDlayer *gpl;
@ -437,6 +439,10 @@ static void build_channel_keylist(ChannelListElement *elem, blender::float2 rang
fcurve_to_keylist(elem->adt, elem->fcu, elem->keylist, elem->saction_flag, range);
break;
}
case ChannelType::ANIMATION: {
animation_to_keylist(elem->adt, elem->anim, elem->keylist, elem->saction_flag, range);
break;
}
case ChannelType::ACTION: {
action_to_keylist(elem->adt, elem->act, elem->keylist, elem->saction_flag, range);
break;
@ -705,6 +711,25 @@ void ED_add_action_group_channel(ChannelDrawList *channel_list,
draw_elem->channel_locked = locked;
}
void ED_add_animation_channel(ChannelDrawList *channel_list,
AnimData *adt,
Animation *anim,
const float ypos,
const float yscale_fac,
int saction_flag)
{
BLI_assert(anim);
const bool locked = (anim && (ID_IS_LINKED(anim) || ID_IS_OVERRIDE_LIBRARY(anim)));
saction_flag &= ~SACTION_SHOW_EXTREMES;
ChannelListElement *draw_elem = channel_list_add_element(
channel_list, ChannelType::ANIMATION, ypos, yscale_fac, eSAction_Flag(saction_flag));
draw_elem->adt = adt;
draw_elem->anim = anim;
draw_elem->channel_locked = locked;
}
void ED_add_action_channel(ChannelDrawList *channel_list,
AnimData *adt,
bAction *act,

View File

@ -30,6 +30,10 @@
#include "ED_keyframes_edit.hh"
#include "ED_markers.hh"
#include "ANIM_animation.hh"
using namespace blender;
/* This file defines an API and set of callback-operators for
* non-destructive editing of keyframe data.
*
@ -162,6 +166,32 @@ static short agrp_keyframes_loop(KeyframeEditData *ked,
return 0;
}
#ifdef WITH_ANIM_BAKLAVA
/* Loop over all keyframes in the Animation. */
static short anim_keyframes_loop(KeyframeEditData *ked,
animrig::Animation &anim,
animrig::Binding *binding,
KeyframeEditFunc key_ok,
KeyframeEditFunc key_cb,
FcuEditFunc fcu_cb)
{
if (!binding) {
/* Valid situation, and will not have any FCurves. */
return 0;
}
Span<FCurve *> fcurves = animrig::fcurves_for_animation(anim, binding->handle);
for (FCurve *fcurve : fcurves) {
if (ANIM_fcurve_keyframes_loop(ked, fcurve, key_ok, key_cb, fcu_cb)) {
return 1;
}
}
return 0;
}
#endif
/* This function is used to loop over the keyframe data in an Action */
static short act_keyframes_loop(KeyframeEditData *ked,
bAction *act,
@ -385,9 +415,20 @@ short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked,
*/
case ALE_GROUP: /* action group */
return agrp_keyframes_loop(ked, (bActionGroup *)ale->data, key_ok, key_cb, fcu_cb);
case ALE_ANIM: { /* Animation data-block. */
#ifdef WITH_ANIM_BAKLAVA
/* This assumes that the ALE_ANIM channel is shown in the dopesheet context, underneath the
* data-block that owns `ale->adt`. So that means that the loop is limited to the keys that
* belong to that binding. */
animrig::Animation &anim = static_cast<Animation *>(ale->key_data)->wrap();
animrig::Binding *binding = anim.binding_for_handle(ale->adt->binding_handle);
return anim_keyframes_loop(ked, anim, binding, key_ok, key_cb, fcu_cb);
#else
return 0;
#endif
}
case ALE_ACT: /* action */
return act_keyframes_loop(ked, (bAction *)ale->key_data, key_ok, key_cb, fcu_cb);
case ALE_OB: /* object */
return ob_keyframes_loop(ked, ads, (Object *)ale->key_data, key_ok, key_cb, fcu_cb);
case ALE_SCE: /* scene */
@ -423,9 +464,12 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked,
*/
case ALE_GROUP: /* action group */
return agrp_keyframes_loop(ked, (bActionGroup *)data, key_ok, key_cb, fcu_cb);
case ALE_ANIM:
/* This function is only used in nlaedit_apply_scale_exec(). Since the NLA has no support for
* Animation data-blocks in strips, there is no need to implement this here. */
return 0;
case ALE_ACT: /* action */
return act_keyframes_loop(ked, (bAction *)data, key_ok, key_cb, fcu_cb);
case ALE_OB: /* object */
return ob_keyframes_loop(ked, ads, (Object *)data, key_ok, key_cb, fcu_cb);
case ALE_SCE: /* scene */

View File

@ -36,6 +36,8 @@
#include "ED_anim_api.hh"
#include "ED_keyframes_keylist.hh"
#include "ANIM_animation.hh"
/* *************************** Keyframe Processing *************************** */
/* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
@ -1165,6 +1167,25 @@ void action_group_to_keylist(AnimData *adt,
}
}
/**
* Assumption: the animation is bound to adt->binding_handle. This assumption will break when we
* have things like reference strips, where the strip can reference another binding handle.
*/
void animation_to_keylist(AnimData *adt,
Animation *anim,
AnimKeylist *keylist,
const int saction_flag,
blender::float2 range)
{
BLI_assert(adt);
BLI_assert(anim);
BLI_assert(GS(anim->id.name) == ID_AN);
for (FCurve *fcurve : fcurves_for_animation(anim->wrap(), adt->binding_handle)) {
fcurve_to_keylist(adt, fcurve, keylist, saction_flag, range);
}
}
void action_to_keylist(AnimData *adt,
bAction *act,
AnimKeylist *keylist,

View File

@ -169,7 +169,7 @@ struct bAnimListElem {
*/
/** ID block that channel is attached to */
ID *id;
/** source of the animation data attached to ID block (for convenience) */
/** source of the animation data attached to ID block */
AnimData *adt;
/**
@ -212,6 +212,7 @@ enum eAnim_ChannelType {
ANIMTYPE_NLACONTROLS,
ANIMTYPE_NLACURVE,
ANIMTYPE_FILLANIM,
ANIMTYPE_FILLACTD,
ANIMTYPE_FILLDRIVERS,
@ -271,6 +272,7 @@ enum eAnim_KeyType {
ALE_OB, /* Object summary */
ALE_ACT, /* Action summary */
ALE_GROUP, /* Action Group summary */
ALE_ANIM, /* Animation data-block summary. */
ALE_GREASE_PENCIL_CEL, /* Grease Pencil Cels. */
ALE_GREASE_PENCIL_DATA, /* Grease Pencil Cels summary. */
@ -404,6 +406,7 @@ ENUM_OPERATORS(eAnimFilter_Flags, ANIMFILTER_TMP_IGNORE_ONLYSEL);
#define EXPANDED_ACTC(actc) ((actc->flag & ACT_COLLAPSED) == 0)
/* 'Sub-AnimData' channels */
#define EXPANDED_DRVD(adt) ((adt->flag & ADT_DRIVERS_COLLAPSED) == 0)
#define EXPANDED_ADT(adt) ((adt->flag & ADT_UI_EXPANDED) != 0)
/* Actions (also used for Dopesheet) */
/** Action Channel Group. */

View File

@ -14,6 +14,7 @@
#include "ED_keyframes_keylist.hh"
struct Animation;
struct AnimData;
struct ChannelDrawList;
struct FCurve;
@ -72,6 +73,13 @@ void ED_add_action_group_channel(ChannelDrawList *draw_list,
float ypos,
float yscale_fac,
int saction_flag);
/* Animation Summary.*/
void ED_add_animation_channel(ChannelDrawList *channel_list,
AnimData *adt,
Animation *anim,
float ypos,
float yscale_fac,
int saction_flag);
/* Action Summary */
void ED_add_action_channel(ChannelDrawList *draw_list,
AnimData *adt,

View File

@ -13,6 +13,7 @@
#include "DNA_curve_types.h"
struct Animation;
struct AnimData;
struct CacheFile;
struct FCurve;
@ -161,6 +162,9 @@ void action_group_to_keylist(AnimData *adt,
AnimKeylist *keylist,
int saction_flag,
blender::float2 range);
/* Animation */
void animation_to_keylist(
AnimData *adt, Animation *anim, AnimKeylist *keylist, int saction_flag, blender::float2 range);
/* Action */
void action_to_keylist(
AnimData *adt, bAction *act, AnimKeylist *keylist, int saction_flag, blender::float2 range);

View File

@ -18,6 +18,7 @@
/* Types --------------------------------------------------------------- */
#include "DNA_anim_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@ -221,6 +222,7 @@ static void draw_backdrops(bAnimContext *ac, ListBase &anim_data, View2D *v2d, u
break;
}
case ANIMTYPE_FILLACTD:
case ANIMTYPE_FILLANIM:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR: {
immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
@ -366,6 +368,14 @@ static void draw_keyframes(bAnimContext *ac,
scale_factor,
action_flag);
break;
case ALE_ANIM:
ED_add_animation_channel(draw_list,
adt,
static_cast<Animation *>(ale->key_data),
ycenter,
scale_factor,
action_flag);
break;
case ALE_ACT:
ED_add_action_channel(draw_list,
adt,

View File

@ -112,6 +112,11 @@ static void actkeys_list_element_to_keylist(bAnimContext *ac,
ob_to_keylist(ads, ob, keylist, 0, range);
break;
}
case ALE_ANIM: {
Animation *anim = (Animation *)ale->key_data;
animation_to_keylist(adt, anim, keylist, 0, range);
break;
}
case ALE_ACT: {
bAction *act = (bAction *)ale->key_data;
action_to_keylist(adt, act, keylist, 0, range);

View File

@ -261,6 +261,9 @@ static int mouse_nla_tracks(bContext *C, bAnimContext *ac, int track_index, shor
}
break;
}
case ANIMTYPE_FILLANIM:
/* The NLA doesn't support Animation data-blocks. */
break;
default:
if (G.debug & G_DEBUG) {
printf("Error: Invalid track type in mouse_nla_tracks()\n");

View File

@ -1224,6 +1224,10 @@ typedef enum eAnimData_Flag {
/** F-Curves from this AnimData block are always visible. */
ADT_CURVES_ALWAYS_VISIBLE = (1 << 17),
/** Animation pointer to by this AnimData block is expanded in UI. This is stored on the AnimData
* so that each user of the Animation can have its own expansion/contraction state. */
ADT_UI_EXPANDED = (1 << 18),
} eAnimData_Flag;
/* Base Struct for Anim ------------------------------------- */
@ -1272,6 +1276,9 @@ typedef struct Animation {
int binding_array_num;
int32_t last_binding_handle;
uint8_t flag;
uint8_t _pad0[7];
#ifdef __cplusplus
blender::animrig::Animation &wrap();
const blender::animrig::Animation &wrap() const;