feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -36,13 +36,6 @@
#include "core/templates/sort_array.h"
#include "scene/2d/audio_listener_2d.h"
#include "scene/2d/camera_2d.h"
#include "scene/2d/physics/collision_object_2d.h"
#ifndef _3D_DISABLED
#include "scene/3d/audio_listener_3d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/physics/collision_object_3d.h"
#include "scene/3d/world_environment.h"
#endif // _3D_DISABLED
#include "scene/gui/control.h"
#include "scene/gui/label.h"
#include "scene/gui/popup.h"
@ -56,6 +49,20 @@
#include "servers/audio_server.h"
#include "servers/rendering/rendering_server_globals.h"
#ifndef _3D_DISABLED
#include "scene/3d/audio_listener_3d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/world_environment.h"
#endif // _3D_DISABLED
#ifndef PHYSICS_2D_DISABLED
#include "scene/2d/physics/collision_object_2d.h"
#endif // PHYSICS_2D_DISABLED
#ifndef PHYSICS_3D_DISABLED
#include "scene/3d/physics/collision_object_3d.h"
#endif // PHYSICS_3D_DISABLED
void ViewportTexture::setup_local_to_scene() {
// For the same target viewport, setup is only allowed once to prevent multiple free or multiple creations.
if (!vp_changed) {
@ -287,7 +294,7 @@ void Viewport::_sub_window_register(Window *p_window) {
ERR_FAIL_COND(gui.sub_windows[i].window == p_window);
}
if (gui.sub_windows.size() == 0) {
if (gui.sub_windows.is_empty()) {
subwindow_canvas = RS::get_singleton()->canvas_create();
RS::get_singleton()->viewport_attach_canvas(viewport, subwindow_canvas);
RS::get_singleton()->viewport_set_canvas_stacking(viewport, subwindow_canvas, SUBWINDOW_CANVAS_LAYER, 0);
@ -317,7 +324,13 @@ void Viewport::_sub_window_register(Window *p_window) {
void Viewport::_sub_window_update(Window *p_window) {
int index = _sub_window_find(p_window);
ERR_FAIL_COND(index == -1);
// _sub_window_update is sometimes called deferred, and the window may have been closed since then.
// For example, when the user resizes the game window.
// In that case, _sub_window_find will not find it, which is expected.
if (index == -1) {
return;
}
SubWindow &sw = gui.sub_windows.write[index];
sw.pending_window_update = false;
@ -452,7 +465,7 @@ void Viewport::_sub_window_remove(Window *p_window) {
RS::get_singleton()->free(sw.canvas_item);
gui.sub_windows.remove_at(index);
if (gui.sub_windows.size() == 0) {
if (gui.sub_windows.is_empty()) {
RS::get_singleton()->free(subwindow_canvas);
subwindow_canvas = RID();
}
@ -502,18 +515,14 @@ int Viewport::_sub_window_find(Window *p_window) const {
}
void Viewport::_update_viewport_path() {
if (viewport_textures.is_empty()) {
if (!is_inside_tree()) {
return;
}
Node *scene_root = get_scene_file_path().is_empty() ? get_owner() : this;
if (!scene_root && is_inside_tree()) {
scene_root = get_tree()->get_edited_scene_root();
}
if (scene_root && (scene_root == this || scene_root->is_ancestor_of(this))) {
NodePath path_in_scene = scene_root->get_path_to(this);
for (ViewportTexture *E : viewport_textures) {
E->path = path_in_scene;
for (ViewportTexture *E : viewport_textures) {
Node *loc_scene = E->get_local_scene();
if (loc_scene) {
E->path = loc_scene->get_path_to(this);
}
}
}
@ -543,11 +552,14 @@ void Viewport::_notification(int p_what) {
#endif // _3D_DISABLED
add_to_group("_viewports");
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
if (get_tree()->is_debugging_collisions_hint()) {
#ifndef PHYSICS_2D_DISABLED
PhysicsServer2D::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(), get_tree()->get_collision_debug_contact_count());
contact_2d_debug = RenderingServer::get_singleton()->canvas_item_create();
RenderingServer::get_singleton()->canvas_item_set_parent(contact_2d_debug, current_canvas);
#ifndef _3D_DISABLED
#endif // PHYSICS_2D_DISABLED
#ifndef PHYSICS_3D_DISABLED
PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world_3d()->get_space(), get_tree()->get_collision_debug_contact_count());
contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create();
RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, false);
@ -557,9 +569,10 @@ void Viewport::_notification(int p_what) {
RenderingServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh);
RenderingServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world_3d()->get_scenario());
RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true);
#endif // _3D_DISABLED
#endif // PHYSICS_3D_DISABLED
set_physics_process_internal(true);
}
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
} break;
case NOTIFICATION_READY: {
@ -598,17 +611,21 @@ void Viewport::_notification(int p_what) {
RenderingServer::get_singleton()->viewport_set_scenario(viewport, RID());
RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
#ifndef PHYSICS_2D_DISABLED
if (contact_2d_debug.is_valid()) {
RenderingServer::get_singleton()->free(contact_2d_debug);
contact_2d_debug = RID();
}
#endif // PHYSICS_2D_DISABLED
#ifndef PHYSICS_3D_DISABLED
if (contact_3d_debug_multimesh.is_valid()) {
RenderingServer::get_singleton()->free(contact_3d_debug_multimesh);
RenderingServer::get_singleton()->free(contact_3d_debug_instance);
contact_3d_debug_instance = RID();
contact_3d_debug_multimesh = RID();
}
#endif // PHYSICS_3D_DISABLED
remove_from_group("_viewports");
set_physics_process_internal(false);
@ -621,11 +638,13 @@ void Viewport::_notification(int p_what) {
_update_viewport_path();
} break;
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (!get_tree()) {
return;
}
#ifndef PHYSICS_2D_DISABLED
if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) {
RenderingServer::get_singleton()->canvas_item_clear(contact_2d_debug);
RenderingServer::get_singleton()->canvas_item_set_draw_index(contact_2d_debug, 0xFFFFF); //very high index
@ -638,7 +657,8 @@ void Viewport::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(contact_2d_debug, Rect2(points[i] - Vector2(2, 2), Vector2(5, 5)), ccol);
}
}
#ifndef _3D_DISABLED
#endif // PHYSICS_2D_DISABLED
#ifndef PHYSICS_3D_DISABLED
if (get_tree()->is_debugging_collisions_hint() && contact_3d_debug_multimesh.is_valid()) {
Vector<Vector3> points = PhysicsServer3D::get_singleton()->space_get_contacts(find_world_3d()->get_space());
int point_count = PhysicsServer3D::get_singleton()->space_get_contact_count(find_world_3d()->get_space());
@ -651,8 +671,9 @@ void Viewport::_notification(int p_what) {
RS::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh, i, point_transform);
}
}
#endif // _3D_DISABLED
#endif // PHYSICS_3D_DISABLED
} break;
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
case NOTIFICATION_VP_MOUSE_ENTER: {
gui.mouse_in_viewport = true;
@ -685,6 +706,7 @@ void Viewport::_notification(int p_what) {
}
}
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
void Viewport::_process_picking() {
if (!is_inside_tree()) {
return;
@ -701,7 +723,7 @@ void Viewport::_process_picking() {
physics_picking_events.clear();
return;
}
#ifndef _3D_DISABLED
#ifndef XR_DISABLED
if (use_xr) {
if (XRServer::get_singleton() != nullptr) {
Ref<XRInterface> xr_interface = XRServer::get_singleton()->get_primary_interface();
@ -712,21 +734,23 @@ void Viewport::_process_picking() {
}
}
}
#endif
#endif // XR_DISABLED
_drop_physics_mouseover(true);
#ifndef _3D_DISABLED
#ifndef PHYSICS_3D_DISABLED
Vector2 last_pos(1e20, 1e20);
CollisionObject3D *last_object = nullptr;
ObjectID last_id;
PhysicsDirectSpaceState3D::RayResult result;
#endif // _3D_DISABLED
#endif // PHYSICS_3D_DISABLED
#ifndef PHYSICS_2D_DISABLED
PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
#endif // PHYSICS_2D_DISABLED
SubViewportContainer *parent_svc = Object::cast_to<SubViewportContainer>(get_parent());
bool parent_ignore_mouse = (parent_svc && parent_svc->get_mouse_filter() == Control::MOUSE_FILTER_IGNORE);
bool parent_ignore_mouse = (parent_svc && parent_svc->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_IGNORE);
bool create_passive_hover_event = true;
if (gui.mouse_over || parent_ignore_mouse) {
// When the mouse is over a Control node, passive hovering would cause input events for Colliders, that are behind Control nodes.
@ -803,6 +827,7 @@ void Viewport::_process_picking() {
pos = st->get_position();
}
#ifndef PHYSICS_2D_DISABLED
if (ss2d) {
// Send to 2D.
@ -895,15 +920,16 @@ void Viewport::_process_picking() {
_cleanup_mouseover_colliders(false, false, frame);
}
}
#endif // PHYSICS_2D_DISABLED
#ifndef _3D_DISABLED
#ifndef PHYSICS_3D_DISABLED
if (physics_object_picking_first_only && is_input_handled()) {
continue;
}
CollisionObject3D *capture_object = nullptr;
if (physics_object_capture.is_valid()) {
capture_object = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture));
capture_object = ObjectDB::get_instance<CollisionObject3D>(physics_object_capture);
if (!capture_object || !camera_3d || (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed())) {
physics_object_capture = ObjectID();
} else {
@ -952,7 +978,7 @@ void Viewport::_process_picking() {
if (is_mouse && new_collider != physics_object_over) {
if (physics_object_over.is_valid()) {
CollisionObject3D *previous_co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
CollisionObject3D *previous_co = ObjectDB::get_instance<CollisionObject3D>(physics_object_over);
if (previous_co) {
previous_co->_mouse_exit();
}
@ -975,9 +1001,10 @@ void Viewport::_process_picking() {
last_pos = pos;
}
}
#endif // _3D_DISABLED
#endif // PHYSICS_3D_DISABLED
}
}
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
RID Viewport::get_viewport_rid() const {
ERR_READ_THREAD_GUARD_V(RID());
@ -1002,10 +1029,10 @@ void Viewport::update_canvas_items() {
_update_canvas_items(this);
}
bool Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, bool p_allocated) {
bool Viewport::_set_size(const Size2i &p_size, const Size2 &p_size_2d_override, bool p_allocated) {
Transform2D stretch_transform_new = Transform2D();
if (is_size_2d_override_stretch_enabled() && p_size_2d_override.width > 0 && p_size_2d_override.height > 0) {
Size2 scale = Size2(p_size) / Size2(p_size_2d_override);
Size2 scale = Size2(p_size) / p_size_2d_override;
stretch_transform_new.scale(scale);
}
@ -1058,7 +1085,7 @@ bool Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
}
Size2i Viewport::_get_size() const {
#ifndef _3D_DISABLED
#ifndef XR_DISABLED
if (use_xr) {
if (XRServer::get_singleton() != nullptr) {
Ref<XRInterface> xr_interface = XRServer::get_singleton()->get_primary_interface();
@ -1069,12 +1096,12 @@ Size2i Viewport::_get_size() const {
}
return Size2i();
}
#endif // _3D_DISABLED
#endif // XR_DISABLED
return size;
}
Size2i Viewport::_get_size_2d_override() const {
Size2 Viewport::_get_size_2d_override() const {
return size_2d_override;
}
@ -1092,7 +1119,7 @@ Rect2 Viewport::get_visible_rect() const {
r = Rect2(Point2(), size);
}
if (size_2d_override != Size2i()) {
if (size_2d_override != Size2()) {
r.size = size_2d_override;
}
@ -1488,7 +1515,28 @@ String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Cont
return tooltip;
}
void Viewport::cancel_tooltip() {
_gui_cancel_tooltip();
}
void Viewport::show_tooltip(Control *p_control) {
if (!p_control) {
return;
}
if (gui.tooltip_timer.is_valid()) {
gui.tooltip_timer->release_connections();
gui.tooltip_timer = Ref<SceneTreeTimer>();
}
gui.tooltip_control = p_control;
_gui_show_tooltip_at(p_control->get_size() / 2);
}
void Viewport::_gui_show_tooltip() {
_gui_show_tooltip_at(gui.last_mouse_pos);
}
void Viewport::_gui_show_tooltip_at(const Point2i &p_pos) {
if (!gui.tooltip_control) {
return;
}
@ -1509,6 +1557,7 @@ void Viewport::_gui_show_tooltip() {
// This way, the custom tooltip from `ConnectionsDockTree` can create
// its own tooltip without conflicting with the default one, even an empty tooltip.
if (base_tooltip && !base_tooltip->is_visible()) {
memdelete(base_tooltip);
return;
}
@ -1546,6 +1595,8 @@ void Viewport::_gui_show_tooltip() {
panel->set_flag(Window::FLAG_POPUP, false);
panel->set_flag(Window::FLAG_MOUSE_PASSTHROUGH, true);
panel->set_wrap_controls(true);
panel->set_default_canvas_item_texture_filter(get_default_canvas_item_texture_filter());
panel->set_default_canvas_item_texture_repeat(get_default_canvas_item_texture_repeat());
panel->add_child(base_tooltip);
panel->gui_parent = this;
@ -1557,20 +1608,19 @@ void Viewport::_gui_show_tooltip() {
if (!window) { // Not embedded.
window = gui.tooltip_popup->get_parent_visible_window();
}
float win_scale = window->content_scale_factor;
Size2 scale = get_popup_base_transform().get_scale();
real_t popup_scale = MIN(scale.x, scale.y);
Point2 tooltip_offset = GLOBAL_GET("display/mouse_cursor/tooltip_position_offset");
if (!gui.tooltip_popup->is_embedded()) {
tooltip_offset *= win_scale;
}
tooltip_offset *= popup_scale;
Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_contents_minimum_size());
Rect2i vr;
if (gui.tooltip_popup->is_embedded()) {
vr = gui.tooltip_popup->get_embedder()->get_visible_rect();
} else {
panel->content_scale_factor = win_scale;
r.size *= win_scale;
vr = window->get_usable_parent_rect();
}
panel->content_scale_factor = popup_scale;
r.size *= popup_scale;
r.size = r.size.ceil();
r.size = r.size.min(panel->get_max_size());
@ -1822,9 +1872,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
#ifdef DEBUG_ENABLED
if (EngineDebugger::get_singleton()) {
Array arr;
arr.push_back(gui.mouse_focus->get_path());
arr.push_back(gui.mouse_focus->get_class());
Array arr = { gui.mouse_focus->get_path(), gui.mouse_focus->get_class() };
EngineDebugger::get_singleton()->send_message("scene:click_ctrl", arr);
}
#endif
@ -1834,7 +1882,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
while (ci) {
Control *control = Object::cast_to<Control>(ci);
if (control) {
if (control->get_focus_mode() != Control::FOCUS_NONE) {
if (control->get_focus_mode_with_recursive() != Control::FOCUS_NONE) {
// Grabbing unhovered focus can cause issues when mouse is dragged
// with another button held down.
if (control != gui.key_focus && gui.mouse_over_hierarchy.has(control)) {
@ -2085,7 +2133,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
} else {
ObjectID control_id = gui.touch_focus[touch_index];
Control *over = control_id.is_valid() ? Object::cast_to<Control>(ObjectDB::get_instance(control_id)) : nullptr;
Control *over = control_id.is_valid() ? ObjectDB::get_instance<Control>(control_id) : nullptr;
if (over && over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); // Make a copy.
pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
@ -2120,7 +2168,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (drag_event.is_valid()) {
const int drag_event_index = drag_event->get_index();
ObjectID control_id = gui.touch_focus[drag_event_index];
Control *over = control_id.is_valid() ? Object::cast_to<Control>(ObjectDB::get_instance(control_id)) : nullptr;
Control *over = control_id.is_valid() ? ObjectDB::get_instance<Control>(control_id) : nullptr;
if (!over) {
over = gui_find_control(drag_event->get_position());
}
@ -2178,6 +2226,17 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
Control *from = gui.key_focus ? gui.key_focus : nullptr;
if (!from) {
for (int i = 0; i < get_child_count(true); i++) {
Control *c = Object::cast_to<Control>(get_child(i, true));
if (!c || !c->is_visible_in_tree() || c->is_set_as_top_level()) {
continue;
}
from = c;
break;
}
}
if (from && p_event->is_pressed()) {
Control *next = nullptr;
@ -2194,6 +2253,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
next = from->find_prev_valid_focus();
}
if (p_event->is_action_pressed(SNAME("ui_accessibility_drag_and_drop")) && input->is_action_just_pressed(SNAME("ui_accessibility_drag_and_drop"))) {
if (gui_is_dragging()) {
from->accessibility_drop();
} else {
from->accessibility_drag();
}
}
if (p_event->is_action_pressed(SNAME("ui_up")) && input->is_action_just_pressed(SNAME("ui_up"))) {
next = from->_get_focus_neighbor(SIDE_TOP);
}
@ -2218,6 +2285,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
next = from->find_prev_valid_focus();
}
if (p_event->is_action_pressed(SNAME("ui_accessibility_drag_and_drop"), true, true)) {
if (gui_is_dragging()) {
from->accessibility_drop();
} else {
from->accessibility_drag();
}
}
if (p_event->is_action_pressed(SNAME("ui_up"), true, true)) {
next = from->_get_focus_neighbor(SIDE_TOP);
}
@ -2243,9 +2318,13 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
void Viewport::_perform_drop(Control *p_control) {
gui_perform_drop_at(p_control ? p_control->get_local_mouse_position() : Vector2(), p_control);
}
void Viewport::gui_perform_drop_at(const Point2 &p_pos, Control *p_control) {
// Without any arguments, simply cancel Drag and Drop.
if (p_control) {
gui.drag_successful = _gui_drop(p_control, p_control->get_local_mouse_position(), false);
gui.drag_successful = _gui_drop(p_control, p_pos, false);
} else {
gui.drag_successful = false;
}
@ -2259,6 +2338,7 @@ void Viewport::_perform_drop(Control *p_control) {
Viewport *section_root = get_section_root_viewport();
section_root->gui.drag_data = Variant();
gui.dragging = false;
gui.drag_description = String();
section_root->gui.global_dragging = false;
gui.drag_mouse_over = nullptr;
Viewport::_propagate_drag_notification(section_root, NOTIFICATION_DRAG_END);
@ -2287,12 +2367,23 @@ void Viewport::gui_set_root_order_dirty() {
gui.roots_order_dirty = true;
}
void Viewport::_gui_force_drag_start() {
Viewport *section_root = get_section_root_viewport();
section_root->gui.global_dragging = true;
}
void Viewport::_gui_force_drag_cancel() {
Viewport *section_root = get_section_root_viewport();
section_root->gui.global_dragging = false;
}
void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control) {
ERR_FAIL_COND_MSG(p_data.get_type() == Variant::NIL, "Drag data must be a value.");
gui.dragging = true;
Viewport *section_root = get_section_root_viewport();
section_root->gui.global_dragging = true;
ERR_FAIL_COND(!section_root->gui.global_dragging);
gui.dragging = true;
section_root->gui.drag_data = p_data;
gui.mouse_focus = nullptr;
gui.mouse_focus_mask.clear();
@ -2324,7 +2415,7 @@ Control *Viewport::_gui_get_drag_preview() {
if (gui.drag_preview_id.is_null()) {
return nullptr;
} else {
Control *drag_preview = Object::cast_to<Control>(ObjectDB::get_instance(gui.drag_preview_id));
Control *drag_preview = ObjectDB::get_instance<Control>(gui.drag_preview_id);
if (!drag_preview) {
ERR_PRINT("Don't free the control set as drag preview.");
gui.drag_preview_id = ObjectID();
@ -2412,7 +2503,7 @@ void Viewport::_gui_update_mouse_over() {
int found = gui.mouse_over_hierarchy.find(ancestor_control);
if (found >= 0) {
// Remove the node if the propagation chain has been broken or it is now MOUSE_FILTER_IGNORE.
if (removing || ancestor_control->get_mouse_filter() == Control::MOUSE_FILTER_IGNORE) {
if (removing || ancestor_control->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_IGNORE) {
needs_exit.push_back(found);
}
}
@ -2423,14 +2514,14 @@ void Viewport::_gui_update_mouse_over() {
}
reached_top = true;
}
if (!removing && ancestor_control->get_mouse_filter() != Control::MOUSE_FILTER_IGNORE) {
if (!removing && ancestor_control->get_mouse_filter_with_recursive() != Control::MOUSE_FILTER_IGNORE) {
new_mouse_over_hierarchy.push_back(ancestor_control);
// Add the node if it was not found and it is now not MOUSE_FILTER_IGNORE.
if (found < 0) {
needs_enter.push_back(ancestor_control);
}
}
if (ancestor_control->get_mouse_filter() == Control::MOUSE_FILTER_STOP) {
if (ancestor_control->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_STOP) {
// MOUSE_FILTER_STOP breaks the propagation chain.
if (reached_top) {
break;
@ -2550,11 +2641,13 @@ void Viewport::_drop_mouse_focus() {
}
void Viewport::_drop_physics_mouseover(bool p_paused_only) {
#ifndef PHYSICS_2D_DISABLED
_cleanup_mouseover_colliders(true, p_paused_only);
#endif // PHYSICS_2D_DISABLED
#ifndef _3D_DISABLED
#ifndef PHYSICS_3D_DISABLED
if (physics_object_over.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
CollisionObject3D *co = ObjectDB::get_instance<CollisionObject3D>(physics_object_over);
if (co) {
if (!co->is_inside_tree()) {
physics_object_over = ObjectID();
@ -2566,7 +2659,7 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
}
}
}
#endif // _3D_DISABLED
#endif // PHYSICS_3D_DISABLED
}
void Viewport::_gui_grab_click_focus(Control *p_control) {
@ -2660,11 +2753,11 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw
int limit = p_subwindow->theme_cache.resize_margin;
if (ABS(dist_x) > limit) {
if (Math::abs(dist_x) > limit) {
return SUB_WINDOW_RESIZE_DISABLED;
}
if (ABS(dist_y) > limit) {
if (Math::abs(dist_y) > limit) {
return SUB_WINDOW_RESIZE_DISABLED;
}
@ -3089,7 +3182,7 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
while (ancestor) {
Control *ancestor_control = Object::cast_to<Control>(ancestor);
if (ancestor_control) {
if (ancestor_control->get_mouse_filter() != Control::MOUSE_FILTER_IGNORE) {
if (ancestor_control->get_mouse_filter_with_recursive() != Control::MOUSE_FILTER_IGNORE) {
int found = gui.mouse_over_hierarchy.find(ancestor_control);
if (found >= 0) {
common_ancestor = gui.mouse_over_hierarchy[found];
@ -3097,7 +3190,7 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
}
over_ancestors.push_back(ancestor_control);
}
if (ancestor_control->get_mouse_filter() == Control::MOUSE_FILTER_STOP) {
if (ancestor_control->get_mouse_filter_with_recursive() == Control::MOUSE_FILTER_STOP) {
// MOUSE_FILTER_STOP breaks the propagation chain.
break;
}
@ -3339,6 +3432,7 @@ void Viewport::_push_unhandled_input_internal(const Ref<InputEvent> &p_event) {
get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, p_event, this);
}
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
if (physics_object_picking && !is_input_handled()) {
if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED &&
(Object::cast_to<InputEventMouse>(*p_event) ||
@ -3350,6 +3444,7 @@ void Viewport::_push_unhandled_input_internal(const Ref<InputEvent> &p_event) {
set_input_as_handled();
}
}
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
}
void Viewport::notify_mouse_entered() {
@ -3368,6 +3463,7 @@ void Viewport::notify_mouse_exited() {
_mouse_leave_viewport();
}
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
void Viewport::set_physics_object_picking(bool p_enable) {
ERR_MAIN_THREAD_GUARD;
physics_object_picking = p_enable;
@ -3403,6 +3499,7 @@ void Viewport::set_physics_object_picking_first_only(bool p_enable) {
bool Viewport::get_physics_object_picking_first_only() {
return physics_object_picking_first_only;
}
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const {
ERR_READ_THREAD_GUARD_V(Vector2());
@ -3446,6 +3543,19 @@ void Viewport::set_disable_input_override(bool p_disable) {
disable_input_override = p_disable;
}
String Viewport::gui_get_drag_description() const {
ERR_READ_THREAD_GUARD_V(String());
if (get_section_root_viewport()->gui.drag_description.is_empty()) {
return RTR("Drag-and-drop data");
} else {
return get_section_root_viewport()->gui.drag_description;
}
}
void Viewport::gui_set_drag_description(const String &p_description) {
gui.drag_description = p_description;
}
Variant Viewport::gui_get_drag_data() const {
ERR_READ_THREAD_GUARD_V(Variant());
return get_section_root_viewport()->gui.drag_data;
@ -4039,6 +4149,7 @@ void Viewport::_camera_2d_set(Camera2D *p_camera_2d) {
camera_2d = p_camera_2d;
}
#ifndef PHYSICS_2D_DISABLED
void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference) {
List<ObjectID> to_erase;
List<ObjectID> to_mouse_exit;
@ -4108,6 +4219,7 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus
shapes_to_mouse_exit.pop_front();
}
}
#endif // PHYSICS_2D_DISABLED
AudioListener2D *Viewport::get_audio_listener_2d() const {
ERR_READ_THREAD_GUARD_V(nullptr);
@ -4235,6 +4347,7 @@ void Viewport::_audio_listener_3d_make_next_current(AudioListener3D *p_exclude)
}
}
#ifndef PHYSICS_3D_DISABLED
void Viewport::_collision_object_3d_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
Transform3D object_transform = p_object->get_global_transform();
Transform3D camera_transform = p_camera->get_global_transform();
@ -4252,6 +4365,7 @@ void Viewport::_collision_object_3d_input_event(CollisionObject3D *p_object, Cam
physics_last_camera_transform = camera_transform;
physics_last_id = id;
}
#endif // PHYSICS_3D_DISABLED
Camera3D *Viewport::get_camera_3d() const {
ERR_READ_THREAD_GUARD_V(nullptr);
@ -4802,12 +4916,14 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_texture"), &Viewport::get_texture);
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking);
ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
ClassDB::bind_method(D_METHOD("set_physics_object_picking_sort", "enable"), &Viewport::set_physics_object_picking_sort);
ClassDB::bind_method(D_METHOD("get_physics_object_picking_sort"), &Viewport::get_physics_object_picking_sort);
ClassDB::bind_method(D_METHOD("set_physics_object_picking_first_only", "enable"), &Viewport::set_physics_object_picking_first_only);
ClassDB::bind_method(D_METHOD("get_physics_object_picking_first_only"), &Viewport::get_physics_object_picking_first_only);
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid);
ClassDB::bind_method(D_METHOD("push_text_input", "text"), &Viewport::push_text_input);
@ -4824,6 +4940,8 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("gui_cancel_drag"), &Viewport::gui_cancel_drag);
ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data);
ClassDB::bind_method(D_METHOD("gui_get_drag_description"), &Viewport::gui_get_drag_description);
ClassDB::bind_method(D_METHOD("gui_set_drag_description", "description"), &Viewport::gui_set_drag_description);
ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging);
ClassDB::bind_method(D_METHOD("gui_is_drag_successful"), &Viewport::gui_is_drag_successful);
@ -4885,7 +5003,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mesh_lod_threshold", "pixels"), &Viewport::set_mesh_lod_threshold);
ClassDB::bind_method(D_METHOD("get_mesh_lod_threshold"), &Viewport::get_mesh_lod_threshold);
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
ClassDB::bind_method(D_METHOD("_process_picking"), &Viewport::_process_picking);
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d);
@ -4976,10 +5096,12 @@ void Viewport::_bind_methods() {
#ifndef _3D_DISABLED
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
#endif // _3D_DISABLED
#if !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
ADD_GROUP("Physics", "physics_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking_sort"), "set_physics_object_picking_sort", "get_physics_object_picking_sort");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking_first_only"), "set_physics_object_picking_first_only", "get_physics_object_picking_first_only");
#endif // !defined(PHYSICS_2D_DISABLED) || !defined(PHYSICS_3D_DISABLED)
ADD_GROUP("GUI", "gui_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
@ -5223,7 +5345,10 @@ void SubViewport::set_size_2d_override(const Size2i &p_size) {
Size2i SubViewport::get_size_2d_override() const {
ERR_READ_THREAD_GUARD_V(Size2i());
return _get_size_2d_override();
// Rounding will cause offset issues with the
// exact positioning of subwindows, but changing the
// type of size_2d_override would break compatibility.
return Size2i((_get_size_2d_override() + Size2(0.5, 0.5)).floor());
}
void SubViewport::set_size_2d_override_stretch(bool p_enable) {