diff options
author | Richard Antalik <richardantalik@gmail.com> | 2022-04-04 15:25:13 +0300 |
---|---|---|
committer | Richard Antalik <richardantalik@gmail.com> | 2022-04-04 15:28:55 +0300 |
commit | e49fef45cef7d53ae856a943e125838cdfcea0a0 (patch) | |
tree | b2b299823e5fa423788784da9741c2d27b06c211 | |
parent | 3ce6c5adfc6e9afd8a4db8d91084ae707db9b262 (diff) |
VSE: Use edge panning
Add edge panning feature to transform operator. It works in same way as
in node editor, but Y axis is limited by usable range up to 128
channels.
Reviewed By: Severin
Differential Revision: https://developer.blender.org/D14310
5 files changed, 83 insertions, 10 deletions
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 262d341e885..27556922f5e 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -2893,10 +2893,12 @@ def km_sequencer(params): ("sequencer.slip", {"type": 'S', "value": 'PRESS'}, None), ("wm.context_set_int", {"type": 'O', "value": 'PRESS'}, {"properties": [("data_path", 'scene.sequence_editor.overlay_frame'), ("value", 0)]}), - ("transform.seq_slide", {"type": 'G', "value": 'PRESS'}, None), - ("transform.seq_slide", {"type": params.select_mouse, "value": 'CLICK_DRAG'}, None), + ("transform.seq_slide", {"type": 'G', "value": 'PRESS'}, + {"properties": [("view2d_edge_pan", True)]}), + ("transform.seq_slide", {"type": params.select_mouse, "value": 'CLICK_DRAG'}, + {"properties": [("view2d_edge_pan", True)]}), ("transform.transform", {"type": 'E', "value": 'PRESS'}, - {"properties": [("mode", 'TIME_EXTEND')]}), + {"properties": [("mode", 'TIME_EXTEND'), ("view2d_edge_pan", True)]}), ("marker.add", {"type": 'M', "value": 'PRESS'}, None), ("marker.rename", {"type": 'M', "value": 'PRESS', "ctrl": True}, None), ("sequencer.select_side_of_frame", {"type": 'LEFT_BRACKET', "value": 'PRESS'}, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 4282465c0ca..56b0bd04a71 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -447,6 +447,8 @@ typedef struct View2DEdgePanData { struct ARegion *region; /** View2d we're operating in. */ struct View2D *v2d; + /* Limit maximum pannable area */ + struct rctf limit; /** Panning should only start once being in the inside rect once (e.g. adding nodes can happen * outside). */ @@ -492,6 +494,12 @@ void UI_view2d_edge_pan_init(struct bContext *C, float delay, float zoom_influence); +/** + * Set area which can be panned + */ +void UI_view2d_edge_pan_set_limits( + struct View2DEdgePanData *vpd, float xmin, float xmax, float ymin, float ymax); + void UI_view2d_edge_pan_reset(struct View2DEdgePanData *vpd); /** diff --git a/source/blender/editors/interface/view2d_edge_pan.cc b/source/blender/editors/interface/view2d_edge_pan.cc index ab1672ae8f6..82959d96043 100644 --- a/source/blender/editors/interface/view2d_edge_pan.cc +++ b/source/blender/editors/interface/view2d_edge_pan.cc @@ -67,6 +67,7 @@ void UI_view2d_edge_pan_init(bContext *C, vpd->area = CTX_wm_area(C); vpd->region = CTX_wm_region(C); vpd->v2d = &vpd->region->v2d; + BLI_rctf_init(&vpd->limit, -FLT_MAX, FLT_MAX, -FLT_MAX, FLT_MAX); BLI_assert(speed_ramp > 0.0f); vpd->inside_pad = inside_pad; @@ -87,6 +88,12 @@ void UI_view2d_edge_pan_init(bContext *C, UI_view2d_edge_pan_reset(vpd); } +void UI_view2d_edge_pan_set_limits( + View2DEdgePanData *vpd, float xmin, float xmax, float ymin, float ymax) +{ + BLI_rctf_init(&vpd->limit, xmin, xmax, ymin, ymax); +} + void UI_view2d_edge_pan_reset(View2DEdgePanData *vpd) { vpd->edge_pan_start_time_x = 0.0; @@ -220,20 +227,23 @@ void UI_view2d_edge_pan_apply(bContext *C, View2DEdgePanData *vpd, const int xy[ vpd->enabled = true; } + rctf *cur = &vpd->v2d->cur; + rctf *limit = &vpd->limit; + int pan_dir_x = 0; int pan_dir_y = 0; if (vpd->enabled && ((vpd->outside_pad == 0) || BLI_rcti_isect_pt_v(&outside_rect, xy))) { /* Find whether the mouse is beyond X and Y edges. */ - if (xy[0] > inside_rect.xmax) { + if (xy[0] > inside_rect.xmax && cur->xmax < limit->xmax) { pan_dir_x = 1; } - else if (xy[0] < inside_rect.xmin) { + else if (xy[0] < inside_rect.xmin && cur->xmin > limit->xmin) { pan_dir_x = -1; } - if (xy[1] > inside_rect.ymax) { + if (xy[1] > inside_rect.ymax && cur->ymax < limit->ymax) { pan_dir_y = 1; } - else if (xy[1] < inside_rect.ymin) { + else if (xy[1] < inside_rect.ymin && cur->ymin > limit->ymin) { pan_dir_y = -1; } } diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index b355b459c1e..16a96001fd2 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -35,6 +35,13 @@ #include "transform.h" #include "transform_convert.h" +#define SEQ_EDGE_PAN_INSIDE_PAD 2 +#define SEQ_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for panning, use whole screen. */ +#define SEQ_EDGE_PAN_SPEED_RAMP 1 +#define SEQ_EDGE_PAN_MAX_SPEED 4 /* In UI units per second, slower than default. */ +#define SEQ_EDGE_PAN_DELAY 1.0f +#define SEQ_EDGE_PAN_ZOOM_INFLUENCE 0.5f + /** Used for sequencer transform. */ typedef struct TransDataSeq { struct Sequence *seq; @@ -55,6 +62,10 @@ typedef struct TransSeq { TransDataSeq *tdseq; int selection_channel_range_min; int selection_channel_range_max; + + /* Initial rect of the view2d, used for computing offset during edge panning */ + rctf initial_v2d_cur; + View2DEdgePanData edge_pan; } TransSeq; /* -------------------------------------------------------------------- */ @@ -673,6 +684,18 @@ void createTransSeqData(TransInfo *t) td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransSeq TransData2D"); ts->tdseq = tdsq = MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq"); + /* Custom data to enable edge panning during transformation. */ + UI_view2d_edge_pan_init(t->context, + &ts->edge_pan, + SEQ_EDGE_PAN_INSIDE_PAD, + SEQ_EDGE_PAN_OUTSIDE_PAD, + SEQ_EDGE_PAN_SPEED_RAMP, + SEQ_EDGE_PAN_MAX_SPEED, + SEQ_EDGE_PAN_DELAY, + SEQ_EDGE_PAN_ZOOM_INFLUENCE); + UI_view2d_edge_pan_set_limits(&ts->edge_pan, -FLT_MAX, FLT_MAX, 1, MAXSEQ + 1); + ts->initial_v2d_cur = t->region->v2d.cur; + /* loop 2: build transdata array */ SeqToTransData_build(t, ed->seqbasep, td, td2d, tdsq); @@ -710,8 +733,36 @@ BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int s } } +static void view2d_edge_pan_loc_compensate(TransInfo *t, float loc_in[2], float r_loc[2]) +{ + TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; + + /* Initial and current view2D rects for additional transform due to view panning and zooming */ + const rctf *rect_src = &ts->initial_v2d_cur; + const rctf *rect_dst = &t->region->v2d.cur; + + copy_v2_v2(r_loc, loc_in); + /* Additional offset due to change in view2D rect. */ + BLI_rctf_transform_pt_v(rect_dst, rect_src, r_loc, r_loc); +} + static void flushTransSeq(TransInfo *t) { + TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; + if (t->options & CTX_VIEW2D_EDGE_PAN) { + if (t->state == TRANS_CANCEL) { + UI_view2d_edge_pan_cancel(t->context, &ts->edge_pan); + } + else { + /* Edge panning functions expect window coordinates, mval is relative to region */ + const int xy[2] = { + t->region->winrct.xmin + t->mval[0], + t->region->winrct.ymin + t->mval[1], + }; + UI_view2d_edge_pan_apply(t->context, &ts->edge_pan, xy); + } + } + /* Editing null check already done */ ListBase *seqbasep = seqbase_active_get(t); @@ -727,7 +778,9 @@ static void flushTransSeq(TransInfo *t) for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) { tdsq = (TransDataSeq *)td->extra; seq = tdsq->seq; - new_frame = round_fl_to_int(td2d->loc[0]); + float loc[2]; + view2d_edge_pan_loc_compensate(t, td->loc, loc); + new_frame = round_fl_to_int(loc[0]); switch (tdsq->sel_flag) { case SELECT: @@ -735,7 +788,7 @@ static void flushTransSeq(TransInfo *t) const int offset = new_frame - tdsq->start_offset - seq->start; SEQ_transform_translate_sequence(t->scene, seq, offset); } - seq->machine = round_fl_to_int(td2d->loc[1]); + seq->machine = round_fl_to_int(loc[1]); CLAMP(seq->machine, 1, MAXSEQ); break; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index efbb7375af4..ec49cef4067 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1255,7 +1255,7 @@ static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot) WM_operatortype_props_advanced_begin(ot); - Transform_Properties(ot, P_SNAP); + Transform_Properties(ot, P_SNAP | P_VIEW2D_EDGE_PAN); } static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot) |