From 17cb2a6da0c88eb509448447e10bc73a38398895 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Tue, 20 Oct 2020 22:16:55 +0200 Subject: UI: Move gesture selection with spacebar This patch adds a modal key to move the selection box/lasso/line while drawing it. It also sets "repeat": False on the animation playback key to prevent accidental playback if the spacebar is released after the mouse button. Reviewed By: #user_interface, pablovazquez, Severin Differential Revision: https://developer.blender.org/D9227 --- .../keyconfig/keymap_data/blender_default.py | 38 ++++++++++++++----- .../keymap_data/industry_compatible_data.py | 2 +- source/blender/windowmanager/WM_types.h | 2 + source/blender/windowmanager/intern/wm_gesture.c | 1 + .../blender/windowmanager/intern/wm_gesture_ops.c | 43 +++++++++++++++++++++- source/blender/windowmanager/intern/wm_operators.c | 35 ++++++++++++++++++ source/blender/windowmanager/wm_event_types.h | 3 ++ 7 files changed, 111 insertions(+), 13 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index b27cdbec308..a711ffb9df8 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -394,7 +394,7 @@ def km_window(params): ("wm.window_new", {"type": 'W', "value": 'PRESS', "ctrl": True, "alt": True}, None), ("wm.window_fullscreen_toggle", {"type": 'F11', "value": 'PRESS', "alt": True}, None), ("wm.doc_view_manual_ui_context", {"type": 'F1', "value": 'PRESS', "alt": True}, None), - ("wm.search_menu", {"type": 'SPACE', "value": 'PRESS'}, None), + ("wm.search_menu", {"type": 'SPACE', "value": 'PRESS', "repeat": False}, None), ("wm.redraw_timer", {"type": 'T', "value": 'PRESS', "ctrl": True, "alt": True}, None), ("wm.debug_menu", {"type": 'D', "value": 'PRESS', "ctrl": True, "alt": True}, None), ]) @@ -470,11 +470,11 @@ def km_window(params): ) elif params.spacebar_action == 'PLAY': items.append( - ("wm.toolbar", {"type": 'SPACE', "value": 'PRESS', "shift": True}, None), + ("wm.toolbar", {"type": 'SPACE', "value": 'PRESS', "shift": True, "repeat": False}, None), ) elif params.spacebar_action == 'SEARCH': items.append( - ("wm.search_menu", {"type": 'SPACE', "value": 'PRESS'}, None), + ("wm.search_menu", {"type": 'SPACE', "value": 'PRESS', "repeat": False}, None), ) else: assert False @@ -526,8 +526,8 @@ def km_screen(params): if not params.legacy: items.extend([ - ("screen.screen_full_area", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None), - ("screen.screen_full_area", {"type": 'SPACE', "value": 'PRESS', "ctrl": True, "alt": True}, + ("screen.screen_full_area", {"type": 'SPACE', "value": 'PRESS', "ctrl": True, "repeat": False}, None), + ("screen.screen_full_area", {"type": 'SPACE', "value": 'PRESS', "ctrl": True, "alt": True, "repeat": False}, {"properties": [("use_hide_panels", True)]}), ("screen.redo_last", {"type": 'F9', "value": 'PRESS'}, None), ]) @@ -1267,7 +1267,7 @@ def km_view3d(params): {"properties": [("type", 'LEFT')]}), ("view3d.view_roll", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, {"properties": [("type", 'RIGHT')]}), - ("transform.create_orientation", {"type": 'SPACE', "value": 'PRESS', "ctrl": True, "alt": True}, + ("transform.create_orientation", {"type": 'SPACE', "value": 'PRESS', "ctrl": True, "alt": True, "repeat": False}, {"properties": [("use", True)]}), ("transform.translate", {"type": 'T', "value": 'PRESS', "shift": True, "repeat": False}, {"properties": [("texture_space", True)]}), @@ -1280,7 +1280,7 @@ def km_view3d(params): {"properties": [("data_path", 'tool_settings.transform_pivot_point'), ("value", 'MEDIAN_POINT')]}), ("wm.context_toggle", {"type": 'COMMA', "value": 'PRESS', "alt": True}, {"properties": [("data_path", 'tool_settings.use_transform_pivot_point_align')]}), - ("wm.context_toggle", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, + ("wm.context_toggle", {"type": 'SPACE', "value": 'PRESS', "ctrl": True, "repeat": False}, {"properties": [("data_path", 'space_data.show_gizmo_context')]}), ("wm.context_set_enum", {"type": 'PERIOD', "value": 'PRESS'}, {"properties": [("data_path", 'tool_settings.transform_pivot_point'), ("value", 'CURSOR')]}), @@ -2940,17 +2940,17 @@ def km_frames(params): # New playback if params.spacebar_action in {'TOOL', 'SEARCH'}: items.append( - ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS', "shift": True}, None), + ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS', "shift": True, "repeat": False}, None), ) elif params.spacebar_action == 'PLAY': items.append( - ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS'}, None), + ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS', "repeat": False}, None), ) else: assert False items.extend([ - ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS', "shift": True, "ctrl": True}, + ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS', "shift": True, "ctrl": True, "repeat": False}, {"properties": [("reverse", True)]}), ]) else: @@ -5094,6 +5094,7 @@ def km_gesture_border(_params): ("SELECT", {"type": 'LEFTMOUSE', "value": 'RELEASE', "any": True}, None), ("BEGIN", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None), ("DESELECT", {"type": 'MIDDLEMOUSE', "value": 'RELEASE'}, None), + ("MOVE", {"type": 'SPACE', "value": 'ANY', "repeat": False, "any": True}, None), ]) return keymap @@ -5132,6 +5133,22 @@ def km_gesture_straight_line(_params): ("CANCEL", {"type": 'RIGHTMOUSE', "value": 'ANY', "any": True}, None), ("BEGIN", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("SELECT", {"type": 'LEFTMOUSE', "value": 'RELEASE', "any": True}, None), + ("MOVE", {"type": 'SPACE', "value": 'ANY', "repeat": False, "any": True}, None), + ]) + + return keymap + + +def km_gesture_lasso(_params): + items = [] + keymap = ( + "Gesture Lasso", + {"space_type": 'EMPTY', "region_type": 'WINDOW', "modal": True}, + {"items": items}, + ) + + items.extend([ + ("MOVE", {"type": 'SPACE', "value": 'ANY', "repeat": False, "any": True}, None), ]) return keymap @@ -6917,6 +6934,7 @@ def generate_keymaps(params=None): km_gesture_border(params), km_gesture_zoom_border(params), km_gesture_straight_line(params), + km_gesture_lasso(params), km_standard_modal_map(params), km_knife_tool_modal_map(params), km_custom_normals_modal_map(params), diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index 99df1a422e3..a3a5c853b29 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -2139,7 +2139,7 @@ def km_frames(params): {"properties": [("end", True)]}), ("screen.frame_jump", {"type": 'MEDIA_FIRST', "value": 'PRESS'}, {"properties": [("end", False)]}), - ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS'}, None), + ("screen.animation_play", {"type": 'SPACE', "value": 'PRESS', "repeat": False}, None), ("screen.animation_cancel", {"type": 'ESC', "value": 'PRESS'}, None), ("screen.animation_play", {"type": 'MEDIA_PLAY', "value": 'PRESS'}, None), ("screen.animation_cancel", {"type": 'MEDIA_STOP', "value": 'PRESS'}, None), diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index acd72a4b1fd..05a35e030ff 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -498,6 +498,8 @@ typedef struct wmGesture { uint is_active_prev : 1; /** Use for gestures that support both immediate or delayed activation. */ uint wait_for_input : 1; + /** Use for gestures that can be moved, like box selection */ + uint move : 1; /** * customdata diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 6d36000abb4..ae8b78876c2 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -62,6 +62,7 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent gesture->winrct = region->winrct; gesture->user_data.use_free = true; /* Free if userdata is set. */ gesture->modal_state = GESTURE_MODAL_NOP; + gesture->move = false; if (ELEM(type, WM_GESTURE_RECT, diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 2c79b1f2215..fe21935ec88 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -29,9 +29,11 @@ #include "MEM_guardedalloc.h" +#include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" #include "BLI_math.h" +#include "BLI_rect.h" #include "BKE_context.h" @@ -209,6 +211,11 @@ int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event) rect->xmin = rect->xmax = event->x - gesture->winrct.xmin; rect->ymin = rect->ymax = event->y - gesture->winrct.ymin; } + else if (gesture->move) { + BLI_rcti_translate(rect, + (event->x - gesture->winrct.xmin) - rect->xmax, + (event->y - gesture->winrct.ymin) - rect->ymax); + } else { rect->xmax = event->x - gesture->winrct.xmin; rect->ymax = event->y - gesture->winrct.ymin; @@ -219,6 +226,9 @@ int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event) } else if (event->type == EVT_MODAL_MAP) { switch (event->val) { + case GESTURE_MODAL_MOVE: + gesture->move = !gesture->move; + break; case GESTURE_MODAL_BEGIN: if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) { gesture->is_active = true; @@ -652,9 +662,14 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) wmGesture *gesture = op->customdata; switch (event->type) { + case EVT_MODAL_MAP: + switch (event->val) { + case GESTURE_MODAL_MOVE: + gesture->move = !gesture->move; + break; + } case MOUSEMOVE: case INBETWEEN_MOUSEMOVE: - wm_gesture_tag_redraw(CTX_wm_window(C)); if (gesture->points == gesture->points_alloc) { @@ -671,9 +686,16 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) x = (event->x - gesture->winrct.xmin - lasso[0]); y = (event->y - gesture->winrct.ymin - lasso[1]); + /* move the lasso */ + if (gesture->move) { + for (int i = 0; i < gesture->points; i++) { + lasso[0 - (i * 2)] += x; + lasso[1 - (i * 2)] += y; + } + } /* make a simple distance check to get a smoother lasso * add only when at least 2 pixels between this and previous location */ - if ((x * x + y * y) > 4) { + else if ((x * x + y * y) > (2 * UI_DPI_FAC) ^ 2) { lasso += 2; lasso[0] = event->x - gesture->winrct.xmin; lasso[1] = event->y - gesture->winrct.ymin; @@ -877,6 +899,12 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev rect->xmin = rect->xmax = event->x - gesture->winrct.xmin; rect->ymin = rect->ymax = event->y - gesture->winrct.ymin; } + else if (gesture->move) { + BLI_rcti_translate(rect, + (event->x - gesture->winrct.xmin) - rect->xmax, + (event->y - gesture->winrct.ymin) - rect->ymax); + gesture_straightline_apply(C, op); + } else { rect->xmax = event->x - gesture->winrct.xmin; rect->ymax = event->y - gesture->winrct.ymin; @@ -887,6 +915,9 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev } else if (event->type == EVT_MODAL_MAP) { switch (event->val) { + case GESTURE_MODAL_MOVE: + gesture->move = !gesture->move; + break; case GESTURE_MODAL_BEGIN: if (gesture->is_active == false) { gesture->is_active = true; @@ -929,6 +960,11 @@ int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmE rect->xmin = rect->xmax = event->x - gesture->winrct.xmin; rect->ymin = rect->ymax = event->y - gesture->winrct.ymin; } + else if (gesture->move) { + BLI_rcti_translate(rect, + (event->x - gesture->winrct.xmin) - rect->xmax, + (event->y - gesture->winrct.ymin) - rect->ymax); + } else { rect->xmax = event->x - gesture->winrct.xmin; rect->ymax = event->y - gesture->winrct.ymin; @@ -938,6 +974,9 @@ int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmE } else if (event->type == EVT_MODAL_MAP) { switch (event->val) { + case GESTURE_MODAL_MOVE: + gesture->move = !gesture->move; + break; case GESTURE_MODAL_BEGIN: if (gesture->is_active == false) { gesture->is_active = true; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c51086c5f0a..bbe2ff4b81a 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3805,6 +3805,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf) {GESTURE_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, + {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -3831,6 +3832,7 @@ static void gesture_box_modal_keymap(wmKeyConfig *keyconf) {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, {GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""}, + {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -3881,6 +3883,38 @@ static void gesture_box_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_box"); } +/* lasso modal operators */ +static void gesture_lasso_modal_keymap(wmKeyConfig *keyconf) +{ + static const EnumPropertyItem modal_items[] = { + {GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Lasso"); + + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } + + keymap = WM_modalkeymap_ensure(keyconf, "Gesture Lasso", modal_items); + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_lasso"); + WM_modalkeymap_assign(keymap, "GPENCIL_OT_stroke_cutter"); + WM_modalkeymap_assign(keymap, "GPENCIL_OT_select_lasso"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_lasso"); + WM_modalkeymap_assign(keymap, "PAINT_OT_mask_lasso_gesture"); + WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_lasso_gesture"); + WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_lasso_gesture"); + WM_modalkeymap_assign(keymap, "ACTION_OT_select_lasso"); + WM_modalkeymap_assign(keymap, "CLIP_OT_select_lasso"); + WM_modalkeymap_assign(keymap, "GRAPH_OT_select_lasso"); + WM_modalkeymap_assign(keymap, "NODE_OT_select_lasso"); + WM_modalkeymap_assign(keymap, "UV_OT_select_lasso"); +} + /* zoom to border modal operators */ static void gesture_zoom_border_modal_keymap(wmKeyConfig *keyconf) { @@ -3917,6 +3951,7 @@ void wm_window_keymap(wmKeyConfig *keyconf) gesture_box_modal_keymap(keyconf); gesture_zoom_border_modal_keymap(keyconf); gesture_straightline_modal_keymap(keyconf); + gesture_lasso_modal_keymap(keyconf); WM_keymap_fix_linking(); } diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index c8f282e678f..de8ca0dc68a 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -490,6 +490,9 @@ enum { /** circle select: size brush (for trackpad event). */ GESTURE_MODAL_CIRCLE_SIZE = 11, + + /** Move selection area. */ + GESTURE_MODAL_MOVE = 12, }; #ifdef __cplusplus -- cgit v1.2.3