diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 0db26735d65..39e34c0f42c 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -428,6 +428,7 @@ typedef enum { GHOST_kStandardCursorHandClosed, GHOST_kStandardCursorHandPoint, GHOST_kStandardCursorBlade, + GHOST_kStandardCursorSlip, GHOST_kStandardCursorCustom, #define GHOST_kStandardCursorNumCursors (int(GHOST_kStandardCursorCustom) + 1) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cc b/intern/ghost/intern/GHOST_SystemWayland.cc index 0969a20a3e2..215eed8f8d1 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cc +++ b/intern/ghost/intern/GHOST_SystemWayland.cc @@ -2893,6 +2893,8 @@ static std::optional gwl_seat_cursor_find_wl_sh return std::nullopt; case GHOST_kStandardCursorBlade: return std::nullopt; + case GHOST_kStandardCursorSlip: + return std::nullopt; case GHOST_kStandardCursorCustom: return std::nullopt; } diff --git a/release/datafiles/cursors/cursor_slip.svg b/release/datafiles/cursors/cursor_slip.svg new file mode 100644 index 00000000000..5a07c1c1f03 --- /dev/null +++ b/release/datafiles/cursors/cursor_slip.svg @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/release/datafiles/icons/ops.sequencer.slip.dat b/release/datafiles/icons/ops.sequencer.slip.dat new file mode 100644 index 00000000000..8232941b716 --- /dev/null +++ b/release/datafiles/icons/ops.sequencer.slip.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c729938f088f015b66fae7dfde3e0a2f18dee4c790b74354e1f4e372bdc03441 +size 3050 diff --git a/release/datafiles/icons_blend/toolbar.blend b/release/datafiles/icons_blend/toolbar.blend index 9ac838d971c..fd281f70717 100644 --- a/release/datafiles/icons_blend/toolbar.blend +++ b/release/datafiles/icons_blend/toolbar.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c40c877c54afd91d6fc4d5999d8d511eef69ed553c8d6a7fe9ac15a66ad7e4b3 -size 2666476 +oid sha256:77cb80cb0db21bfebd39b19541a57e2bcc0cf4089ce1acae8037f650d086bfd2 +size 2714741 diff --git a/scripts/presets/keyconfig/keymap_data/blender_default.py b/scripts/presets/keyconfig/keymap_data/blender_default.py index 9c4a64c72b1..2ff1575832a 100644 --- a/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -3101,7 +3101,7 @@ def km_sequencer(params): op_menu("SEQUENCER_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}), op_menu("SEQUENCER_MT_change", {"type": 'C', "value": 'PRESS'}), op_menu_pie("SEQUENCER_MT_view_pie", {"type": 'ACCENT_GRAVE', "value": 'PRESS'}), - ("sequencer.slip", {"type": 'S', "value": 'PRESS'}, None), + ("sequencer.slip", {"type": 'S', "value": 'PRESS'}, {"properties": [("use_cursor_position", False)]}), ("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'}, @@ -8514,6 +8514,26 @@ def km_sequencer_tool_blade(_params): ) +def km_sequencer_tool_slip(_params): + return ( + "Sequencer Tool: Slip", + {"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'}, + {"items": [ + ("sequencer.slip", {"type": 'LEFTMOUSE', "value": 'PRESS'}, + {"properties": [ + ("slip_keyframes", True), + ("use_cursor_position", True), + ]}), + ("sequencer.slip", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [ + ("slip_keyframes", True), + ("use_cursor_position", True), + ("ignore_connections", True), + ]}), + ]}, + ) + + # ------------------------------------------------------------------------------ # Tool System (Sequencer, Preview) @@ -8850,6 +8870,7 @@ def generate_keymaps(params=None): km_3d_view_tool_paint_grease_pencil_trim(params), km_3d_view_tool_edit_grease_pencil_texture_gradient(params), km_sequencer_tool_blade(params), + km_sequencer_tool_slip(params), km_sequencer_preview_tool_generic_cursor(params), km_sequencer_preview_tool_sample(params), km_sequencer_preview_tool_move(params), diff --git a/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index beacf6a4490..08bff5411ea 100644 --- a/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -1887,6 +1887,7 @@ def km_sequencer(params): # Tools op_tool_cycle("builtin.select_box", {"type": 'Q', "value": 'PRESS'}), op_tool_cycle("builtin.blade", {"type": 'B', "value": 'PRESS'}), + op_tool_cycle("builtin.slip", {"type": 'S', "value": 'PRESS'}), ]) return keymap diff --git a/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/scripts/startup/bl_ui/space_toolsystem_toolbar.py index ecbb5ff0603..8e4ce562343 100644 --- a/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -3158,6 +3158,18 @@ class _defs_sequencer_generic: options={'KEYMAP_FALLBACK'}, ) + @ToolDef.from_fn + def slip(): + return dict( + idname="builtin.slip", + label="Slip", + description=( + "Shift underlying strip content without affecting handles" + ), + icon="ops.sequencer.slip", + keymap="Sequencer Tool: Slip", + ) + @ToolDef.from_fn def sample(): return dict( @@ -3960,6 +3972,7 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel): 'SEQUENCER': [ _defs_sequencer_select.box_timeline, _defs_sequencer_generic.blade, + _defs_sequencer_generic.slip ], 'SEQUENCER_PREVIEW': [ _defs_sequencer_select.box_timeline, diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index f4176dda8de..cfd6616acff 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -152,6 +152,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES ops.sculpt.polyline_trim ops.sequencer.blade ops.sequencer.retime + ops.sequencer.slip ops.transform.bone_envelope ops.transform.bone_size ops.transform.edge_slide @@ -965,6 +966,7 @@ if(WITH_BLENDER) cursor_pointer cursor_right_handle cursor_s_arrow + cursor_slip cursor_stop cursor_swap_area cursor_text_edit diff --git a/source/blender/editors/space_sequencer/sequencer_edit.cc b/source/blender/editors/space_sequencer/sequencer_edit.cc index 0c80896ffbd..685c94fc798 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.cc +++ b/source/blender/editors/space_sequencer/sequencer_edit.cc @@ -766,12 +766,31 @@ static void slip_update_header(const Scene *scene, ED_area_status_text(area, msg); } -static SlipData *slip_data_init(const Scene *scene) +static SlipData *slip_data_init(bContext *C, const wmOperator *op, const wmEvent *event) { - Editing *ed = seq::editing_get(scene); + const Scene *scene = CTX_data_scene(C); + const Editing *ed = seq::editing_get(scene); + const View2D *v2d = UI_view2d_fromcontext(C); + SlipData *data = MEM_new("slipdata"); - VectorSet strips = seq::query_selected_strips(ed->current_strips()); + VectorSet strips; + if (RNA_boolean_get(op->ptr, "use_cursor_position") && event) { + Strip *strip = strip_under_mouse_get(scene, v2d, event->mval); + if (strip) { + strips.add(strip); + } + if (!RNA_boolean_get(op->ptr, "ignore_connections")) { + VectorSet connections = seq::connected_strips_get(strip); + for (Strip *connection : connections) { + strips.add(connection); + } + } + } + else { + strips = seq::query_selected_strips(ed->current_strips()); + } + ListBase *channels = seq::channels_displayed_get(seq::editing_get(scene)); strips.remove_if([&](Strip *strip) { return (seq::transform_single_image_check(strip) || seq::transform_is_locked(channels, strip)); @@ -818,7 +837,7 @@ static wmOperatorStatus sequencer_slip_invoke(bContext *C, wmOperator *op, const ScrArea *area = CTX_wm_area(C); View2D *v2d = UI_view2d_fromcontext(C); - SlipData *data = slip_data_init(scene); + SlipData *data = slip_data_init(C, op, event); if (data == nullptr) { return OPERATOR_CANCELLED; } @@ -958,7 +977,7 @@ static wmOperatorStatus sequencer_slip_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_sequencer_scene(C); - SlipData *data = slip_data_init(scene); + SlipData *data = slip_data_init(C, op, nullptr); if (data == nullptr) { return OPERATOR_CANCELLED; } @@ -1110,6 +1129,16 @@ void SEQUENCER_OT_slip(wmOperatorType *ot) false, "Slip Keyframes", "Move the keyframes alongside the media"); + RNA_def_boolean(ot->srna, + "use_cursor_position", + false, + "Use Cursor Position", + "Slip strips under mouse cursor instead of all selected strips"); + RNA_def_boolean(ot->srna, + "ignore_connections", + false, + "Ignore Connections", + "Do not slip connected strips if using cursor position"); } /** \} */ diff --git a/source/blender/editors/space_sequencer/space_sequencer.cc b/source/blender/editors/space_sequencer/space_sequencer.cc index c8c1dc3020e..e3689396241 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.cc +++ b/source/blender/editors/space_sequencer/space_sequencer.cc @@ -673,9 +673,7 @@ static void sequencer_main_cursor(wmWindow *win, ScrArea *area, ARegion *region) int wmcursor = WM_CURSOR_DEFAULT; const bToolRef *tref = area->runtime.tool; - if (tref == nullptr || - !(STRPREFIX(tref->idname, "builtin.select") || STREQ(tref->idname, "builtin.blade"))) - { + if (tref == nullptr) { WM_cursor_set(win, wmcursor); return; } @@ -707,12 +705,19 @@ static void sequencer_main_cursor(wmWindow *win, ScrArea *area, ARegion *region) } const Editing *ed = seq::editing_get(scene); - if (STREQ(tref->idname, "builtin.blade")) { + if (STREQ(tref->idname, "builtin.blade") || STREQ(tref->idname, "builtin.slip")) { int mval[2] = {int(mouse_co_region[0]), int(mouse_co_region[1])}; Strip *strip = strip_under_mouse_get(scene, v2d, mval); - ListBase *channels = seq::channels_displayed_get(ed); if (strip != nullptr) { - wmcursor = seq::transform_is_locked(channels, strip) ? WM_CURSOR_STOP : WM_CURSOR_BLADE; + ListBase *channels = seq::channels_displayed_get(ed); + const bool locked = seq::transform_is_locked(channels, strip); + if (STREQ(tref->idname, "builtin.blade")) { + wmcursor = locked ? WM_CURSOR_STOP : WM_CURSOR_BLADE; + } + else if (STREQ(tref->idname, "builtin.slip")) { + wmcursor = (locked || seq::transform_single_image_check(strip)) ? WM_CURSOR_STOP : + WM_CURSOR_SLIP; + } } WM_cursor_set(win, wmcursor); return; diff --git a/source/blender/windowmanager/intern/wm_cursors.cc b/source/blender/windowmanager/intern/wm_cursors.cc index 68292e95034..34dcdb1d2c2 100644 --- a/source/blender/windowmanager/intern/wm_cursors.cc +++ b/source/blender/windowmanager/intern/wm_cursors.cc @@ -153,6 +153,8 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) return GHOST_kStandardCursorBothHandles; case WM_CURSOR_BLADE: return GHOST_kStandardCursorBlade; + case WM_CURSOR_SLIP: + return GHOST_kStandardCursorSlip; default: return GHOST_kStandardCursorCustom; } @@ -1017,5 +1019,6 @@ void wm_init_cursor_data() wm_add_cursor(WM_CURSOR_BOTH_HANDLES, datatoc_cursor_both_handles_svg, {0.5f, 0.5f}); wm_add_cursor(WM_CURSOR_RIGHT_HANDLE, datatoc_cursor_right_handle_svg, {0.5f, 0.5f}); wm_add_cursor(WM_CURSOR_LEFT_HANDLE, datatoc_cursor_left_handle_svg, {0.5f, 0.5f}); + wm_add_cursor(WM_CURSOR_SLIP, datatoc_cursor_slip_svg, {0.5f, 0.5f}); #endif /* !WITH_HEADLESS */ } diff --git a/source/blender/windowmanager/wm_cursors.hh b/source/blender/windowmanager/wm_cursors.hh index a085bae9ffb..b8d0864e01f 100644 --- a/source/blender/windowmanager/wm_cursors.hh +++ b/source/blender/windowmanager/wm_cursors.hh @@ -64,6 +64,7 @@ enum WMCursorType { WM_CURSOR_LEFT_HANDLE, WM_CURSOR_RIGHT_HANDLE, WM_CURSOR_BOTH_HANDLES, + WM_CURSOR_SLIP, /* --- ALWAYS LAST ----- */ WM_CURSOR_NUM,