From e937df1a7c660c872c54f077deb20a3302d6701e Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 28 Apr 2023 16:26:38 -0300 Subject: [PATCH] Transform: upport navigation while transforming in 3D view Implements a new option in keymap settings: - "Navigate during Transform" Note that with the option enabled, the keymap changes as follows: |Modal Map (Blender):| Conflict: | Current: | New: |---|---|---|--- | Increase Proportional Influence | VIEW3D_OT_zoom | Wheel Down | Alt Wheel Down | Decrease Proportional Influence | VIEW3D_OT_zoom | Wheel Up | Alt Wheel Up | Adjust Proportional Influence | VIEW3D_OT_rotate | Mouse/Trackpad Pan | Alt Mouse/Trackpad Pan | Increase Max AutoIK Chain Length | VIEW3D_OT_zoom | Wheel Down | Alt Wheel Down | Decrease Max AutoIK Chain Length | VIEW3D_OT_zoom | Wheel Up | Alt Wheel Up | Automatic Constraint | VIEW3D_OT_rotate | Middle Mouse | Alt Middle Mouse | Automatic Constraint Plane | VIEW3D_OT_move | Shift Middle Mouse | Shift Alt Middle Mouse --- scripts/presets/keyconfig/Blender.py | 11 +++++ .../keyconfig/keymap_data/blender_default.py | 40 ++++++++++------ scripts/startup/bl_ui/space_view3d.py | 18 +++++-- source/blender/editors/include/ED_transform.h | 3 +- source/blender/editors/transform/transform.c | 12 ++--- source/blender/editors/transform/transform.h | 3 ++ .../editors/transform/transform_generics.c | 12 +++++ .../blender/editors/transform/transform_ops.c | 48 ++++++++++++++++--- 8 files changed, 114 insertions(+), 33 deletions(-) diff --git a/scripts/presets/keyconfig/Blender.py b/scripts/presets/keyconfig/Blender.py index 52e4c2d4229..2eb63b16ee8 100644 --- a/scripts/presets/keyconfig/Blender.py +++ b/scripts/presets/keyconfig/Blender.py @@ -250,6 +250,15 @@ class Prefs(bpy.types.KeyConfigPreferences): update=update_fn, ) + use_transform_navigation: BoolProperty( + name="Navigate during Transform", + description=( + "Enable view navigation while using transform operators. " + "Proportional Influence, Automatic Constraints and Auto IK Chain Length shortcuts will require holding Alt key"), + default=False, + update=update_fn, + ) + def draw(self, layout): from bpy import context @@ -313,6 +322,7 @@ class Prefs(bpy.types.KeyConfigPreferences): sub.prop(self, "use_v3d_tab_menu") sub.prop(self, "use_pie_click_drag") sub.prop(self, "use_v3d_shade_ex_pie") + sub.prop(self, "use_transform_navigation") # File Browser settings. col = layout.column() @@ -365,6 +375,7 @@ def load(): use_alt_click_leader=kc_prefs.use_alt_click_leader, use_pie_click_drag=kc_prefs.use_pie_click_drag, use_file_single_click=kc_prefs.use_file_single_click, + use_transform_navigation=kc_prefs.use_transform_navigation, ), ) diff --git a/scripts/presets/keyconfig/keymap_data/blender_default.py b/scripts/presets/keyconfig/keymap_data/blender_default.py index abcf5c1015a..ee7f5c0d1da 100644 --- a/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -93,6 +93,8 @@ class Params: # Since this means with RMB select enabled in edit-mode for e.g. # `Ctrl-LMB` would be caught by box-select instead of add/extrude. "tool_maybe_tweak_event", + # Changes some transformers modal key-map items to avoid conflicts with navigation operations + "use_transform_navigation", ) def __init__( @@ -119,6 +121,7 @@ class Params: use_file_single_click=False, v3d_tilde_action='VIEW', v3d_alt_mmb_drag_action='RELATIVE', + use_transform_navigation=False, ): from sys import platform self.apple = (platform == 'darwin') @@ -209,6 +212,7 @@ class Params: self.pie_value = 'CLICK_DRAG' if use_pie_click_drag else 'PRESS' self.tool_tweak_event = {"type": self.tool_mouse, "value": 'CLICK_DRAG'} self.tool_maybe_tweak_event = {"type": self.tool_mouse, "value": self.tool_maybe_tweak_value} + self.use_transform_navigation = use_transform_navigation # ------------------------------------------------------------------------------ @@ -1312,7 +1316,7 @@ def km_uv_editor(params): {"properties": [("extend", True)]}), ]) - # 3D cursor + # 2D cursor if params.cursor_tweak_event: items.extend([ ("uv.cursor_set", params.cursor_set_event, None), @@ -1581,13 +1585,16 @@ def km_view3d(params): # Transform. ("transform.translate", {"type": params.select_mouse, "value": 'CLICK_DRAG'}, None), op_tool_optional( - ("transform.translate", {"type": 'G', "value": 'PRESS'}, None), + ("transform.translate", {"type": 'G', "value": 'PRESS'}, + {"properties": [("allow_navigation", params.use_transform_navigation)]}), (op_tool_cycle, "builtin.move"), params), op_tool_optional( - ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None), + ("transform.rotate", {"type": 'R', "value": 'PRESS'}, + {"properties": [("allow_navigation", params.use_transform_navigation)]}), (op_tool_cycle, "builtin.rotate"), params), op_tool_optional( - ("transform.resize", {"type": 'S', "value": 'PRESS'}, None), + ("transform.resize", {"type": 'S', "value": 'PRESS'}, + {"properties": [("allow_navigation", params.use_transform_navigation)]}), (op_tool_cycle, "builtin.scale"), params), op_tool_optional( ("transform.tosphere", {"type": 'S', "value": 'PRESS', "shift": True, "alt": True}, None), @@ -4681,10 +4688,13 @@ def km_paint_curve(params): ("paintcurve.delete_point", {"type": 'DEL', "value": 'PRESS'}, None), ("paintcurve.draw", {"type": 'RET', "value": 'PRESS'}, None), ("paintcurve.draw", {"type": 'NUMPAD_ENTER', "value": 'PRESS'}, None), - ("transform.translate", {"type": 'G', "value": 'PRESS'}, None), + ("transform.translate", {"type": 'G', "value": 'PRESS'}, + {"properties": [("allow_navigation", params.use_transform_navigation)]}), ("transform.translate", {"type": params.select_mouse, "value": 'CLICK_DRAG'}, None), - ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None), - ("transform.resize", {"type": 'S', "value": 'PRESS'}, None), + ("transform.rotate", {"type": 'R', "value": 'PRESS'}, + {"properties": [("allow_navigation", params.use_transform_navigation)]}), + ("transform.resize", {"type": 'S', "value": 'PRESS'}, + {"properties": [("allow_navigation", params.use_transform_navigation)]}), ]) return keymap @@ -5844,7 +5854,7 @@ def km_eyedropper_colorramp_pointsampling_map(_params): return keymap -def km_transform_modal_map(_params): +def km_transform_modal_map(params): items = [] keymap = ( "Transform Modal Map", @@ -5884,24 +5894,24 @@ def km_transform_modal_map(_params): ("PROPORTIONAL_SIZE_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True}, None), ("PROPORTIONAL_SIZE_UP", {"type": 'PAGE_UP', "value": 'PRESS', "shift": True, "repeat": True}, None), ("PROPORTIONAL_SIZE_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True}, None), - ("PROPORTIONAL_SIZE_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS'}, None), - ("PROPORTIONAL_SIZE_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS'}, None), + ("PROPORTIONAL_SIZE_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "alt": params.use_transform_navigation}, None), + ("PROPORTIONAL_SIZE_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "alt": params.use_transform_navigation}, None), ("PROPORTIONAL_SIZE_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True}, None), ("PROPORTIONAL_SIZE_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True}, None), - ("PROPORTIONAL_SIZE", {"type": 'TRACKPADPAN', "value": 'ANY'}, None), + ("PROPORTIONAL_SIZE", {"type": 'TRACKPADPAN', "value": 'ANY', "alt": params.use_transform_navigation}, None), ("AUTOIK_CHAIN_LEN_UP", {"type": 'PAGE_UP', "value": 'PRESS', "repeat": True}, None), ("AUTOIK_CHAIN_LEN_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True}, None), ("AUTOIK_CHAIN_LEN_UP", {"type": 'PAGE_UP', "value": 'PRESS', "shift": True, "repeat": True}, None), ("AUTOIK_CHAIN_LEN_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True}, None), - ("AUTOIK_CHAIN_LEN_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS'}, None), - ("AUTOIK_CHAIN_LEN_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS'}, None), + ("AUTOIK_CHAIN_LEN_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "alt": params.use_transform_navigation}, None), + ("AUTOIK_CHAIN_LEN_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "alt": params.use_transform_navigation}, None), ("AUTOIK_CHAIN_LEN_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True}, None), ("AUTOIK_CHAIN_LEN_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True}, None), ("INSERTOFS_TOGGLE_DIR", {"type": 'T', "value": 'PRESS'}, None), ("NODE_ATTACH_ON", {"type": 'LEFT_ALT', "value": 'RELEASE', "any": True}, None), ("NODE_ATTACH_OFF", {"type": 'LEFT_ALT', "value": 'PRESS', "any": True}, None), - ("AUTOCONSTRAIN", {"type": 'MIDDLEMOUSE', "value": 'ANY'}, None), - ("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True}, None), + ("AUTOCONSTRAIN", {"type": 'MIDDLEMOUSE', "value": 'ANY', "alt": params.use_transform_navigation}, None), + ("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True, "alt": params.use_transform_navigation}, None), ("PRECISION", {"type": 'LEFT_SHIFT', "value": 'ANY', "any": True}, None), ("PRECISION", {"type": 'RIGHT_SHIFT', "value": 'ANY', "any": True}, None), ]) diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 07a1aa02955..7837df869b4 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -1038,10 +1038,22 @@ class VIEW3D_MT_transform_base: # TODO: get rid of the custom text strings? def draw(self, context): layout = self.layout + allow_navigation = getattr( + context.window_manager.keyconfigs.active.preferences, + "use_transform_navigation", + False) - layout.operator("transform.translate") - layout.operator("transform.rotate") - layout.operator("transform.resize", text="Scale") + props = layout.operator("transform.translate") + props.release_confirm = False + props.allow_navigation = allow_navigation + + props = layout.operator("transform.rotate") + props.release_confirm = False + props.allow_navigation = allow_navigation + + props = layout.operator("transform.resize", text="Scale") + props.release_confirm = False + props.allow_navigation = allow_navigation layout.separator() diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 1af4ee05374..d121dec7bc2 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -125,8 +125,9 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_CURSOR_EDIT (1 << 16) #define P_CLNOR_INVALIDATE (1 << 17) #define P_VIEW2D_EDGE_PAN (1 << 18) +#define P_VIEW3D_NAVIGATION (1 << 19) /* For properties performed when confirming the transformation. */ -#define P_POST_TRANSFORM (1 << 19) +#define P_POST_TRANSFORM (1 << 20) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 73938f1d959..77725b5bd0d 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -92,9 +92,6 @@ void setTransformViewMatrices(TransInfo *t) unit_m4(t->persinv); t->persp = RV3D_ORTHO; } - - calculateCenter2D(t); - calculateCenterLocal(t, t->center_global); } void setTransformViewAspect(TransInfo *t, float r_aspect[3]) @@ -926,15 +923,16 @@ static bool transform_event_modal_constraint(TransInfo *t, short modal_type) int transformEvent(TransInfo *t, const wmEvent *event) { bool handled = false; + bool is_navigating = t->vod ? ((RegionView3D *)t->region->regiondata)->rflag & RV3D_NAVIGATING : + false; /* Handle modal numinput events first, if already activated. */ - if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && hasNumInput(&t->num) && - handleNumInput(t->context, &(t->num), event)) - { + if (!is_navigating && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && + hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event)) { t->redraw |= TREDRAW_HARD; handled = true; } - else if (event->type == MOUSEMOVE) { + else if (!is_navigating && event->type == MOUSEMOVE) { copy_v2_v2_int(t->mval, event->mval); /* Use this for soft redraw. Might cause flicker in object mode */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index fcca03b981e..c49e8338e12 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -41,6 +41,7 @@ struct TransDataContainer; struct TransInfo; struct TransSnap; struct ViewLayer; +struct ViewOpsData; struct bContext; struct wmEvent; struct wmKeyConfig; @@ -673,6 +674,8 @@ typedef struct TransInfo { /** Currently only used for random curve of proportional editing. */ struct RNG *rng; + struct ViewOpsData *vod; + /** Typically for mode settings. */ TransCustomDataContainer custom; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 70806896743..3d3ad5a2dd5 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -660,7 +660,15 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->flag |= T_NO_CURSOR_WRAP; } + if (op && (t->flag & T_MODAL) && !(t->flag & T_RELEASE_CONFIRM) && + (prop = RNA_struct_find_property(op->ptr, "allow_navigation")) && + RNA_property_boolean_get(op->ptr, prop)) { + t->vod = ED_view3d_navigation_init(C); + } + setTransformViewMatrices(t); + calculateCenter2D(t); + calculateCenterLocal(t, t->center_global); initNumInput(&t->num); transform_gizmo_3d_model_from_constraint_and_mode_init(t); @@ -770,6 +778,10 @@ void postTrans(bContext *C, TransInfo *t) } freeSnapping(t); + + if (t->vod) { + ED_view3d_navigation_free(C, t->vod); + } } void applyTransObjects(TransInfo *t) diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 12e9a99a323..b501649a614 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -399,7 +399,7 @@ static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event) static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) { - int exit_code; + int exit_code = OPERATOR_PASS_THROUGH; TransInfo *t = op->customdata; const eTfmMode mode_prev = t->mode; @@ -419,6 +419,31 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) exit_code = transformEvent(t, event); t->context = NULL; + /* Allow navigation while transforming. */ + if (t->vod && (exit_code & OPERATOR_PASS_THROUGH) && ED_view3d_navigation_do(C, t->vod, event)) { + RegionView3D *rv3d = t->region->regiondata; + if (rv3d->rflag & RV3D_NAVIGATING) { + /* Do not update transform while navigating. This can be distracting. */ + return OPERATOR_RUNNING_MODAL; + } + + if (t->modifiers & MOD_PRECISION) { + /* Remove Precision modifier, it may have be unintentionally enabled. */ + t->modifiers &= ~MOD_PRECISION; + t->mouse.precision = 0; + } + + /* Make sure `t->mval` is up to date before calling #transformViewUpdate. */ + copy_v2_v2_int(t->mval, event->mval); + + /* Call before #applyMouseInput. */ + tranformViewUpdate(t); + + /* Mouse input is outdated. */ + applyMouseInput(t, &t->mouse, t->mval, t->values); + t->redraw |= TREDRAW_HARD; + } + transformApply(C, t); exit_code |= transformEnd(C, t); @@ -752,6 +777,15 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) RNA_def_property_flag(prop, PROP_HIDDEN); } + if (flags & P_VIEW3D_NAVIGATION) { + prop = RNA_def_boolean(ot->srna, + "allow_navigation", + 0, + "Allow Navigation", + "Allow navigation while transforming"); + RNA_def_property_flag(prop, PROP_HIDDEN); + } + if (flags & P_POST_TRANSFORM) { prop = RNA_def_boolean(ot->srna, "use_automerge_and_split", @@ -786,7 +820,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_VIEW2D_EDGE_PAN | - P_POST_TRANSFORM); + P_VIEW3D_NAVIGATION | P_POST_TRANSFORM); } static void TRANSFORM_OT_resize(struct wmOperatorType *ot) @@ -825,7 +859,7 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | - P_OPTIONS | P_GPENCIL_EDIT | P_CENTER); + P_OPTIONS | P_GPENCIL_EDIT | P_CENTER | P_VIEW3D_NAVIGATION); } static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot) @@ -902,7 +936,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | - P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER); + P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER | P_VIEW3D_NAVIGATION); } static void TRANSFORM_OT_tilt(struct wmOperatorType *ot) @@ -1147,7 +1181,7 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) "When Even mode is active, flips between the two adjacent edge loops"); RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents"); - Transform_Properties(ot, P_MIRROR | P_GEO_SNAP | P_CORRECT_UV); + Transform_Properties(ot, P_MIRROR | P_GEO_SNAP | P_CORRECT_UV | P_VIEW3D_NAVIGATION); } static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) @@ -1182,7 +1216,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) "When Even mode is active, flips between the two adjacent edge loops"); RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents"); - Transform_Properties(ot, P_MIRROR | P_GEO_SNAP | P_CORRECT_UV); + Transform_Properties(ot, P_MIRROR | P_GEO_SNAP | P_CORRECT_UV | P_VIEW3D_NAVIGATION); } static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) @@ -1330,7 +1364,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | - P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER); + P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER | P_VIEW3D_NAVIGATION); } static int transform_from_gizmo_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) -- 2.30.2