Skip to content

Commit f215384

Browse files
committed
Merge pull request #105625 from zmn-hamid/zoom_drag_2d
Add drag zoom feature with CTRL+MiddleMouseButton
2 parents d51e0f9 + 82e23da commit f215384

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)