Browse Source

Add gesture to ViewPanner and simplify a bit its API

Gilles Roudière 2 years ago
parent
commit
a3b431b09d

+ 7 - 18
editor/animation_bezier_editor.cpp

@@ -1489,32 +1489,21 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 	}
 	}
 }
 }
 
 
-void AnimationBezierTrackEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	_pan_callback(-p_scroll_vec * 32);
-}
-
-void AnimationBezierTrackEdit::_pan_callback(Vector2 p_scroll_vec) {
+void AnimationBezierTrackEdit::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
 	v_scroll += p_scroll_vec.y * v_zoom;
 	v_scroll += p_scroll_vec.y * v_zoom;
 	v_scroll = CLAMP(v_scroll, -100000, 100000);
 	v_scroll = CLAMP(v_scroll, -100000, 100000);
 	timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale());
 	timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale());
 	queue_redraw();
 	queue_redraw();
 }
 }
 
 
-void AnimationBezierTrackEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
+void AnimationBezierTrackEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
 	const float v_zoom_orig = v_zoom;
 	const float v_zoom_orig = v_zoom;
-	if (p_alt) {
+	Ref<InputEventWithModifiers> iewm = p_event;
+	if (iewm.is_valid() && iewm->is_alt_pressed()) {
 		// Alternate zoom (doesn't affect timeline).
 		// Alternate zoom (doesn't affect timeline).
-		if (p_scroll_vec.y > 0) {
-			v_zoom = MIN(v_zoom * 1.2, 100000);
-		} else {
-			v_zoom = MAX(v_zoom / 1.2, 0.000001);
-		}
+		v_zoom = CLAMP(v_zoom * p_zoom_factor, 0.000001, 100000);
 	} else {
 	} else {
-		if (p_scroll_vec.y > 0) {
-			timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
-		} else {
-			timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
-		}
+		timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / p_zoom_factor);
 	}
 	}
 	v_scroll = v_scroll + (p_origin.y - get_size().y / 2.0) * (v_zoom - v_zoom_orig);
 	v_scroll = v_scroll + (p_origin.y - get_size().y / 2.0) * (v_zoom - v_zoom_orig);
 	queue_redraw();
 	queue_redraw();
@@ -1681,7 +1670,7 @@ void AnimationBezierTrackEdit::_bind_methods() {
 
 
 AnimationBezierTrackEdit::AnimationBezierTrackEdit() {
 AnimationBezierTrackEdit::AnimationBezierTrackEdit() {
 	panner.instantiate();
 	panner.instantiate();
-	panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_scroll_callback), callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback));
+	panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback));
 
 
 	play_position = memnew(Control);
 	play_position = memnew(Control);
 	play_position->set_mouse_filter(MOUSE_FILTER_PASS);
 	play_position->set_mouse_filter(MOUSE_FILTER_PASS);

+ 2 - 3
editor/animation_bezier_editor.h

@@ -174,9 +174,8 @@ class AnimationBezierTrackEdit : public Control {
 	SelectionSet selection;
 	SelectionSet selection;
 
 
 	Ref<ViewPanner> panner;
 	Ref<ViewPanner> panner;
-	void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _pan_callback(Vector2 p_scroll_vec);
-	void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	void _draw_line_clipped(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, int p_clip_left, int p_clip_right);
 	void _draw_line_clipped(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, int p_clip_left, int p_clip_right);
 	void _draw_track(int p_track, const Color &p_color);
 	void _draw_track(int p_track, const Color &p_color);

+ 13 - 33
editor/animation_track_editor.cpp

@@ -1704,25 +1704,13 @@ Control::CursorShape AnimationTimelineEdit::get_cursor_shape(const Point2 &p_pos
 	}
 	}
 }
 }
 
 
-void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	// Timeline has no vertical scroll, so we change it to horizontal.
-	p_scroll_vec.x += p_scroll_vec.y;
-	_pan_callback(-p_scroll_vec * 32);
-}
-
-void AnimationTimelineEdit::_pan_callback(Vector2 p_scroll_vec) {
+void AnimationTimelineEdit::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
 	set_value(get_value() - p_scroll_vec.x / get_zoom_scale());
 	set_value(get_value() - p_scroll_vec.x / get_zoom_scale());
 }
 }
 
 
-void AnimationTimelineEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
-	double new_zoom_value;
+void AnimationTimelineEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
 	double current_zoom_value = get_zoom()->get_value();
 	double current_zoom_value = get_zoom()->get_value();
-	if (current_zoom_value <= 0.1) {
-		new_zoom_value = MAX(0.01, current_zoom_value - 0.01 * SIGN(p_scroll_vec.y));
-	} else {
-		new_zoom_value = p_scroll_vec.y > 0 ? MAX(0.01, current_zoom_value / 1.05) : current_zoom_value * 1.05;
-	}
-	get_zoom()->set_value(new_zoom_value);
+	get_zoom()->set_value(MAX(0.01, current_zoom_value * p_zoom_factor));
 }
 }
 
 
 void AnimationTimelineEdit::set_use_fps(bool p_use_fps) {
 void AnimationTimelineEdit::set_use_fps(bool p_use_fps) {
@@ -1798,7 +1786,8 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
 	len_hb->hide();
 	len_hb->hide();
 
 
 	panner.instantiate();
 	panner.instantiate();
-	panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_scroll_callback), callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback));
+	panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback));
+	panner->set_pan_axis(ViewPanner::PAN_AXIS_HORIZONTAL);
 
 
 	set_layout_direction(Control::LAYOUT_DIRECTION_LTR);
 	set_layout_direction(Control::LAYOUT_DIRECTION_LTR);
 }
 }
@@ -5358,32 +5347,23 @@ void AnimationTrackEditor::_toggle_bezier_edit() {
 	}
 	}
 }
 }
 
 
-void AnimationTrackEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	if (p_alt) {
+void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
+	Ref<InputEventWithModifiers> iewm = p_event;
+	if (iewm.is_valid() && iewm->is_alt_pressed()) {
 		if (p_scroll_vec.x < 0 || p_scroll_vec.y < 0) {
 		if (p_scroll_vec.x < 0 || p_scroll_vec.y < 0) {
 			goto_prev_step(true);
 			goto_prev_step(true);
 		} else {
 		} else {
 			goto_next_step(true);
 			goto_next_step(true);
 		}
 		}
 	} else {
 	} else {
-		_pan_callback(-p_scroll_vec * 32);
+		timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale());
+		scroll->set_v_scroll(scroll->get_v_scroll() - p_scroll_vec.y);
 	}
 	}
 }
 }
 
 
-void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec) {
-	timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale());
-	scroll->set_v_scroll(scroll->get_v_scroll() - p_scroll_vec.y);
-}
-
-void AnimationTrackEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
-	double new_zoom_value;
+void AnimationTrackEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
 	double current_zoom_value = timeline->get_zoom()->get_value();
 	double current_zoom_value = timeline->get_zoom()->get_value();
-	if (current_zoom_value <= 0.1) {
-		new_zoom_value = MAX(0.01, current_zoom_value - 0.01 * SIGN(p_scroll_vec.y));
-	} else {
-		new_zoom_value = p_scroll_vec.y > 0 ? MAX(0.01, current_zoom_value / 1.05) : current_zoom_value * 1.05;
-	}
-	timeline->get_zoom()->set_value(new_zoom_value);
+	timeline->get_zoom()->set_value(MAX(0.01, current_zoom_value * p_zoom_factor));
 }
 }
 
 
 void AnimationTrackEditor::_cancel_bezier_edit() {
 void AnimationTrackEditor::_cancel_bezier_edit() {
@@ -6398,7 +6378,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
 	timeline->connect("length_changed", callable_mp(this, &AnimationTrackEditor::_update_length));
 	timeline->connect("length_changed", callable_mp(this, &AnimationTrackEditor::_update_length));
 
 
 	panner.instantiate();
 	panner.instantiate();
-	panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_scroll_callback), callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback));
+	panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback));
 
 
 	scroll = memnew(ScrollContainer);
 	scroll = memnew(ScrollContainer);
 	timeline_vbox->add_child(scroll);
 	timeline_vbox->add_child(scroll);

+ 4 - 6
editor/animation_track_editor.h

@@ -159,9 +159,8 @@ class AnimationTimelineEdit : public Range {
 	bool use_fps = false;
 	bool use_fps = false;
 
 
 	Ref<ViewPanner> panner;
 	Ref<ViewPanner> panner;
-	void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _pan_callback(Vector2 p_scroll_vec);
-	void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	bool dragging_timeline = false;
 	bool dragging_timeline = false;
 	bool dragging_hsize = false;
 	bool dragging_hsize = false;
@@ -460,9 +459,8 @@ class AnimationTrackEditor : public VBoxContainer {
 	PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr);
 	PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr);
 
 
 	Ref<ViewPanner> panner;
 	Ref<ViewPanner> panner;
-	void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _pan_callback(Vector2 p_scroll_vec);
-	void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	void _timeline_value_changed(double);
 	void _timeline_value_changed(double);
 
 

+ 12 - 44
editor/plugins/canvas_item_editor_plugin.cpp

@@ -1259,57 +1259,25 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
 		}
 		}
 	}
 	}
 
 
-	Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
-	if (magnify_gesture.is_valid() && !p_already_accepted) {
-		// Zoom gesture
-		_zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
-		return true;
-	}
-
-	Ref<InputEventPanGesture> pan_gesture = p_event;
-	if (pan_gesture.is_valid() && !p_already_accepted) {
-		// If ctrl key pressed, then zoom instead of pan.
-		if (pan_gesture->is_ctrl_pressed()) {
-			const real_t factor = pan_gesture->get_delta().y;
-
-			zoom_widget->set_zoom_by_increments(1);
-			if (factor != 1.f) {
-				zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * factor + 1.f));
-			}
-			_zoom_on_position(zoom_widget->get_zoom(), pan_gesture->get_position());
-
-			return true;
-		}
-
-		// Pan gesture
-		const Vector2 delta = (pan_speed / zoom) * pan_gesture->get_delta();
-		view_offset.x += delta.x;
-		view_offset.y += delta.y;
-		update_viewport();
-		return true;
-	}
-
 	return false;
 	return false;
 }
 }
 
 
-void CanvasItemEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	_pan_callback(-p_scroll_vec * pan_speed);
-}
-
-void CanvasItemEditor::_pan_callback(Vector2 p_scroll_vec) {
+void CanvasItemEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
 	view_offset.x -= p_scroll_vec.x / zoom;
 	view_offset.x -= p_scroll_vec.x / zoom;
 	view_offset.y -= p_scroll_vec.y / zoom;
 	view_offset.y -= p_scroll_vec.y / zoom;
 	update_viewport();
 	update_viewport();
 }
 }
 
 
-void CanvasItemEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
-	int scroll_sign = (int)SIGN(p_scroll_vec.y);
-	// Inverted so that scrolling up (-1) zooms in, scrolling down (+1) zooms out.
-	zoom_widget->set_zoom_by_increments(-scroll_sign, p_alt);
-	if (!Math::is_equal_approx(ABS(p_scroll_vec.y), (real_t)1.0)) {
-		// Handle high-precision (analog) scrolling.
-		zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * ABS(p_scroll_vec.y) + 1.f));
+void CanvasItemEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+	Ref<InputEventMouseButton> mb = p_event;
+	if (mb.is_valid()) {
+		// Special behvior for scroll events, as the zoom_by_increment method can smartly end up on powers of two.
+		int increment = p_zoom_factor > 1.0 ? 1 : -1;
+		zoom_widget->set_zoom_by_increments(increment, mb->is_alt_pressed());
+	} else {
+		zoom_widget->set_zoom(zoom_widget->get_zoom() * p_zoom_factor);
 	}
 	}
+
 	_zoom_on_position(zoom_widget->get_zoom(), p_origin);
 	_zoom_on_position(zoom_widget->get_zoom(), p_origin);
 }
 }
 
 
@@ -3868,7 +3836,7 @@ void CanvasItemEditor::_update_editor_settings() {
 	context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles")));
 	context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles")));
 
 
 	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->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")));
-	pan_speed = int(EDITOR_GET("editors/panning/2d_editor_pan_speed"));
+	panner->set_scroll_speed(EDITOR_GET("editors/panning/2d_editor_pan_speed"));
 	warped_panning = bool(EDITOR_GET("editors/panning/warped_mouse_panning"));
 	warped_panning = bool(EDITOR_GET("editors/panning/warped_mouse_panning"));
 }
 }
 
 
@@ -5059,7 +5027,7 @@ CanvasItemEditor::CanvasItemEditor() {
 	zoom_widget->connect("zoom_changed", callable_mp(this, &CanvasItemEditor::_update_zoom));
 	zoom_widget->connect("zoom_changed", callable_mp(this, &CanvasItemEditor::_update_zoom));
 
 
 	panner.instantiate();
 	panner.instantiate();
-	panner->set_callbacks(callable_mp(this, &CanvasItemEditor::_scroll_callback), callable_mp(this, &CanvasItemEditor::_pan_callback), callable_mp(this, &CanvasItemEditor::_zoom_callback));
+	panner->set_callbacks(callable_mp(this, &CanvasItemEditor::_pan_callback), callable_mp(this, &CanvasItemEditor::_zoom_callback));
 
 
 	viewport = memnew(CanvasItemEditorViewport(this));
 	viewport = memnew(CanvasItemEditorViewport(this));
 	viewport_scrollable->add_child(viewport);
 	viewport_scrollable->add_child(viewport);

+ 2 - 4
editor/plugins/canvas_item_editor_plugin.h

@@ -363,10 +363,8 @@ private:
 
 
 	Ref<ViewPanner> panner;
 	Ref<ViewPanner> panner;
 	bool warped_panning = true;
 	bool warped_panning = true;
-	int pan_speed = 20;
-	void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _pan_callback(Vector2 p_scroll_vec);
-	void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	bool _is_node_locked(const Node *p_node) const;
 	bool _is_node_locked(const Node *p_node) const;
 	bool _is_node_movable(const Node *p_node, bool p_popup_warning = false);
 	bool _is_node_movable(const Node *p_node, bool p_popup_warning = false);

+ 4 - 12
editor/plugins/polygon_2d_editor_plugin.cpp

@@ -939,21 +939,13 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
 	}
 	}
 }
 }
 
 
-void Polygon2DEditor::_uv_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	_uv_pan_callback(-p_scroll_vec * 32);
-}
-
-void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec) {
+void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
 	uv_hscroll->set_value(uv_hscroll->get_value() - p_scroll_vec.x);
 	uv_hscroll->set_value(uv_hscroll->get_value() - p_scroll_vec.x);
 	uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y);
 	uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y);
 }
 }
 
 
-void Polygon2DEditor::_uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
-	if (p_scroll_vec.y < 0) {
-		uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * Math::abs(p_scroll_vec.y))));
-	} else {
-		uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * Math::abs(p_scroll_vec.y))));
-	}
+void Polygon2DEditor::_uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+	uv_zoom->set_value(uv_zoom->get_value() * p_zoom_factor);
 }
 }
 
 
 void Polygon2DEditor::_uv_scroll_changed(real_t) {
 void Polygon2DEditor::_uv_scroll_changed(real_t) {
@@ -1478,7 +1470,7 @@ Polygon2DEditor::Polygon2DEditor() {
 	bone_scroll->add_child(bone_scroll_vb);
 	bone_scroll->add_child(bone_scroll_vb);
 
 
 	uv_panner.instantiate();
 	uv_panner.instantiate();
-	uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_scroll_callback), callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback));
+	uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback));
 
 
 	uv_edit_draw->connect("draw", callable_mp(this, &Polygon2DEditor::_uv_draw));
 	uv_edit_draw->connect("draw", callable_mp(this, &Polygon2DEditor::_uv_draw));
 	uv_edit_draw->connect("gui_input", callable_mp(this, &Polygon2DEditor::_uv_input));
 	uv_edit_draw->connect("gui_input", callable_mp(this, &Polygon2DEditor::_uv_input));

+ 2 - 3
editor/plugins/polygon_2d_editor_plugin.h

@@ -90,9 +90,8 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
 	TextureRect *uv_icon_zoom = nullptr;
 	TextureRect *uv_icon_zoom = nullptr;
 
 
 	Ref<ViewPanner> uv_panner;
 	Ref<ViewPanner> uv_panner;
-	void _uv_scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _uv_pan_callback(Vector2 p_scroll_vec);
-	void _uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	VBoxContainer *bone_scroll_main_vb = nullptr;
 	VBoxContainer *bone_scroll_main_vb = nullptr;
 	ScrollContainer *bone_scroll = nullptr;
 	ScrollContainer *bone_scroll = nullptr;

+ 4 - 12
editor/plugins/texture_region_editor_plugin.cpp

@@ -620,22 +620,14 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
 	}
 	}
 }
 }
 
 
-void TextureRegionEditor::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	_pan_callback(-p_scroll_vec * 32);
-}
-
-void TextureRegionEditor::_pan_callback(Vector2 p_scroll_vec) {
+void TextureRegionEditor::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
 	p_scroll_vec /= draw_zoom;
 	p_scroll_vec /= draw_zoom;
 	hscroll->set_value(hscroll->get_value() - p_scroll_vec.x);
 	hscroll->set_value(hscroll->get_value() - p_scroll_vec.x);
 	vscroll->set_value(vscroll->get_value() - p_scroll_vec.y);
 	vscroll->set_value(vscroll->get_value() - p_scroll_vec.y);
 }
 }
 
 
-void TextureRegionEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
-	if (p_scroll_vec.y < 0) {
-		_zoom_on_position(draw_zoom * ((0.95 + (0.05 * Math::abs(p_scroll_vec.y))) / 0.95), p_origin);
-	} else {
-		_zoom_on_position(draw_zoom * (1 - (0.05 * Math::abs(p_scroll_vec.y))), p_origin);
-	}
+void TextureRegionEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+	_zoom_on_position(draw_zoom * p_zoom_factor, p_origin);
 }
 }
 
 
 void TextureRegionEditor::_scroll_changed(float) {
 void TextureRegionEditor::_scroll_changed(float) {
@@ -1169,7 +1161,7 @@ TextureRegionEditor::TextureRegionEditor() {
 	hb_grid->hide();
 	hb_grid->hide();
 
 
 	panner.instantiate();
 	panner.instantiate();
-	panner->set_callbacks(callable_mp(this, &TextureRegionEditor::_scroll_callback), callable_mp(this, &TextureRegionEditor::_pan_callback), callable_mp(this, &TextureRegionEditor::_zoom_callback));
+	panner->set_callbacks(callable_mp(this, &TextureRegionEditor::_pan_callback), callable_mp(this, &TextureRegionEditor::_zoom_callback));
 
 
 	edit_draw = memnew(Panel);
 	edit_draw = memnew(Panel);
 	vb->add_child(edit_draw);
 	vb->add_child(edit_draw);

+ 2 - 3
editor/plugins/texture_region_editor_plugin.h

@@ -103,9 +103,8 @@ class TextureRegionEditor : public AcceptDialog {
 	bool request_center = false;
 	bool request_center = false;
 
 
 	Ref<ViewPanner> panner;
 	Ref<ViewPanner> panner;
-	void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _pan_callback(Vector2 p_scroll_vec);
-	void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	void _set_snap_mode(int p_mode);
 	void _set_snap_mode(int p_mode);
 	void _set_snap_off_x(float p_val);
 	void _set_snap_off_x(float p_val);

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

@@ -47,18 +47,14 @@ void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) {
 	}
 	}
 }
 }
 
 
-void TileAtlasView::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	_pan_callback(-p_scroll_vec * 32);
-}
-
-void TileAtlasView::_pan_callback(Vector2 p_scroll_vec) {
+void TileAtlasView::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
 	panning += p_scroll_vec;
 	panning += p_scroll_vec;
 	_update_zoom_and_panning(true);
 	_update_zoom_and_panning(true);
 	emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
 	emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
 }
 }
 
 
-void TileAtlasView::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
-	zoom_widget->set_zoom_by_increments(-p_scroll_vec.y * 2);
+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);
 	emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
 	emit_signal(SNAME("transform_changed"), zoom_widget->get_zoom(), panning);
 }
 }
@@ -583,7 +579,7 @@ TileAtlasView::TileAtlasView() {
 	add_child(button_center_view);
 	add_child(button_center_view);
 
 
 	panner.instantiate();
 	panner.instantiate();
-	panner->set_callbacks(callable_mp(this, &TileAtlasView::_scroll_callback), callable_mp(this, &TileAtlasView::_pan_callback), callable_mp(this, &TileAtlasView::_zoom_callback));
+	panner->set_callbacks(callable_mp(this, &TileAtlasView::_pan_callback), callable_mp(this, &TileAtlasView::_zoom_callback));
 	panner->set_enable_rmb(true);
 	panner->set_enable_rmb(true);
 
 
 	center_container = memnew(CenterContainer);
 	center_container = memnew(CenterContainer);

+ 2 - 3
editor/plugins/tiles/tile_atlas_view.h

@@ -65,9 +65,8 @@ private:
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;
 
 
 	Ref<ViewPanner> panner;
 	Ref<ViewPanner> panner;
-	void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _pan_callback(Vector2 p_scroll_vec);
-	void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	HashMap<Vector2, HashMap<int, Rect2i>> alternative_tiles_rect_cache;
 	HashMap<Vector2, HashMap<int, Rect2i>> alternative_tiles_rect_cache;
 	void _update_alternative_tiles_rect_cache();
 	void _update_alternative_tiles_rect_cache();

+ 5 - 23
scene/gui/graph_edit.cpp

@@ -1380,34 +1380,15 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
 			accept_event();
 			accept_event();
 		}
 		}
 	}
 	}
-
-	Ref<InputEventMagnifyGesture> magnify_gesture = p_ev;
-	if (magnify_gesture.is_valid()) {
-		set_zoom_custom(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
-	}
-
-	Ref<InputEventPanGesture> pan_gesture = p_ev;
-	if (pan_gesture.is_valid()) {
-		h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
-		v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
-	}
-}
-
-void GraphEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
-	if (p_scroll_vec.x != 0) {
-		h_scroll->set_value(h_scroll->get_value() + (h_scroll->get_page() * Math::abs(p_scroll_vec.x) / 8) * SIGN(p_scroll_vec.x));
-	} else {
-		v_scroll->set_value(v_scroll->get_value() + (v_scroll->get_page() * Math::abs(p_scroll_vec.y) / 8) * SIGN(p_scroll_vec.y));
-	}
 }
 }
 
 
-void GraphEdit::_pan_callback(Vector2 p_scroll_vec) {
+void GraphEdit::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
 	h_scroll->set_value(h_scroll->get_value() - p_scroll_vec.x);
 	h_scroll->set_value(h_scroll->get_value() - p_scroll_vec.x);
 	v_scroll->set_value(v_scroll->get_value() - p_scroll_vec.y);
 	v_scroll->set_value(v_scroll->get_value() - p_scroll_vec.y);
 }
 }
 
 
-void GraphEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) {
-	set_zoom_custom(p_scroll_vec.y < 0 ? zoom * zoom_step : zoom / zoom_step, p_origin);
+void GraphEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
+	set_zoom_custom(zoom * p_zoom_factor, p_origin);
 }
 }
 
 
 void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity) {
 void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity) {
@@ -1502,6 +1483,7 @@ void GraphEdit::set_zoom_step(float p_zoom_step) {
 	}
 	}
 
 
 	zoom_step = p_zoom_step;
 	zoom_step = p_zoom_step;
+	panner->set_scroll_zoom_factor(zoom_step);
 }
 }
 
 
 float GraphEdit::get_zoom_step() const {
 float GraphEdit::get_zoom_step() const {
@@ -2421,7 +2403,7 @@ GraphEdit::GraphEdit() {
 	zoom_max = (1 * Math::pow(zoom_step, 4));
 	zoom_max = (1 * Math::pow(zoom_step, 4));
 
 
 	panner.instantiate();
 	panner.instantiate();
-	panner->set_callbacks(callable_mp(this, &GraphEdit::_scroll_callback), callable_mp(this, &GraphEdit::_pan_callback), callable_mp(this, &GraphEdit::_zoom_callback));
+	panner->set_callbacks(callable_mp(this, &GraphEdit::_pan_callback), callable_mp(this, &GraphEdit::_zoom_callback));
 
 
 	top_layer = memnew(GraphEditFilter(this));
 	top_layer = memnew(GraphEditFilter(this));
 	add_child(top_layer, false, INTERNAL_MODE_BACK);
 	add_child(top_layer, false, INTERNAL_MODE_BACK);

+ 2 - 3
scene/gui/graph_edit.h

@@ -129,9 +129,8 @@ private:
 
 
 	Ref<ViewPanner> panner;
 	Ref<ViewPanner> panner;
 	bool warped_panning = true;
 	bool warped_panning = true;
-	void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
-	void _pan_callback(Vector2 p_scroll_vec);
-	void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
+	void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
+	void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
 
 
 	bool arrange_nodes_button_hidden = false;
 	bool arrange_nodes_button_hidden = false;
 
 

+ 60 - 24
scene/gui/view_panner.cpp

@@ -43,36 +43,42 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
 		if (scroll_vec != Vector2() && mb->is_pressed()) {
 		if (scroll_vec != Vector2() && mb->is_pressed()) {
 			if (control_scheme == SCROLL_PANS) {
 			if (control_scheme == SCROLL_PANS) {
 				if (mb->is_ctrl_pressed()) {
 				if (mb->is_ctrl_pressed()) {
-					scroll_vec.y *= mb->get_factor();
-					callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
+					// Compute the zoom factor.
+					float zoom_factor = mb->get_factor() <= 0 ? 1.0 : mb->get_factor();
+					zoom_factor = ((scroll_zoom_factor - 1.0) * zoom_factor) + 1.0;
+					float zoom = (scroll_vec.x + scroll_vec.y) > 0 ? 1.0 / scroll_zoom_factor : scroll_zoom_factor;
+					callback_helper(zoom_callback, varray(zoom, mb->get_position(), p_event));
 					return true;
 					return true;
 				} else {
 				} else {
-					Vector2 panning;
-					if (mb->is_shift_pressed()) {
-						panning.x += mb->get_factor() * scroll_vec.y;
-						panning.y += mb->get_factor() * scroll_vec.x;
-					} else {
-						panning.y += mb->get_factor() * scroll_vec.y;
-						panning.x += mb->get_factor() * scroll_vec.x;
+					Vector2 panning = scroll_vec * mb->get_factor();
+					if (pan_axis == PAN_AXIS_HORIZONTAL) {
+						panning = Vector2(panning.x + panning.y, 0);
+					} else if (pan_axis == PAN_AXIS_VERTICAL) {
+						panning = Vector2(0, panning.x + panning.y);
+					} else if (mb->is_shift_pressed()) {
+						panning = Vector2(panning.y, panning.x);
 					}
 					}
-					callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
+					callback_helper(pan_callback, varray(-panning * scroll_speed, p_event));
 					return true;
 					return true;
 				}
 				}
 			} else {
 			} else {
 				if (mb->is_ctrl_pressed()) {
 				if (mb->is_ctrl_pressed()) {
-					Vector2 panning;
-					if (mb->is_shift_pressed()) {
-						panning.x += mb->get_factor() * scroll_vec.y;
-						panning.y += mb->get_factor() * scroll_vec.x;
-					} else {
-						panning.y += mb->get_factor() * scroll_vec.y;
-						panning.x += mb->get_factor() * scroll_vec.x;
+					Vector2 panning = scroll_vec * mb->get_factor();
+					if (pan_axis == PAN_AXIS_HORIZONTAL) {
+						panning = Vector2(panning.x + panning.y, 0);
+					} else if (pan_axis == PAN_AXIS_VERTICAL) {
+						panning = Vector2(0, panning.x + panning.y);
+					} else if (mb->is_shift_pressed()) {
+						panning = Vector2(panning.y, panning.x);
 					}
 					}
-					callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed()));
+					callback_helper(pan_callback, varray(-panning * scroll_speed, p_event));
 					return true;
 					return true;
 				} else if (!mb->is_shift_pressed()) {
 				} else if (!mb->is_shift_pressed()) {
-					scroll_vec.y *= mb->get_factor();
-					callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed()));
+					// Compute the zoom factor.
+					float zoom_factor = mb->get_factor() <= 0 ? 1.0 : mb->get_factor();
+					zoom_factor = ((scroll_zoom_factor - 1.0) * zoom_factor) + 1.0;
+					float zoom = (scroll_vec.x + scroll_vec.y) > 0 ? 1.0 / scroll_zoom_factor : scroll_zoom_factor;
+					callback_helper(zoom_callback, varray(zoom, mb->get_position(), p_event));
 					return true;
 					return true;
 				}
 				}
 			}
 			}
@@ -102,14 +108,31 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect)
 	if (mm.is_valid()) {
 	if (mm.is_valid()) {
 		if (is_dragging) {
 		if (is_dragging) {
 			if (p_canvas_rect != Rect2()) {
 			if (p_canvas_rect != Rect2()) {
-				callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect)));
+				callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect), p_event));
 			} else {
 			} else {
-				callback_helper(pan_callback, varray(mm->get_relative()));
+				callback_helper(pan_callback, varray(mm->get_relative(), p_event));
 			}
 			}
 			return true;
 			return true;
 		}
 		}
 	}
 	}
 
 
+	Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+	if (magnify_gesture.is_valid()) {
+		// Zoom gesture
+		callback_helper(zoom_callback, varray(magnify_gesture->get_factor(), magnify_gesture->get_position(), p_event));
+		return true;
+	}
+
+	Ref<InputEventPanGesture> pan_gesture = p_event;
+	if (pan_gesture.is_valid()) {
+		callback_helper(pan_callback, varray(-pan_gesture->get_delta(), p_event));
+	}
+
+	Ref<InputEventScreenDrag> screen_drag = p_event;
+	if (screen_drag.is_valid()) {
+		callback_helper(pan_callback, varray(screen_drag->get_relative(), p_event));
+	}
+
 	Ref<InputEventKey> k = p_event;
 	Ref<InputEventKey> k = p_event;
 	if (k.is_valid()) {
 	if (k.is_valid()) {
 		if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
 		if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) {
@@ -140,8 +163,7 @@ void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) {
 	p_callback.callp(argptr, p_args.size(), result, ce);
 	p_callback.callp(argptr, p_args.size(), result, ce);
 }
 }
 
 
-void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) {
-	scroll_callback = p_scroll_callback;
+void ViewPanner::set_callbacks(Callable p_pan_callback, Callable p_zoom_callback) {
 	pan_callback = p_pan_callback;
 	pan_callback = p_pan_callback;
 	zoom_callback = p_zoom_callback;
 	zoom_callback = p_zoom_callback;
 }
 }
@@ -163,6 +185,20 @@ void ViewPanner::set_simple_panning_enabled(bool p_enabled) {
 	simple_panning_enabled = p_enabled;
 	simple_panning_enabled = p_enabled;
 }
 }
 
 
+void ViewPanner::set_scroll_speed(int p_scroll_speed) {
+	ERR_FAIL_COND(p_scroll_speed <= 0);
+	scroll_speed = p_scroll_speed;
+}
+
+void ViewPanner::set_scroll_zoom_factor(float p_scroll_zoom_factor) {
+	ERR_FAIL_COND(p_scroll_zoom_factor <= 1.0);
+	scroll_zoom_factor = p_scroll_zoom_factor;
+}
+
+void ViewPanner::set_pan_axis(PanAxis p_pan_axis) {
+	pan_axis = p_pan_axis;
+}
+
 void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
 void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) {
 	set_control_scheme(p_scheme);
 	set_control_scheme(p_scheme);
 	set_pan_shortcut(p_shortcut);
 	set_pan_shortcut(p_shortcut);

+ 14 - 2
scene/gui/view_panner.h

@@ -45,7 +45,17 @@ public:
 		SCROLL_PANS,
 		SCROLL_PANS,
 	};
 	};
 
 
+	enum PanAxis {
+		PAN_AXIS_BOTH,
+		PAN_AXIS_HORIZONTAL,
+		PAN_AXIS_VERTICAL,
+	};
+
 private:
 private:
+	int scroll_speed = 32;
+	float scroll_zoom_factor = 1.1;
+	PanAxis pan_axis = PAN_AXIS_BOTH;
+
 	bool is_dragging = false;
 	bool is_dragging = false;
 	bool pan_key_pressed = false;
 	bool pan_key_pressed = false;
 	bool force_drag = false;
 	bool force_drag = false;
@@ -55,7 +65,6 @@ private:
 
 
 	Ref<Shortcut> pan_view_shortcut;
 	Ref<Shortcut> pan_view_shortcut;
 
 
-	Callable scroll_callback;
 	Callable pan_callback;
 	Callable pan_callback;
 	Callable zoom_callback;
 	Callable zoom_callback;
 
 
@@ -63,11 +72,14 @@ private:
 	ControlScheme control_scheme = SCROLL_ZOOMS;
 	ControlScheme control_scheme = SCROLL_ZOOMS;
 
 
 public:
 public:
-	void set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback);
+	void set_callbacks(Callable p_pan_callback, Callable p_zoom_callback);
 	void set_control_scheme(ControlScheme p_scheme);
 	void set_control_scheme(ControlScheme p_scheme);
 	void set_enable_rmb(bool p_enable);
 	void set_enable_rmb(bool p_enable);
 	void set_pan_shortcut(Ref<Shortcut> p_shortcut);
 	void set_pan_shortcut(Ref<Shortcut> p_shortcut);
 	void set_simple_panning_enabled(bool p_enabled);
 	void set_simple_panning_enabled(bool p_enabled);
+	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 setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning);
 	void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning);