summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Sauermann <6299227+Sauermann@users.noreply.github.com>2023-06-06 20:42:41 +0200
committerMarkus Sauermann <6299227+Sauermann@users.noreply.github.com>2023-06-09 11:29:43 +0200
commitd1fa284e652e2c50d5bcd723cd5e355dce12a887 (patch)
treefe10c1c2b752463e97c4cbc57304915be1fc02ed
parented63b9ea236addd0d9cb6e0c6a862bd8fdf4978e (diff)
downloadredot-engine-d1fa284e652e2c50d5bcd723cd5e355dce12a887.tar.gz
Fix mouse position with screen transform
When a Viewport is not directly attached to the screen, the function `Viewport::get_mouse_position` can't rely on `get_screen_transform`, because that function is ambiguous in these situations. In these cases it is necessary to use the mouse position from the most recent mouse IputEvent.
-rw-r--r--scene/main/viewport.cpp11
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/main/window.cpp8
-rw-r--r--scene/main/window.h1
4 files changed, 21 insertions, 1 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index ab3cd69492..eaeacf9366 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1351,7 +1351,11 @@ Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) {
Vector2 Viewport::get_mouse_position() const {
ERR_READ_THREAD_GUARD_V(Vector2());
- if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_MOUSE)) {
+ if (!is_directly_attached_to_screen()) {
+ // Rely on the most recent mouse coordinate from an InputEventMouse in push_input.
+ // In this case get_screen_transform is not applicable, because it is ambiguous.
+ return gui.last_mouse_pos;
+ } else if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_MOUSE)) {
return get_screen_transform_internal(true).affine_inverse().xform(DisplayServer::get_singleton()->mouse_get_position());
} else {
// Fallback to Input for getting mouse position in case of emulated mouse.
@@ -4595,6 +4599,11 @@ Transform2D SubViewport::get_popup_base_transform() const {
return c->get_screen_transform() * container_transform * get_final_transform();
}
+bool SubViewport::is_directly_attached_to_screen() const {
+ // SubViewports, that are used as Textures are not considered to be directly attached to screen.
+ return Object::cast_to<SubViewportContainer>(get_parent()) && get_parent()->get_viewport() && get_parent()->get_viewport()->is_directly_attached_to_screen();
+}
+
void SubViewport::_notification(int p_what) {
ERR_MAIN_THREAD_GUARD;
switch (p_what) {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 1cb32d4509..d7c5f0eeb5 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -669,6 +669,7 @@ public:
Transform2D get_screen_transform() const;
virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const;
virtual Transform2D get_popup_base_transform() const { return Transform2D(); }
+ virtual bool is_directly_attached_to_screen() const { return false; };
#ifndef _3D_DISABLED
bool use_xr = false;
@@ -800,6 +801,7 @@ public:
virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const override;
virtual Transform2D get_popup_base_transform() const override;
+ virtual bool is_directly_attached_to_screen() const override;
void _validate_property(PropertyInfo &p_property) const;
SubViewport();
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 26aa06e1a4..31aeb70d40 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -2475,6 +2475,14 @@ Transform2D Window::get_popup_base_transform() const {
return popup_base_transform;
}
+bool Window::is_directly_attached_to_screen() const {
+ if (get_embedder()) {
+ return get_embedder()->is_directly_attached_to_screen();
+ }
+ // Distinguish between the case that this is a native Window and not inside the tree.
+ return is_inside_tree();
+}
+
void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
diff --git a/scene/main/window.h b/scene/main/window.h
index bf5d6a13ee..d0afd0ff9f 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -401,6 +401,7 @@ public:
virtual Transform2D get_final_transform() const override;
virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const override;
virtual Transform2D get_popup_base_transform() const override;
+ virtual bool is_directly_attached_to_screen() const override;
Rect2i get_parent_rect() const;
virtual DisplayServer::WindowID get_window_id() const override;