Fix #102737: Keyframe jump operator includes hidden curves in Graph Editor #108549

Merged
Christoph Lendenfeld merged 1 commits from ChrisLend/blender:fix_graph_keyframe_jump into blender-v3.6-release 2023-06-08 11:02:24 +02:00
5 changed files with 112 additions and 1 deletions

View File

@ -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)]}),

View File

@ -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;

Maybe add acomment that explains that there is another operator for this specifically for the graph editor.

Maybe add acomment that explains that there is another operator for this specifically for the graph editor.
}
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";

View File

@ -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))
{

View File

@ -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);

View File

@ -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);