summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/canvas_item.cpp284
-rw-r--r--scene/main/canvas_item.h126
-rw-r--r--scene/main/canvas_layer.h1
-rw-r--r--scene/main/http_request.cpp2
-rw-r--r--scene/main/http_request.h6
-rw-r--r--scene/main/node.cpp108
-rw-r--r--scene/main/node.h26
-rw-r--r--scene/main/scene_tree.cpp38
-rw-r--r--scene/main/scene_tree.h8
-rw-r--r--scene/main/shader_globals_override.cpp3
-rw-r--r--scene/main/shader_globals_override.h2
-rw-r--r--scene/main/timer.cpp2
-rw-r--r--scene/main/viewport.cpp997
-rw-r--r--scene/main/viewport.h181
-rw-r--r--scene/main/window.cpp10
-rw-r--r--scene/main/window.h6
16 files changed, 710 insertions, 1090 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 0a76351885..f329332725 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -30,289 +30,17 @@
#include "canvas_item.h"
-#include "core/input/input.h"
#include "core/object/message_queue.h"
#include "scene/2d/canvas_group.h"
#include "scene/main/canvas_layer.h"
-#include "scene/main/viewport.h"
#include "scene/main/window.h"
+#include "scene/resources/canvas_item_material.h"
#include "scene/resources/font.h"
+#include "scene/resources/multimesh.h"
#include "scene/resources/style_box.h"
-#include "scene/resources/texture.h"
+#include "scene/resources/world_2d.h"
#include "scene/scene_string_names.h"
-#include "servers/rendering_server.h"
-Mutex CanvasItemMaterial::material_mutex;
-SelfList<CanvasItemMaterial>::List *CanvasItemMaterial::dirty_materials = nullptr;
-Map<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData> CanvasItemMaterial::shader_map;
-CanvasItemMaterial::ShaderNames *CanvasItemMaterial::shader_names = nullptr;
-
-void CanvasItemMaterial::init_shaders() {
- dirty_materials = memnew(SelfList<CanvasItemMaterial>::List);
-
- shader_names = memnew(ShaderNames);
-
- shader_names->particles_anim_h_frames = "particles_anim_h_frames";
- shader_names->particles_anim_v_frames = "particles_anim_v_frames";
- shader_names->particles_anim_loop = "particles_anim_loop";
-}
-
-void CanvasItemMaterial::finish_shaders() {
- memdelete(dirty_materials);
- memdelete(shader_names);
- dirty_materials = nullptr;
-}
-
-void CanvasItemMaterial::_update_shader() {
- dirty_materials->remove(&element);
-
- MaterialKey mk = _compute_key();
- if (mk.key == current_key.key) {
- return; //no update required in the end
- }
-
- if (shader_map.has(current_key)) {
- shader_map[current_key].users--;
- if (shader_map[current_key].users == 0) {
- //deallocate shader, as it's no longer in use
- RS::get_singleton()->free(shader_map[current_key].shader);
- shader_map.erase(current_key);
- }
- }
-
- current_key = mk;
-
- if (shader_map.has(mk)) {
- RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader);
- shader_map[mk].users++;
- return;
- }
-
- //must create a shader!
-
- String code = "shader_type canvas_item;\nrender_mode ";
- switch (blend_mode) {
- case BLEND_MODE_MIX:
- code += "blend_mix";
- break;
- case BLEND_MODE_ADD:
- code += "blend_add";
- break;
- case BLEND_MODE_SUB:
- code += "blend_sub";
- break;
- case BLEND_MODE_MUL:
- code += "blend_mul";
- break;
- case BLEND_MODE_PREMULT_ALPHA:
- code += "blend_premul_alpha";
- break;
- case BLEND_MODE_DISABLED:
- code += "blend_disabled";
- break;
- }
-
- switch (light_mode) {
- case LIGHT_MODE_NORMAL:
- break;
- case LIGHT_MODE_UNSHADED:
- code += ",unshaded";
- break;
- case LIGHT_MODE_LIGHT_ONLY:
- code += ",light_only";
- break;
- }
-
- code += ";\n";
-
- if (particles_animation) {
- code += "uniform int particles_anim_h_frames;\n";
- code += "uniform int particles_anim_v_frames;\n";
- code += "uniform bool particles_anim_loop;\n\n";
-
- code += "void vertex() {\n";
- code += " float h_frames = float(particles_anim_h_frames);\n";
- code += " float v_frames = float(particles_anim_v_frames);\n";
- code += " VERTEX.xy /= vec2(h_frames, v_frames);\n";
- code += " float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n";
- code += " float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n";
- code += " if (!particles_anim_loop) {\n";
- code += " particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n";
- code += " } else {\n";
- code += " particle_frame = mod(particle_frame, particle_total_frames);\n";
- code += " }";
- code += " UV /= vec2(h_frames, v_frames);\n";
- code += " UV += vec2(mod(particle_frame, h_frames) / h_frames, floor(particle_frame / h_frames) / v_frames);\n";
- code += "}\n";
- }
-
- ShaderData shader_data;
- shader_data.shader = RS::get_singleton()->shader_create();
- shader_data.users = 1;
-
- RS::get_singleton()->shader_set_code(shader_data.shader, code);
-
- shader_map[mk] = shader_data;
-
- RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader);
-}
-
-void CanvasItemMaterial::flush_changes() {
- MutexLock lock(material_mutex);
-
- while (dirty_materials->first()) {
- dirty_materials->first()->self()->_update_shader();
- }
-}
-
-void CanvasItemMaterial::_queue_shader_change() {
- MutexLock lock(material_mutex);
-
- if (!element.in_list()) {
- dirty_materials->add(&element);
- }
-}
-
-bool CanvasItemMaterial::_is_shader_dirty() const {
- MutexLock lock(material_mutex);
-
- return element.in_list();
-}
-
-void CanvasItemMaterial::set_blend_mode(BlendMode p_blend_mode) {
- blend_mode = p_blend_mode;
- _queue_shader_change();
-}
-
-CanvasItemMaterial::BlendMode CanvasItemMaterial::get_blend_mode() const {
- return blend_mode;
-}
-
-void CanvasItemMaterial::set_light_mode(LightMode p_light_mode) {
- light_mode = p_light_mode;
- _queue_shader_change();
-}
-
-CanvasItemMaterial::LightMode CanvasItemMaterial::get_light_mode() const {
- return light_mode;
-}
-
-void CanvasItemMaterial::set_particles_animation(bool p_particles_anim) {
- particles_animation = p_particles_anim;
- _queue_shader_change();
- notify_property_list_changed();
-}
-
-bool CanvasItemMaterial::get_particles_animation() const {
- return particles_animation;
-}
-
-void CanvasItemMaterial::set_particles_anim_h_frames(int p_frames) {
- particles_anim_h_frames = p_frames;
- RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames);
-}
-
-int CanvasItemMaterial::get_particles_anim_h_frames() const {
- return particles_anim_h_frames;
-}
-
-void CanvasItemMaterial::set_particles_anim_v_frames(int p_frames) {
- particles_anim_v_frames = p_frames;
- RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames);
-}
-
-int CanvasItemMaterial::get_particles_anim_v_frames() const {
- return particles_anim_v_frames;
-}
-
-void CanvasItemMaterial::set_particles_anim_loop(bool p_loop) {
- particles_anim_loop = p_loop;
- RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop);
-}
-
-bool CanvasItemMaterial::get_particles_anim_loop() const {
- return particles_anim_loop;
-}
-
-void CanvasItemMaterial::_validate_property(PropertyInfo &property) const {
- if (property.name.begins_with("particles_anim_") && !particles_animation) {
- property.usage = PROPERTY_USAGE_NONE;
- }
-}
-
-RID CanvasItemMaterial::get_shader_rid() const {
- ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
- return shader_map[current_key].shader;
-}
-
-Shader::Mode CanvasItemMaterial::get_shader_mode() const {
- return Shader::MODE_CANVAS_ITEM;
-}
-
-void CanvasItemMaterial::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &CanvasItemMaterial::set_blend_mode);
- ClassDB::bind_method(D_METHOD("get_blend_mode"), &CanvasItemMaterial::get_blend_mode);
-
- ClassDB::bind_method(D_METHOD("set_light_mode", "light_mode"), &CanvasItemMaterial::set_light_mode);
- ClassDB::bind_method(D_METHOD("get_light_mode"), &CanvasItemMaterial::get_light_mode);
-
- ClassDB::bind_method(D_METHOD("set_particles_animation", "particles_anim"), &CanvasItemMaterial::set_particles_animation);
- ClassDB::bind_method(D_METHOD("get_particles_animation"), &CanvasItemMaterial::get_particles_animation);
-
- ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &CanvasItemMaterial::set_particles_anim_h_frames);
- ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &CanvasItemMaterial::get_particles_anim_h_frames);
-
- ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &CanvasItemMaterial::set_particles_anim_v_frames);
- ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &CanvasItemMaterial::get_particles_anim_v_frames);
-
- ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "loop"), &CanvasItemMaterial::set_particles_anim_loop);
- ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &CanvasItemMaterial::get_particles_anim_loop);
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply,Premultiplied Alpha"), "set_blend_mode", "get_blend_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mode", PROPERTY_HINT_ENUM, "Normal,Unshaded,Light Only"), "set_light_mode", "get_light_mode");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_animation"), "set_particles_animation", "get_particles_animation");
-
- ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop");
-
- BIND_ENUM_CONSTANT(BLEND_MODE_MIX);
- BIND_ENUM_CONSTANT(BLEND_MODE_ADD);
- BIND_ENUM_CONSTANT(BLEND_MODE_SUB);
- BIND_ENUM_CONSTANT(BLEND_MODE_MUL);
- BIND_ENUM_CONSTANT(BLEND_MODE_PREMULT_ALPHA);
-
- BIND_ENUM_CONSTANT(LIGHT_MODE_NORMAL);
- BIND_ENUM_CONSTANT(LIGHT_MODE_UNSHADED);
- BIND_ENUM_CONSTANT(LIGHT_MODE_LIGHT_ONLY);
-}
-
-CanvasItemMaterial::CanvasItemMaterial() :
- element(this) {
- set_particles_anim_h_frames(1);
- set_particles_anim_v_frames(1);
- set_particles_anim_loop(false);
-
- current_key.invalid_key = 1;
- _queue_shader_change();
-}
-
-CanvasItemMaterial::~CanvasItemMaterial() {
- MutexLock lock(material_mutex);
-
- if (shader_map.has(current_key)) {
- shader_map[current_key].users--;
- if (shader_map[current_key].users == 0) {
- //deallocate shader, as it's no longer in use
- RS::get_singleton()->free(shader_map[current_key].shader);
- shader_map.erase(current_key);
- }
-
- RS::get_singleton()->material_set_shader(_get_material(), RID());
- }
-}
-
-///////////////////////////////////////////////////////////////////
#ifdef TOOLS_ENABLED
bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
if (_edit_use_rect()) {
@@ -423,9 +151,7 @@ void CanvasItem::_update_callback() {
current_item_drawn = this;
notification(NOTIFICATION_DRAW);
emit_signal(SceneStringNames::get_singleton()->draw);
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_draw);
- }
+ GDVIRTUAL_CALL(_draw);
current_item_drawn = nullptr;
drawing = false;
}
@@ -1206,7 +932,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_clip_children", "enable"), &CanvasItem::set_clip_children);
ClassDB::bind_method(D_METHOD("is_clipping_children"), &CanvasItem::is_clipping_children);
- BIND_VMETHOD(MethodInfo("_draw"));
+ GDVIRTUAL_BIND(_draw);
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index f264764870..a591cab485 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -33,132 +33,15 @@
#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
-#include "scene/resources/material.h"
-#include "scene/resources/multimesh.h"
-#include "scene/resources/shader.h"
-#include "scene/resources/texture.h"
+#include "scene/resources/canvas_item_material.h"
#include "servers/text_server.h"
class CanvasLayer;
-class Viewport;
class Font;
-
+class MultiMesh;
class StyleBox;
-
-class CanvasItemMaterial : public Material {
- GDCLASS(CanvasItemMaterial, Material);
-
-public:
- enum BlendMode {
- BLEND_MODE_MIX,
- BLEND_MODE_ADD,
- BLEND_MODE_SUB,
- BLEND_MODE_MUL,
- BLEND_MODE_PREMULT_ALPHA,
- BLEND_MODE_DISABLED
- };
-
- enum LightMode {
- LIGHT_MODE_NORMAL,
- LIGHT_MODE_UNSHADED,
- LIGHT_MODE_LIGHT_ONLY
- };
-
-private:
- union MaterialKey {
- struct {
- uint32_t blend_mode : 4;
- uint32_t light_mode : 4;
- uint32_t particles_animation : 1;
- uint32_t invalid_key : 1;
- };
-
- uint32_t key = 0;
-
- bool operator<(const MaterialKey &p_key) const {
- return key < p_key.key;
- }
- };
-
- struct ShaderNames {
- StringName particles_anim_h_frames;
- StringName particles_anim_v_frames;
- StringName particles_anim_loop;
- };
-
- static ShaderNames *shader_names;
-
- struct ShaderData {
- RID shader;
- int users = 0;
- };
-
- static Map<MaterialKey, ShaderData> shader_map;
-
- MaterialKey current_key;
-
- _FORCE_INLINE_ MaterialKey _compute_key() const {
- MaterialKey mk;
- mk.key = 0;
- mk.blend_mode = blend_mode;
- mk.light_mode = light_mode;
- mk.particles_animation = particles_animation;
- return mk;
- }
-
- static Mutex material_mutex;
- static SelfList<CanvasItemMaterial>::List *dirty_materials;
- SelfList<CanvasItemMaterial> element;
-
- void _update_shader();
- _FORCE_INLINE_ void _queue_shader_change();
- _FORCE_INLINE_ bool _is_shader_dirty() const;
-
- BlendMode blend_mode = BLEND_MODE_MIX;
- LightMode light_mode = LIGHT_MODE_NORMAL;
- bool particles_animation = false;
-
- // Initialized in the constructor.
- int particles_anim_h_frames;
- int particles_anim_v_frames;
- bool particles_anim_loop;
-
-protected:
- static void _bind_methods();
- void _validate_property(PropertyInfo &property) const override;
-
-public:
- void set_blend_mode(BlendMode p_blend_mode);
- BlendMode get_blend_mode() const;
-
- void set_light_mode(LightMode p_light_mode);
- LightMode get_light_mode() const;
-
- void set_particles_animation(bool p_particles_anim);
- bool get_particles_animation() const;
-
- void set_particles_anim_h_frames(int p_frames);
- int get_particles_anim_h_frames() const;
- void set_particles_anim_v_frames(int p_frames);
- int get_particles_anim_v_frames() const;
-
- void set_particles_anim_loop(bool p_loop);
- bool get_particles_anim_loop() const;
-
- static void init_shaders();
- static void finish_shaders();
- static void flush_changes();
-
- virtual RID get_shader_rid() const override;
-
- virtual Shader::Mode get_shader_mode() const override;
-
- CanvasItemMaterial();
- virtual ~CanvasItemMaterial();
-};
-
-VARIANT_ENUM_CAST(CanvasItemMaterial::BlendMode)
-VARIANT_ENUM_CAST(CanvasItemMaterial::LightMode)
+class Window;
+class World2D;
class CanvasItem : public Node {
GDCLASS(CanvasItem, Node);
@@ -259,6 +142,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ GDVIRTUAL0(_draw)
public:
enum {
NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED, //unique
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index 5de1ebf18d..9d8e0c203d 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -32,7 +32,6 @@
#define CANVAS_LAYER_H
#include "scene/main/node.h"
-#include "scene/resources/world_2d.h"
class Viewport;
class CanvasLayer : public Node {
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 2c6cefa771..f24d880045 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -30,7 +30,7 @@
#include "http_request.h"
#include "core/io/compression.h"
-#include "core/string/ustring.h"
+#include "scene/main/timer.h"
void HTTPRequest::_redirect_request(const String &p_new_url) {
}
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 22e822253f..673cf3a740 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -31,12 +31,12 @@
#ifndef HTTPREQUEST_H
#define HTTPREQUEST_H
-#include "core/io/file_access.h"
#include "core/io/http_client.h"
#include "core/os/thread.h"
#include "core/templates/safe_refcount.h"
-#include "node.h"
-#include "scene/main/timer.h"
+#include "scene/main/node.h"
+
+class Timer;
class HTTPRequest : public Node {
GDCLASS(HTTPRequest, Node);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index f1e5574351..4ea4579bf9 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -54,16 +54,11 @@ int Node::orphan_node_count = 0;
void Node::_notification(int p_notification) {
switch (p_notification) {
case NOTIFICATION_PROCESS: {
- if (get_script_instance()) {
- Variant time = get_process_delta_time();
- get_script_instance()->call(SceneStringNames::get_singleton()->_process, time);
- }
+ GDVIRTUAL_CALL(_process, get_process_delta_time());
+
} break;
case NOTIFICATION_PHYSICS_PROCESS: {
- if (get_script_instance()) {
- Variant time = get_physics_process_delta_time();
- get_script_instance()->call(SceneStringNames::get_singleton()->_physics_process, time);
- }
+ GDVIRTUAL_CALL(_physics_process, get_process_delta_time());
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -116,6 +111,9 @@ void Node::_notification(int p_notification) {
memdelete(data.path_cache);
data.path_cache = nullptr;
}
+ if (data.filename.length()) {
+ get_multiplayer()->scene_enter_exit_notify(data.filename, this, false);
+ }
} break;
case NOTIFICATION_PATH_CHANGED: {
if (data.path_cache) {
@@ -125,27 +123,30 @@ void Node::_notification(int p_notification) {
} break;
case NOTIFICATION_READY: {
if (get_script_instance()) {
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_input)) {
+ if (GDVIRTUAL_IS_OVERRIDEN(_input)) {
set_process_input(true);
}
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_unhandled_input)) {
+ if (GDVIRTUAL_IS_OVERRIDEN(_unhandled_input)) {
set_process_unhandled_input(true);
}
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_unhandled_key_input)) {
+ if (GDVIRTUAL_IS_OVERRIDEN(_unhandled_key_input)) {
set_process_unhandled_key_input(true);
}
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_process)) {
+ if (GDVIRTUAL_IS_OVERRIDEN(_process)) {
set_process(true);
}
-
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_physics_process)) {
+ if (GDVIRTUAL_IS_OVERRIDEN(_physics_process)) {
set_physics_process(true);
}
- get_script_instance()->call(SceneStringNames::get_singleton()->_ready);
+ GDVIRTUAL_CALL(_ready);
+ }
+ if (data.filename.length()) {
+ ERR_FAIL_COND(!is_inside_tree());
+ get_multiplayer()->scene_enter_exit_notify(data.filename, this, true);
}
} break;
@@ -214,9 +215,7 @@ void Node::_propagate_enter_tree() {
notification(NOTIFICATION_ENTER_TREE);
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_enter_tree);
- }
+ GDVIRTUAL_CALL(_enter_tree);
emit_signal(SceneStringNames::get_singleton()->tree_entered);
@@ -262,9 +261,8 @@ void Node::_propagate_exit_tree() {
data.blocked--;
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_exit_tree);
- }
+ GDVIRTUAL_CALL(_exit_tree);
+
emit_signal(SceneStringNames::get_singleton()->tree_exiting);
notification(NOTIFICATION_EXIT_TREE, true);
@@ -705,7 +703,7 @@ bool Node::is_enabled() const {
return _is_enabled();
}
-float Node::get_physics_process_delta_time() const {
+double Node::get_physics_process_delta_time() const {
if (data.tree) {
return data.tree->get_physics_process_time();
} else {
@@ -713,7 +711,7 @@ float Node::get_physics_process_delta_time() const {
}
}
-float Node::get_process_delta_time() const {
+double Node::get_process_delta_time() const {
if (data.tree) {
return data.tree->get_process_time();
} else {
@@ -2458,7 +2456,7 @@ NodePath Node::get_import_path() const {
static void _add_nodes_to_options(const Node *p_base, const Node *p_node, List<String> *r_options) {
#ifdef TOOLS_ENABLED
- const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\"";
+ const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\"";
#else
const String quote_style = "\"";
#endif
@@ -2467,7 +2465,7 @@ static void _add_nodes_to_options(const Node *p_base, const Node *p_node, List<S
return;
}
String n = p_base->get_path_to(p_node);
- r_options->push_back(quote_style + n + quote_style);
+ r_options->push_back(n.quote(quote_style));
for (int i = 0; i < p_node->get_child_count(); i++) {
_add_nodes_to_options(p_base, p_node->get_child(i), r_options);
}
@@ -2489,9 +2487,14 @@ void Node::clear_internal_tree_resource_paths() {
}
TypedArray<String> Node::get_configuration_warnings() const {
- if (get_script_instance() && get_script_instance()->get_script().is_valid() &&
- get_script_instance()->get_script()->is_tool() && get_script_instance()->has_method("_get_configuration_warnings")) {
- return get_script_instance()->call("_get_configuration_warnings");
+ Vector<String> warnings;
+ if (GDVIRTUAL_CALL(_get_configuration_warnings, warnings)) {
+ TypedArray<String> ret;
+ ret.resize(warnings.size());
+ for (int i = 0; i < warnings.size(); i++) {
+ ret[i] = warnings[i];
+ }
+ return ret;
}
return Array();
}
@@ -2537,6 +2540,37 @@ void Node::request_ready() {
data.ready_first = true;
}
+void Node::_call_input(const Ref<InputEvent> &p_event) {
+ GDVIRTUAL_CALL(_input, p_event);
+ if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
+ return;
+ }
+ input(p_event);
+}
+void Node::_call_unhandled_input(const Ref<InputEvent> &p_event) {
+ GDVIRTUAL_CALL(_unhandled_input, p_event);
+ if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
+ return;
+ }
+ unhandled_input(p_event);
+}
+void Node::_call_unhandled_key_input(const Ref<InputEvent> &p_event) {
+ GDVIRTUAL_CALL(_unhandled_key_input, p_event);
+ if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
+ return;
+ }
+ unhandled_key_input(p_event);
+}
+
+void Node::input(const Ref<InputEvent> &p_event) {
+}
+
+void Node::unhandled_input(const Ref<InputEvent> &p_event) {
+}
+
+void Node::unhandled_key_input(const Ref<InputEvent> &p_key_event) {
+}
+
void Node::_bind_methods() {
GLOBAL_DEF("editor/node_naming/name_num_separator", 0);
ProjectSettings::get_singleton()->set_custom_property_info("editor/node_naming/name_num_separator", PropertyInfo(Variant::INT, "editor/node_naming/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"));
@@ -2730,15 +2764,15 @@ void Node::_bind_methods() {
ADD_GROUP("Editor Description", "editor_");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "set_editor_description", "get_editor_description");
- BIND_VMETHOD(MethodInfo("_process", PropertyInfo(Variant::FLOAT, "delta")));
- BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::FLOAT, "delta")));
- BIND_VMETHOD(MethodInfo("_enter_tree"));
- BIND_VMETHOD(MethodInfo("_exit_tree"));
- BIND_VMETHOD(MethodInfo("_ready"));
- BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEventKey")));
- BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, "String"), "_get_configuration_warnings"));
+ GDVIRTUAL_BIND(_process, "delta");
+ GDVIRTUAL_BIND(_physics_process, "delta");
+ GDVIRTUAL_BIND(_enter_tree);
+ GDVIRTUAL_BIND(_exit_tree);
+ GDVIRTUAL_BIND(_ready);
+ GDVIRTUAL_BIND(_get_configuration_warnings);
+ GDVIRTUAL_BIND(_input, "event");
+ GDVIRTUAL_BIND(_unhandled_input, "event");
+ GDVIRTUAL_BIND(_unhandled_key_input, "event");
}
String Node::_get_name_num_separator() {
diff --git a/scene/main/node.h b/scene/main/node.h
index 0a88553ea1..a07accba2f 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -202,11 +202,33 @@ protected:
static String _get_name_num_separator();
friend class SceneState;
+ friend class MultiplayerReplicator;
void _add_child_nocheck(Node *p_child, const StringName &p_name);
void _set_owner_nocheck(Node *p_owner);
void _set_name_nocheck(const StringName &p_name);
+ //call from SceneTree
+ void _call_input(const Ref<InputEvent> &p_event);
+ void _call_unhandled_input(const Ref<InputEvent> &p_event);
+ void _call_unhandled_key_input(const Ref<InputEvent> &p_event);
+
+protected:
+ virtual void input(const Ref<InputEvent> &p_event);
+ virtual void unhandled_input(const Ref<InputEvent> &p_event);
+ virtual void unhandled_key_input(const Ref<InputEvent> &p_key_event);
+
+ GDVIRTUAL1(_process, double)
+ GDVIRTUAL1(_physics_process, double)
+ GDVIRTUAL0(_enter_tree)
+ GDVIRTUAL0(_exit_tree)
+ GDVIRTUAL0(_ready)
+ GDVIRTUAL0RC(Vector<String>, _get_configuration_warnings)
+
+ GDVIRTUAL1(_input, Ref<InputEvent>)
+ GDVIRTUAL1(_unhandled_input, Ref<InputEvent>)
+ GDVIRTUAL1(_unhandled_key_input, Ref<InputEvent>)
+
public:
enum {
// you can make your own, but don't use the same numbers as other notifications in other nodes
@@ -339,11 +361,11 @@ public:
/* PROCESSING */
void set_physics_process(bool p_process);
- float get_physics_process_delta_time() const;
+ double get_physics_process_delta_time() const;
bool is_physics_processing() const;
void set_process(bool p_process);
- float get_process_delta_time() const;
+ double get_process_delta_time() const;
bool is_processing() const;
void set_physics_process_internal(bool p_process_internal);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index dcbbebbc55..8260d0dff5 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -499,7 +499,7 @@ bool SceneTree::process(double p_time) {
_call_idle_callbacks();
#ifdef TOOLS_ENABLED
-
+#ifndef _3D_DISABLED
if (Engine::get_singleton()->is_editor_hint()) {
//simple hack to reload fallback environment if it changed from editor
String env_path = ProjectSettings::get_singleton()->get(SNAME("rendering/environment/defaults/default_environment"));
@@ -522,8 +522,8 @@ bool SceneTree::process(double p_time) {
get_root()->get_world_3d()->set_fallback_environment(fallback);
}
}
-
-#endif
+#endif // _3D_DISABLED
+#endif // TOOLS_ENABLED
return _quit;
}
@@ -867,7 +867,7 @@ void SceneMainLoop::_update_listener_2d() {
*/
-void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport) {
+void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport) {
Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E) {
return;
@@ -886,9 +886,6 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
int node_count = nodes_copy.size();
Node **nodes = nodes_copy.ptrw();
- Variant arg = p_input;
- const Variant *v[1] = { &arg };
-
call_lock++;
for (int i = node_count - 1; i >= 0; i--) {
@@ -905,14 +902,16 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
continue;
}
- Callable::CallError err;
- // Call both script and native method.
- if (n->get_script_instance()) {
- n->get_script_instance()->call(p_method, (const Variant **)v, 1, err);
- }
- MethodBind *method = ClassDB::get_method(n->get_class_name(), p_method);
- if (method) {
- method->call(n, (const Variant **)v, 1, err);
+ switch (p_call_type) {
+ case CALL_INPUT_TYPE_INPUT:
+ n->_call_input(p_input);
+ break;
+ case CALL_INPUT_TYPE_UNHANDLED_INPUT:
+ n->_call_unhandled_input(p_input);
+ break;
+ case CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT:
+ n->_call_unhandled_key_input(p_input);
+ break;
}
}
@@ -1333,20 +1332,21 @@ SceneTree::SceneTree() {
root = memnew(Window);
root->set_name("root");
+#ifndef _3D_DISABLED
if (!root->get_world_3d().is_valid()) {
root->set_world_3d(Ref<World3D>(memnew(World3D)));
}
+ root->set_as_audio_listener_3d(true);
+#endif // _3D_DISABLED
// Initialize network state.
set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
- //root->set_world_2d( Ref<World2D>( memnew( World2D )));
- root->set_as_audio_listener(true);
root->set_as_audio_listener_2d(true);
current_scene = nullptr;
const int msaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/msaa", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/quality/msaa", PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Fast),4× (Average),8× (Slow),16× (Slower)")));
root->set_msaa(Viewport::MSAA(msaa_mode));
const int ssaa_mode = GLOBAL_DEF("rendering/anti_aliasing/quality/screen_space_aa", 0);
@@ -1397,6 +1397,7 @@ SceneTree::SceneTree() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/sdf/oversize", PropertyInfo(Variant::INT, "rendering/2d/sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/sdf/scale", PropertyInfo(Variant::INT, "rendering/2d/sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"));
+#ifndef _3D_DISABLED
{ // Load default fallback environment.
// Get possible extensions.
List<String> exts;
@@ -1428,6 +1429,7 @@ SceneTree::SceneTree() {
}
}
}
+#endif // _3D_DISABLED
root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true));
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index cfb95bd6b5..b1b94ae910 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -204,8 +204,14 @@ private:
void _main_window_close();
void _main_window_go_back();
+ enum CallInputType {
+ CALL_INPUT_TYPE_INPUT,
+ CALL_INPUT_TYPE_UNHANDLED_INPUT,
+ CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT,
+ };
+
//used by viewport
- void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport);
+ void _call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport);
protected:
void _notification(int p_notification);
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index d22a6b2875..9477e300d1 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -30,8 +30,7 @@
#include "shader_globals_override.h"
-#include "core/core_string_names.h"
-#include "scene/main/window.h"
+#include "scene/3d/node_3d.h"
#include "scene/scene_string_names.h"
StringName *ShaderGlobalsOverride::_remap(const StringName &p_name) const {
diff --git a/scene/main/shader_globals_override.h b/scene/main/shader_globals_override.h
index 2d9c3c76bd..ab4b9de727 100644
--- a/scene/main/shader_globals_override.h
+++ b/scene/main/shader_globals_override.h
@@ -31,7 +31,7 @@
#ifndef SHADER_GLOBALS_OVERRIDE_H
#define SHADER_GLOBALS_OVERRIDE_H
-#include "scene/3d/node_3d.h"
+#include "scene/main/node.h"
class ShaderGlobalsOverride : public Node {
GDCLASS(ShaderGlobalsOverride, Node);
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index b5a2a30b3b..9e462eb1c8 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -30,8 +30,6 @@
#include "timer.h"
-#include "core/config/engine.h"
-
void Timer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 8e7182df46..ea2323c651 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -30,33 +30,28 @@
#include "viewport.h"
-#include "core/config/project_settings.h"
#include "core/core_string_names.h"
#include "core/debugger/engine_debugger.h"
-#include "core/input/input.h"
-#include "core/os/os.h"
+#include "core/object/message_queue.h"
#include "core/string/translation.h"
-
+#include "core/templates/pair.h"
#include "scene/2d/camera_2d.h"
#include "scene/2d/collision_object_2d.h"
+#ifndef _3D_DISABLED
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_object_3d.h"
#include "scene/3d/listener_3d.h"
-#include "scene/3d/node_3d.h"
#include "scene/3d/world_environment.h"
+#endif // _3D_DISABLED
#include "scene/gui/control.h"
#include "scene/gui/label.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/panel.h"
-#include "scene/gui/panel_container.h"
-#include "scene/gui/popup_menu.h"
+#include "scene/gui/popup.h"
#include "scene/main/canvas_layer.h"
-#include "scene/main/timer.h"
#include "scene/main/window.h"
#include "scene/resources/mesh.h"
+#include "scene/resources/text_line.h"
+#include "scene/resources/world_2d.h"
#include "scene/scene_string_names.h"
-#include "servers/display_server.h"
-#include "servers/physics_server_2d.h"
void ViewportTexture::setup_local_to_scene() {
if (vp) {
@@ -184,24 +179,6 @@ public:
/////////////////////////////////////
-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) {
- 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
- if (object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) {
- Ref<InputEventMouseMotion> mm = p_input_event;
- if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
- return; //discarded
- }
- }
- 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;
-}
-
void Viewport::_sub_window_update_order() {
for (int i = 0; i < gui.sub_windows.size(); i++) {
RS::get_singleton()->canvas_item_set_draw_index(gui.sub_windows[i].canvas_item, i);
@@ -388,27 +365,6 @@ void Viewport::_sub_window_remove(Window *p_window) {
RenderingServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, p_window->parent ? p_window->parent->viewport : RID());
}
-void Viewport::_own_world_3d_changed() {
- ERR_FAIL_COND(world_3d.is_null());
- ERR_FAIL_COND(own_world_3d.is_null());
-
- if (is_inside_tree()) {
- _propagate_exit_world(this);
- }
-
- own_world_3d = world_3d->duplicate();
-
- if (is_inside_tree()) {
- _propagate_enter_world(this);
- }
-
- if (is_inside_tree()) {
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
- }
-
- _update_listener();
-}
-
void Viewport::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -422,19 +378,19 @@ void Viewport::_notification(int p_what) {
}
current_canvas = find_world_2d()->get_canvas();
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
-
- _update_listener();
_update_listener_2d();
+#ifndef _3D_DISABLED
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ _update_listener_3d();
+#endif // _3D_DISABLED
add_to_group("_viewports");
if (get_tree()->is_debugging_collisions_hint()) {
- //2D
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, find_world_2d()->get_canvas());
- //3D
+#ifndef _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, true);
@@ -444,15 +400,15 @@ 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);
+#endif // _3D_DISABLED
}
} break;
case NOTIFICATION_READY: {
#ifndef _3D_DISABLED
- if (listeners.size() && !listener) {
+ if (listener_3d_set.size() && !listener_3d) {
Listener3D *first = nullptr;
- for (Set<Listener3D *>::Element *E = listeners.front(); E; E = E->next()) {
+ for (Set<Listener3D *>::Element *E = listener_3d_set.front(); E; E = E->next()) {
if (first == nullptr || first->is_greater_than(E->get())) {
first = E->get();
}
@@ -463,10 +419,10 @@ void Viewport::_notification(int p_what) {
}
}
- if (cameras.size() && !camera_3d) {
+ if (camera_3d_set.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()) {
+ for (Set<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) {
if (first == nullptr || first->is_greater_than(E->get())) {
first = E->get();
}
@@ -476,8 +432,7 @@ void Viewport::_notification(int p_what) {
first->make_current();
}
}
-#endif
-
+#endif // _3D_DISABLED
} break;
case NOTIFICATION_EXIT_TREE: {
_gui_cancel_tooltip();
@@ -515,7 +470,7 @@ 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
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());
@@ -528,6 +483,7 @@ void Viewport::_notification(int p_what) {
RS::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh, i, point_transform);
}
}
+#endif // _3D_DISABLED
} break;
case NOTIFICATION_WM_MOUSE_EXIT: {
_drop_physics_mouseover();
@@ -560,12 +516,6 @@ void Viewport::_process_picking() {
_drop_physics_mouseover(true);
-#ifndef _3D_DISABLED
- Vector2 last_pos(1e20, 1e20);
- CollisionObject3D *last_object = nullptr;
- ObjectID last_id;
-#endif
- PhysicsDirectSpaceState3D::RayResult result;
PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
if (physics_has_last_mousepos) {
@@ -713,7 +663,7 @@ void Viewport::_process_picking() {
}
if (send_event) {
- co->_input_event(this, ev, res[i].shape);
+ co->_input_event_call(this, ev, res[i].shape);
}
}
}
@@ -726,12 +676,16 @@ void Viewport::_process_picking() {
}
#ifndef _3D_DISABLED
+ Vector2 last_pos(1e20, 1e20);
+ CollisionObject3D *last_object = nullptr;
+ ObjectID last_id;
+ PhysicsDirectSpaceState3D::RayResult result;
bool captured = false;
if (physics_object_capture.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture));
if (co && camera_3d) {
- _collision_object_input_event(co, camera_3d, ev, Vector3(), Vector3(), 0);
+ _collision_object_3d_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();
@@ -748,7 +702,7 @@ 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_3d, ev, result.position, result.normal, result.shape);
+ _collision_object_3d_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;
}
@@ -765,8 +719,8 @@ void Viewport::_process_picking() {
ObjectID new_collider;
if (col) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider);
- if (co) {
- _collision_object_input_event(co, camera_3d, ev, result.position, result.normal, result.shape);
+ if (co && co->can_process()) {
+ _collision_object_3d_input_event(co, camera_3d, ev, result.position, result.normal, result.shape);
last_object = co;
last_id = result.collider_id;
new_collider = last_id;
@@ -798,7 +752,7 @@ void Viewport::_process_picking() {
last_pos = pos;
}
}
-#endif
+#endif // _3D_DISABLED
}
}
@@ -865,31 +819,15 @@ Rect2 Viewport::get_visible_rect() const {
return r;
}
-void Viewport::_update_listener() {
-}
-
void Viewport::_update_listener_2d() {
/*
- if (is_inside_tree() && audio_listener && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))
+ if (is_inside_tree() && audio_listener_3d && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))
SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, find_world_2d()->get_sound_space());
else
SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, RID());
*/
}
-void Viewport::set_as_audio_listener(bool p_enable) {
- if (p_enable == audio_listener) {
- return;
- }
-
- audio_listener = p_enable;
- _update_listener();
-}
-
-bool Viewport::is_audio_listener() const {
- return audio_listener;
-}
-
void Viewport::set_as_audio_listener_2d(bool p_enable) {
if (p_enable == audio_listener_2d) {
return;
@@ -904,15 +842,6 @@ 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;
@@ -973,131 +902,10 @@ Transform2D Viewport::get_global_canvas_transform() const {
return global_canvas_transform;
}
-void Viewport::_listener_transform_changed_notify() {
-}
-
-void Viewport::_listener_set(Listener3D *p_listener) {
-#ifndef _3D_DISABLED
-
- if (listener == p_listener) {
- return;
- }
-
- listener = p_listener;
-
- _update_listener();
- _listener_transform_changed_notify();
-#endif
-}
-
-bool Viewport::_listener_add(Listener3D *p_listener) {
- listeners.insert(p_listener);
- return listeners.size() == 1;
-}
-
-void Viewport::_listener_remove(Listener3D *p_listener) {
- listeners.erase(p_listener);
- if (listener == p_listener) {
- listener = nullptr;
- }
-}
-
-#ifndef _3D_DISABLED
-void Viewport::_listener_make_next_current(Listener3D *p_exclude) {
- if (listeners.size() > 0) {
- for (Set<Listener3D *>::Element *E = listeners.front(); E; E = E->next()) {
- if (p_exclude == E->get()) {
- continue;
- }
- if (!E->get()->is_inside_tree()) {
- continue;
- }
- if (listener != nullptr) {
- return;
- }
-
- E->get()->make_current();
- }
- } else {
- // Attempt to reset listener to the camera position
- if (camera_3d != nullptr) {
- _update_listener();
- _camera_3d_transform_changed_notify();
- }
- }
-}
-#endif
-
-void Viewport::_camera_3d_transform_changed_notify() {
-#ifndef _3D_DISABLED
-#endif
-}
-
-void Viewport::_camera_3d_set(Camera3D *p_camera) {
-#ifndef _3D_DISABLED
-
- if (camera_3d == p_camera) {
- return;
- }
-
- if (camera_3d) {
- camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
- }
-
- camera_3d = p_camera;
-
- if (!camera_override) {
- 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_3d) {
- camera_3d->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
- }
-
- _update_listener();
- _camera_3d_transform_changed_notify();
-#endif
-}
-
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_3d_remove(Camera3D *p_camera) {
- cameras.erase(p_camera);
- if (camera_3d == p_camera) {
- camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
- camera_3d = nullptr;
- }
-}
-
-#ifndef _3D_DISABLED
-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;
- }
- if (!E->get()->is_inside_tree()) {
- continue;
- }
- if (camera_3d != nullptr) {
- return;
- }
-
- E->get()->make_current();
- }
-}
-#endif
-
void Viewport::_canvas_layer_add(CanvasLayer *p_canvas_layer) {
canvas_layers.insert(p_canvas_layer);
}
@@ -1121,7 +929,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
}
if (parent && parent->find_world_2d() == p_world_2d) {
- WARN_PRINT("Unable to use parent world_3d as world_2d");
+ WARN_PRINT("Unable to use parent world_2d as world_2d");
return;
}
@@ -1154,33 +962,6 @@ Ref<World2D> Viewport::find_world_2d() const {
}
}
-void Viewport::_propagate_enter_world(Node *p_node) {
- if (p_node != this) {
- if (!p_node->is_inside_tree()) { //may not have entered scene yet
- return;
- }
-
-#ifndef _3D_DISABLED
- if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
- p_node->notification(Node3D::NOTIFICATION_ENTER_WORLD);
- } else {
-#endif
- Viewport *v = Object::cast_to<Viewport>(p_node);
- if (v) {
- if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
- return;
- }
- }
-#ifndef _3D_DISABLED
- }
-#endif
- }
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _propagate_enter_world(p_node->get_child(i));
- }
-}
-
void Viewport::_propagate_viewport_notification(Node *p_node, int p_what) {
p_node->notification(p_what);
for (int i = 0; i < p_node->get_child_count(); i++) {
@@ -1192,174 +973,14 @@ void Viewport::_propagate_viewport_notification(Node *p_node, int p_what) {
}
}
-void Viewport::_propagate_exit_world(Node *p_node) {
- if (p_node != this) {
- if (!p_node->is_inside_tree()) { //may have exited scene already
- return;
- }
-
-#ifndef _3D_DISABLED
- if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
- p_node->notification(Node3D::NOTIFICATION_EXIT_WORLD);
- } else {
-#endif
- Viewport *v = Object::cast_to<Viewport>(p_node);
- if (v) {
- if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
- return;
- }
- }
-#ifndef _3D_DISABLED
- }
-#endif
- }
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _propagate_exit_world(p_node->get_child(i));
- }
-}
-
-void Viewport::set_world_3d(const Ref<World3D> &p_world_3d) {
- if (world_3d == p_world_3d) {
- return;
- }
-
- if (is_inside_tree()) {
- _propagate_exit_world(this);
- }
-
- if (own_world_3d.is_valid() && world_3d.is_valid()) {
- world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- }
-
- world_3d = p_world_3d;
-
- if (own_world_3d.is_valid()) {
- if (world_3d.is_valid()) {
- own_world_3d = world_3d->duplicate();
- world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- } else {
- own_world_3d = Ref<World3D>(memnew(World3D));
- }
- }
-
- if (is_inside_tree()) {
- _propagate_enter_world(this);
- }
-
- if (is_inside_tree()) {
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
- }
-
- _update_listener();
-}
-
-Ref<World3D> Viewport::get_world_3d() const {
- return world_3d;
-}
-
Ref<World2D> Viewport::get_world_2d() const {
return world_2d;
}
-Ref<World3D> Viewport::find_world_3d() const {
- if (own_world_3d.is_valid()) {
- return own_world_3d;
- } else if (world_3d.is_valid()) {
- return world_3d;
- } else if (parent) {
- return parent->find_world_3d();
- } else {
- return Ref<World3D>();
- }
-}
-
-Listener3D *Viewport::get_listener() const {
- return listener;
-}
-
-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) {
-#ifndef _3D_DISABLED
- if (p_enable == camera_override) {
- return;
- }
-
- if (p_enable) {
- camera_override.rid = RenderingServer::get_singleton()->camera_create();
- } else {
- RenderingServer::get_singleton()->free(camera_override.rid);
- camera_override.rid = RID();
- }
-
- if (p_enable) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid);
- } else if (camera_3d) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
- } else {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
- }
-#endif
-}
-
-bool Viewport::is_camera_override_enabled() const {
- return camera_override;
-}
-
-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);
- }
-}
-
-Transform3D Viewport::get_camera_override_transform() const {
- if (camera_override) {
- return camera_override.transform;
- }
-
- return Transform3D();
-}
-
-void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
- if (camera_override) {
- if (camera_override.fov == p_fovy_degrees && camera_override.z_near == p_z_near &&
- camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_PERSPECTIVE) {
- return;
- }
-
- camera_override.fov = p_fovy_degrees;
- camera_override.z_near = p_z_near;
- camera_override.z_far = p_z_far;
- camera_override.projection = CameraOverrideData::PROJECTION_PERSPECTIVE;
-
- RenderingServer::get_singleton()->camera_set_perspective(camera_override.rid, camera_override.fov, camera_override.z_near, camera_override.z_far);
- }
-}
-
-void Viewport::set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far) {
- if (camera_override) {
- if (camera_override.size == p_size && camera_override.z_near == p_z_near &&
- camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_ORTHOGONAL) {
- return;
- }
-
- camera_override.size = p_size;
- camera_override.z_near = p_z_near;
- camera_override.z_far = p_z_far;
- camera_override.projection = CameraOverrideData::PROJECTION_ORTHOGONAL;
-
- RenderingServer::get_singleton()->camera_set_orthogonal(camera_override.rid, camera_override.size, camera_override.z_near, camera_override.z_far);
- }
-}
-
Transform2D Viewport::get_final_transform() const {
return stretch_transform * global_canvas_transform;
}
@@ -1384,16 +1005,6 @@ 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;
}
@@ -1624,27 +1235,7 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
Control *control = Object::cast_to<Control>(ci);
if (control) {
if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
- control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it)
- }
- if (gui.key_event_accepted) {
- break;
- }
- if (!control->is_inside_tree()) {
- break;
- }
-
- if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
- // Call both script and native methods.
- Callable::CallError error;
- Variant event = ev;
- const Variant *args[1] = { &event };
- if (control->get_script_instance()) {
- control->get_script_instance()->call(SceneStringNames::get_singleton()->_gui_input, args, 1, error);
- }
- MethodBind *method = ClassDB::get_method(control->get_class_name(), SceneStringNames::get_singleton()->_gui_input);
- if (method) {
- method->call(control, args, 1, error);
- }
+ control->_call_gui_input(ev);
}
if (!control->is_inside_tree() || control->is_set_as_top_level()) {
@@ -2372,10 +1963,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.key_focus) {
gui.key_event_accepted = false;
if (gui.key_focus->can_process()) {
- gui.key_focus->call(SceneStringNames::get_singleton()->_gui_input, p_event);
- if (gui.key_focus) { //maybe lost it
- gui.key_focus->emit_signal(SceneStringNames::get_singleton()->gui_input, p_event);
- }
+ gui.key_focus->_call_gui_input(p_event);
}
if (gui.key_event_accepted) {
@@ -2595,7 +2183,7 @@ void Viewport::_drop_mouse_focus() {
mb->set_global_position(c->get_local_mouse_position());
mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(false);
- c->call(SceneStringNames::get_singleton()->_gui_input, mb);
+ c->_call_gui_input(mb);
}
}
}
@@ -2616,7 +2204,7 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
}
}
}
-#endif
+#endif // _3D_DISABLED
}
void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference) {
@@ -2707,7 +2295,7 @@ void Viewport::_post_gui_grab_click_focus() {
mb->set_position(click);
mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(false);
- gui.mouse_focus->call(SceneStringNames::get_singleton()->_gui_input, mb);
+ gui.mouse_focus->_call_gui_input(mb);
}
}
@@ -2725,7 +2313,7 @@ void Viewport::_post_gui_grab_click_focus() {
mb->set_position(click);
mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(true);
- gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb);
+ MessageQueue::get_singleton()->push_callable(callable_mp(gui.mouse_focus, &Control::_call_gui_input), mb);
}
}
}
@@ -2733,9 +2321,9 @@ void Viewport::_post_gui_grab_click_focus() {
///////////////////////////////
-void Viewport::input_text(const String &p_text) {
+void Viewport::push_text_input(const String &p_text) {
if (gui.subwindow_focused) {
- gui.subwindow_focused->input_text(p_text);
+ gui.subwindow_focused->push_text_input(p_text);
return;
}
@@ -3055,7 +2643,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
return true;
}
-void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
+void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(!is_inside_tree());
if (disable_input) {
@@ -3085,7 +2673,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
}
if (!is_input_handled()) {
- get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
+ get_tree()->_call_input_pause(input_group, SceneTree::CALL_INPUT_TYPE_INPUT, ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
}
if (!is_input_handled()) {
@@ -3093,12 +2681,12 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
}
event_count++;
- //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",ev); //special one for GUI, as controls use their own process check
}
-void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
+void Viewport::push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(p_event.is_null());
ERR_FAIL_COND(!is_inside_tree());
+ local_input_handled = false;
if (disable_input || !_can_consume_input_events()) {
return;
@@ -3116,11 +2704,11 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
}
// Unhandled Input
- get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", ev, this);
+ get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, ev, this);
- // Unhandled key Input - used for performance reasons - This is called a lot less then _unhandled_input since it ignores MouseMotion, etc
- if (!is_input_handled() && Object::cast_to<InputEventKey>(*ev) != nullptr) {
- get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", ev, this);
+ // Unhandled key Input - used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, etc
+ if (!is_input_handled() && (Object::cast_to<InputEventKey>(*ev) != nullptr || Object::cast_to<InputEventShortcut>(*ev) != nullptr)) {
+ get_tree()->_call_input_pause(unhandled_key_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, ev, this);
}
if (physics_object_picking && !is_input_handled()) {
@@ -3137,44 +2725,6 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
}
}
-void Viewport::set_use_own_world_3d(bool p_world_3d) {
- if (p_world_3d == own_world_3d.is_valid()) {
- return;
- }
-
- if (is_inside_tree()) {
- _propagate_exit_world(this);
- }
-
- if (!p_world_3d) {
- own_world_3d = Ref<World3D>();
- if (world_3d.is_valid()) {
- world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- }
- } else {
- if (world_3d.is_valid()) {
- own_world_3d = world_3d->duplicate();
- world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- } else {
- own_world_3d = Ref<World3D>(memnew(World3D));
- }
- }
-
- if (is_inside_tree()) {
- _propagate_enter_world(this);
- }
-
- if (is_inside_tree()) {
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
- }
-
- _update_listener();
-}
-
-bool Viewport::is_using_own_world_3d() const {
- return own_world_3d.is_valid();
-}
-
void Viewport::set_physics_object_picking(bool p_enable) {
physics_object_picking = p_enable;
if (physics_object_picking) {
@@ -3275,6 +2825,7 @@ void Viewport::set_lod_threshold(float p_pixels) {
lod_threshold = p_pixels;
RS::get_singleton()->viewport_set_lod_threshold(viewport, lod_threshold);
}
+
float Viewport::get_lod_threshold() const {
return lod_threshold;
}
@@ -3487,6 +3038,7 @@ void Viewport::set_sdf_oversize(SDFOversize p_sdf_oversize) {
sdf_oversize = p_sdf_oversize;
RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
}
+
Viewport::SDFOversize Viewport::get_sdf_oversize() const {
return sdf_oversize;
}
@@ -3496,17 +3048,415 @@ void Viewport::set_sdf_scale(SDFScale p_sdf_scale) {
sdf_scale = p_sdf_scale;
RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
}
+
Viewport::SDFScale Viewport::get_sdf_scale() const {
return sdf_scale;
}
+#ifndef _3D_DISABLED
+Listener3D *Viewport::get_listener_3d() const {
+ return listener_3d;
+}
+
+void Viewport::set_as_audio_listener_3d(bool p_enable) {
+ if (p_enable == audio_listener_3d) {
+ return;
+ }
+
+ audio_listener_3d = p_enable;
+ _update_listener_3d();
+}
+
+bool Viewport::is_audio_listener_3d() const {
+ return audio_listener_3d;
+}
+
+void Viewport::_update_listener_3d() {
+}
+
+void Viewport::_listener_transform_3d_changed_notify() {
+}
+
+void Viewport::_listener_3d_set(Listener3D *p_listener) {
+ if (listener_3d == p_listener) {
+ return;
+ }
+
+ listener_3d = p_listener;
+
+ _update_listener_3d();
+ _listener_transform_3d_changed_notify();
+}
+
+bool Viewport::_listener_3d_add(Listener3D *p_listener) {
+ listener_3d_set.insert(p_listener);
+ return listener_3d_set.size() == 1;
+}
+
+void Viewport::_listener_3d_remove(Listener3D *p_listener) {
+ listener_3d_set.erase(p_listener);
+ if (listener_3d == p_listener) {
+ listener_3d = nullptr;
+ }
+}
+
+void Viewport::_listener_3d_make_next_current(Listener3D *p_exclude) {
+ if (listener_3d_set.size() > 0) {
+ for (Set<Listener3D *>::Element *E = listener_3d_set.front(); E; E = E->next()) {
+ if (p_exclude == E->get()) {
+ continue;
+ }
+ if (!E->get()->is_inside_tree()) {
+ continue;
+ }
+ if (listener_3d != nullptr) {
+ return;
+ }
+
+ E->get()->make_current();
+ }
+ } else {
+ // Attempt to reset listener to the camera position
+ if (camera_3d != nullptr) {
+ _update_listener_3d();
+ _camera_3d_transform_changed_notify();
+ }
+ }
+}
+
+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();
+ ObjectID id = p_object->get_instance_id();
+
+ //avoid sending the fake event unnecessarily if nothing really changed in the context
+ if (object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) {
+ Ref<InputEventMouseMotion> mm = p_input_event;
+ if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
+ return; //discarded
+ }
+ }
+ p_object->_input_event_call(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;
+}
+
+Camera3D *Viewport::get_camera_3d() const {
+ return camera_3d;
+}
+
+void Viewport::_camera_3d_transform_changed_notify() {
+}
+
+void Viewport::_camera_3d_set(Camera3D *p_camera) {
+ if (camera_3d == p_camera) {
+ return;
+ }
+
+ if (camera_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ }
+
+ camera_3d = p_camera;
+
+ if (!camera_3d_override) {
+ 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_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
+ }
+
+ _update_listener_3d();
+ _camera_3d_transform_changed_notify();
+}
+
+bool Viewport::_camera_3d_add(Camera3D *p_camera) {
+ camera_3d_set.insert(p_camera);
+ return camera_3d_set.size() == 1;
+}
+
+void Viewport::_camera_3d_remove(Camera3D *p_camera) {
+ camera_3d_set.erase(p_camera);
+ if (camera_3d == p_camera) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ camera_3d = nullptr;
+ }
+}
+
+void Viewport::_camera_3d_make_next_current(Camera3D *p_exclude) {
+ for (Set<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) {
+ if (p_exclude == E->get()) {
+ continue;
+ }
+ if (!E->get()->is_inside_tree()) {
+ continue;
+ }
+ if (camera_3d != nullptr) {
+ return;
+ }
+
+ E->get()->make_current();
+ }
+}
+
+void Viewport::enable_camera_3d_override(bool p_enable) {
+ if (p_enable == camera_3d_override) {
+ return;
+ }
+
+ if (p_enable) {
+ camera_3d_override.rid = RenderingServer::get_singleton()->camera_create();
+ } else {
+ RenderingServer::get_singleton()->free(camera_3d_override.rid);
+ camera_3d_override.rid = RID();
+ }
+
+ if (p_enable) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d_override.rid);
+ } else if (camera_3d) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
+ } else {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
+ }
+}
+
+void Viewport::set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far) {
+ if (camera_3d_override) {
+ if (camera_3d_override.fov == p_fovy_degrees && camera_3d_override.z_near == p_z_near &&
+ camera_3d_override.z_far == p_z_far && camera_3d_override.projection == Camera3DOverrideData::PROJECTION_PERSPECTIVE) {
+ return;
+ }
+
+ camera_3d_override.fov = p_fovy_degrees;
+ camera_3d_override.z_near = p_z_near;
+ camera_3d_override.z_far = p_z_far;
+ camera_3d_override.projection = Camera3DOverrideData::PROJECTION_PERSPECTIVE;
+
+ RenderingServer::get_singleton()->camera_set_perspective(camera_3d_override.rid, camera_3d_override.fov, camera_3d_override.z_near, camera_3d_override.z_far);
+ }
+}
+
+void Viewport::set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far) {
+ if (camera_3d_override) {
+ if (camera_3d_override.size == p_size && camera_3d_override.z_near == p_z_near &&
+ camera_3d_override.z_far == p_z_far && camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) {
+ return;
+ }
+
+ camera_3d_override.size = p_size;
+ camera_3d_override.z_near = p_z_near;
+ camera_3d_override.z_far = p_z_far;
+ camera_3d_override.projection = Camera3DOverrideData::PROJECTION_ORTHOGONAL;
+
+ RenderingServer::get_singleton()->camera_set_orthogonal(camera_3d_override.rid, camera_3d_override.size, camera_3d_override.z_near, camera_3d_override.z_far);
+ }
+}
+
+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;
+}
+
+bool Viewport::is_camera_3d_override_enabled() const {
+ return camera_3d_override;
+}
+
+void Viewport::set_camera_3d_override_transform(const Transform3D &p_transform) {
+ if (camera_3d_override) {
+ camera_3d_override.transform = p_transform;
+ RenderingServer::get_singleton()->camera_set_transform(camera_3d_override.rid, p_transform);
+ }
+}
+
+Transform3D Viewport::get_camera_3d_override_transform() const {
+ if (camera_3d_override) {
+ return camera_3d_override.transform;
+ }
+
+ return Transform3D();
+}
+
+Ref<World3D> Viewport::get_world_3d() const {
+ return world_3d;
+}
+
+Ref<World3D> Viewport::find_world_3d() const {
+ if (own_world_3d.is_valid()) {
+ return own_world_3d;
+ } else if (world_3d.is_valid()) {
+ return world_3d;
+ } else if (parent) {
+ return parent->find_world_3d();
+ } else {
+ return Ref<World3D>();
+ }
+}
+
+void Viewport::set_world_3d(const Ref<World3D> &p_world_3d) {
+ if (world_3d == p_world_3d) {
+ return;
+ }
+
+ if (is_inside_tree()) {
+ _propagate_exit_world_3d(this);
+ }
+
+ if (own_world_3d.is_valid() && world_3d.is_valid()) {
+ world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ }
+
+ world_3d = p_world_3d;
+
+ if (own_world_3d.is_valid()) {
+ if (world_3d.is_valid()) {
+ own_world_3d = world_3d->duplicate();
+ world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ } else {
+ own_world_3d = Ref<World3D>(memnew(World3D));
+ }
+ }
+
+ if (is_inside_tree()) {
+ _propagate_enter_world_3d(this);
+ }
+
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ }
+
+ _update_listener_3d();
+}
+
+void Viewport::_own_world_3d_changed() {
+ ERR_FAIL_COND(world_3d.is_null());
+ ERR_FAIL_COND(own_world_3d.is_null());
+
+ if (is_inside_tree()) {
+ _propagate_exit_world_3d(this);
+ }
+
+ own_world_3d = world_3d->duplicate();
+
+ if (is_inside_tree()) {
+ _propagate_enter_world_3d(this);
+ }
+
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ }
+
+ _update_listener_3d();
+}
+
+void Viewport::set_use_own_world_3d(bool p_world_3d) {
+ if (p_world_3d == own_world_3d.is_valid()) {
+ return;
+ }
+
+ if (is_inside_tree()) {
+ _propagate_exit_world_3d(this);
+ }
+
+ if (!p_world_3d) {
+ own_world_3d = Ref<World3D>();
+ if (world_3d.is_valid()) {
+ world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ }
+ } else {
+ if (world_3d.is_valid()) {
+ own_world_3d = world_3d->duplicate();
+ world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ } else {
+ own_world_3d = Ref<World3D>(memnew(World3D));
+ }
+ }
+
+ if (is_inside_tree()) {
+ _propagate_enter_world_3d(this);
+ }
+
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ }
+
+ _update_listener_3d();
+}
+
+bool Viewport::is_using_own_world_3d() const {
+ return own_world_3d.is_valid();
+}
+
+void Viewport::_propagate_enter_world_3d(Node *p_node) {
+ if (p_node != this) {
+ if (!p_node->is_inside_tree()) { //may not have entered scene yet
+ return;
+ }
+
+ if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
+ p_node->notification(Node3D::NOTIFICATION_ENTER_WORLD);
+ } else {
+ Viewport *v = Object::cast_to<Viewport>(p_node);
+ if (v) {
+ if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
+ return;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _propagate_enter_world_3d(p_node->get_child(i));
+ }
+}
+
+void Viewport::_propagate_exit_world_3d(Node *p_node) {
+ if (p_node != this) {
+ if (!p_node->is_inside_tree()) { //may have exited scene already
+ return;
+ }
+
+ if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
+ p_node->notification(Node3D::NOTIFICATION_EXIT_WORLD);
+ } else {
+ Viewport *v = Object::cast_to<Viewport>(p_node);
+ if (v) {
+ if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
+ return;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _propagate_exit_world_3d(p_node->get_child(i));
+ }
+}
+
+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;
+}
+#endif // _3D_DISABLED
+
void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d);
ClassDB::bind_method(D_METHOD("find_world_2d"), &Viewport::find_world_2d);
- ClassDB::bind_method(D_METHOD("set_world_3d", "world_3d"), &Viewport::set_world_3d);
- ClassDB::bind_method(D_METHOD("get_world_3d"), &Viewport::get_world_3d);
- ClassDB::bind_method(D_METHOD("find_world_3d"), &Viewport::find_world_3d);
ClassDB::bind_method(D_METHOD("set_canvas_transform", "xform"), &Viewport::set_canvas_transform);
ClassDB::bind_method(D_METHOD("get_canvas_transform"), &Viewport::get_canvas_transform);
@@ -3536,34 +3486,20 @@ void Viewport::_bind_methods() {
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);
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("get_viewport_rid"), &Viewport::get_viewport_rid);
- ClassDB::bind_method(D_METHOD("input_text", "text"), &Viewport::input_text);
- 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("push_text_input", "text"), &Viewport::push_text_input);
+ ClassDB::bind_method(D_METHOD("push_input", "event", "in_local_coords"), &Viewport::push_input, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("push_unhandled_input", "event", "in_local_coords"), &Viewport::push_unhandled_input, DEFVAL(false));
- 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_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);
-
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);
@@ -3621,17 +3557,37 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_process_picking"), &Viewport::_process_picking);
+#ifndef _3D_DISABLED
+ ClassDB::bind_method(D_METHOD("set_world_3d", "world_3d"), &Viewport::set_world_3d);
+ ClassDB::bind_method(D_METHOD("get_world_3d"), &Viewport::get_world_3d);
+ ClassDB::bind_method(D_METHOD("find_world_3d"), &Viewport::find_world_3d);
+
+ 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_3d"), &Viewport::get_camera_3d);
+ ClassDB::bind_method(D_METHOD("set_as_audio_listener_3d", "enable"), &Viewport::set_as_audio_listener_3d);
+ ClassDB::bind_method(D_METHOD("is_audio_listener_3d"), &Viewport::is_audio_listener_3d);
+
+ 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("set_use_xr", "use"), &Viewport::set_use_xr);
+ ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
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");
+#endif // _3D_DISABLED
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::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, "msaa", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Fast),4× (Average),8× (Slow),16× (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");
@@ -3642,7 +3598,6 @@ void Viewport::_bind_methods() {
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");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener", "is_audio_listener");
ADD_GROUP("Physics", "physics_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking");
ADD_GROUP("GUI", "gui_");
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index b5c49a8a97..b24de77e6b 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -31,26 +31,25 @@
#ifndef VIEWPORT_H
#define VIEWPORT_H
-#include "core/math/transform_2d.h"
-#include "core/templates/pair.h"
#include "scene/main/node.h"
#include "scene/resources/texture.h"
-#include "scene/resources/world_2d.h"
-#include "servers/display_server.h"
-#include "servers/rendering_server.h"
+#ifndef _3D_DISABLED
class Camera3D;
-class Camera2D;
+class CollisionObject3D;
class Listener3D;
-class Control;
+class World3D;
+#endif // _3D_DISABLED
+
+class Camera2D;
class CanvasItem;
class CanvasLayer;
-class Panel;
+class Control;
class Label;
-class Timer;
-class Viewport;
-class CollisionObject3D;
class SceneTreeTimer;
+class Viewport;
+class Window;
+class World2D;
class ViewportTexture : public Texture2D {
GDCLASS(ViewportTexture, Texture2D);
@@ -194,39 +193,13 @@ private:
Viewport *parent = nullptr;
- Listener3D *listener = nullptr;
- Set<Listener3D *> listeners;
-
- struct CameraOverrideData {
- Transform3D transform;
- enum Projection {
- PROJECTION_PERSPECTIVE,
- PROJECTION_ORTHOGONAL
- };
- Projection projection = Projection::PROJECTION_PERSPECTIVE;
- float fov = 0.0;
- float size = 0.0;
- float z_near = 0.0;
- float z_far = 0.0;
- RID rid;
-
- operator bool() const {
- return rid != RID();
- }
- } camera_override;
-
- Camera3D *camera_3d = nullptr;
Camera2D *camera_2d = nullptr;
- Set<Camera3D *> cameras;
Set<CanvasLayer *> canvas_layers;
RID viewport;
RID current_canvas;
RID subwindow_canvas;
- bool audio_listener = false;
- RID internal_listener;
-
bool audio_listener_2d = false;
RID internal_listener_2d;
@@ -240,7 +213,6 @@ private:
Size2i size = Size2i(512, 512);
Size2i size_2d_override;
bool size_allocated = false;
- bool use_xr = false;
RID contact_2d_debug;
RID contact_3d_debug_multimesh;
@@ -274,8 +246,6 @@ private:
} physics_last_mouse_state;
- void _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);
-
bool handle_input_locally = true;
bool local_input_handled = false;
@@ -287,8 +257,6 @@ private:
void _cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference = 0);
Ref<World2D> world_2d;
- Ref<World3D> world_3d;
- Ref<World3D> own_world_3d;
Rect2i to_screen_rect;
StringName input_group;
@@ -296,13 +264,10 @@ private:
StringName unhandled_input_group;
StringName unhandled_key_input_group;
- void _update_listener();
void _update_listener_2d();
bool disable_3d = false;
- void _propagate_enter_world(Node *p_node);
- void _propagate_exit_world(Node *p_node);
void _propagate_viewport_notification(Node *p_node, int p_what);
void _update_global_transform();
@@ -375,7 +340,7 @@ private:
Variant drag_data;
ObjectID drag_preview_id;
Ref<SceneTreeTimer> tooltip_timer;
- float tooltip_delay = 0.0;
+ double tooltip_delay = 0.0;
Transform2D focus_inv_xform;
bool roots_order_dirty = false;
List<Control *> roots;
@@ -443,20 +408,6 @@ private:
bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check);
- friend class Listener3D;
- void _listener_transform_changed_notify();
- void _listener_set(Listener3D *p_listener);
- bool _listener_add(Listener3D *p_listener); //true if first
- void _listener_remove(Listener3D *p_listener);
- void _listener_make_next_current(Listener3D *p_exclude);
-
- friend class Camera3D;
- void _camera_3d_transform_changed_notify();
- void _camera_3d_set(Camera3D *p_camera);
- bool _camera_3d_add(Camera3D *p_camera); //true if first
- void _camera_3d_remove(Camera3D *p_camera);
- void _camera_3d_make_next_current(Camera3D *p_exclude);
-
friend class Camera2D;
void _camera_2d_set(Camera2D *p_camera_2d);
@@ -471,8 +422,6 @@ private:
void _gui_set_root_order_dirty();
- void _own_world_3d_changed();
-
friend class Window;
void _sub_window_update_order();
@@ -500,38 +449,16 @@ protected:
public:
uint64_t get_processed_events_count() const { return event_count; }
- Listener3D *get_listener() const;
- Camera3D *get_camera_3d() const;
Camera2D *get_camera_2d() const;
-
- void enable_camera_override(bool p_enable);
- bool is_camera_override_enabled() const;
-
- void set_camera_override_transform(const Transform3D &p_transform);
- Transform3D get_camera_override_transform() const;
-
- void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
- void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far);
-
- void set_as_audio_listener(bool p_enable);
- bool is_audio_listener() const;
-
void set_as_audio_listener_2d(bool p_enable);
bool is_audio_listener_2d() const;
- void set_disable_3d(bool p_disable);
- bool is_3d_disabled() const;
-
void update_canvas_items();
Rect2 get_visible_rect() const;
RID get_viewport_rid() const;
- void set_world_3d(const Ref<World3D> &p_world_3d);
void set_world_2d(const Ref<World2D> &p_world_2d);
- Ref<World3D> get_world_3d() const;
- Ref<World3D> find_world_3d() const;
-
Ref<World2D> get_world_2d() const;
Ref<World2D> find_world_2d() const;
@@ -552,9 +479,6 @@ public:
void set_transparent_background(bool p_enable);
bool has_transparent_background() const;
- void set_use_xr(bool p_use_xr);
- bool is_using_xr();
-
Ref<ViewportTexture> get_texture() const;
void set_shadow_atlas_size(int p_size);
@@ -584,12 +508,9 @@ public:
Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const;
Vector2 get_camera_rect_size() const;
- void set_use_own_world_3d(bool p_world_3d);
- bool is_using_own_world_3d() const;
-
- void input_text(const String &p_text);
- void input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
- void unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
+ void push_text_input(const String &p_text);
+ void push_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
+ void push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
void set_disable_input(bool p_disable);
bool is_input_disabled() const;
@@ -654,6 +575,80 @@ public:
void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control);
+#ifndef _3D_DISABLED
+ bool use_xr = false;
+ friend class Listener3D;
+ Listener3D *listener_3d = nullptr;
+ Set<Listener3D *> listener_3d_set;
+ bool audio_listener_3d = false;
+ RID internal_listener_3d;
+ Listener3D *get_listener_3d() const;
+ void set_as_audio_listener_3d(bool p_enable);
+ bool is_audio_listener_3d() const;
+ void _update_listener_3d();
+ void _listener_transform_3d_changed_notify();
+ void _listener_3d_set(Listener3D *p_listener);
+ bool _listener_3d_add(Listener3D *p_listener); //true if first
+ void _listener_3d_remove(Listener3D *p_listener);
+ void _listener_3d_make_next_current(Listener3D *p_exclude);
+
+ void _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);
+
+ struct Camera3DOverrideData {
+ Transform3D transform;
+ enum Projection {
+ PROJECTION_PERSPECTIVE,
+ PROJECTION_ORTHOGONAL
+ };
+ Projection projection = Projection::PROJECTION_PERSPECTIVE;
+ real_t fov = 0.0;
+ real_t size = 0.0;
+ real_t z_near = 0.0;
+ real_t z_far = 0.0;
+ RID rid;
+
+ operator bool() const {
+ return rid != RID();
+ }
+ } camera_3d_override;
+
+ friend class Camera3D;
+ Camera3D *camera_3d = nullptr;
+ Set<Camera3D *> camera_3d_set;
+ Camera3D *get_camera_3d() const;
+ void _camera_3d_transform_changed_notify();
+ void _camera_3d_set(Camera3D *p_camera);
+ bool _camera_3d_add(Camera3D *p_camera); //true if first
+ void _camera_3d_remove(Camera3D *p_camera);
+ void _camera_3d_make_next_current(Camera3D *p_exclude);
+
+ void enable_camera_3d_override(bool p_enable);
+ bool is_camera_3d_override_enabled() const;
+
+ void set_camera_3d_override_transform(const Transform3D &p_transform);
+ Transform3D get_camera_3d_override_transform() const;
+
+ void set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far);
+ void set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far);
+
+ void set_disable_3d(bool p_disable);
+ bool is_3d_disabled() const;
+
+ Ref<World3D> world_3d;
+ Ref<World3D> own_world_3d;
+ void set_world_3d(const Ref<World3D> &p_world_3d);
+ Ref<World3D> get_world_3d() const;
+ Ref<World3D> find_world_3d() const;
+ void _own_world_3d_changed();
+ void set_use_own_world_3d(bool p_world_3d);
+ bool is_using_own_world_3d() const;
+ void _propagate_enter_world_3d(Node *p_node);
+ void _propagate_exit_world_3d(Node *p_node);
+
+ void set_use_xr(bool p_use_xr);
+ bool is_using_xr();
+#endif // _3D_DISABLED
+
Viewport();
~Viewport();
};
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 1f1da7cefb..b9c0ae5a4a 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -31,10 +31,8 @@
#include "window.h"
#include "core/debugger/engine_debugger.h"
-#include "core/os/keyboard.h"
#include "core/string/translation.h"
#include "scene/gui/control.h"
-#include "scene/resources/font.h"
#include "scene/scene_string_names.h"
void Window::set_title(const String &p_title) {
@@ -302,7 +300,7 @@ void Window::_propagate_window_notification(Node *p_node, int p_notification) {
Node *child = p_node->get_child(i);
Window *window = Object::cast_to<Window>(child);
if (window) {
- break;
+ continue;
}
_propagate_window_notification(child, p_notification);
}
@@ -918,14 +916,14 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
- input(p_ev);
+ push_input(p_ev);
if (!is_input_handled()) {
- unhandled_input(p_ev);
+ push_unhandled_input(p_ev);
}
}
void Window::_window_input_text(const String &p_text) {
- input_text(p_text);
+ push_text_input(p_text);
}
void Window::_window_drop_files(const Vector<String> &p_files) {
diff --git a/scene/main/window.h b/scene/main/window.h
index 7013694a06..4f31d9cd1f 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -32,10 +32,12 @@
#define WINDOW_H
#include "scene/main/viewport.h"
-#include "scene/resources/theme.h"
-#include "servers/display_server.h"
class Control;
+class Font;
+class StyleBox;
+class Theme;
+
class Window : public Viewport {
GDCLASS(Window, Viewport)
public: