Browse Source

Implement warped mouse panning for 2D & 3D editors
Enabled by default as in Blender, but can be disabled separately for 2D & 3D;
the core functionality is in Input so this could be reused or even exposed to scripts in the future

Pedro J. Estébanez 8 năm trước cách đây
mục cha
commit
2c2c48ffb3

+ 1 - 0
core/os/input.h

@@ -78,6 +78,7 @@ public:
 	virtual int get_mouse_button_mask() const = 0;
 
 	virtual void warp_mouse_pos(const Vector2 &p_to) = 0;
+	virtual Point2i warp_mouse_motion(const InputEventMouseMotion &p_motion, const Rect2 &p_rect) = 0;
 
 	virtual Vector3 get_gravity() = 0;
 	virtual Vector3 get_accelerometer() = 0;

+ 3 - 0
editor/editor_settings.cpp

@@ -582,6 +582,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	hints["3d_editor/zoom_modifier"] = PropertyInfo(Variant::INT, "3d_editor/zoom_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
 	set("3d_editor/emulate_numpad", false);
 	set("3d_editor/emulate_3_button_mouse", false);
+	set("3d_editor/warped_mouse_panning", true);
 
 	set("2d_editor/bone_width", 5);
 	set("2d_editor/bone_color1", Color(1.0, 1.0, 1.0, 0.9));
@@ -591,6 +592,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 
 	set("2d_editor/keep_margins_when_changing_anchors", false);
 
+	set("2d_editor/warped_mouse_panning", true);
+
 	set("game_window_placement/rect", 0);
 	hints["game_window_placement/rect"] = PropertyInfo(Variant::INT, "game_window_placement/rect", PROPERTY_HINT_ENUM, "Default,Centered,Custom Position,Force Maximized,Force Full Screen");
 	String screen_hints = TTR("Default (Same as Editor)");

+ 9 - 2
editor/plugins/canvas_item_editor_plugin.cpp

@@ -1462,8 +1462,15 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent &p_event) {
 
 			if ((m.button_mask & BUTTON_MASK_LEFT && tool == TOOL_PAN) || m.button_mask & BUTTON_MASK_MIDDLE || (m.button_mask & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
 
-				h_scroll->set_val(h_scroll->get_val() - m.relative_x / zoom);
-				v_scroll->set_val(v_scroll->get_val() - m.relative_y / zoom);
+				Point2i relative;
+				if (bool(EditorSettings::get_singleton()->get("2d_editor/warped_mouse_panning"))) {
+					relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
+				} else {
+					relative = Point2i(m.relative_x, m.relative_y);
+				}
+
+				h_scroll->set_val(h_scroll->get_val() - relative.x / zoom);
+				v_scroll->set_val(v_scroll->get_val() - relative.y / zoom);
 			}
 
 			return;

+ 9 - 1
editor/plugins/spatial_editor_plugin.cpp

@@ -30,6 +30,7 @@
 #include "print_string.h"
 
 #include "camera_matrix.h"
+#include "core/os/input.h"
 #include "editor/animation_editor.h"
 #include "editor/editor_node.h"
 #include "editor/editor_settings.h"
@@ -1470,12 +1471,19 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
 					if (nav_scheme == NAVIGATION_MAYA && m.mod.shift)
 						pan_speed *= pan_speed_modifier;
 
+					Point2i relative;
+					if (bool(EditorSettings::get_singleton()->get("3d_editor/warped_mouse_panning"))) {
+						relative = Input::get_singleton()->warp_mouse_motion(m, surface->get_global_rect());
+					} else {
+						relative = Point2i(m.relative_x, m.relative_y);
+					}
+
 					Transform camera_transform;
 
 					camera_transform.translate(cursor.pos);
 					camera_transform.basis.rotate(Vector3(0, 1, 0), cursor.y_rot);
 					camera_transform.basis.rotate(Vector3(1, 0, 0), cursor.x_rot);
-					Vector3 translation(-m.relative_x * pan_speed, m.relative_y * pan_speed, 0);
+					Vector3 translation(-relative.x * pan_speed, relative.y * pan_speed, 0);
 					translation *= cursor.distance / DISTANCE_DEFAULT;
 					camera_transform.translate(translation);
 					cursor.pos = camera_transform.origin;

+ 11 - 0
main/input_default.cpp

@@ -433,6 +433,17 @@ void InputDefault::warp_mouse_pos(const Vector2 &p_to) {
 	OS::get_singleton()->warp_mouse_pos(p_to);
 }
 
+Point2i InputDefault::warp_mouse_motion(const InputEventMouseMotion &p_motion, const Rect2 &p_rect) {
+
+	const Point2i rel_warped(Math::fmod(p_motion.relative_x, p_rect.size.x), Math::fmod(p_motion.relative_y, p_rect.size.y));
+	const Point2i pos_local = Point2i(p_motion.global_x, p_motion.global_y) - p_rect.pos;
+	const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y));
+	if (pos_warped != pos_local) {
+		OS::get_singleton()->warp_mouse_pos(pos_warped + p_rect.pos);
+	}
+	return rel_warped;
+}
+
 void InputDefault::iteration(float p_step) {
 }
 

+ 1 - 0
main/input_default.h

@@ -184,6 +184,7 @@ public:
 	virtual int get_mouse_button_mask() const;
 
 	virtual void warp_mouse_pos(const Vector2 &p_to);
+	virtual Point2i warp_mouse_motion(const InputEventMouseMotion &p_motion, const Rect2 &p_rect);
 
 	virtual void parse_input_event(const InputEvent &p_event);