Fix #102737: Keyframe jump operator includes hidden curves in Graph Editor #108549
|
@ -1821,6 +1821,10 @@ def km_graph_editor(params):
|
||||||
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
|
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
|
||||||
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
|
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
|
||||||
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, 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', "ctrl": True}, None),
|
||||||
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
|
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
|
||||||
{"properties": [("extend", True)]}),
|
{"properties": [("extend", True)]}),
|
||||||
|
|
|
@ -3179,6 +3179,12 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
|
||||||
return OPERATOR_FINISHED;
|
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)
|
static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
ot->name = "Jump to Keyframe";
|
ot->name = "Jump to Keyframe";
|
||||||
|
@ -3187,7 +3193,7 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
||||||
|
|
||||||
ot->exec = keyframe_jump_exec;
|
ot->exec = keyframe_jump_exec;
|
||||||
|
|
||||||
ot->poll = ED_operator_screenactive_norender;
|
ot->poll = keyframe_jump_poll;
|
||||||
ot->flag = OPTYPE_UNDO_GROUPED;
|
ot->flag = OPTYPE_UNDO_GROUPED;
|
||||||
ot->undo_group = "Frame Change";
|
ot->undo_group = "Frame Change";
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_nla.h"
|
#include "BKE_nla.h"
|
||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
|
#include "BKE_scene.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph_build.h"
|
#include "DEG_depsgraph_build.h"
|
||||||
|
|
||||||
|
@ -2178,6 +2179,104 @@ void GRAPH_OT_frame_jump(wmOperatorType *ot)
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
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 */
|
/* snap 2D cursor value to the average value of selected keyframe */
|
||||||
static int graphkeys_snap_cursor_value_exec(bContext *C, wmOperator *UNUSED(op))
|
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_easing_type(struct wmOperatorType *ot);
|
||||||
|
|
||||||
void GRAPH_OT_frame_jump(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_cursor_value(struct wmOperatorType *ot);
|
||||||
void GRAPH_OT_snap(struct wmOperatorType *ot);
|
void GRAPH_OT_snap(struct wmOperatorType *ot);
|
||||||
void GRAPH_OT_equalize_handles(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_equalize_handles);
|
||||||
WM_operatortype_append(GRAPH_OT_mirror);
|
WM_operatortype_append(GRAPH_OT_mirror);
|
||||||
WM_operatortype_append(GRAPH_OT_frame_jump);
|
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_snap_cursor_value);
|
||||||
WM_operatortype_append(GRAPH_OT_handle_type);
|
WM_operatortype_append(GRAPH_OT_handle_type);
|
||||||
WM_operatortype_append(GRAPH_OT_interpolation_type);
|
WM_operatortype_append(GRAPH_OT_interpolation_type);
|
||||||
|
|
Loading…
Reference in New Issue