Browse Source

Merge pull request #105625 from zmn-hamid/zoom_drag_2d

Add drag zoom feature with CTRL+MiddleMouseButton
Thaddeus Crews 3 tháng trước cách đây
mục cha
commit
f215384aaa

+ 3 - 0
doc/classes/EditorSettings.xml

@@ -582,6 +582,9 @@
 		<member name="editors/panning/warped_mouse_panning" type="bool" setter="" getter="">
 			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.
 		</member>
+		<member name="editors/panning/zoom_style" type="int" setter="" getter="">
+			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.
+		</member>
 		<member name="editors/polygon_editor/auto_bake_delay" type="float" setter="" getter="">
 			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.
 		</member>

+ 1 - 0
editor/editor_settings.cpp

@@ -920,6 +920,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	_initial_set("editors/panning/simple_panning", false);
 	_initial_set("editors/panning/warped_mouse_panning", true);
 	_initial_set("editors/panning/2d_editor_pan_speed", 20, true);
+	EDITOR_SETTING_BASIC(Variant::INT, PROPERTY_HINT_ENUM, "editors/panning/zoom_style", 0, "Vertical,Horizontal");
 
 	// Tiles editor
 	_initial_set("editors/tiles_editor/display_grid", true);

+ 1 - 0
editor/plugins/canvas_item_editor_plugin.cpp

@@ -4129,6 +4129,7 @@ void CanvasItemEditor::_update_editor_settings() {
 	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")));
 	panner->set_scroll_speed(EDITOR_GET("editors/panning/2d_editor_pan_speed"));
 	panner->setup_warped_panning(get_viewport(), EDITOR_GET("editors/panning/warped_mouse_panning"));
+	panner->set_zoom_style((ViewPanner::ZoomStyle)EDITOR_GET("editors/panning/zoom_style").operator int());
 }
 
 void CanvasItemEditor::_project_settings_changed() {

+ 3 - 4
editor/plugins/tiles/tile_atlas_view.cpp

@@ -52,7 +52,7 @@ void TileAtlasView::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event)
 
 void TileAtlasView::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
 	zoom_widget->set_zoom(zoom_widget->get_zoom() * p_zoom_factor);
-	_update_zoom_and_panning(true);
+	_update_zoom_and_panning(true, p_origin);
 	emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
 }
 
@@ -92,7 +92,7 @@ Size2i TileAtlasView::_compute_alternative_tiles_control_size() {
 	return size;
 }
 
-void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos) {
+void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos, const Vector2 &p_mouse_pos) {
 	if (tile_set_atlas_source.is_null()) {
 		return;
 	}
@@ -132,8 +132,7 @@ void TileAtlasView::_update_zoom_and_panning(bool p_zoom_on_mouse_pos) {
 
 	// Zoom on the position.
 	if (p_zoom_on_mouse_pos) {
-		// Offset the panning relative to the center of panel.
-		Vector2 relative_mpos = get_local_mouse_position() - get_size() / 2;
+		Vector2 relative_mpos = p_mouse_pos - get_size() / 2;
 		panning = (panning - relative_mpos) * zoom / previous_zoom + relative_mpos;
 	} else {
 		// Center of panel.

+ 1 - 1
editor/plugins/tiles/tile_atlas_view.h

@@ -58,7 +58,7 @@ private:
 	Button *button_center_view = nullptr;
 	CenterContainer *center_container = nullptr;
 	Vector2 panning;
-	void _update_zoom_and_panning(bool p_zoom_on_mouse_pos = false);
+	void _update_zoom_and_panning(bool p_zoom_on_mouse_pos = false, const Vector2 &p_mouse_pos = Vector2());
 	void _zoom_widget_changed();
 	void _center_view();
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;

+ 39 - 9
scene/gui/view_panner.cpp

@@ -92,16 +92,26 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
 			return false;
 		}
 
-		bool is_drag_event = mb->get_button_index() == MouseButton::MIDDLE ||
+		drag_type = DragType::DRAG_TYPE_NONE;
+
+		bool is_drag_zoom_event = mb->get_button_index() == MouseButton::MIDDLE && mb->is_ctrl_pressed();
+
+		if (is_drag_zoom_event) {
+			if (mb->is_pressed()) {
+				drag_type = DragType::DRAG_TYPE_ZOOM;
+				drag_zoom_position = mb->get_position();
+			}
+			return true;
+		}
+
+		bool is_drag_pan_event = mb->get_button_index() == MouseButton::MIDDLE ||
 				(enable_rmb && mb->get_button_index() == MouseButton::RIGHT) ||
 				(!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning()) ||
 				(force_drag && mb->get_button_index() == MouseButton::LEFT);
 
-		if (is_drag_event) {
+		if (is_drag_pan_event) {
 			if (mb->is_pressed()) {
-				is_dragging = true;
-			} else {
-				is_dragging = false;
+				drag_type = DragType::DRAG_TYPE_PAN;
 			}
 			return mb->get_button_index() != MouseButton::LEFT || mb->is_pressed(); // Don't consume LMB release events (it fixes some selection problems).
 		}
@@ -109,13 +119,23 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
 
 	Ref<InputEventMouseMotion> mm = p_event;
 	if (mm.is_valid()) {
-		if (is_dragging) {
+		if (drag_type == DragType::DRAG_TYPE_PAN) {
 			if (warped_panning_viewport && p_canvas_rect.has_area()) {
 				pan_callback.call(warped_panning_viewport->wrap_mouse_in_rect(mm->get_relative(), p_canvas_rect), p_event);
 			} else {
 				pan_callback.call(mm->get_relative(), p_event);
 			}
 			return true;
+		} else if (drag_type == DragType::DRAG_TYPE_ZOOM) {
+			float drag_zoom_distance = 0.0;
+			if (zoom_style == ZoomStyle::ZOOM_VERTICAL) {
+				drag_zoom_distance = mm->get_relative().y;
+			} else if (zoom_style == ZoomStyle::ZOOM_HORIZONTAL) {
+				drag_zoom_distance = mm->get_relative().x * -1.0; // Needs to be flipped to match the 3D horizontal zoom style.
+			}
+			float drag_zoom_factor = 1.0 + (drag_zoom_distance * scroll_zoom_factor * drag_zoom_sensitivity_factor);
+			zoom_callback.call(drag_zoom_factor, drag_zoom_position, p_event);
+			return true;
 		}
 	}
 
@@ -157,7 +177,11 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
 		if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
 			pan_key_pressed = k->is_pressed();
 			if (simple_panning_enabled || Input::get_singleton()->get_mouse_button_mask().has_flag(MouseButtonMask::LEFT)) {
-				is_dragging = pan_key_pressed;
+				if (pan_key_pressed) {
+					drag_type = DragType::DRAG_TYPE_PAN;
+				} else if (drag_type == DragType::DRAG_TYPE_PAN) {
+					drag_type = DragType::DRAG_TYPE_NONE;
+				}
 			}
 			return true;
 		}
@@ -168,7 +192,9 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
 
 void ViewPanner::release_pan_key() {
 	pan_key_pressed = false;
-	is_dragging = false;
+	if (drag_type == DragType::DRAG_TYPE_PAN) {
+		drag_type = DragType::DRAG_TYPE_NONE;
+	}
 }
 
 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) {
 	pan_axis = p_pan_axis;
 }
 
+void ViewPanner::set_zoom_style(ZoomStyle p_zoom_style) {
+	zoom_style = p_zoom_style;
+}
+
 void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
 	set_control_scheme(p_scheme);
 	set_pan_shortcut(p_shortcut);
@@ -218,7 +248,7 @@ void ViewPanner::setup_warped_panning(Viewport *p_viewport, bool p_allowed) {
 }
 
 bool ViewPanner::is_panning() const {
-	return is_dragging || pan_key_pressed;
+	return (drag_type == DragType::DRAG_TYPE_PAN) || pan_key_pressed;
 }
 
 void ViewPanner::set_force_drag(bool p_force) {

+ 19 - 1
scene/gui/view_panner.h

@@ -51,15 +51,32 @@ public:
 		PAN_AXIS_VERTICAL,
 	};
 
+	enum DragType {
+		DRAG_TYPE_NONE,
+		DRAG_TYPE_PAN,
+		DRAG_TYPE_ZOOM,
+	};
+
+	enum ZoomStyle {
+		ZOOM_VERTICAL,
+		ZOOM_HORIZONTAL,
+	};
+
 private:
 	int scroll_speed = 32;
 	float scroll_zoom_factor = 1.1;
 	PanAxis pan_axis = PAN_AXIS_BOTH;
 
-	bool is_dragging = false;
 	bool pan_key_pressed = false;
 	bool force_drag = false;
 
+	DragType drag_type = DragType::DRAG_TYPE_NONE;
+
+	ZoomStyle zoom_style = ZoomStyle::ZOOM_VERTICAL;
+
+	Vector2 drag_zoom_position;
+	float drag_zoom_sensitivity_factor = -0.01f;
+
 	bool enable_rmb = false;
 	bool simple_panning_enabled = false;
 
@@ -80,6 +97,7 @@ public:
 	void set_scroll_speed(int p_scroll_speed);
 	void set_scroll_zoom_factor(float p_scroll_zoom_factor);
 	void set_pan_axis(PanAxis p_pan_axis);
+	void set_zoom_style(ZoomStyle p_zoom_style);
 
 	void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning);
 	void setup_warped_panning(Viewport *p_viewport, bool p_allowed);