summaryrefslogtreecommitdiff
path: root/scene/main/viewport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main/viewport.cpp')
-rw-r--r--scene/main/viewport.cpp564
1 files changed, 318 insertions, 246 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 54b670df6c..f81b512b0c 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -37,6 +37,7 @@
#include "core/os/os.h"
#include "core/string/translation.h"
+#include "scene/2d/camera_2d.h"
#include "scene/2d/collision_object_2d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_object_3d.h"
@@ -131,7 +132,7 @@ bool ViewportTexture::has_alpha() const {
return false;
}
-Ref<Image> ViewportTexture::get_data() const {
+Ref<Image> ViewportTexture::get_image() const {
ERR_FAIL_COND_V_MSG(!vp, Ref<Image>(), "Viewport Texture must be set to use it.");
return RS::get_singleton()->texture_2d_get(vp->texture_rid);
}
@@ -183,22 +184,9 @@ public:
/////////////////////////////////////
-void Viewport::update_worlds() {
- if (!is_inside_tree()) {
- return;
- }
-
- Rect2 abstracted_rect = Rect2(Vector2(), get_visible_rect().size);
- Rect2 xformed_rect = (global_canvas_transform * canvas_transform).affine_inverse().xform(abstracted_rect);
- find_world_2d()->_update_viewport(this, xformed_rect);
- find_world_2d()->_update();
-
- find_world_3d()->_update(get_tree()->get_frame());
-}
-
void Viewport::_collision_object_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) {
- Transform object_transform = p_object->get_global_transform();
- Transform camera_transform = p_camera->get_global_transform();
+ Transform3D object_transform = p_object->get_global_transform();
+ Transform3D camera_transform = p_camera->get_global_transform();
ObjectID id = p_object->get_instance_id();
//avoid sending the fake event unnecessarily if nothing really changed in the context
@@ -208,7 +196,7 @@ void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera
return; //discarded
}
}
- p_object->_input_event(camera, p_input_event, p_pos, p_normal, p_shape);
+ p_object->_input_event(camera_3d, p_input_event, p_pos, p_normal, p_shape);
physics_last_object_transform = object_transform;
physics_last_camera_transform = camera_transform;
physics_last_id = id;
@@ -261,16 +249,16 @@ void Viewport::_sub_window_update(Window *p_window) {
Rect2i r = Rect2i(p_window->get_position(), sw.window->get_size());
if (!p_window->get_flag(Window::FLAG_BORDERLESS)) {
- Ref<StyleBox> panel = p_window->get_theme_stylebox("panel_window");
+ Ref<StyleBox> panel = p_window->get_theme_stylebox(SNAME("panel_window"));
panel->draw(sw.canvas_item, r);
// Draw the title bar text.
- Ref<Font> title_font = p_window->get_theme_font("title_font");
- int font_size = p_window->get_theme_font_size("title_font_size");
- Color title_color = p_window->get_theme_color("title_color");
- int title_height = p_window->get_theme_constant("title_height");
- int close_h_ofs = p_window->get_theme_constant("close_h_ofs");
- int close_v_ofs = p_window->get_theme_constant("close_v_ofs");
+ Ref<Font> title_font = p_window->get_theme_font(SNAME("title_font"));
+ int font_size = p_window->get_theme_font_size(SNAME("title_font_size"));
+ Color title_color = p_window->get_theme_color(SNAME("title_color"));
+ int title_height = p_window->get_theme_constant(SNAME("title_height"));
+ int close_h_ofs = p_window->get_theme_constant(SNAME("close_h_ofs"));
+ int close_v_ofs = p_window->get_theme_constant(SNAME("close_v_ofs"));
TextLine title_text = TextLine(p_window->get_title(), title_font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs);
@@ -278,8 +266,8 @@ void Viewport::_sub_window_update(Window *p_window) {
int x = (r.size.width - title_text.get_size().x) / 2;
int y = (-title_height - title_text.get_size().y) / 2;
- Color font_outline_color = p_window->get_theme_color("title_outline_modulate");
- int outline_size = p_window->get_theme_constant("title_outline_size");
+ Color font_outline_color = p_window->get_theme_color(SNAME("title_outline_modulate"));
+ int outline_size = p_window->get_theme_constant(SNAME("title_outline_size"));
if (outline_size > 0 && font_outline_color.a > 0) {
title_text.draw_outline(sw.canvas_item, r.position + Point2(x, y), outline_size, font_outline_color);
}
@@ -441,8 +429,6 @@ void Viewport::_notification(int p_what) {
_update_listener();
_update_listener_2d();
- find_world_2d()->_register_viewport(this, Rect2());
-
add_to_group("_viewports");
if (get_tree()->is_debugging_collisions_hint()) {
//2D
@@ -459,6 +445,7 @@ 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_VISIBLE_IN_ALL_ROOMS, true);
+ set_physics_process_internal(true);
}
} break;
@@ -477,7 +464,7 @@ void Viewport::_notification(int p_what) {
}
}
- if (cameras.size() && !camera) {
+ if (cameras.size() && !camera_3d) {
//there are cameras but no current camera, pick first in tree and make it current
Camera3D *first = nullptr;
for (Set<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
@@ -492,16 +479,9 @@ void Viewport::_notification(int p_what) {
}
#endif
- // Enable processing for tooltips, collision debugging, physics object picking, etc.
- set_process_internal(true);
- set_physics_process_internal(true);
-
} break;
case NOTIFICATION_EXIT_TREE: {
_gui_cancel_tooltip();
- if (world_2d.is_valid()) {
- world_2d->_remove_viewport(this);
- }
RenderingServer::get_singleton()->viewport_set_scenario(viewport, RID());
RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
@@ -518,6 +498,7 @@ void Viewport::_notification(int p_what) {
}
remove_from_group("_viewports");
+ set_physics_process_internal(false);
RS::get_singleton()->viewport_set_active(viewport, false);
RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, RID());
@@ -528,6 +509,7 @@ void Viewport::_notification(int p_what) {
gui.tooltip_timer -= get_process_delta_time();
if (gui.tooltip_timer < 0) {
_gui_show_tooltip();
+ set_process_internal(false);
}
}
@@ -553,7 +535,7 @@ void Viewport::_notification(int p_what) {
RS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count);
for (int i = 0; i < point_count; i++) {
- Transform point_transform;
+ Transform3D point_transform;
point_transform.origin = points[i];
RS::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh, i, point_transform);
}
@@ -612,15 +594,15 @@ void Viewport::_process_picking() {
if (!has_mouse_event) {
Ref<InputEventMouseMotion> mm;
- mm.instance();
+ mm.instantiate();
mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
mm->set_global_position(physics_last_mousepos);
mm->set_position(physics_last_mousepos);
- mm->set_alt(physics_last_mouse_state.alt);
- mm->set_shift(physics_last_mouse_state.shift);
- mm->set_control(physics_last_mouse_state.control);
- mm->set_metakey(physics_last_mouse_state.meta);
+ mm->set_alt_pressed(physics_last_mouse_state.alt);
+ mm->set_shift_pressed(physics_last_mouse_state.shift);
+ mm->set_ctrl_pressed(physics_last_mouse_state.control);
+ mm->set_meta_pressed(physics_last_mouse_state.meta);
mm->set_button_mask(physics_last_mouse_state.mouse_mask);
physics_picking_events.push_back(mm);
}
@@ -641,10 +623,10 @@ void Viewport::_process_picking() {
physics_has_last_mousepos = true;
physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mm->get_alt();
- physics_last_mouse_state.shift = mm->get_shift();
- physics_last_mouse_state.control = mm->get_control();
- physics_last_mouse_state.meta = mm->get_metakey();
+ physics_last_mouse_state.alt = mm->is_alt_pressed();
+ physics_last_mouse_state.shift = mm->is_shift_pressed();
+ physics_last_mouse_state.control = mm->is_ctrl_pressed();
+ physics_last_mouse_state.meta = mm->is_meta_pressed();
physics_last_mouse_state.mouse_mask = mm->get_button_mask();
}
@@ -656,15 +638,15 @@ void Viewport::_process_picking() {
physics_has_last_mousepos = true;
physics_last_mousepos = pos;
- physics_last_mouse_state.alt = mb->get_alt();
- physics_last_mouse_state.shift = mb->get_shift();
- physics_last_mouse_state.control = mb->get_control();
- physics_last_mouse_state.meta = mb->get_metakey();
+ physics_last_mouse_state.alt = mb->is_alt_pressed();
+ physics_last_mouse_state.shift = mb->is_shift_pressed();
+ physics_last_mouse_state.control = mb->is_ctrl_pressed();
+ physics_last_mouse_state.meta = mb->is_meta_pressed();
if (mb->is_pressed()) {
- physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1));
+ physics_last_mouse_state.mouse_mask |= (MouseButton)(1 << (mb->get_button_index() - 1));
} else {
- physics_last_mouse_state.mouse_mask &= ~(1 << (mb->get_button_index() - 1));
+ physics_last_mouse_state.mouse_mask &= (MouseButton) ~(1 << (mb->get_button_index() - 1));
// If touch mouse raised, assume we don't know last mouse pos until new events come
if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) {
@@ -676,10 +658,10 @@ void Viewport::_process_picking() {
Ref<InputEventKey> k = ev;
if (k.is_valid()) {
//only for mask
- physics_last_mouse_state.alt = k->get_alt();
- physics_last_mouse_state.shift = k->get_shift();
- physics_last_mouse_state.control = k->get_control();
- physics_last_mouse_state.meta = k->get_metakey();
+ physics_last_mouse_state.alt = k->is_alt_pressed();
+ physics_last_mouse_state.shift = k->is_shift_pressed();
+ physics_last_mouse_state.control = k->is_ctrl_pressed();
+ physics_last_mouse_state.meta = k->is_meta_pressed();
continue;
}
@@ -724,7 +706,6 @@ void Viewport::_process_picking() {
bool send_event = true;
if (is_mouse) {
Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
-
if (!F) {
physics_2d_mouseover.insert(res[i].collider_id, frame);
co->_mouse_enter();
@@ -735,6 +716,13 @@ void Viewport::_process_picking() {
send_event = false;
}
}
+ Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *SF = physics_2d_shape_mouseover.find(Pair(res[i].collider_id, res[i].shape));
+ if (!SF) {
+ physics_2d_shape_mouseover.insert(Pair(res[i].collider_id, res[i].shape), frame);
+ co->_mouse_shape_enter(res[i].shape);
+ } else {
+ SF->get() = frame;
+ }
}
if (send_event) {
@@ -746,25 +734,7 @@ void Viewport::_process_picking() {
}
if (is_mouse) {
- List<Map<ObjectID, uint64_t>::Element *> to_erase;
-
- for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
- if (E->get() != frame) {
- Object *o = ObjectDB::get_instance(E->key());
- if (o) {
- CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
- if (co) {
- co->_mouse_exit();
- }
- }
- to_erase.push_back(E);
- }
- }
-
- while (to_erase.size()) {
- physics_2d_mouseover.erase(to_erase.front()->get());
- to_erase.pop_front();
- }
+ _cleanup_mouseover_colliders(false, false, frame);
}
}
@@ -773,8 +743,8 @@ void Viewport::_process_picking() {
if (physics_object_capture.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture));
- if (co && camera) {
- _collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0);
+ if (co && camera_3d) {
+ _collision_object_input_event(co, camera_3d, ev, Vector3(), Vector3(), 0);
captured = true;
if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
physics_object_capture = ObjectID();
@@ -791,16 +761,16 @@ void Viewport::_process_picking() {
if (last_id.is_valid()) {
if (ObjectDB::get_instance(last_id) && last_object) {
//good, exists
- _collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape);
+ _collision_object_input_event(last_object, camera_3d, ev, result.position, result.normal, result.shape);
if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
physics_object_capture = last_id;
}
}
}
} else {
- if (camera) {
- Vector3 from = camera->project_ray_origin(pos);
- Vector3 dir = camera->project_ray_normal(pos);
+ if (camera_3d) {
+ Vector3 from = camera_3d->project_ray_origin(pos);
+ Vector3 dir = camera_3d->project_ray_normal(pos);
PhysicsDirectSpaceState3D *space = PhysicsServer3D::get_singleton()->space_get_direct_state(find_world_3d()->get_space());
if (space) {
@@ -808,8 +778,8 @@ void Viewport::_process_picking() {
ObjectID new_collider;
if (col) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider);
- if (co && co->can_process()) {
- _collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape);
+ if (co) {
+ _collision_object_input_event(co, camera_3d, ev, result.position, result.normal, result.shape);
last_object = co;
last_id = result.collider_id;
new_collider = last_id;
@@ -877,7 +847,7 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
update_canvas_items();
- emit_signal("size_changed");
+ emit_signal(SNAME("size_changed"));
}
Size2i Viewport::_get_size() const {
@@ -947,6 +917,15 @@ bool Viewport::is_audio_listener_2d() const {
return audio_listener_2d;
}
+void Viewport::set_disable_3d(bool p_disable) {
+ disable_3d = p_disable;
+ RenderingServer::get_singleton()->viewport_set_disable_3d(viewport, disable_3d);
+}
+
+bool Viewport::is_3d_disabled() const {
+ return disable_3d;
+}
+
void Viewport::enable_canvas_transform_override(bool p_enable) {
if (override_canvas_transform == p_enable) {
return;
@@ -1054,64 +1033,68 @@ void Viewport::_listener_make_next_current(Listener3D *p_exclude) {
}
} else {
// Attempt to reset listener to the camera position
- if (camera != nullptr) {
+ if (camera_3d != nullptr) {
_update_listener();
- _camera_transform_changed_notify();
+ _camera_3d_transform_changed_notify();
}
}
}
#endif
-void Viewport::_camera_transform_changed_notify() {
+void Viewport::_camera_3d_transform_changed_notify() {
#ifndef _3D_DISABLED
#endif
}
-void Viewport::_camera_set(Camera3D *p_camera) {
+void Viewport::_camera_3d_set(Camera3D *p_camera) {
#ifndef _3D_DISABLED
- if (camera == p_camera) {
+ if (camera_3d == p_camera) {
return;
}
- if (camera) {
- camera->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ if (camera_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
}
- camera = p_camera;
+ camera_3d = p_camera;
if (!camera_override) {
- if (camera) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
+ if (camera_3d) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
} else {
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
}
}
- if (camera) {
- camera->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
+ if (camera_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
}
_update_listener();
- _camera_transform_changed_notify();
+ _camera_3d_transform_changed_notify();
#endif
}
-bool Viewport::_camera_add(Camera3D *p_camera) {
+void Viewport::_camera_2d_set(Camera2D *p_camera_2d) {
+ camera_2d = p_camera_2d;
+}
+
+bool Viewport::_camera_3d_add(Camera3D *p_camera) {
cameras.insert(p_camera);
return cameras.size() == 1;
}
-void Viewport::_camera_remove(Camera3D *p_camera) {
+void Viewport::_camera_3d_remove(Camera3D *p_camera) {
cameras.erase(p_camera);
- if (camera == p_camera) {
- camera->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
- camera = nullptr;
+ if (camera_3d == p_camera) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ camera_3d = nullptr;
}
}
#ifndef _3D_DISABLED
-void Viewport::_camera_make_next_current(Camera3D *p_exclude) {
+void Viewport::_camera_3d_make_next_current(Camera3D *p_exclude) {
for (Set<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
if (p_exclude == E->get()) {
continue;
@@ -1119,7 +1102,7 @@ void Viewport::_camera_make_next_current(Camera3D *p_exclude) {
if (!E->get()->is_inside_tree()) {
continue;
}
- if (camera != nullptr) {
+ if (camera_3d != nullptr) {
return;
}
@@ -1156,14 +1139,13 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
}
if (is_inside_tree()) {
- find_world_2d()->_remove_viewport(this);
RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
}
if (p_world_2d.is_valid()) {
world_2d = p_world_2d;
} else {
- WARN_PRINT("Invalid world_3d");
+ WARN_PRINT("Invalid world_2d");
world_2d = Ref<World2D>(memnew(World2D));
}
@@ -1172,7 +1154,6 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
if (is_inside_tree()) {
current_canvas = find_world_2d()->get_canvas();
RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
- find_world_2d()->_register_viewport(this, Rect2());
}
}
@@ -1310,8 +1291,12 @@ Listener3D *Viewport::get_listener() const {
return listener;
}
-Camera3D *Viewport::get_camera() const {
- return camera;
+Camera3D *Viewport::get_camera_3d() const {
+ return camera_3d;
+}
+
+Camera2D *Viewport::get_camera_2d() const {
+ return camera_2d;
}
void Viewport::enable_camera_override(bool p_enable) {
@@ -1329,8 +1314,8 @@ void Viewport::enable_camera_override(bool p_enable) {
if (p_enable) {
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid);
- } else if (camera) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
+ } else if (camera_3d) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
} else {
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
}
@@ -1341,19 +1326,19 @@ bool Viewport::is_camera_override_enabled() const {
return camera_override;
}
-void Viewport::set_camera_override_transform(const Transform &p_transform) {
+void Viewport::set_camera_override_transform(const Transform3D &p_transform) {
if (camera_override) {
camera_override.transform = p_transform;
RenderingServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform);
}
}
-Transform Viewport::get_camera_override_transform() const {
+Transform3D Viewport::get_camera_override_transform() const {
if (camera_override) {
return camera_override.transform;
}
- return Transform();
+ return Transform3D();
}
void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -1412,6 +1397,16 @@ void Viewport::_update_canvas_items(Node *p_node) {
}
}
+void Viewport::set_use_xr(bool p_use_xr) {
+ use_xr = p_use_xr;
+
+ RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
+}
+
+bool Viewport::is_using_xr() {
+ return use_xr;
+}
+
Ref<ViewportTexture> Viewport::get_texture() const {
return default_texture;
}
@@ -1495,6 +1490,7 @@ void Viewport::_gui_sort_roots() {
void Viewport::_gui_cancel_tooltip() {
gui.tooltip_control = nullptr;
gui.tooltip_timer = -1;
+ set_process_internal(false);
if (gui.tooltip_popup) {
gui.tooltip_popup->queue_delete();
gui.tooltip_popup = nullptr;
@@ -1563,6 +1559,9 @@ void Viewport::_gui_show_tooltip() {
return;
}
+ // Popup window which houses the tooltip content.
+ TooltipPanel *panel = memnew(TooltipPanel);
+
// Controls can implement `make_custom_tooltip` to provide their own tooltip.
// This should be a Control node which will be added as child to a TooltipPanel.
Control *base_tooltip = tooltip_owner->make_custom_tooltip(tooltip_text);
@@ -1572,11 +1571,11 @@ void Viewport::_gui_show_tooltip() {
gui.tooltip_label = memnew(TooltipLabel);
gui.tooltip_label->set_text(tooltip_text);
base_tooltip = gui.tooltip_label;
+ panel->connect("mouse_entered", callable_mp(this, &Viewport::_gui_cancel_tooltip));
}
base_tooltip->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
- TooltipPanel *panel = memnew(TooltipPanel);
panel->set_transient(false);
panel->set_flag(Window::FLAG_NO_FOCUS, true);
panel->set_wrap_controls(true);
@@ -1621,10 +1620,10 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
Ref<InputEventMouseButton> mb = p_input;
bool cant_stop_me_now = (mb.is_valid() &&
- (mb->get_button_index() == BUTTON_WHEEL_DOWN ||
- mb->get_button_index() == BUTTON_WHEEL_UP ||
- mb->get_button_index() == BUTTON_WHEEL_LEFT ||
- mb->get_button_index() == BUTTON_WHEEL_RIGHT));
+ (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN ||
+ mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP ||
+ mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT ||
+ mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT));
Ref<InputEventPanGesture> pn = p_input;
cant_stop_me_now = pn.is_valid() || cant_stop_me_now;
@@ -1711,7 +1710,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) {
//_unblock();
}
-Control *Viewport::_gui_find_control(const Point2 &p_global) {
+Control *Viewport::gui_find_control(const Point2 &p_global) {
//aca va subwindows
_gui_sort_roots();
@@ -1756,7 +1755,7 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
Control *c = Object::cast_to<Control>(p_node);
- if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) {
+ if (!c || !c->is_clipping_contents() || c->has_point(matrix.affine_inverse().xform(p_global))) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i));
if (!ci || ci->is_set_as_top_level()) {
@@ -1770,19 +1769,22 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
}
}
- if (!c) {
+ if (!c || c->data.mouse_filter == Control::MOUSE_FILTER_IGNORE) {
return nullptr;
}
matrix.affine_invert();
+ if (!c->has_point(matrix.xform(p_global))) {
+ return nullptr;
+ }
- //conditions for considering this as a valid control for return
- if (c->data.mouse_filter != Control::MOUSE_FILTER_IGNORE && c->has_point(matrix.xform(p_global)) && (!gui.drag_preview || (c != gui.drag_preview && !gui.drag_preview->is_a_parent_of(c)))) {
+ Control *drag_preview = _gui_get_drag_preview();
+ if (!drag_preview || (c != drag_preview && !drag_preview->is_ancestor_of(c))) {
r_inv_xform = matrix;
return c;
- } else {
- return nullptr;
}
+
+ return nullptr;
}
bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check) {
@@ -1827,6 +1829,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *over = nullptr;
Point2 mpos = mb->get_position();
+ gui.last_mouse_pos = mpos;
if (mb->is_pressed()) {
Size2 pos = mpos;
if (gui.mouse_focus_mask) {
@@ -1847,7 +1850,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
parent_xform=data.parent_canvas_item->get_global_transform();
*/
- gui.mouse_focus = _gui_find_control(pos);
+ gui.mouse_focus = gui_find_control(pos);
gui.last_mouse_focus = gui.mouse_focus;
if (!gui.mouse_focus) {
@@ -1857,7 +1860,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1);
- if (mb->get_button_index() == BUTTON_LEFT) {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
gui.drag_accum = Vector2();
gui.drag_attempted = false;
}
@@ -1880,7 +1883,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
#endif
- if (mb->get_button_index() == BUTTON_LEFT) { //assign focus
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { //assign focus
CanvasItem *ci = gui.mouse_focus;
while (ci) {
Control *control = Object::cast_to<Control>(ci);
@@ -1911,7 +1914,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
set_input_as_handled();
- if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
+ if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
//alternate drop use (when using force_drag(), as proposed by #5342
if (gui.mouse_focus) {
_gui_drop(gui.mouse_focus, pos, false);
@@ -1920,9 +1923,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.drag_data = Variant();
gui.dragging = false;
- if (gui.drag_preview) {
- memdelete(gui.drag_preview);
- gui.drag_preview = nullptr;
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ memdelete(drag_preview);
+ gui.drag_preview_id = ObjectID();
}
_propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
//change mouse accordingly
@@ -1930,14 +1934,15 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
_gui_cancel_tooltip();
} else {
- if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
+ if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (gui.drag_mouse_over) {
_gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false);
}
- if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) {
- memdelete(gui.drag_preview);
- gui.drag_preview = nullptr;
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ memdelete(drag_preview);
+ gui.drag_preview_id = ObjectID();
}
gui.drag_data = Variant();
@@ -1973,7 +1978,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
_gui_call_input(mouse_focus, mb);
}
- /*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==BUTTON_LEFT) {
+ /*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==MOUSE_BUTTON_LEFT) {
_propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
gui.drag_data=Variant(); //always clear
}*/
@@ -1986,7 +1991,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
- over = _gui_find_control(mpos);
+ over = gui_find_control(mpos);
}
if (gui.mouse_focus_mask == 0 && over != gui.mouse_over) {
@@ -2017,7 +2022,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *over = nullptr;
// D&D
- if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
gui.drag_accum += mm->get_relative();
float len = gui.drag_accum.length();
if (len > 10) {
@@ -2034,10 +2039,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.mouse_focus_mask = 0;
break;
} else {
- if (gui.drag_preview != nullptr) {
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored.");
- memdelete(gui.drag_preview);
- gui.drag_preview = nullptr;
+ memdelete(drag_preview);
+ gui.drag_preview_id = ObjectID();
}
gui.dragging = false;
}
@@ -2068,7 +2074,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
- over = _gui_find_control(mpos);
+ over = gui_find_control(mpos);
}
if (over != gui.mouse_over) {
@@ -2136,6 +2142,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.tooltip_control = over;
gui.tooltip_pos = over->get_screen_transform().xform(pos);
gui.tooltip_timer = gui.tooltip_delay;
+ set_process_internal(true);
}
}
@@ -2177,8 +2184,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.drag_data.get_type() != Variant::NIL) {
//handle dragandrop
- if (gui.drag_preview) {
- gui.drag_preview->set_position(mpos);
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ drag_preview->set_position(mpos);
}
gui.drag_mouse_over = over;
@@ -2194,7 +2202,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
embedder = this;
viewport_pos = mpos;
} else {
- //not an embeder, but may be a subwindow of an embedder
+ //not an embedder, but may be a subwindow of an embedder
Window *w = Object::cast_to<Window>(this);
if (w) {
if (w->is_embedded()) {
@@ -2216,7 +2224,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Window *sw = embedder->gui.sub_windows[i].window;
Rect2 swrect = Rect2i(sw->get_position(), sw->get_size());
if (!sw->get_flag(Window::FLAG_BORDERLESS)) {
- int title_height = sw->get_theme_constant("title_height");
+ int title_height = sw->get_theme_constant(SNAME("title_height"));
swrect.position.y -= title_height;
swrect.size.y += title_height;
}
@@ -2254,12 +2262,12 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Transform2D ai = (viewport_under->get_final_transform().affine_inverse() * viewport_under->_get_input_pre_xform());
viewport_pos = ai.xform(viewport_pos);
//find control under at pos
- gui.drag_mouse_over = viewport_under->_gui_find_control(viewport_pos);
+ gui.drag_mouse_over = viewport_under->gui_find_control(viewport_pos);
if (gui.drag_mouse_over) {
Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse();
gui.drag_mouse_over_pos = localizer.xform(viewport_pos);
- if (mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) {
bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true);
if (!can_drop) {
@@ -2282,7 +2290,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (touch_event.is_valid()) {
Size2 pos = touch_event->get_position();
if (touch_event->is_pressed()) {
- Control *over = _gui_find_control(pos);
+ Control *over = gui_find_control(pos);
if (over) {
if (over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); //make a copy
@@ -2317,7 +2325,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Size2 pos = gesture_event->get_position();
- Control *over = _gui_find_control(pos);
+ Control *over = gui_find_control(pos);
if (over) {
if (over->can_process()) {
gesture_event = gesture_event->xformed_by(Transform2D()); //make a copy
@@ -2338,7 +2346,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (drag_event.is_valid()) {
Control *over = gui.mouse_focus;
if (!over) {
- over = _gui_find_control(drag_event->get_position());
+ over = gui_find_control(drag_event->get_position());
}
if (over) {
if (over->can_process()) {
@@ -2384,37 +2392,35 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *from = gui.key_focus ? gui.key_focus : nullptr; //hmm
//keyboard focus
- //if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
+ //if (from && p_event->is_pressed() && !p_event->is_alt_pressed() && !p_event->is_meta_pressed() && !p_event->key->is_command_pressed()) {
Ref<InputEventKey> k = p_event;
- //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be.
- bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey());
+ //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be.
+ bool mods = k.is_valid() && (k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_shift_pressed() || k->is_meta_pressed());
if (from && p_event->is_pressed()) {
Control *next = nullptr;
- Input *input = Input::get_singleton();
-
- if (p_event->is_action_pressed("ui_focus_next") && input->is_action_just_pressed("ui_focus_next")) {
+ if (p_event->is_action_pressed("ui_focus_next", true)) {
next = from->find_next_valid_focus();
}
- if (p_event->is_action_pressed("ui_focus_prev") && input->is_action_just_pressed("ui_focus_prev")) {
+ if (p_event->is_action_pressed("ui_focus_prev", true)) {
next = from->find_prev_valid_focus();
}
- if (!mods && p_event->is_action_pressed("ui_up") && input->is_action_just_pressed("ui_up")) {
+ if (!mods && p_event->is_action_pressed("ui_up", true)) {
next = from->_get_focus_neighbor(SIDE_TOP);
}
- if (!mods && p_event->is_action_pressed("ui_left") && input->is_action_just_pressed("ui_left")) {
+ if (!mods && p_event->is_action_pressed("ui_left", true)) {
next = from->_get_focus_neighbor(SIDE_LEFT);
}
- if (!mods && p_event->is_action_pressed("ui_right") && input->is_action_just_pressed("ui_right")) {
+ if (!mods && p_event->is_action_pressed("ui_right", true)) {
next = from->_get_focus_neighbor(SIDE_RIGHT);
}
- if (!mods && p_event->is_action_pressed("ui_down") && input->is_action_just_pressed("ui_down")) {
+ if (!mods && p_event->is_action_pressed("ui_down", true)) {
next = from->_get_focus_neighbor(SIDE_BOTTOM);
}
@@ -2453,15 +2459,29 @@ void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
ERR_FAIL_COND(p_control->is_inside_tree());
ERR_FAIL_COND(p_control->get_parent() != nullptr);
- if (gui.drag_preview) {
- memdelete(gui.drag_preview);
+ Control *drag_preview = _gui_get_drag_preview();
+ if (drag_preview) {
+ memdelete(drag_preview);
}
p_control->set_as_top_level(true);
p_control->set_position(gui.last_mouse_pos);
p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport
p_control->raise();
- gui.drag_preview = p_control;
+ gui.drag_preview_id = p_control->get_instance_id();
+}
+
+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));
+ if (!drag_preview) {
+ ERR_PRINT("Don't free the control set as drag preview.");
+ gui.drag_preview_id = ObjectID();
+ }
+ return drag_preview;
+ }
}
void Viewport::_gui_remove_root_control(List<Control *>::Element *RI) {
@@ -2517,6 +2537,8 @@ void Viewport::_gui_remove_control(Control *p_control) {
}
Window *Viewport::get_base_window() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), nullptr);
+
Viewport *v = const_cast<Viewport *>(this);
Window *w = Object::cast_to<Window>(v);
while (!w) {
@@ -2551,7 +2573,7 @@ void Viewport::_gui_control_grab_focus(Control *p_control) {
}
get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus_for_window", (Node *)get_base_window());
gui.key_focus = p_control;
- emit_signal("gui_focus_changed", p_control);
+ emit_signal(SNAME("gui_focus_changed"), p_control);
p_control->notification(Control::NOTIFICATION_FOCUS_ENTER);
p_control->update();
}
@@ -2573,10 +2595,10 @@ void Viewport::_drop_mouse_focus() {
for (int i = 0; i < 3; i++) {
if (mask & (1 << i)) {
Ref<InputEventMouseButton> mb;
- mb.instance();
+ mb.instantiate();
mb->set_position(c->get_local_mouse_position());
mb->set_global_position(c->get_local_mouse_position());
- mb->set_button_index(i + 1);
+ mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(false);
c->call(SceneStringNames::get_singleton()->_gui_input, mb);
}
@@ -2586,20 +2608,41 @@ void Viewport::_drop_mouse_focus() {
void Viewport::_drop_physics_mouseover(bool p_paused_only) {
physics_has_last_mousepos = false;
+ _cleanup_mouseover_colliders(true, p_paused_only);
+
+#ifndef _3D_DISABLED
+ if (physics_object_over.is_valid()) {
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
+ if (co) {
+ if (!(p_paused_only && co->can_process())) {
+ co->_mouse_exit();
+ physics_object_over = ObjectID();
+ physics_object_capture = ObjectID();
+ }
+ }
+ }
+#endif
+}
+
+void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference) {
List<Map<ObjectID, uint64_t>::Element *> to_erase;
for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
+ if (!p_clean_all_frames && E->get() == p_frame_reference) {
+ continue;
+ }
+
Object *o = ObjectDB::get_instance(E->key());
if (o) {
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
if (co) {
- if (p_paused_only && co->can_process()) {
+ if (p_clean_all_frames && p_paused_only && co->can_process()) {
continue;
}
co->_mouse_exit();
- to_erase.push_back(E);
}
}
+ to_erase.push_back(E);
}
while (to_erase.size()) {
@@ -2607,18 +2650,31 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
to_erase.pop_front();
}
-#ifndef _3D_DISABLED
- if (physics_object_over.is_valid()) {
- CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
- if (co) {
- if (!(p_paused_only && co->can_process())) {
- co->_mouse_exit();
- physics_object_over = ObjectID();
- physics_object_capture = ObjectID();
+ // Per-shape
+ List<Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *> shapes_to_erase;
+
+ for (Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *E = physics_2d_shape_mouseover.front(); E; E = E->next()) {
+ if (!p_clean_all_frames && E->get() == p_frame_reference) {
+ continue;
+ }
+
+ Object *o = ObjectDB::get_instance(E->key().first);
+ if (o) {
+ CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
+ if (co) {
+ if (p_clean_all_frames && p_paused_only && co->can_process()) {
+ continue;
+ }
+ co->_mouse_shape_exit(E->key().second);
}
}
+ shapes_to_erase.push_back(E);
+ }
+
+ while (shapes_to_erase.size()) {
+ physics_2d_shape_mouseover.erase(shapes_to_erase.front()->get());
+ shapes_to_erase.pop_front();
}
-#endif
}
Control *Viewport::_gui_get_focus_owner() {
@@ -2627,7 +2683,7 @@ Control *Viewport::_gui_get_focus_owner() {
void Viewport::_gui_grab_click_focus(Control *p_control) {
gui.mouse_click_grabber = p_control;
- call_deferred("_post_gui_grab_click_focus");
+ call_deferred(SNAME("_post_gui_grab_click_focus"));
}
void Viewport::_post_gui_grab_click_focus() {
@@ -2649,12 +2705,12 @@ void Viewport::_post_gui_grab_click_focus() {
for (int i = 0; i < 3; i++) {
if (mask & (1 << i)) {
Ref<InputEventMouseButton> mb;
- mb.instance();
+ mb.instantiate();
- //send unclic
+ //send unclick
mb->set_position(click);
- mb->set_button_index(i + 1);
+ mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(false);
gui.mouse_focus->call(SceneStringNames::get_singleton()->_gui_input, mb);
}
@@ -2667,12 +2723,12 @@ void Viewport::_post_gui_grab_click_focus() {
for (int i = 0; i < 3; i++) {
if (mask & (1 << i)) {
Ref<InputEventMouseButton> mb;
- mb.instance();
+ mb.instantiate();
- //send clic
+ //send click
mb->set_position(click);
- mb->set_button_index(i + 1);
+ mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(true);
gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb);
}
@@ -2700,7 +2756,7 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw
Rect2i r = Rect2i(p_subwindow->get_position(), p_subwindow->get_size());
- int title_height = p_subwindow->get_theme_constant("title_height");
+ int title_height = p_subwindow->get_theme_constant(SNAME("title_height"));
r.position.y -= title_height;
r.size.y += title_height;
@@ -2712,7 +2768,7 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw
int dist_x = p_point.x < r.position.x ? (p_point.x - r.position.x) : (p_point.x > (r.position.x + r.size.x) ? (p_point.x - (r.position.x + r.size.x)) : 0);
int dist_y = p_point.y < r.position.y ? (p_point.y - r.position.y) : (p_point.y > (r.position.y + r.size.y) ? (p_point.y - (r.position.y + r.size.y)) : 0);
- int limit = p_subwindow->get_theme_constant("resize_margin");
+ int limit = p_subwindow->get_theme_constant(SNAME("resize_margin"));
if (ABS(dist_x) > limit) {
return SUB_WINDOW_RESIZE_DISABLED;
@@ -2762,7 +2818,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_V(gui.subwindow_focused == nullptr, false);
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) {
if (gui.subwindow_drag_close_rect.has_point(mb->get_position())) {
//close window
@@ -2794,7 +2850,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
new_rect.position.x = 0;
}
- int title_height = gui.subwindow_focused->get_flag(Window::FLAG_BORDERLESS) ? 0 : gui.subwindow_focused->get_theme_constant("title_height");
+ int title_height = gui.subwindow_focused->get_flag(Window::FLAG_BORDERLESS) ? 0 : gui.subwindow_focused->get_theme_constant(SNAME("title_height"));
if (new_rect.position.y < title_height) {
new_rect.position.y = title_height;
@@ -2887,7 +2943,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
//if the event is a mouse button, we need to check whether another window was clicked
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
bool click_on_window = false;
for (int i = gui.sub_windows.size() - 1; i >= 0; i--) {
SubWindow &sw = gui.sub_windows.write[i];
@@ -2898,7 +2954,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
if (!sw.window->get_flag(Window::FLAG_BORDERLESS)) {
//check top bar
- int title_height = sw.window->get_theme_constant("title_height");
+ int title_height = sw.window->get_theme_constant(SNAME("title_height"));
Rect2i title_bar = r;
title_bar.position.y -= title_height;
title_bar.size.y = title_height;
@@ -2906,9 +2962,9 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
if (title_bar.has_point(mb->get_position())) {
click_on_window = true;
- int close_h_ofs = sw.window->get_theme_constant("close_h_ofs");
- int close_v_ofs = sw.window->get_theme_constant("close_v_ofs");
- Ref<Texture2D> close_icon = sw.window->get_theme_icon("close");
+ int close_h_ofs = sw.window->get_theme_constant(SNAME("close_h_ofs"));
+ int close_v_ofs = sw.window->get_theme_constant(SNAME("close_v_ofs"));
+ Ref<Texture2D> close_icon = sw.window->get_theme_icon(SNAME("close"));
Rect2 close_rect;
close_rect.position = Vector2(r.position.x + r.size.x - close_v_ofs, r.position.y - close_h_ofs);
@@ -3011,7 +3067,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
return;
}
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this)) {
return;
}
@@ -3046,13 +3102,14 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
}
void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
+ ERR_FAIL_COND(p_event.is_null());
ERR_FAIL_COND(!is_inside_tree());
if (disable_input || !_can_consume_input_events()) {
return;
}
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this)) {
return;
}
@@ -3125,8 +3182,13 @@ bool Viewport::is_using_own_world_3d() const {
void Viewport::set_physics_object_picking(bool p_enable) {
physics_object_picking = p_enable;
- if (!physics_object_picking) {
+ if (physics_object_picking) {
+ add_to_group("_picking_viewports");
+ } else {
physics_picking_events.clear();
+ if (is_in_group("_picking_viewports")) {
+ remove_from_group("_picking_viewports");
+ }
}
}
@@ -3155,20 +3217,17 @@ Variant Viewport::gui_get_drag_data() const {
return gui.drag_data;
}
-String Viewport::get_configuration_warning() const {
+TypedArray<String> Viewport::get_configuration_warnings() const {
/*if (get_parent() && !Object::cast_to<Control>(get_parent()) && !render_target) {
return TTR("This viewport is not set as render target. If you intend for it to display its contents directly to the screen, make it a child of a Control so it can obtain a size. Otherwise, make it a RenderTarget and assign its internal texture to some node for display.");
}*/
- String warning = Node::get_configuration_warning();
+ TypedArray<String> warnings = Node::get_configuration_warnings();
if (size.x == 0 || size.y == 0) {
- if (!warning.is_empty()) {
- warning += "\n\n";
- }
- warning += TTR("Viewport size must be greater than 0 to render anything.");
+ warnings.push_back(TTR("Viewport size must be greater than 0 to render anything."));
}
- return warning;
+ return warnings;
}
void Viewport::gui_reset_canvas_sort_index() {
@@ -3206,8 +3265,9 @@ Viewport::ScreenSpaceAA Viewport::get_screen_space_aa() const {
}
void Viewport::set_use_debanding(bool p_use_debanding) {
- if (use_debanding == p_use_debanding)
+ if (use_debanding == p_use_debanding) {
return;
+ }
use_debanding = p_use_debanding;
RS::get_singleton()->viewport_set_use_debanding(viewport, p_use_debanding);
}
@@ -3224,6 +3284,21 @@ float Viewport::get_lod_threshold() const {
return lod_threshold;
}
+void Viewport::set_use_occlusion_culling(bool p_use_occlusion_culling) {
+ if (use_occlusion_culling == p_use_occlusion_culling) {
+ return;
+ }
+
+ use_occlusion_culling = p_use_occlusion_culling;
+ RS::get_singleton()->viewport_set_use_occlusion_culling(viewport, p_use_occlusion_culling);
+
+ notify_property_list_changed();
+}
+
+bool Viewport::is_using_occlusion_culling() const {
+ return use_occlusion_culling;
+}
+
void Viewport::set_debug_draw(DebugDraw p_debug_draw) {
debug_draw = p_debug_draw;
RS::get_singleton()->viewport_set_debug_draw(viewport, RS::ViewportDebugDraw(p_debug_draw));
@@ -3233,8 +3308,8 @@ Viewport::DebugDraw Viewport::get_debug_draw() const {
return debug_draw;
}
-int Viewport::get_render_info(RenderInfo p_info) {
- return RS::get_singleton()->viewport_get_render_info(viewport, RS::ViewportRenderInfo(p_info));
+int Viewport::get_render_info(RenderInfoType p_type, RenderInfo p_info) {
+ return RS::get_singleton()->viewport_get_render_info(viewport, RS::ViewportRenderInfoType(p_type), RS::ViewportRenderInfo(p_info));
}
void Viewport::set_snap_controls_to_pixels(bool p_enable) {
@@ -3292,6 +3367,7 @@ bool Viewport::is_input_handled() const {
return local_input_handled;
} else {
const Viewport *vp = this;
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
while (true) {
if (Object::cast_to<Window>(vp)) {
break;
@@ -3313,9 +3389,6 @@ bool Viewport::is_handling_input_locally() const {
return handle_input_locally;
}
-void Viewport::_validate_property(PropertyInfo &property) const {
-}
-
void Viewport::set_default_canvas_item_texture_filter(DefaultCanvasItemTextureFilter p_filter) {
ERR_FAIL_INDEX(p_filter, DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX);
@@ -3460,10 +3533,16 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_debanding", "enable"), &Viewport::set_use_debanding);
ClassDB::bind_method(D_METHOD("is_using_debanding"), &Viewport::is_using_debanding);
+ ClassDB::bind_method(D_METHOD("set_use_occlusion_culling", "enable"), &Viewport::set_use_occlusion_culling);
+ ClassDB::bind_method(D_METHOD("is_using_occlusion_culling"), &Viewport::is_using_occlusion_culling);
+
ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw);
ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw);
- ClassDB::bind_method(D_METHOD("get_render_info", "info"), &Viewport::get_render_info);
+ ClassDB::bind_method(D_METHOD("get_render_info", "type", "info"), &Viewport::get_render_info);
+
+ ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr);
+ ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
ClassDB::bind_method(D_METHOD("get_texture"), &Viewport::get_texture);
@@ -3475,12 +3554,11 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("input", "event", "in_local_coords"), &Viewport::input, DEFVAL(false));
ClassDB::bind_method(D_METHOD("unhandled_input", "event", "in_local_coords"), &Viewport::unhandled_input, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("update_worlds"), &Viewport::update_worlds);
-
ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &Viewport::set_use_own_world_3d);
ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &Viewport::is_using_own_world_3d);
- ClassDB::bind_method(D_METHOD("get_camera"), &Viewport::get_camera);
+ ClassDB::bind_method(D_METHOD("get_camera_3d"), &Viewport::get_camera_3d);
+ ClassDB::bind_method(D_METHOD("get_camera_2d"), &Viewport::get_camera_2d);
ClassDB::bind_method(D_METHOD("set_as_audio_listener", "enable"), &Viewport::set_as_audio_listener);
ClassDB::bind_method(D_METHOD("is_audio_listener"), &Viewport::is_audio_listener);
@@ -3488,6 +3566,9 @@ void Viewport::_bind_methods() {
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);
+ ClassDB::bind_method(D_METHOD("set_disable_3d", "disable"), &Viewport::set_disable_3d);
+ ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
+
ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position);
ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse);
@@ -3545,21 +3626,24 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_process_picking"), &Viewport::_process_picking);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", PROPERTY_USAGE_NONE), "set_world_2d", "get_world_2d");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transparent_bg"), "set_transparent_background", "has_transparent_background");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");
ADD_GROUP("Rendering", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled,FXAA"), "set_screen_space_aa", "get_screen_space_aa");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"), "set_msaa", "get_msaa");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), "set_screen_space_aa", "get_screen_space_aa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
ADD_GROUP("Canvas Items", "canvas_item_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
ADD_GROUP("Audio Listener", "audio_listener_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
@@ -3580,8 +3664,8 @@ void Viewport::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 1);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 2);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 3);
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_canvas_transform", "get_canvas_transform");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_global_canvas_transform", "get_global_canvas_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_canvas_transform", "get_canvas_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_canvas_transform", "get_global_canvas_transform");
ADD_SIGNAL(MethodInfo("size_changed"));
ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
@@ -3607,22 +3691,23 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(SCREEN_SPACE_AA_MAX);
BIND_ENUM_CONSTANT(RENDER_INFO_OBJECTS_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_VERTICES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_SHADER_CHANGES_IN_FRAME);
- BIND_ENUM_CONSTANT(RENDER_INFO_SURFACE_CHANGES_IN_FRAME);
+ BIND_ENUM_CONSTANT(RENDER_INFO_PRIMITIVES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_DRAW_CALLS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_INFO_MAX);
+ BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_VISIBLE);
+ BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_SHADOW);
+ BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_MAX);
+
BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLED);
BIND_ENUM_CONSTANT(DEBUG_DRAW_UNSHADED);
BIND_ENUM_CONSTANT(DEBUG_DRAW_LIGHTING);
BIND_ENUM_CONSTANT(DEBUG_DRAW_OVERDRAW);
BIND_ENUM_CONSTANT(DEBUG_DRAW_WIREFRAME);
BIND_ENUM_CONSTANT(DEBUG_DRAW_NORMAL_BUFFER);
- BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_ALBEDO);
- BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_LIGHTING);
- BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_EMISSION);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_ALBEDO);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_LIGHTING);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_EMISSION);
BIND_ENUM_CONSTANT(DEBUG_DRAW_SHADOW_ATLAS);
BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE);
@@ -3637,6 +3722,7 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(DEBUG_DRAW_CLUSTER_SPOT_LIGHTS);
BIND_ENUM_CONSTANT(DEBUG_DRAW_CLUSTER_DECALS);
BIND_ENUM_CONSTANT(DEBUG_DRAW_CLUSTER_REFLECTION_PROBES);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_OCCLUDERS)
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
@@ -3667,7 +3753,7 @@ Viewport::Viewport() {
viewport = RenderingServer::get_singleton()->viewport_create();
texture_rid = RenderingServer::get_singleton()->viewport_get_texture(viewport);
- default_texture.instance();
+ default_texture.instantiate();
default_texture->vp = const_cast<Viewport *>(this);
viewport_textures.insert(default_texture.ptr());
default_texture->proxy = RS::get_singleton()->texture_proxy_create(texture_rid);
@@ -3711,16 +3797,6 @@ Viewport::~Viewport() {
/////////////////////////////////
-void SubViewport::set_use_xr(bool p_use_xr) {
- xr = p_use_xr;
-
- RS::get_singleton()->viewport_set_use_xr(get_viewport_rid(), xr);
-}
-
-bool SubViewport::is_using_xr() {
- return xr;
-}
-
void SubViewport::set_size(const Size2i &p_size) {
_set_size(p_size, _get_size_2d_override(), Rect2i(), _stretch_transform(), true);
}
@@ -3793,9 +3869,6 @@ void SubViewport::_notification(int p_what) {
}
void SubViewport::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &SubViewport::set_use_xr);
- ClassDB::bind_method(D_METHOD("is_using_xr"), &SubViewport::is_using_xr);
-
ClassDB::bind_method(D_METHOD("set_size", "size"), &SubViewport::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &SubViewport::get_size);
@@ -3811,7 +3884,6 @@ void SubViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &SubViewport::set_clear_mode);
ClassDB::bind_method(D_METHOD("get_clear_mode"), &SubViewport::get_clear_mode);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "xr"), "set_use_xr", "is_using_xr");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size_2d_override"), "set_size_2d_override", "get_size_2d_override");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "size_2d_override_stretch"), "set_size_2d_override_stretch", "is_size_2d_override_stretch_enabled");