Fix #102737: Keyframe jump operator includes hidden curves in Graph Editor
The graph editor has the function to hide the display of FCurves and to only draw keyframes on selected curves. Both options were not respected when executing the frame jump operator, meaning it would jump to potentially hidden keyframes. This patch adds a new operator that is specific to the Graph Editor and that respects those features. The only possible issue that could arise from this is a slight confusion for the user why they behave differently between editors. Especially with only the Graph Editor and the 3D view open. In general I think it's an improvement and follows the "you can only modify what you see" mantra in blender Also Resolves #97701 Pull Request: https://projects.blender.org/blender/blender/pulls/108549
This commit is contained in:
committed by
Christoph Lendenfeld
parent
9e598aa0ef
commit
2387290e4f
@@ -1821,6 +1821,10 @@ def km_graph_editor(params):
|
||||
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
|
||||
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
|
||||
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
|
||||
("graph.keyframe_jump", {"type": 'UP_ARROW', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("next", True)]}),
|
||||
("graph.keyframe_jump", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("next", False)]}),
|
||||
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, None),
|
||||
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
|
||||
{"properties": [("extend", True)]}),
|
||||
|
||||
@@ -3179,6 +3179,12 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static bool keyframe_jump_poll(bContext *C)
|
||||
{
|
||||
/* There is a keyframe jump operator specifically for the Graph Editor. */
|
||||
return ED_operator_screenactive_norender(C) && CTX_wm_area(C)->spacetype != SPACE_GRAPH;
|
||||
}
|
||||
|
||||
static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Jump to Keyframe";
|
||||
@@ -3187,7 +3193,7 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
||||
|
||||
ot->exec = keyframe_jump_exec;
|
||||
|
||||
ot->poll = ED_operator_screenactive_norender;
|
||||
ot->poll = keyframe_jump_poll;
|
||||
ot->flag = OPTYPE_UNDO_GROUPED;
|
||||
ot->undo_group = "Frame Change";
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "DEG_depsgraph_build.h"
|
||||
|
||||
@@ -2178,6 +2179,104 @@ void GRAPH_OT_frame_jump(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
static bool find_closest_frame(const FCurve *fcu,
|
||||
const float frame,
|
||||
const bool next,
|
||||
float *closest_frame)
|
||||
{
|
||||
bool replace;
|
||||
int bezt_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, frame, fcu->totvert, &replace);
|
||||
|
||||
BezTriple *bezt;
|
||||
if (next) {
|
||||
if (replace) {
|
||||
bezt_index++;
|
||||
}
|
||||
if (bezt_index > fcu->totvert - 1) {
|
||||
return false;
|
||||
}
|
||||
bezt = &fcu->bezt[bezt_index];
|
||||
}
|
||||
else {
|
||||
if (bezt_index - 1 < 0) {
|
||||
return false;
|
||||
}
|
||||
bezt = &fcu->bezt[bezt_index - 1];
|
||||
}
|
||||
|
||||
*closest_frame = bezt->vec[1][0];
|
||||
return true;
|
||||
}
|
||||
|
||||
static int keyframe_jump_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
bool next = RNA_boolean_get(op->ptr, "next");
|
||||
|
||||
/* Get editor data. */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
|
||||
ANIMFILTER_NODUPLIS);
|
||||
if (U.animation_flag & USER_ANIM_ONLY_SHOW_SELECTED_CURVE_KEYS) {
|
||||
filter |= ANIMFILTER_SEL;
|
||||
}
|
||||
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
float closest_frame = next ? FLT_MAX : -FLT_MAX;
|
||||
bool found = false;
|
||||
|
||||
const float current_frame = BKE_scene_frame_get(scene);
|
||||
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
|
||||
const FCurve *fcu = ale->key_data;
|
||||
if (!fcu->bezt) {
|
||||
continue;
|
||||
}
|
||||
float closest_fcu_frame;
|
||||
if (!find_closest_frame(fcu, current_frame, next, &closest_fcu_frame)) {
|
||||
continue;
|
||||
}
|
||||
if ((next && closest_fcu_frame < closest_frame) ||
|
||||
(!next && closest_fcu_frame > closest_frame)) {
|
||||
closest_frame = closest_fcu_frame;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
BKE_report(op->reports, RPT_INFO, "No more keyframes to jump to in this direction");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_scene_frame_set(scene, closest_frame);
|
||||
|
||||
/* Set notifier that things have changed. */
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPH_OT_keyframe_jump(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Jump to Keyframe";
|
||||
ot->description = "Jump to previous/next keyframe";
|
||||
ot->idname = "GRAPH_OT_keyframe_jump";
|
||||
|
||||
ot->exec = keyframe_jump_exec;
|
||||
|
||||
ot->poll = graphkeys_framejump_poll;
|
||||
ot->flag = OPTYPE_UNDO_GROUPED;
|
||||
ot->undo_group = "Frame Change";
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", "");
|
||||
}
|
||||
|
||||
/* snap 2D cursor value to the average value of selected keyframe */
|
||||
static int graphkeys_snap_cursor_value_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
|
||||
@@ -130,6 +130,7 @@ void GRAPH_OT_extrapolation_type(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_easing_type(struct wmOperatorType *ot);
|
||||
|
||||
void GRAPH_OT_frame_jump(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_keyframe_jump(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_snap_cursor_value(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_snap(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_equalize_handles(struct wmOperatorType *ot);
|
||||
|
||||
@@ -448,6 +448,7 @@ void graphedit_operatortypes(void)
|
||||
WM_operatortype_append(GRAPH_OT_equalize_handles);
|
||||
WM_operatortype_append(GRAPH_OT_mirror);
|
||||
WM_operatortype_append(GRAPH_OT_frame_jump);
|
||||
WM_operatortype_append(GRAPH_OT_keyframe_jump);
|
||||
WM_operatortype_append(GRAPH_OT_snap_cursor_value);
|
||||
WM_operatortype_append(GRAPH_OT_handle_type);
|
||||
WM_operatortype_append(GRAPH_OT_interpolation_type);
|
||||
|
||||
Reference in New Issue
Block a user