From e584bc320a9cf6be7a16fc159bb26b5ced5572fb Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 7 Oct 2020 12:46:58 +0200 Subject: Fix T76595: Indicate the Active Keyframe in Graph Editor Currently there is a panel that says "Active Keyframe" for numerically editing one keyframe's values, but in the code there is no concept of the "active keyframe." This patch adds an "active keyframe index" to each FCurve, and displays it with a theme color for the active vertex (which didn't exist before) if the FCurve is active. {F8536092 size=full} The active keyframe is not currently set for select operations other than basic click-select, which mirrors the behavior in the 3D view. Reviewed By: Severin, looch Maniphest Tasks: T76595 Differential Revision: https://developer.blender.org/D7737 --- source/blender/blenkernel/BKE_fcurve.h | 3 +++ source/blender/blenkernel/intern/fcurve.c | 32 +++++++++++++++++++++++ source/blender/blenkernel/intern/fcurve_test.cc | 34 +++++++++++++++++++++++++ 3 files changed, 69 insertions(+) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 9b6189612ba..e42d1cbbc78 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -244,6 +244,9 @@ bool BKE_fcurve_calc_bounds(struct FCurve *fcu, const bool do_sel_only, const bool include_handles); +void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt); +int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu); + /* .............. */ /* Are keyframes on F-Curve of any use (to final result, and to show in editors)? */ diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index d0f23221ed0..856e0e872b3 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -829,6 +829,38 @@ bool BKE_fcurve_calc_range( /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Active Keyframe + * \{ */ + +/** + * Set the index that stores the FCurve's active keyframe, assuming that \a active_bezt + * is already part of `fcu->bezt`. If NULL, set active keyframe index to "none." + */ +void BKE_fcurve_active_keyframe_set(FCurve *fcu, const BezTriple *active_bezt) +{ + fcu->active_keyframe_index = (active_bezt == NULL) ? FCURVE_ACTIVE_KEYFRAME_NONE : + active_bezt - fcu->bezt; +} + +/** + * Get the active keyframe index, with sanity checks for point bounds. + */ +int BKE_fcurve_active_keyframe_index(const FCurve *fcu) +{ + const int active_keyframe_index = fcu->active_keyframe_index; + + /* Sanity checks. */ + if ((fcu->bezt == NULL) || (active_keyframe_index >= fcu->totvert) || + (active_keyframe_index < 0)) { + return FCURVE_ACTIVE_KEYFRAME_NONE; + } + + return active_keyframe_index; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Status Checks * \{ */ diff --git a/source/blender/blenkernel/intern/fcurve_test.cc b/source/blender/blenkernel/intern/fcurve_test.cc index dd672df744b..7e3f64925d4 100644 --- a/source/blender/blenkernel/intern/fcurve_test.cc +++ b/source/blender/blenkernel/intern/fcurve_test.cc @@ -273,4 +273,38 @@ TEST(fcurve_subdivide, BKE_bezt_subdivide_handles) BKE_fcurve_free(fcu); } +TEST(fcurve_active_keyframe, ActiveKeyframe) +{ + FCurve *fcu = BKE_fcurve_create(); + + /* There should be no active keyframe with no points. */ + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), FCURVE_ACTIVE_KEYFRAME_NONE); + + /* Check that adding new points sets the active index. */ + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.5f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 8.0f, 15.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), 1); + EXPECT_EQ(insert_vert_fcurve(fcu, 14.0f, 8.2f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 2); + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), 2); + + /* Check clearing the index. */ + BKE_fcurve_active_keyframe_set(fcu, NULL); + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), FCURVE_ACTIVE_KEYFRAME_NONE); + + /* Check a "normal" action. */ + BKE_fcurve_active_keyframe_set(fcu, &fcu->bezt[2]); + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), 2); + + /* Check out of bounds. */ + BKE_fcurve_active_keyframe_set(fcu, fcu->bezt - 20); + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), FCURVE_ACTIVE_KEYFRAME_NONE); + + /* Check out of bounds again. */ + BKE_fcurve_active_keyframe_set(fcu, fcu->bezt + 4); + EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), FCURVE_ACTIVE_KEYFRAME_NONE); + + BKE_fcurve_free(fcu); +} + } // namespace blender::bke::tests -- cgit v1.2.3