diff --git a/source/blender/animrig/intern/animdata.cc b/source/blender/animrig/intern/animdata.cc index 6f4f2237d91..aa2b215526a 100644 --- a/source/blender/animrig/intern/animdata.cc +++ b/source/blender/animrig/intern/animdata.cc @@ -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); } diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt index 811d769872d..3a0b9db1ef3 100644 --- a/source/blender/editors/animation/CMakeLists.txt +++ b/source/blender/editors/animation/CMakeLists.txt @@ -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}") diff --git a/source/blender/editors/animation/anim_channels_defines.cc b/source/blender/editors/animation/anim_channels_defines.cc index 3dec1d0dc98..03ff472e72e 100644 --- a/source/blender/editors/animation/anim_channels_defines.cc +++ b/source/blender/editors/animation/anim_channels_defines.cc @@ -9,6 +9,7 @@ #include #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 } } diff --git a/source/blender/editors/animation/anim_channels_edit.cc b/source/blender/editors/animation/anim_channels_edit.cc index 96b57a4b6a6..c99558a6fad 100644 --- a/source/blender/editors/animation/anim_channels_edit.cc +++ b/source/blender/editors/animation/anim_channels_edit.cc @@ -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: diff --git a/source/blender/editors/animation/anim_deps.cc b/source/blender/editors/animation/anim_deps.cc index 23a6fea7970..16adbc4032f 100644 --- a/source/blender/editors/animation/anim_deps.cc +++ b/source/blender/editors/animation/anim_deps.cc @@ -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); } } diff --git a/source/blender/editors/animation/anim_filter.cc b/source/blender/editors/animation/anim_filter.cc index 8f4820f4542..efbdf9ad733 100644 --- a/source/blender/editors/animation/anim_filter.cc +++ b/source/blender/editors/animation/anim_filter.cc @@ -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) +/* quick macro to test if AnimData has usable Action */ +#define ANIMDATA_HAS_KEYS(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) || \ @@ -511,6 +516,9 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type) driversOk \ } \ } \ + else if ((id)->adt->animation) { \ + animOk \ + } \ else { \ if (ANIMDATA_HAS_NLA(id)) { \ nlaKeysOk \ @@ -580,6 +588,36 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type) /* ----------- 'Private' Stuff --------------- */ +/** + * Set `ale` so that it points to the top-most 'summary' channel of the given `adt`. + * So this is either the Animation or the Action, or empty. + */ +static void key_data_from_adt(bAnimListElem &ale, AnimData *adt) +{ + ale.adt = adt; + + if (!adt) { + ale.key_data = nullptr; + ale.datatype = ALE_NONE; + 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; + return; + } + + ale.key_data = nullptr; + ale.datatype = ALE_NONE; +} + /* this function allocates memory for a new bAnimListElem struct for the * provided animation channel-data. */ @@ -634,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; @@ -655,244 +702,125 @@ static bAnimListElem *make_new_animlistelem(void *data, } case ANIMTYPE_DSMAT: { Material *ma = (Material *)data; - AnimData *adt = ma->adt; - ale->flag = FILTER_MAT_OBJD(ma); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, ma->adt); break; } case ANIMTYPE_DSLAM: { Light *la = (Light *)data; - AnimData *adt = la->adt; - ale->flag = FILTER_LAM_OBJD(la); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, la->adt); break; } case ANIMTYPE_DSCAM: { Camera *ca = (Camera *)data; - AnimData *adt = ca->adt; - ale->flag = FILTER_CAM_OBJD(ca); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, ca->adt); break; } case ANIMTYPE_DSCACHEFILE: { CacheFile *cache_file = (CacheFile *)data; - AnimData *adt = cache_file->adt; - ale->flag = FILTER_CACHEFILE_OBJD(cache_file); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, cache_file->adt); break; } case ANIMTYPE_DSCUR: { Curve *cu = (Curve *)data; - AnimData *adt = cu->adt; - ale->flag = FILTER_CUR_OBJD(cu); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, cu->adt); break; } case ANIMTYPE_DSARM: { bArmature *arm = (bArmature *)data; - AnimData *adt = arm->adt; - ale->flag = FILTER_ARM_OBJD(arm); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, arm->adt); break; } case ANIMTYPE_DSMESH: { Mesh *mesh = (Mesh *)data; - AnimData *adt = mesh->adt; - ale->flag = FILTER_MESH_OBJD(mesh); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, mesh->adt); break; } case ANIMTYPE_DSLAT: { Lattice *lt = (Lattice *)data; - AnimData *adt = lt->adt; - ale->flag = FILTER_LATTICE_OBJD(lt); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, lt->adt); break; } case ANIMTYPE_DSSPK: { Speaker *spk = (Speaker *)data; - AnimData *adt = spk->adt; - ale->flag = FILTER_SPK_OBJD(spk); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, spk->adt); break; } case ANIMTYPE_DSHAIR: { Curves *curves = (Curves *)data; - AnimData *adt = curves->adt; - ale->flag = FILTER_CURVES_OBJD(curves); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, curves->adt); break; } case ANIMTYPE_DSPOINTCLOUD: { PointCloud *pointcloud = (PointCloud *)data; - AnimData *adt = pointcloud->adt; - ale->flag = FILTER_POINTS_OBJD(pointcloud); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, pointcloud->adt); break; } case ANIMTYPE_DSVOLUME: { Volume *volume = (Volume *)data; - AnimData *adt = volume->adt; - ale->flag = FILTER_VOLUME_OBJD(volume); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, volume->adt); break; } case ANIMTYPE_DSSKEY: { Key *key = (Key *)data; - AnimData *adt = key->adt; - ale->flag = FILTER_SKE_OBJD(key); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, key->adt); break; } case ANIMTYPE_DSWOR: { World *wo = (World *)data; - AnimData *adt = wo->adt; - ale->flag = FILTER_WOR_SCED(wo); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, wo->adt); break; } case ANIMTYPE_DSNTREE: { bNodeTree *ntree = (bNodeTree *)data; - AnimData *adt = ntree->adt; - ale->flag = FILTER_NTREE_DATA(ntree); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, ntree->adt); break; } case ANIMTYPE_DSLINESTYLE: { FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data; - AnimData *adt = linestyle->adt; - ale->flag = FILTER_LS_SCED(linestyle); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, linestyle->adt); break; } case ANIMTYPE_DSPART: { ParticleSettings *part = (ParticleSettings *)ale->data; - AnimData *adt = part->adt; - ale->flag = FILTER_PART_OBJD(part); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, part->adt); break; } case ANIMTYPE_DSTEX: { Tex *tex = (Tex *)data; - AnimData *adt = tex->adt; - ale->flag = FILTER_TEX_DATA(tex); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, tex->adt); break; } case ANIMTYPE_DSGPENCIL: { bGPdata *gpd = (bGPdata *)data; - AnimData *adt = gpd->adt; - /* NOTE: we just reuse the same expand filter for this case */ ale->flag = EXPANDED_GPD(gpd); /* XXX: currently, this is only used for access to its animation data */ - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, gpd->adt); break; } case ANIMTYPE_DSMCLIP: { MovieClip *clip = (MovieClip *)data; - AnimData *adt = clip->adt; - ale->flag = EXPANDED_MCLIP(clip); - - ale->key_data = (adt) ? adt->action : nullptr; - ale->datatype = ALE_ACT; - - ale->adt = BKE_animdata_from_id(static_cast(data)); + key_data_from_adt(*ale, clip->adt); break; } case ANIMTYPE_NLACONTROLS: { @@ -1366,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 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, @@ -1501,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 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 @@ -1692,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); }); } @@ -2968,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 */ @@ -3147,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 */ diff --git a/source/blender/editors/animation/keyframes_draw.cc b/source/blender/editors/animation/keyframes_draw.cc index bdb2ddbef4c..72c78d0c067 100644 --- a/source/blender/editors/animation/keyframes_draw.cc +++ b/source/blender/editors/animation/keyframes_draw.cc @@ -376,6 +376,7 @@ enum class ChannelType { SCENE, OBJECT, FCURVE, + ANIMATION, ACTION, ACTION_GROUP, GREASE_PENCIL_CELS, @@ -401,6 +402,7 @@ struct ChannelListElement { Object *ob; AnimData *adt; FCurve *fcu; + Animation *anim; bAction *act; bActionGroup *agrp; bGPDlayer *gpl; @@ -429,6 +431,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; @@ -697,6 +703,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, diff --git a/source/blender/editors/animation/keyframes_edit.cc b/source/blender/editors/animation/keyframes_edit.cc index bf6c3820b2b..6d78e8dd142 100644 --- a/source/blender/editors/animation/keyframes_edit.cc +++ b/source/blender/editors/animation/keyframes_edit.cc @@ -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 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(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 */ diff --git a/source/blender/editors/animation/keyframes_keylist.cc b/source/blender/editors/animation/keyframes_keylist.cc index dd63e53452d..be735e292f3 100644 --- a/source/blender/editors/animation/keyframes_keylist.cc +++ b/source/blender/editors/animation/keyframes_keylist.cc @@ -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, diff --git a/source/blender/editors/include/ED_anim_api.hh b/source/blender/editors/include/ED_anim_api.hh index 6e5d016408a..48849684376 100644 --- a/source/blender/editors/include/ED_anim_api.hh +++ b/source/blender/editors/include/ED_anim_api.hh @@ -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. */ diff --git a/source/blender/editors/include/ED_keyframes_draw.hh b/source/blender/editors/include/ED_keyframes_draw.hh index 79b43a133e2..e43eb30c93c 100644 --- a/source/blender/editors/include/ED_keyframes_draw.hh +++ b/source/blender/editors/include/ED_keyframes_draw.hh @@ -12,6 +12,7 @@ #include "DNA_curve_types.h" +struct Animation; struct AnimData; struct ChannelDrawList; struct FCurve; @@ -70,6 +71,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, diff --git a/source/blender/editors/include/ED_keyframes_keylist.hh b/source/blender/editors/include/ED_keyframes_keylist.hh index 80ea0badfe7..48e68dbf272 100644 --- a/source/blender/editors/include/ED_keyframes_keylist.hh +++ b/source/blender/editors/include/ED_keyframes_keylist.hh @@ -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); diff --git a/source/blender/editors/space_action/action_draw.cc b/source/blender/editors/space_action/action_draw.cc index fd053686af8..606e3091d8c 100644 --- a/source/blender/editors/space_action/action_draw.cc +++ b/source/blender/editors/space_action/action_draw.cc @@ -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(ale->key_data), + ycenter, + scale_factor, + action_flag); + break; case ALE_ACT: ED_add_action_channel(draw_list, adt, diff --git a/source/blender/editors/space_action/action_select.cc b/source/blender/editors/space_action/action_select.cc index 0624da7b9a5..764c8b4fbf8 100644 --- a/source/blender/editors/space_action/action_select.cc +++ b/source/blender/editors/space_action/action_select.cc @@ -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); diff --git a/source/blender/editors/space_nla/nla_tracks.cc b/source/blender/editors/space_nla/nla_tracks.cc index f4c3f93d621..4edb1396f0e 100644 --- a/source/blender/editors/space_nla/nla_tracks.cc +++ b/source/blender/editors/space_nla/nla_tracks.cc @@ -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"); diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index ea28e6af38e..407b59f8631 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -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;