Skip to content

Commit 82e23da

Browse files
committed
Add drag zoom feature with CTRL+MiddleMouseButton
This change introduces a DragType enum to scene/gui/view_panner.cpp of dragging, which includes: - DRAG_TYPE_NONE: Not dragging - DRAG_TYPE_PAN: Panning (dragging using MMB) - DRAG_TYPE_ZOOM: Zooming (dragging using CTRL+MMB) The goal of this change is the third option, which was already available in 3D viewport but not in 2D. This feature should work in other editors as well such as Animation Track Editor and Visual Shader Editor and so on.
1 parent 80a3d20 commit 82e23da

File tree

7 files changed

+67
-15
lines changed

7 files changed

+67
-15
lines changed

doc/classes/EditorSettings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@
582582
<member name="editors/panning/warped_mouse_panning" type="bool" setter="" getter="">
583583
If [code]true[/code], warps the mouse around the 2D viewport while panning in the 2D editor. This makes it possible to pan over a large area without having to exit panning and adjust the mouse cursor.
584584
</member>
585+
<member name="editors/panning/zoom_style" type="int" setter="" getter="">
586+
The mouse cursor movement direction to use when drag-zooming in any editor (except 3D scene editor) by moving the mouse. This does not affect zooming with the mouse wheel.
587+
</member>
585588
<member name="editors/polygon_editor/auto_bake_delay" type="float" setter="" getter="">
586589
The delay in seconds until more complex and performance costly polygon editors commit their outlines, e.g. the 2D navigation polygon editor rebakes the navigation mesh polygons. A negative value stops the auto bake.
587590
</member>

editor/editor_settings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
920920
_initial_set("editors/panning/simple_panning", false);
921921
_initial_set("editors/panning/warped_mouse_panning", true);
922922
_initial_set("editors/panning/2d_editor_pan_speed", 20, true);
923+
EDITOR_SETTING_BASIC(Variant::INT, PROPERTY_HINT_ENUM, "editors/panning/zoom_style", 0, "Vertical,Horizontal");
923924

924925
// Tiles editor
925926
_initial_set("editors/tiles_editor/display_grid", true);

editor/plugins/canvas_item_editor_plugin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,6 +4129,7 @@ void CanvasItemEditor::_update_editor_settings() {
41294129
panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/2d_editor_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning")));
41304130
panner->set_scroll_speed(EDITOR_GET("editors/panning/2d_editor_pan_speed"));
41314131
panner->setup_warped_panning(get_viewport(), EDITOR_GET("editors/panning/warped_mouse_panning"));
4132+
panner->set_zoom_style((ViewPanner::ZoomStyle)EDITOR_GET("editors/panning/zoom_style").operator int());
41324133
}
41334134

41344135
void CanvasItemEditor::_project_settings_changed() {

editor/plugins/tiles/tile_atlas_view.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ void TileAtlasView::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event)
5252

5353
void TileAtlasView::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
5454
zoom_widget->set_zoom(zoom_widget->get_zoom() * p_zoom_factor);
55-
_update_zoom_and_panning(true);
55+
_update_zoom_and_panning(true, p_origin);
5656
emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
5757
}
5858

@@ -92,7 +92,7 @@ Size2i TileAtlasView::_compute_alternative_tiles_control_size() {
9292
return size;
9393
}
9494

95-
void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos) {
95+
void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos, const Vector2 &p_mouse_pos) {
9696
if (tile_set_atlas_source.is_null()) {
9797
return;
9898
}
@@ -132,8 +132,7 @@ void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos) {
132132

133133
// Zoom on the position.
134134
if (p_zoom_on_mouse_pos) {
135-
// Offset the panning relative to the center of panel.
136-
Vector2 relative_mpos = get_local_mouse_position() - get_size() / 2;
135+
Vector2 relative_mpos = p_mouse_pos - get_size() / 2;
137136
panning = (panning - relative_mpos) * zoom / previous_zoom + relative_mpos;
138137
} else {
139138
// Center of panel.

editor/plugins/tiles/tile_atlas_view.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class TileAtlasView : public Control {
5858
Button *button_center_view = nullptr;
5959
CenterContainer *center_container = nullptr;
6060
Vector2 panning;
61-
void _update_zoom_and_panning(bool p_zoom_on_mouse_pos = false);
61+
void _update_zoom_and_panning(bool p_zoom_on_mouse_pos = false, const Vector2 &p_mouse_pos = Vector2());
6262
void _zoom_widget_changed();
6363
void _center_view();
6464
virtual void gui_input(const Ref<InputEvent> &p_event) override;

scene/gui/view_panner.cpp

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,30 +92,50 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
9292
return false;
9393
}
9494

95-
bool is_drag_event = mb->get_button_index() == MouseButton::MIDDLE ||
95+
drag_type = DragType::DRAG_TYPE_NONE;
96+
97+
bool is_drag_zoom_event = mb->get_button_index() == MouseButton::MIDDLE && mb->is_ctrl_pressed();
98+
99+
if (is_drag_zoom_event) {
100+
if (mb->is_pressed()) {
101+
drag_type = DragType::DRAG_TYPE_ZOOM;
102+
drag_zoom_position = mb->get_position();
103+
}
104+
return true;
105+
}
106+
107+
bool is_drag_pan_event = mb->get_button_index() == MouseButton::MIDDLE ||
96108
(enable_rmb && mb->get_button_index() == MouseButton::RIGHT) ||
97109
(!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning()) ||
98110
(force_drag && mb->get_button_index() == MouseButton::LEFT);
99111

100-
if (is_drag_event) {
112+
if (is_drag_pan_event) {
101113
if (mb->is_pressed()) {
102-
is_dragging = true;
103-
} else {
104-
is_dragging = false;
114+
drag_type = DragType::DRAG_TYPE_PAN;
105115
}
106116
return mb->get_button_index() != MouseButton::LEFT || mb->is_pressed(); // Don't consume LMB release events (it fixes some selection problems).
107117
}
108118
}
109119

110120
Ref<InputEventMouseMotion> mm = p_event;
111121
if (mm.is_valid()) {
112-
if (is_dragging) {
122+
if (drag_type == DragType::DRAG_TYPE_PAN) {
113123
if (warped_panning_viewport && p_canvas_rect.has_area()) {
114124
pan_callback.call(warped_panning_viewport->wrap_mouse_in_rect(mm->get_relative(), p_canvas_rect), p_event);
115125
} else {
116126
pan_callback.call(mm->get_relative(), p_event);
117127
}
118128
return true;
129+
} else if (drag_type == DragType::DRAG_TYPE_ZOOM) {
130+
float drag_zoom_distance = 0.0;
131+
if (zoom_style == ZoomStyle::ZOOM_VERTICAL) {
132+
drag_zoom_distance = mm->get_relative().y;
133+
} else if (zoom_style == ZoomStyle::ZOOM_HORIZONTAL) {
134+
drag_zoom_distance = mm->get_relative().x * -1.0; // Needs to be flipped to match the 3D horizontal zoom style.
135+
}
136+
float drag_zoom_factor = 1.0 + (drag_zoom_distance * scroll_zoom_factor * drag_zoom_sensitivity_factor);
137+
zoom_callback.call(drag_zoom_factor, drag_zoom_position, p_event);
138+
return true;
119139
}
120140
}
121141

@@ -157,7 +177,11 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
157177
if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
158178
pan_key_pressed = k->is_pressed();
159179
if (simple_panning_enabled || Input::get_singleton()->get_mouse_button_mask().has_flag(MouseButtonMask::LEFT)) {
160-
is_dragging = pan_key_pressed;
180+
if (pan_key_pressed) {
181+
drag_type = DragType::DRAG_TYPE_PAN;
182+
} else if (drag_type == DragType::DRAG_TYPE_PAN) {
183+
drag_type = DragType::DRAG_TYPE_NONE;
184+
}
161185
}
162186
return true;
163187
}
@@ -168,7 +192,9 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
168192

169193
void ViewPanner::release_pan_key() {
170194
pan_key_pressed = false;
171-
is_dragging = false;
195+
if (drag_type == DragType::DRAG_TYPE_PAN) {
196+
drag_type = DragType::DRAG_TYPE_NONE;
197+
}
172198
}
173199

174200
void ViewPanner::set_callbacks(Callable p_pan_callback, Callable p_zoom_callback) {
@@ -207,6 +233,10 @@ void ViewPanner::set_pan_axis(PanAxis p_pan_axis) {
207233
pan_axis = p_pan_axis;
208234
}
209235

236+
void ViewPanner::set_zoom_style(ZoomStyle p_zoom_style) {
237+
zoom_style = p_zoom_style;
238+
}
239+
210240
void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
211241
set_control_scheme(p_scheme);
212242
set_pan_shortcut(p_shortcut);
@@ -218,7 +248,7 @@ void ViewPanner::setup_warped_panning(Viewport *p_viewport, bool p_allowed) {
218248
}
219249

220250
bool ViewPanner::is_panning() const {
221-
return is_dragging || pan_key_pressed;
251+
return (drag_type == DragType::DRAG_TYPE_PAN) || pan_key_pressed;
222252
}
223253

224254
void ViewPanner::set_force_drag(bool p_force) {

scene/gui/view_panner.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,32 @@ class ViewPanner : public RefCounted {
5151
PAN_AXIS_VERTICAL,
5252
};
5353

54+
enum DragType {
55+
DRAG_TYPE_NONE,
56+
DRAG_TYPE_PAN,
57+
DRAG_TYPE_ZOOM,
58+
};
59+
60+
enum ZoomStyle {
61+
ZOOM_VERTICAL,
62+
ZOOM_HORIZONTAL,
63+
};
64+
5465
private:
5566
int scroll_speed = 32;
5667
float scroll_zoom_factor = 1.1;
5768
PanAxis pan_axis = PAN_AXIS_BOTH;
5869

59-
bool is_dragging = false;
6070
bool pan_key_pressed = false;
6171
bool force_drag = false;
6272

73+
DragType drag_type = DragType::DRAG_TYPE_NONE;
74+
75+
ZoomStyle zoom_style = ZoomStyle::ZOOM_VERTICAL;
76+
77+
Vector2 drag_zoom_position;
78+
float drag_zoom_sensitivity_factor = -0.01f;
79+
6380
bool enable_rmb = false;
6481
bool simple_panning_enabled = false;
6582

@@ -80,6 +97,7 @@ class ViewPanner : public RefCounted {
8097
void set_scroll_speed(int p_scroll_speed);
8198
void set_scroll_zoom_factor(float p_scroll_zoom_factor);
8299
void set_pan_axis(PanAxis p_pan_axis);
100+
void set_zoom_style(ZoomStyle p_zoom_style);
83101

84102
void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning);
85103
void setup_warped_panning(Viewport *p_viewport, bool p_allowed);

0 commit comments

Comments
 (0)