diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_sequencer.py | 3 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_ops.c | 82 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 5 |
4 files changed, 86 insertions, 5 deletions
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 5e92e088b36..55714e0b0a5 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -2293,6 +2293,9 @@ class SEQUENCER_PT_snapping(Panel): col.prop(sequencer_tool_settings, "snap_ignore_muted", text="Muted Strips") col.prop(sequencer_tool_settings, "snap_ignore_sound", text="Sound Strips") + col = layout.column() + col.prop(sequencer_tool_settings, "use_snap_current_frame_to_strips") + classes = ( SEQUENCER_MT_change, diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 73b9b118148..6f3277397c5 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -51,8 +51,10 @@ #include "DEG_depsgraph.h" +#include "SEQ_iterator.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" +#include "SEQ_transform.h" #include "anim_intern.h" @@ -81,6 +83,49 @@ static bool change_frame_poll(bContext *C) return false; } +static int seq_snap_threshold_get_frame_distance(bContext *C) +{ + const int snap_distance = SEQ_tool_settings_snap_distance_get(CTX_data_scene(C)); + const ARegion *region = CTX_wm_region(C); + return round_fl_to_int(UI_view2d_region_to_view_x(®ion->v2d, snap_distance) - + UI_view2d_region_to_view_x(®ion->v2d, 0)); +} + +static void seq_frame_snap_update_best(const int position, + const int timeline_frame, + int *r_best_frame, + int *r_best_distance) +{ + if (abs(position - timeline_frame) < *r_best_distance) { + *r_best_distance = abs(position - timeline_frame); + *r_best_frame = position; + } +} + +static int seq_frame_apply_snap(bContext *C, Scene *scene, const int timeline_frame) +{ + + ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene, false)); + SeqCollection *strips = SEQ_query_all_strips(seqbase); + + int best_frame = 0; + int best_distance = MAXFRAME; + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, strips) { + seq_frame_snap_update_best( + SEQ_transform_get_left_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + seq_frame_snap_update_best( + SEQ_transform_get_right_handle_frame(seq), timeline_frame, &best_frame, &best_distance); + } + SEQ_collection_free(strips); + + if (best_distance < seq_snap_threshold_get_frame_distance(C)) { + return best_frame; + } + + return timeline_frame; +} + /* Set the new frame number */ static void change_frame_apply(bContext *C, wmOperator *op) { @@ -90,7 +135,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) if (do_snap) { if (CTX_wm_space_seq(C)) { - frame = SEQ_time_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false); + frame = seq_frame_apply_snap(C, scene, frame); } else { frame = BKE_scene_frame_snap_by_seconds(scene, 1.0, frame); @@ -181,6 +226,18 @@ static void change_frame_seq_preview_end(bContext *C) } } +static bool use_sequencer_snapping(bContext *C) +{ + if (!CTX_wm_space_seq(C)) { + return false; + } + + Scene *scene = CTX_data_scene(C); + short snap_flag = SEQ_tool_settings_snap_flag_get(scene); + return (scene->toolsettings->snap_flag & SCE_SNAP_SEQ) && + (snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS); +} + /* Modal Operator init */ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -190,6 +247,10 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event */ RNA_float_set(op->ptr, "frame", frame_from_event(C, event)); + if (use_sequencer_snapping(C)) { + RNA_boolean_set(op->ptr, "snap", true); + } + change_frame_seq_preview_begin(C, event); change_frame_apply(C, op); @@ -231,11 +292,22 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) case EVT_LEFTCTRLKEY: case EVT_RIGHTCTRLKEY: - if (event->val == KM_RELEASE) { - RNA_boolean_set(op->ptr, "snap", false); + /* Use Ctrl key to invert snapping in sequencer. */ + if (use_sequencer_snapping(C)) { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", true); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", false); + } } - else if (event->val == KM_PRESS) { - RNA_boolean_set(op->ptr, "snap", true); + else { + if (event->val == KM_RELEASE) { + RNA_boolean_set(op->ptr, "snap", false); + } + else if (event->val == KM_PRESS) { + RNA_boolean_set(op->ptr, "snap", true); + } } break; } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 5fc6cdf58a3..cd752b220a3 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -2069,6 +2069,7 @@ enum { /** #SequencerToolSettings.snap_flag */ #define SEQ_SNAP_IGNORE_MUTED (1 << 0) #define SEQ_SNAP_IGNORE_SOUND (1 << 1) +#define SEQ_SNAP_CURRENT_FRAME_TO_STRIPS (1 << 2) /** #ToolSettings.snap_node_mode */ #define SCE_SNAP_MODE_NODE_X (1 << 0) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index cb1b0dbd1e5..0a91d5f01bc 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3535,6 +3535,11 @@ static void rna_def_sequencer_tool_settings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_IGNORE_SOUND); RNA_def_property_ui_text(prop, "Ignore Sound Strips", "Don't snap to sound strips"); + prop = RNA_def_property(srna, "use_snap_current_frame_to_strips", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SEQ_SNAP_CURRENT_FRAME_TO_STRIPS); + RNA_def_property_ui_text( + prop, "Snap Current Frame to Strips", "Snap current frame to strip start or end"); + prop = RNA_def_property(srna, "snap_distance", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "snap_distance"); RNA_def_property_int_default(prop, 15); |