diff --git a/source/blender/editors/animation/anim_draw.cc b/source/blender/editors/animation/anim_draw.cc index 31c9c300a79..8c6e1ddd608 100644 --- a/source/blender/editors/animation/anim_draw.cc +++ b/source/blender/editors/animation/anim_draw.cc @@ -588,11 +588,11 @@ static bool find_prev_next_keyframes(bContext *C, int *r_nextfra, int *r_prevfra } /* populate tree with keyframe nodes */ - scene_to_keylist(&ads, scene, keylist, 0); + scene_to_keylist(&ads, scene, keylist, 0, {-FLT_MAX, FLT_MAX}); gpencil_to_keylist(&ads, scene->gpd, keylist, false); if (ob) { - ob_to_keylist(&ads, ob, keylist, 0); + ob_to_keylist(&ads, ob, keylist, 0, {-FLT_MAX, FLT_MAX}); gpencil_to_keylist(&ads, static_cast(ob->data), keylist, false); } diff --git a/source/blender/editors/animation/anim_motion_paths.cc b/source/blender/editors/animation/anim_motion_paths.cc index f1e4381c26f..306682b8087 100644 --- a/source/blender/editors/animation/anim_motion_paths.cc +++ b/source/blender/editors/animation/anim_motion_paths.cc @@ -310,7 +310,7 @@ static void motionpath_calculate_update_range(MPathTarget *mpt, * we ignore all others (which can potentially make an update range unnecessary wide). */ for (FCurve *fcu = static_cast(fcurve_list->first); fcu != nullptr; fcu = fcu->next) { AnimKeylist *keylist = ED_keylist_create(); - fcurve_to_keylist(adt, fcu, keylist, 0); + fcurve_to_keylist(adt, fcu, keylist, 0, {-FLT_MAX, FLT_MAX}); ED_keylist_prepare_for_direct_access(keylist); int fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, keylist, current_frame); @@ -360,7 +360,7 @@ void animviz_motionpath_compute_range(Object *ob, Scene *scene) AnimKeylist *keylist = ED_keylist_create(); LISTBASE_FOREACH (FCurve *, fcu, &ob->adt->action->curves) { - fcurve_to_keylist(ob->adt, fcu, keylist, 0); + fcurve_to_keylist(ob->adt, fcu, keylist, 0, {-FLT_MAX, FLT_MAX}); } Range2f frame_range; @@ -460,12 +460,12 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph, if (agrp) { fcurve_list = &agrp->channels; - action_group_to_keylist(adt, agrp, mpt->keylist, 0); + action_group_to_keylist(adt, agrp, mpt->keylist, 0, {-FLT_MAX, FLT_MAX}); } } else { fcurve_list = &adt->action->curves; - action_to_keylist(adt, adt->action, mpt->keylist, 0); + action_to_keylist(adt, adt->action, mpt->keylist, 0, {-FLT_MAX, FLT_MAX}); } } ED_keylist_prepare_for_direct_access(mpt->keylist); diff --git a/source/blender/editors/animation/keyframes_draw.cc b/source/blender/editors/animation/keyframes_draw.cc index 3dfbb65b9e8..6bdaf543e4c 100644 --- a/source/blender/editors/animation/keyframes_draw.cc +++ b/source/blender/editors/animation/keyframes_draw.cc @@ -416,31 +416,31 @@ struct ChannelListElement { MaskLayer *masklay; }; -static void build_channel_keylist(ChannelListElement *elem) +static void build_channel_keylist(ChannelListElement *elem, blender::float2 range) { switch (elem->type) { case ChannelType::SUMMARY: { - summary_to_keylist(elem->ac, elem->keylist, elem->saction_flag); + summary_to_keylist(elem->ac, elem->keylist, elem->saction_flag, range); break; } case ChannelType::SCENE: { - scene_to_keylist(elem->ads, elem->sce, elem->keylist, elem->saction_flag); + scene_to_keylist(elem->ads, elem->sce, elem->keylist, elem->saction_flag, range); break; } case ChannelType::OBJECT: { - ob_to_keylist(elem->ads, elem->ob, elem->keylist, elem->saction_flag); + ob_to_keylist(elem->ads, elem->ob, elem->keylist, elem->saction_flag, range); break; } case ChannelType::FCURVE: { - fcurve_to_keylist(elem->adt, elem->fcu, elem->keylist, elem->saction_flag); + fcurve_to_keylist(elem->adt, elem->fcu, elem->keylist, elem->saction_flag, range); break; } case ChannelType::ACTION: { - action_to_keylist(elem->adt, elem->act, elem->keylist, elem->saction_flag); + action_to_keylist(elem->adt, elem->act, elem->keylist, elem->saction_flag, range); break; } case ChannelType::ACTION_GROUP: { - action_group_to_keylist(elem->adt, elem->agrp, elem->keylist, elem->saction_flag); + action_group_to_keylist(elem->adt, elem->agrp, elem->keylist, elem->saction_flag, range); break; } case ChannelType::GREASE_PENCIL_CELS: { @@ -506,10 +506,10 @@ ChannelDrawList *ED_channel_draw_list_create() return static_cast(MEM_callocN(sizeof(ChannelDrawList), __func__)); } -static void channel_list_build_keylists(ChannelDrawList *channel_list) +static void channel_list_build_keylists(ChannelDrawList *channel_list, blender::float2 range) { LISTBASE_FOREACH (ChannelListElement *, elem, &channel_list->channels) { - build_channel_keylist(elem); + build_channel_keylist(elem, range); prepare_channel_for_drawing(elem); } } @@ -594,7 +594,7 @@ static void channel_list_draw(ChannelDrawList *channel_list, View2D *v2d) void ED_channel_list_flush(ChannelDrawList *channel_list, View2D *v2d) { - channel_list_build_keylists(channel_list); + channel_list_build_keylists(channel_list, {v2d->cur.xmin, v2d->cur.xmax}); channel_list_draw(channel_list, v2d); } diff --git a/source/blender/editors/animation/keyframes_keylist.cc b/source/blender/editors/animation/keyframes_keylist.cc index e85c51866b2..3104a0bd43c 100644 --- a/source/blender/editors/animation/keyframes_keylist.cc +++ b/source/blender/editors/animation/keyframes_keylist.cc @@ -928,7 +928,10 @@ int actkeyblock_get_valid_hold(const ActKeyColumn *ac) /* *************************** Keyframe List Conversions *************************** */ -void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, const int saction_flag) +void summary_to_keylist(bAnimContext *ac, + AnimKeylist *keylist, + const int saction_flag, + blender::float2 range) { if (!ac) { return; @@ -950,7 +953,8 @@ void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, const int sactio * there isn't really any benefit at all from including them. - Aligorith */ switch (ale->datatype) { case ALE_FCURVE: - fcurve_to_keylist(ale->adt, static_cast(ale->data), keylist, saction_flag); + fcurve_to_keylist( + ale->adt, static_cast(ale->data), keylist, saction_flag, range); break; case ALE_MASKLAY: mask_to_keylist(ac->ads, static_cast(ale->data), keylist); @@ -970,7 +974,11 @@ void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, const int sactio ANIM_animdata_freelist(&anim_data); } -void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, const int saction_flag) +void scene_to_keylist(bDopeSheet *ads, + Scene *sce, + AnimKeylist *keylist, + const int saction_flag, + blender::float2 range) { bAnimContext ac = {nullptr}; ListBase anim_data = {nullptr, nullptr}; @@ -999,13 +1007,17 @@ void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, const i /* Loop through each F-Curve, grabbing the keyframes. */ LISTBASE_FOREACH (const bAnimListElem *, ale, &anim_data) { - fcurve_to_keylist(ale->adt, static_cast(ale->data), keylist, saction_flag); + fcurve_to_keylist(ale->adt, static_cast(ale->data), keylist, saction_flag, range); } ANIM_animdata_freelist(&anim_data); } -void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, const int saction_flag) +void ob_to_keylist(bDopeSheet *ads, + Object *ob, + AnimKeylist *keylist, + const int saction_flag, + blender::float2 range) { bAnimContext ac = {nullptr}; ListBase anim_data = {nullptr, nullptr}; @@ -1036,7 +1048,7 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, const int /* Loop through each F-Curve, grabbing the keyframes. */ LISTBASE_FOREACH (const bAnimListElem *, ale, &anim_data) { - fcurve_to_keylist(ale->adt, static_cast(ale->data), keylist, saction_flag); + fcurve_to_keylist(ale->adt, static_cast(ale->data), keylist, saction_flag, range); } ANIM_animdata_freelist(&anim_data); @@ -1071,13 +1083,18 @@ void cachefile_to_keylist(bDopeSheet *ads, /* Loop through each F-Curve, grabbing the keyframes. */ LISTBASE_FOREACH (const bAnimListElem *, ale, &anim_data) { - fcurve_to_keylist(ale->adt, static_cast(ale->data), keylist, saction_flag); + fcurve_to_keylist( + ale->adt, static_cast(ale->data), keylist, saction_flag, {-FLT_MAX, FLT_MAX}); } ANIM_animdata_freelist(&anim_data); } -void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const int saction_flag) +void fcurve_to_keylist(AnimData *adt, + FCurve *fcu, + AnimKeylist *keylist, + const int saction_flag, + blender::float2 range) { if (!fcu || fcu->totvert == 0 || !fcu->bezt) { return; @@ -1093,8 +1110,22 @@ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const i BezTripleChain chain = {nullptr}; + int start_index = 0; + /* Used in an exclusive way. */ + int end_index = fcu->totvert; + + bool replace; + start_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[0], fcu->totvert, &replace); + if (start_index > 0) { + start_index--; + } + end_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[1], fcu->totvert, &replace); + if (end_index < fcu->totvert) { + end_index++; + } + /* Loop through beztriples, making ActKeysColumns. */ - for (int v = 0; v < fcu->totvert; v++) { + for (int v = start_index; v < end_index; v++) { chain.cur = &fcu->bezt[v]; /* Neighbor columns, accounting for being cyclic. */ @@ -1110,7 +1141,7 @@ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const i add_bezt_to_keycolumns_list(keylist, &chain); } - update_keyblocks(keylist, fcu->bezt, fcu->totvert); + update_keyblocks(keylist, &fcu->bezt[start_index], end_index - start_index); if (adt) { ANIM_nla_mapping_apply_fcurve(adt, fcu, true, false); @@ -1120,7 +1151,8 @@ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const i void action_group_to_keylist(AnimData *adt, bActionGroup *agrp, AnimKeylist *keylist, - const int saction_flag) + const int saction_flag, + blender::float2 range) { if (!agrp) { return; @@ -1130,18 +1162,22 @@ void action_group_to_keylist(AnimData *adt, if (fcu->grp != agrp) { break; } - fcurve_to_keylist(adt, fcu, keylist, saction_flag); + fcurve_to_keylist(adt, fcu, keylist, saction_flag, range); } } -void action_to_keylist(AnimData *adt, bAction *act, AnimKeylist *keylist, const int saction_flag) +void action_to_keylist(AnimData *adt, + bAction *act, + AnimKeylist *keylist, + const int saction_flag, + blender::float2 range) { if (!act) { return; } LISTBASE_FOREACH (FCurve *, fcu, &act->curves) { - fcurve_to_keylist(adt, fcu, keylist, saction_flag); + fcurve_to_keylist(adt, fcu, keylist, saction_flag, range); } } diff --git a/source/blender/editors/animation/keyframes_keylist_test.cc b/source/blender/editors/animation/keyframes_keylist_test.cc index 5f7abf43848..12225529856 100644 --- a/source/blender/editors/animation/keyframes_keylist_test.cc +++ b/source/blender/editors/animation/keyframes_keylist_test.cc @@ -43,7 +43,7 @@ static AnimKeylist *create_test_keylist() build_fcurve(*fcurve); AnimKeylist *keylist = ED_keylist_create(); - fcurve_to_keylist(nullptr, fcurve, keylist, 0); + fcurve_to_keylist(nullptr, fcurve, keylist, 0, {-FLT_MAX, FLT_MAX}); BKE_fcurve_free(fcurve); ED_keylist_prepare_for_direct_access(keylist); diff --git a/source/blender/editors/armature/pose_slide.cc b/source/blender/editors/armature/pose_slide.cc index 06e9fccf174..849f78afa33 100644 --- a/source/blender/editors/armature/pose_slide.cc +++ b/source/blender/editors/armature/pose_slide.cc @@ -1019,7 +1019,7 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, const wmEvent * /* Do this for each F-Curve. */ LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) { FCurve *fcu = (FCurve *)ld->data; - fcurve_to_keylist(pfl->ob->adt, fcu, pso->keylist, 0); + fcurve_to_keylist(pfl->ob->adt, fcu, pso->keylist, 0, {-FLT_MAX, FLT_MAX}); } } @@ -1804,7 +1804,7 @@ static void get_keyed_frames_in_range(ListBase *pflinks, LISTBASE_FOREACH (tPChanFCurveLink *, pfl, pflinks) { LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) { FCurve *fcu = (FCurve *)ld->data; - fcurve_to_keylist(nullptr, fcu, keylist, 0); + fcurve_to_keylist(nullptr, fcu, keylist, 0, {start_frame, end_frame}); } } LISTBASE_FOREACH (ActKeyColumn *, column, ED_keylist_listbase(keylist)) { @@ -1827,7 +1827,7 @@ static void get_selected_frames(ListBase *pflinks, ListBase /*FrameLink*/ *targe LISTBASE_FOREACH (tPChanFCurveLink *, pfl, pflinks) { LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) { FCurve *fcu = (FCurve *)ld->data; - fcurve_to_keylist(nullptr, fcu, keylist, 0); + fcurve_to_keylist(nullptr, fcu, keylist, 0, {-FLT_MAX, FLT_MAX}); } } LISTBASE_FOREACH (ActKeyColumn *, column, ED_keylist_listbase(keylist)) { diff --git a/source/blender/editors/include/ED_keyframes_keylist.hh b/source/blender/editors/include/ED_keyframes_keylist.hh index fac9317f165..6ab50dc8934 100644 --- a/source/blender/editors/include/ED_keyframes_keylist.hh +++ b/source/blender/editors/include/ED_keyframes_keylist.hh @@ -8,6 +8,7 @@ #pragma once +#include "BLI_math_vector_types.hh" #include "BLI_range.h" struct AnimData; @@ -145,26 +146,37 @@ int64_t ED_keylist_array_len(const AnimKeylist *keylist); /* Key-data Generation --------------- */ -/* F-Curve */ -void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, int saction_flag); +/** Add the keyframes of the F-Curve to the keylist. + * \param adt can be a nullptr. + * \param range only adds keys in the given range to the keylist. + */ +void fcurve_to_keylist( + AnimData *adt, FCurve *fcu, AnimKeylist *keylist, int saction_flag, blender::float2 range); /* Action Group */ void action_group_to_keylist(AnimData *adt, bActionGroup *agrp, AnimKeylist *keylist, - int saction_flag); + int saction_flag, + blender::float2 range); /* Action */ -void action_to_keylist(AnimData *adt, bAction *act, AnimKeylist *keylist, int saction_flag); +void action_to_keylist( + AnimData *adt, bAction *act, AnimKeylist *keylist, int saction_flag, blender::float2 range); /* Object */ -void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, int saction_flag); +void ob_to_keylist( + bDopeSheet *ads, Object *ob, AnimKeylist *keylist, int saction_flag, blender::float2 range); /* Cache File */ void cachefile_to_keylist(bDopeSheet *ads, CacheFile *cache_file, AnimKeylist *keylist, int saction_flag); /* Scene */ -void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, int saction_flag); +void scene_to_keylist( + bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, int saction_flag, blender::float2 range); /* DopeSheet Summary */ -void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, int saction_flag); +void summary_to_keylist(bAnimContext *ac, + AnimKeylist *keylist, + int saction_flag, + blender::float2 range); /* Grease Pencil datablock summary (Legacy) */ void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, AnimKeylist *keylist, bool active); diff --git a/source/blender/editors/screen/screen_ops.cc b/source/blender/editors/screen/screen_ops.cc index dba05f7ac81..e196750db4b 100644 --- a/source/blender/editors/screen/screen_ops.cc +++ b/source/blender/editors/screen/screen_ops.cc @@ -3194,10 +3194,10 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) } /* populate tree with keyframe nodes */ - scene_to_keylist(&ads, scene, keylist, 0); + scene_to_keylist(&ads, scene, keylist, 0, {-FLT_MAX, FLT_MAX}); if (ob) { - ob_to_keylist(&ads, ob, keylist, 0); + ob_to_keylist(&ads, ob, keylist, 0, {-FLT_MAX, FLT_MAX}); if (ob->type == OB_GPENCIL_LEGACY) { const bool active = !(scene->flag & SCE_KEYS_NO_SELONLY); diff --git a/source/blender/editors/space_action/action_select.cc b/source/blender/editors/space_action/action_select.cc index e69cdde89b6..d59419d319b 100644 --- a/source/blender/editors/space_action/action_select.cc +++ b/source/blender/editors/space_action/action_select.cc @@ -98,38 +98,40 @@ static void actkeys_list_element_to_keylist(bAnimContext *ac, ads = static_cast(ac->data); } + blender::float2 range = {ac->region->v2d.cur.xmin, ac->region->v2d.cur.xmax}; + if (ale->key_data) { switch (ale->datatype) { case ALE_SCE: { Scene *scene = (Scene *)ale->key_data; - scene_to_keylist(ads, scene, keylist, 0); + scene_to_keylist(ads, scene, keylist, 0, range); break; } case ALE_OB: { Object *ob = (Object *)ale->key_data; - ob_to_keylist(ads, ob, keylist, 0); + ob_to_keylist(ads, ob, keylist, 0, range); break; } case ALE_ACT: { bAction *act = (bAction *)ale->key_data; - action_to_keylist(adt, act, keylist, 0); + action_to_keylist(adt, act, keylist, 0, range); break; } case ALE_FCURVE: { FCurve *fcu = (FCurve *)ale->key_data; - fcurve_to_keylist(adt, fcu, keylist, 0); + fcurve_to_keylist(adt, fcu, keylist, 0, range); break; } } } else if (ale->type == ANIMTYPE_SUMMARY) { /* dopesheet summary covers everything */ - summary_to_keylist(ac, keylist, 0); + summary_to_keylist(ac, keylist, 0, range); } else if (ale->type == ANIMTYPE_GROUP) { /* TODO: why don't we just give groups key_data too? */ bActionGroup *agrp = (bActionGroup *)ale->data; - action_group_to_keylist(adt, agrp, keylist, 0); + action_group_to_keylist(adt, agrp, keylist, 0, range); } else if (ale->type == ANIMTYPE_GREASE_PENCIL_LAYER) { /* TODO: why don't we just give grease pencil layers key_data too? */ diff --git a/source/blender/editors/space_nla/nla_draw.cc b/source/blender/editors/space_nla/nla_draw.cc index 520a88d64ea..396e40dd989 100644 --- a/source/blender/editors/space_nla/nla_draw.cc +++ b/source/blender/editors/space_nla/nla_draw.cc @@ -85,7 +85,7 @@ static void nla_action_draw_keyframes( /* get a list of the keyframes with NLA-scaling applied */ AnimKeylist *keylist = ED_keylist_create(); - action_to_keylist(adt, act, keylist, 0); + action_to_keylist(adt, act, keylist, 0, {-FLT_MAX, FLT_MAX}); if (ED_keylist_is_empty(keylist)) { ED_keylist_free(keylist);