mirror of
https://github.com/godotengine/godot.git
synced 2025-01-24 21:01:50 +08:00
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.
This commit is contained in:
parent
ed63b9ea23
commit
d1fa284e65
@ -1351,7 +1351,11 @@ Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) {
|
|||||||
|
|
||||||
Vector2 Viewport::get_mouse_position() const {
|
Vector2 Viewport::get_mouse_position() const {
|
||||||
ERR_READ_THREAD_GUARD_V(Vector2());
|
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());
|
return get_screen_transform_internal(true).affine_inverse().xform(DisplayServer::get_singleton()->mouse_get_position());
|
||||||
} else {
|
} else {
|
||||||
// Fallback to Input for getting mouse position in case of emulated mouse.
|
// 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();
|
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) {
|
void SubViewport::_notification(int p_what) {
|
||||||
ERR_MAIN_THREAD_GUARD;
|
ERR_MAIN_THREAD_GUARD;
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
|
@ -669,6 +669,7 @@ public:
|
|||||||
Transform2D get_screen_transform() const;
|
Transform2D get_screen_transform() const;
|
||||||
virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const;
|
virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const;
|
||||||
virtual Transform2D get_popup_base_transform() const { return Transform2D(); }
|
virtual Transform2D get_popup_base_transform() const { return Transform2D(); }
|
||||||
|
virtual bool is_directly_attached_to_screen() const { return false; };
|
||||||
|
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
bool use_xr = false;
|
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_screen_transform_internal(bool p_absolute_position = false) const override;
|
||||||
virtual Transform2D get_popup_base_transform() 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;
|
void _validate_property(PropertyInfo &p_property) const;
|
||||||
SubViewport();
|
SubViewport();
|
||||||
|
@ -2475,6 +2475,14 @@ Transform2D Window::get_popup_base_transform() const {
|
|||||||
return popup_base_transform;
|
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() {
|
void Window::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
|
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
|
||||||
ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
|
ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
|
||||||
|
@ -401,6 +401,7 @@ public:
|
|||||||
virtual Transform2D get_final_transform() const override;
|
virtual Transform2D get_final_transform() const override;
|
||||||
virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const override;
|
virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const override;
|
||||||
virtual Transform2D get_popup_base_transform() const override;
|
virtual Transform2D get_popup_base_transform() const override;
|
||||||
|
virtual bool is_directly_attached_to_screen() const override;
|
||||||
|
|
||||||
Rect2i get_parent_rect() const;
|
Rect2i get_parent_rect() const;
|
||||||
virtual DisplayServer::WindowID get_window_id() const override;
|
virtual DisplayServer::WindowID get_window_id() const override;
|
||||||
|
Loading…
Reference in New Issue
Block a user