summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--SConstruct17
-rw-r--r--core/SCsub2
-rw-r--r--core/config/project_settings.cpp4
-rw-r--r--core/core_string_names.cpp6
-rw-r--r--core/core_string_names.h8
-rw-r--r--core/io/marshalls.cpp2
-rw-r--r--core/io/resource.cpp12
-rw-r--r--core/object/class_db.cpp2
-rw-r--r--core/object/message_queue.cpp59
-rw-r--r--core/object/message_queue.h2
-rw-r--r--core/object/object.cpp16
-rw-r--r--core/variant/variant.cpp2
-rw-r--r--core/variant/variant_setget.cpp6
-rw-r--r--doc/classes/CanvasItem.xml10
-rw-r--r--doc/classes/GraphNode.xml3
-rw-r--r--doc/classes/RenderingServer.xml3
-rw-r--r--doc/classes/VisualShaderNodeReroute.xml19
-rw-r--r--drivers/d3d12/rendering_context_driver_d3d12.cpp1
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp10
-rw-r--r--drivers/vulkan/rendering_context_driver_vulkan.cpp28
-rw-r--r--drivers/vulkan/rendering_context_driver_vulkan.h1
-rw-r--r--editor/action_map_editor.cpp4
-rw-r--r--editor/animation_track_editor.cpp20
-rw-r--r--editor/editor_help.cpp16
-rw-r--r--editor/editor_help.h4
-rw-r--r--editor/editor_inspector.cpp18
-rw-r--r--editor/editor_inspector.h2
-rw-r--r--editor/editor_node.cpp6
-rw-r--r--editor/editor_properties.cpp11
-rw-r--r--editor/editor_properties_array_dict.cpp16
-rw-r--r--editor/gui/editor_scene_tabs.cpp1
-rw-r--r--editor/import/resource_importer_imagefont.cpp6
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp10
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp2
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp2
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp10
-rw-r--r--editor/plugins/script_editor_plugin.cpp4
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp20
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_shader_editor.cpp5
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp14
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp6
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp273
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h30
-rw-r--r--editor/scene_tree_dock.cpp1
-rw-r--r--editor/themes/editor_theme_manager.cpp17
-rw-r--r--main/SCsub2
-rw-r--r--main/main.cpp2
-rw-r--r--misc/dist/html/full-size.html2
-rw-r--r--misc/extension_api_validation/4.2-stable.expected13
-rw-r--r--modules/gdscript/gdscript.cpp15
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp19
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.h10
-rw-r--r--modules/gdscript/gdscript_vm.cpp10
-rw-r--r--modules/gltf/gltf_document.cpp73
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp4
-rw-r--r--modules/gridmap/grid_map.cpp4
-rw-r--r--modules/multiplayer/multiplayer_spawner.cpp4
-rw-r--r--modules/multiplayer/scene_cache_interface.cpp4
-rw-r--r--modules/multiplayer/scene_replication_interface.cpp8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.kt81
-rw-r--r--platform/web/export/export_plugin.cpp6
-rw-r--r--scene/2d/animated_sprite_2d.cpp14
-rw-r--r--scene/2d/audio_stream_player_2d.cpp4
-rw-r--r--scene/2d/cpu_particles_2d.cpp2
-rw-r--r--scene/2d/gpu_particles_2d.cpp2
-rw-r--r--scene/2d/mesh_instance_2d.cpp2
-rw-r--r--scene/2d/multimesh_instance_2d.cpp2
-rw-r--r--scene/2d/physics/area_2d.cpp74
-rw-r--r--scene/2d/physics/collision_object_2d.cpp10
-rw-r--r--scene/2d/physics/joints/joint_2d.cpp8
-rw-r--r--scene/2d/physics/rigid_body_2d.cpp30
-rw-r--r--scene/2d/sprite_2d.cpp4
-rw-r--r--scene/2d/tile_map.cpp10
-rw-r--r--scene/2d/tile_map_layer.cpp40
-rw-r--r--scene/2d/touch_screen_button.cpp8
-rw-r--r--scene/2d/visible_on_screen_notifier_2d.cpp4
-rw-r--r--scene/3d/cpu_particles_3d.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp2
-rw-r--r--scene/3d/node_3d.cpp14
-rw-r--r--scene/3d/physics/area_3d.cpp78
-rw-r--r--scene/3d/physics/area_3d.h4
-rw-r--r--scene/3d/physics/collision_object_3d.cpp6
-rw-r--r--scene/3d/physics/joints/joint_3d.cpp8
-rw-r--r--scene/3d/physics/rigid_body_3d.cpp30
-rw-r--r--scene/3d/skeleton_3d.cpp8
-rw-r--r--scene/3d/sprite_3d.cpp22
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.cpp4
-rw-r--r--scene/3d/visual_instance_3d.cpp8
-rw-r--r--scene/animation/animation_blend_tree.cpp16
-rw-r--r--scene/animation/animation_mixer.cpp20
-rw-r--r--scene/animation/animation_player.cpp8
-rw-r--r--scene/animation/animation_tree.cpp6
-rw-r--r--scene/audio/audio_stream_player_internal.cpp4
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/container.cpp4
-rw-r--r--scene/gui/control.cpp22
-rw-r--r--scene/gui/graph_edit.cpp12
-rw-r--r--scene/gui/graph_node.cpp13
-rw-r--r--scene/gui/graph_node.h5
-rw-r--r--scene/gui/nine_patch_rect.cpp2
-rw-r--r--scene/gui/video_stream_player.cpp4
-rw-r--r--scene/main/canvas_item.compat.inc24
-rw-r--r--scene/main/canvas_item.cpp46
-rw-r--r--scene/main/canvas_item.h14
-rw-r--r--scene/main/node.cpp126
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/main/shader_globals_override.cpp12
-rw-r--r--scene/main/window.cpp12
-rw-r--r--scene/register_scene_types.cpp1
-rw-r--r--scene/resources/canvas_item_material.cpp26
-rw-r--r--scene/resources/canvas_item_material.h3
-rw-r--r--scene/resources/material.cpp34
-rw-r--r--scene/resources/material.h4
-rw-r--r--scene/resources/packed_scene.cpp2
-rw-r--r--scene/resources/particle_process_material.cpp25
-rw-r--r--scene/resources/particle_process_material.h3
-rw-r--r--scene/resources/sprite_frames.cpp2
-rw-r--r--scene/resources/visual_shader.cpp96
-rw-r--r--scene/resources/visual_shader.h4
-rw-r--r--scene/resources/visual_shader_nodes.cpp79
-rw-r--r--scene/resources/visual_shader_nodes.h31
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--scene/scene_string_names.h4
-rw-r--r--servers/audio_server.cpp6
-rw-r--r--servers/display_server_headless.h42
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp7
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp288
-rw-r--r--servers/rendering/renderer_canvas_cull.h6
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp13
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp9
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_data_rd.h3
-rw-r--r--servers/rendering/rendering_context_driver.h5
-rw-r--r--servers/rendering/rendering_device.cpp75
-rw-r--r--servers/rendering/rendering_device.h3
-rw-r--r--servers/rendering/rendering_device_graph.cpp83
-rw-r--r--servers/rendering/rendering_device_graph.h22
-rw-r--r--servers/rendering/rendering_server_default.h6
-rw-r--r--servers/rendering_server.compat.inc15
-rw-r--r--servers/rendering_server.cpp6
-rw-r--r--servers/rendering_server.h10
-rw-r--r--tests/core/object/test_object.h4
-rw-r--r--tests/scene/test_curve_2d.h45
-rw-r--r--tests/scene/test_curve_3d.h20
-rw-r--r--version.py2
149 files changed, 1811 insertions, 911 deletions
diff --git a/SConstruct b/SConstruct
index 8ce504ae2b..f7c40416c7 100644
--- a/SConstruct
+++ b/SConstruct
@@ -484,14 +484,15 @@ if methods.get_cmdline_bool("fast_unsafe", env.dev_build):
if env["use_precise_math_checks"]:
env.Append(CPPDEFINES=["PRECISE_MATH_CHECKS"])
-if env.editor_build and env["engine_update_check"]:
- env.Append(CPPDEFINES=["ENGINE_UPDATE_CHECK_ENABLED"])
-
-if not env.File("#main/splash_editor.png").exists():
- # Force disabling editor splash if missing.
- env["no_editor_splash"] = True
-if env["no_editor_splash"]:
- env.Append(CPPDEFINES=["NO_EDITOR_SPLASH"])
+if env.editor_build:
+ if env["engine_update_check"]:
+ env.Append(CPPDEFINES=["ENGINE_UPDATE_CHECK_ENABLED"])
+
+ if not env.File("#main/splash_editor.png").exists():
+ # Force disabling editor splash if missing.
+ env["no_editor_splash"] = True
+ if env["no_editor_splash"]:
+ env.Append(CPPDEFINES=["NO_EDITOR_SPLASH"])
if not env["deprecated"]:
env.Append(CPPDEFINES=["DISABLE_DEPRECATED"])
diff --git a/core/SCsub b/core/SCsub
index 640c6de6a1..a61c0b5fc2 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -166,7 +166,7 @@ def disabled_class_builder(target, source, env):
for c in source[0].read():
cs = c.strip()
if cs != "":
- file.write(f"#define ClassDB_Disable_{cs} 1")
+ file.write(f"#define ClassDB_Disable_{cs} 1\n")
env.CommandNoCache("disabled_classes.gen.h", env.Value(env.disabled_classes), env.Run(disabled_class_builder))
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index a0412e91ff..a116c9c270 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -291,7 +291,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
}
}
} else {
- if (p_name == CoreStringNames::get_singleton()->_custom_features) {
+ if (p_name == CoreStringName(_custom_features)) {
Vector<String> custom_feature_array = String(p_value).split(",");
for (int i = 0; i < custom_feature_array.size(); i++) {
custom_features.insert(custom_feature_array[i]);
@@ -875,7 +875,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const RBMap<S
if (!p_custom_features.is_empty()) {
// Store how many properties are saved, add one for custom features, which must always go first.
file->store_32(count + 1);
- String key = CoreStringNames::get_singleton()->_custom_features;
+ String key = CoreStringName(_custom_features);
file->store_pascal_string(key);
int len;
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index 21645e5efc..1ffe76495d 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -33,12 +33,10 @@
CoreStringNames *CoreStringNames::singleton = nullptr;
CoreStringNames::CoreStringNames() :
- _free(StaticCString::create("free")),
+ free_(StaticCString::create("free")),
changed(StaticCString::create("changed")),
- _script(StaticCString::create("script")),
+ script(StaticCString::create("script")),
script_changed(StaticCString::create("script_changed")),
- ___pdcdata(StaticCString::create("___pdcdata")),
- __getvar(StaticCString::create("__getvar")),
_iter_init(StaticCString::create("_iter_init")),
_iter_next(StaticCString::create("_iter_next")),
_iter_get(StaticCString::create("_iter_get")),
diff --git a/core/core_string_names.h b/core/core_string_names.h
index 1c77cef567..d7ddc39f5e 100644
--- a/core/core_string_names.h
+++ b/core/core_string_names.h
@@ -50,12 +50,10 @@ public:
static CoreStringNames *singleton;
- StringName _free;
+ StringName free_; // "free", conflict with C++ keyword.
StringName changed;
- StringName _script;
+ StringName script;
StringName script_changed;
- StringName ___pdcdata;
- StringName __getvar;
StringName _iter_init;
StringName _iter_next;
StringName _iter_get;
@@ -98,4 +96,6 @@ public:
StringName property_list_changed;
};
+#define CoreStringName(m_name) CoreStringNames::get_singleton()->m_name
+
#endif // CORE_STRING_NAMES_H
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 2cdfacae17..1928f86d6a 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -1696,7 +1696,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
Variant value;
- if (E.name == CoreStringNames::get_singleton()->_script) {
+ if (E.name == CoreStringName(script)) {
Ref<Script> script = obj->get_script();
if (script.is_valid()) {
String path = script->get_path();
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 4c3cfeaa58..24ff0e83d2 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -43,9 +43,9 @@
void Resource::emit_changed() {
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
// Let the connection happen on the main thread, later, since signals are not thread-safe.
- call_deferred("emit_signal", CoreStringNames::get_singleton()->changed);
+ call_deferred("emit_signal", CoreStringName(changed));
} else {
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
}
@@ -172,8 +172,8 @@ void Resource::connect_changed(const Callable &p_callable, uint32_t p_flags) {
callable_mp(this, &Resource::connect_changed).call_deferred(p_callable, p_flags);
return;
}
- if (!is_connected(CoreStringNames::get_singleton()->changed, p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) {
- connect(CoreStringNames::get_singleton()->changed, p_callable, p_flags);
+ if (!is_connected(CoreStringName(changed), p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) {
+ connect(CoreStringName(changed), p_callable, p_flags);
}
}
@@ -183,8 +183,8 @@ void Resource::disconnect_changed(const Callable &p_callable) {
callable_mp(this, &Resource::disconnect_changed).call_deferred(p_callable);
return;
}
- if (is_connected(CoreStringNames::get_singleton()->changed, p_callable)) {
- disconnect(CoreStringNames::get_singleton()->changed, p_callable);
+ if (is_connected(CoreStringName(changed), p_callable)) {
+ disconnect(CoreStringName(changed), p_callable);
}
}
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 6b84dfcee9..7ea26c3fc5 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -1554,7 +1554,7 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia
}
// The "free()" method is special, so we assume it exists and return a Callable.
- if (p_property == CoreStringNames::get_singleton()->_free) {
+ if (p_property == CoreStringName(free_)) {
r_value = Callable(p_object, p_property);
return true;
}
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index 90536e58ff..9351253c6f 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -197,7 +197,7 @@ Error CallQueue::push_notification(ObjectID p_id, int p_notification) {
Message *msg = memnew_placement(buffer_end, Message);
msg->type = TYPE_NOTIFICATION;
- msg->callable = Callable(p_id, CoreStringNames::get_singleton()->notification); //name is meaningless but callable needs it
+ msg->callable = Callable(p_id, CoreStringName(notification)); //name is meaningless but callable needs it
//msg->target;
msg->notification = p_notification;
@@ -224,64 +224,7 @@ void CallQueue::_call_function(const Callable &p_callable, const Variant *p_args
}
}
-Error CallQueue::_transfer_messages_to_main_queue() {
- if (pages.size() == 0) {
- return OK;
- }
-
- CallQueue *mq = MessageQueue::main_singleton;
- DEV_ASSERT(!mq->allocator_is_custom && !allocator_is_custom); // Transferring pages is only safe if using the same alloator parameters.
-
- mq->mutex.lock();
-
- // Here we're transferring the data from this queue to the main one.
- // However, it's very unlikely big amounts of messages will be queued here,
- // so PagedArray/Pool would be overkill. Also, in most cases the data will fit
- // an already existing page of the main queue.
-
- // Let's see if our first (likely only) page fits the current target queue page.
- uint32_t src_page = 0;
- {
- if (mq->pages_used) {
- uint32_t dst_page = mq->pages_used - 1;
- uint32_t dst_offset = mq->page_bytes[dst_page];
- if (dst_offset + page_bytes[0] < uint32_t(PAGE_SIZE_BYTES)) {
- memcpy(mq->pages[dst_page]->data + dst_offset, pages[0]->data, page_bytes[0]);
- mq->page_bytes[dst_page] += page_bytes[0];
- src_page++;
- }
- }
- }
-
- // Any other possibly existing source page needs to be added.
-
- if (mq->pages_used + (pages_used - src_page) > mq->max_pages) {
- fprintf(stderr, "Failed appending thread queue. Message queue out of memory. %s\n", mq->error_text.utf8().get_data());
- mq->statistics();
- mq->mutex.unlock();
- return ERR_OUT_OF_MEMORY;
- }
-
- for (; src_page < pages_used; src_page++) {
- mq->_add_page();
- memcpy(mq->pages[mq->pages_used - 1]->data, pages[src_page]->data, page_bytes[src_page]);
- mq->page_bytes[mq->pages_used - 1] = page_bytes[src_page];
- }
-
- mq->mutex.unlock();
-
- page_bytes[0] = 0;
- pages_used = 1;
-
- return OK;
-}
-
Error CallQueue::flush() {
- // Thread overrides are not meant to be flushed, but appended to the main one.
- if (unlikely(this == MessageQueue::thread_singleton)) {
- return _transfer_messages_to_main_queue();
- }
-
LOCK_MUTEX;
if (pages.size() == 0) {
diff --git a/core/object/message_queue.h b/core/object/message_queue.h
index c2f4ad1643..9f567e4dd0 100644
--- a/core/object/message_queue.h
+++ b/core/object/message_queue.h
@@ -98,8 +98,6 @@ private:
}
}
- Error _transfer_messages_to_main_queue();
-
void _add_page();
void _call_function(const Callable &p_callable, const Variant *p_args, int p_argcount, bool p_show_error);
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 5125ab8a6e..57f8766509 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -260,7 +260,7 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
}
}
- if (p_name == CoreStringNames::get_singleton()->_script) {
+ if (p_name == CoreStringName(script)) {
set_script(p_value);
if (r_valid) {
*r_valid = true;
@@ -351,7 +351,7 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
}
}
- if (p_name == CoreStringNames::get_singleton()->_script) {
+ if (p_name == CoreStringName(script)) {
ret = get_script();
if (r_valid) {
*r_valid = true;
@@ -672,7 +672,7 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Call
}
bool Object::has_method(const StringName &p_method) const {
- if (p_method == CoreStringNames::get_singleton()->_free) {
+ if (p_method == CoreStringName(free_)) {
return true;
}
@@ -698,7 +698,7 @@ int Object::_get_method_argument_count_bind(const StringName &p_method) const {
}
int Object::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
- if (p_method == CoreStringNames::get_singleton()->_free) {
+ if (p_method == CoreStringName(free_)) {
if (r_is_valid) {
*r_is_valid = true;
}
@@ -787,7 +787,7 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) {
Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK;
- if (p_method == CoreStringNames::get_singleton()->_free) {
+ if (p_method == CoreStringName(free_)) {
//free must be here, before anything, always ready
#ifdef DEBUG_ENABLED
if (p_argcount != 0) {
@@ -850,7 +850,7 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_
Variant Object::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK;
- if (p_method == CoreStringNames::get_singleton()->_free) {
+ if (p_method == CoreStringName(free_)) {
// Free is not const, so fail.
r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST;
return Variant();
@@ -979,7 +979,7 @@ void Object::set_script(const Variant &p_script) {
}
notify_property_list_changed(); //scripts may add variables, so refresh is desired
- emit_signal(CoreStringNames::get_singleton()->script_changed);
+ emit_signal(CoreStringName(script_changed));
}
void Object::set_script_instance(ScriptInstance *p_instance) {
@@ -1654,7 +1654,7 @@ void Object::clear_internal_resource_paths() {
}
void Object::notify_property_list_changed() {
- emit_signal(CoreStringNames::get_singleton()->property_list_changed);
+ emit_signal(CoreStringName(property_list_changed));
}
void Object::_bind_methods() {
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 3a499a2bcd..8be00b1358 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -2121,7 +2121,7 @@ Variant::operator ::RID() const {
}
#endif
Callable::CallError ce;
- Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce);
+ Variant ret = _get_obj().obj->callp(CoreStringName(get_rid), nullptr, 0, ce);
if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::RID) {
return ret;
}
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 96c52260d9..48176163a1 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -1384,7 +1384,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
ref.push_back(r_iter);
Variant vref = ref;
const Variant *refp[] = { &vref };
- Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce);
+ Variant ret = _get_obj().obj->callp(CoreStringName(_iter_init), refp, 1, ce);
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
valid = false;
@@ -1619,7 +1619,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
ref.push_back(r_iter);
Variant vref = ref;
const Variant *refp[] = { &vref };
- Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce);
+ Variant ret = _get_obj().obj->callp(CoreStringName(_iter_next), refp, 1, ce);
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
valid = false;
@@ -1811,7 +1811,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
Callable::CallError ce;
ce.error = Callable::CallError::CALL_OK;
const Variant *refp[] = { &r_iter };
- Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce);
+ Variant ret = _get_obj().obj->callp(CoreStringName(_iter_get), refp, 1, ce);
if (ce.error != Callable::CallError::CALL_OK) {
r_valid = false;
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index bf53cb2e14..207045b065 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -84,6 +84,7 @@
Draws a circle. See also [method draw_arc], [method draw_polyline], and [method draw_polygon].
If [param filled] is [code]true[/code], the circle will be filled with the [param color] specified. If [param filled] is [code]false[/code], the circle will be drawn as a stroke with the [param color] and [param width] specified.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
[b]Note:[/b] [param width] is only effective if [param filled] is [code]false[/code].
</description>
</method>
@@ -105,9 +106,12 @@
<param index="3" name="width" type="float" default="-1.0" />
<param index="4" name="dash" type="float" default="2.0" />
<param index="5" name="aligned" type="bool" default="true" />
+ <param index="6" name="antialiased" type="bool" default="false" />
<description>
Draws a dashed line from a 2D point to another, with a given color and width. See also [method draw_multiline] and [method draw_polyline].
If [param width] is negative, then a two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the line parts will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
+ [b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_end_animation">
@@ -175,9 +179,11 @@
<param index="0" name="points" type="PackedVector2Array" />
<param index="1" name="color" type="Color" />
<param index="2" name="width" type="float" default="-1.0" />
+ <param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws multiple disconnected lines with a uniform [param width] and [param color]. Each line is defined by two consecutive points from [param points] array, i.e. i-th segment consists of [code]points[2 * i][/code], [code]points[2 * i + 1][/code] endpoints. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw interconnected lines, use [method draw_polyline] instead.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ [b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_multiline_colors">
@@ -185,9 +191,11 @@
<param index="0" name="points" type="PackedVector2Array" />
<param index="1" name="colors" type="PackedColorArray" />
<param index="2" name="width" type="float" default="-1.0" />
+ <param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws multiple disconnected lines with a uniform [param width] and segment-by-segment coloring. Each segment is defined by two consecutive points from [param points] array and a corresponding color from [param colors] array, i.e. i-th segment consists of [code]points[2 * i][/code], [code]points[2 * i + 1][/code] endpoints and has [code]colors[i][/code] color. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw interconnected lines, use [method draw_polyline_colors] instead.
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ [b]Note:[/b] [param antialiased] is only effective if [param width] is greater than [code]0.0[/code].
</description>
</method>
<method name="draw_multiline_string" qualifiers="const">
@@ -283,9 +291,11 @@
<param index="1" name="color" type="Color" />
<param index="2" name="filled" type="bool" default="true" />
<param index="3" name="width" type="float" default="-1.0" />
+ <param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a rectangle. If [param filled] is [code]true[/code], the rectangle will be filled with the [param color] specified. If [param filled] is [code]false[/code], the rectangle will be drawn as a stroke with the [param color] and [param width] specified. See also [method draw_texture_rect].
If [param width] is negative, then two-point primitives will be drawn instead of a four-point ones. This means that when the CanvasItem is scaled, the lines will remain thin. If this behavior is not desired, then pass a positive [param width] like [code]1.0[/code].
+ If [param antialiased] is [code]true[/code], half transparent "feathers" will be attached to the boundary, making outlines smooth.
[b]Note:[/b] [param width] is only effective if [param filled] is [code]false[/code].
[b]Note:[/b] Unfilled rectangles drawn with a negative [param width] may not display perfectly. For example, corners may be missing or brighter due to overlapping lines (for a translucent [param color]).
</description>
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index ad1028d7f4..cc3acad6d6 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -267,6 +267,9 @@
</method>
</methods>
<members>
+ <member name="ignore_invalid_connection_type" type="bool" setter="set_ignore_invalid_connection_type" getter="is_ignoring_valid_connection_type" default="false">
+ If [code]true[/code], you can connect ports with different types, even if the connection was not explicitly allowed in the parent [GraphEdit].
+ </member>
<member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" overrides="Control" enum="Control.MouseFilter" default="0" />
<member name="title" type="String" setter="set_title" getter="get_title" default="&quot;&quot;">
The text displayed in the GraphNode's title bar.
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 110bc133ef..3ddc0d8f7b 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -214,6 +214,7 @@
<param index="1" name="pos" type="Vector2" />
<param index="2" name="radius" type="float" />
<param index="3" name="color" type="Color" />
+ <param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a circle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_circle].
</description>
@@ -280,6 +281,7 @@
<param index="1" name="points" type="PackedVector2Array" />
<param index="2" name="colors" type="PackedColorArray" />
<param index="3" name="width" type="float" default="-1.0" />
+ <param index="4" name="antialiased" type="bool" default="false" />
<description>
Draws a 2D multiline on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_multiline] and [method CanvasItem.draw_multiline_colors].
</description>
@@ -356,6 +358,7 @@
<param index="0" name="item" type="RID" />
<param index="1" name="rect" type="Rect2" />
<param index="2" name="color" type="Color" />
+ <param index="3" name="antialiased" type="bool" default="false" />
<description>
Draws a rectangle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_rect].
</description>
diff --git a/doc/classes/VisualShaderNodeReroute.xml b/doc/classes/VisualShaderNodeReroute.xml
new file mode 100644
index 0000000000..1baaa7bbb6
--- /dev/null
+++ b/doc/classes/VisualShaderNodeReroute.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeReroute" inherits="VisualShaderNode" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ A node that allows rerouting a connection within the visual shader graph.
+ </brief_description>
+ <description>
+ Automatically adapts its port type to the type of the incoming connection and ensures valid connections.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_port_type" qualifiers="const">
+ <return type="int" enum="VisualShaderNode.PortType" />
+ <description>
+ Returns the port type of the reroute node.
+ </description>
+ </method>
+ </methods>
+</class>
diff --git a/drivers/d3d12/rendering_context_driver_d3d12.cpp b/drivers/d3d12/rendering_context_driver_d3d12.cpp
index 726be064bd..128b8bcd03 100644
--- a/drivers/d3d12/rendering_context_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_context_driver_d3d12.cpp
@@ -173,6 +173,7 @@ Error RenderingContextDriverD3D12::_initialize_devices() {
Device &device = driver_devices[i];
device.name = desc.Description;
device.vendor = Vendor(desc.VendorId);
+ device.workarounds = Workarounds();
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
device.type = DEVICE_TYPE_CPU;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 7048301e57..03f947cd05 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -2394,6 +2394,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
RS::EnvironmentBG bg_mode = environment_get_background(render_data.environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(render_data.environment);
bg_energy_multiplier *= environment_get_bg_intensity(render_data.environment);
+ RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(render_data.environment);
if (render_data.camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(render_data.camera_attributes);
@@ -2404,7 +2405,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if (environment_get_fog_enabled(render_data.environment)) {
+ if (!render_data.transparent_bg && environment_get_fog_enabled(render_data.environment)) {
draw_sky_fog_only = true;
GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color));
}
@@ -2414,13 +2415,13 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if (environment_get_fog_enabled(render_data.environment)) {
+ if (!render_data.transparent_bg && environment_get_fog_enabled(render_data.environment)) {
draw_sky_fog_only = true;
GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color));
}
} break;
case RS::ENV_BG_SKY: {
- draw_sky = true;
+ draw_sky = !render_data.transparent_bg;
} break;
case RS::ENV_BG_CANVAS: {
keep_color = true;
@@ -2433,8 +2434,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
default: {
}
}
+
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
Projection projection = render_data.cam_projection;
if (is_reflection_probe) {
diff --git a/drivers/vulkan/rendering_context_driver_vulkan.cpp b/drivers/vulkan/rendering_context_driver_vulkan.cpp
index 6eb25743f9..7cba820978 100644
--- a/drivers/vulkan/rendering_context_driver_vulkan.cpp
+++ b/drivers/vulkan/rendering_context_driver_vulkan.cpp
@@ -502,6 +502,9 @@ Error RenderingContextDriverVulkan::_initialize_devices() {
driver_device.name = String::utf8(props.deviceName);
driver_device.vendor = Vendor(props.vendorID);
driver_device.type = DeviceType(props.deviceType);
+ driver_device.workarounds = Workarounds();
+
+ _check_driver_workarounds(props, driver_device);
uint32_t queue_family_properties_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &queue_family_properties_count, nullptr);
@@ -515,6 +518,31 @@ Error RenderingContextDriverVulkan::_initialize_devices() {
return OK;
}
+void RenderingContextDriverVulkan::_check_driver_workarounds(const VkPhysicalDeviceProperties &p_device_properties, Device &r_device) {
+ // Workaround for the Adreno 6XX family of devices.
+ //
+ // There's a known issue with the Vulkan driver in this family of devices where it'll crash if a dynamic state for drawing is
+ // used in a command buffer before a dispatch call is issued. As both dynamic scissor and viewport are basic requirements for
+ // the engine to not bake this state into the PSO, the only known way to fix this issue is to reset the command buffer entirely.
+ //
+ // As the render graph has no built in limitations of whether it'll issue compute work before anything needs to draw on the
+ // frame, and there's no guarantee that compute work will never be dependent on rasterization in the future, this workaround
+ // will end recording on the current command buffer any time a compute list is encountered after a draw list was executed.
+ // A new command buffer will be created afterwards and the appropriate synchronization primitives will be inserted.
+ //
+ // Executing this workaround has the added cost of synchronization between all the command buffers that are created as well as
+ // all the individual submissions. This performance hit is accepted for the sake of being able to support these devices without
+ // limiting the design of the renderer.
+ //
+ // This bug was fixed in driver version 512.503.0, so we only enabled it on devices older than this.
+ //
+ r_device.workarounds.avoid_compute_after_draw =
+ r_device.vendor == VENDOR_QUALCOMM &&
+ p_device_properties.deviceID >= 0x6000000 && // Adreno 6xx
+ p_device_properties.driverVersion < VK_MAKE_VERSION(512, 503, 0) &&
+ r_device.name.find("Turnip") < 0;
+}
+
bool RenderingContextDriverVulkan::_use_validation_layers() const {
return Engine::get_singleton()->is_validation_layers_enabled();
}
diff --git a/drivers/vulkan/rendering_context_driver_vulkan.h b/drivers/vulkan/rendering_context_driver_vulkan.h
index 6348f90d55..f1d4021e32 100644
--- a/drivers/vulkan/rendering_context_driver_vulkan.h
+++ b/drivers/vulkan/rendering_context_driver_vulkan.h
@@ -105,6 +105,7 @@ private:
Error _initialize_instance_extensions();
Error _initialize_instance();
Error _initialize_devices();
+ void _check_driver_workarounds(const VkPhysicalDeviceProperties &p_device_properties, Device &r_device);
// Static callbacks.
static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, VkDebugUtilsMessageTypeFlagsEXT p_message_type, const VkDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *p_user_data);
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 7856d454d0..a949899ac4 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -547,8 +547,8 @@ ActionMapEditor::ActionMapEditor() {
action_list_search_by_event->set_h_size_flags(Control::SIZE_EXPAND_FILL);
action_list_search_by_event->set_stretch_ratio(0.75);
action_list_search_by_event->connect("event_changed", callable_mp(this, &ActionMapEditor::_search_by_event));
- action_list_search_by_event->connect(SceneStringNames::get_singleton()->focus_entered, callable_mp(this, &ActionMapEditor::_on_filter_focused));
- action_list_search_by_event->connect(SceneStringNames::get_singleton()->focus_exited, callable_mp(this, &ActionMapEditor::_on_filter_unfocused));
+ action_list_search_by_event->connect(SceneStringName(focus_entered), callable_mp(this, &ActionMapEditor::_on_filter_focused));
+ action_list_search_by_event->connect(SceneStringName(focus_exited), callable_mp(this, &ActionMapEditor::_on_filter_unfocused));
top_hbox->add_child(action_list_search_by_event);
Button *clear_all_search = memnew(Button);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index f21a0816ca..28aef2789b 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -2932,7 +2932,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
}
if (selected || editor->is_selection_active()) {
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
- if (!player->has_animation(SceneStringNames::get_singleton()->RESET) || animation != player->get_animation(SceneStringNames::get_singleton()->RESET)) {
+ if (!player->has_animation(SceneStringName(RESET)) || animation != player->get_animation(SceneStringName(RESET))) {
menu->add_icon_item(get_editor_theme_icon(SNAME("Reload")), TTR("Add RESET Value(s)"), MENU_KEY_ADD_RESET);
}
@@ -3691,8 +3691,8 @@ void AnimationTrackEditor::_animation_track_remove_request(int p_track, Ref<Anim
// Remove corresponding reset tracks if they are no longer needed.
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
- if (player->has_animation(SceneStringNames::get_singleton()->RESET)) {
- Ref<Animation> reset = player->get_animation(SceneStringNames::get_singleton()->RESET);
+ if (player->has_animation(SceneStringName(RESET))) {
+ Ref<Animation> reset = player->get_animation(SceneStringName(RESET));
if (reset != p_from_animation) {
for (int i = 0; i < reset->get_track_count(); i++) {
if (reset->track_get_path(i) == p_from_animation->track_get_path(p_track)) {
@@ -3798,7 +3798,7 @@ void AnimationTrackEditor::make_insert_queue() {
void AnimationTrackEditor::commit_insert_queue() {
bool reset_allowed = true;
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
- if (player->has_animation(SceneStringNames::get_singleton()->RESET) && player->get_animation(SceneStringNames::get_singleton()->RESET) == animation) {
+ if (player->has_animation(SceneStringName(RESET)) && player->get_animation(SceneStringName(RESET)) == animation) {
// Avoid messing with the reset animation itself.
reset_allowed = false;
} else {
@@ -4207,8 +4207,8 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
- if (player->has_animation(SceneStringNames::get_singleton()->RESET)) {
- return player->get_animation(SceneStringNames::get_singleton()->RESET);
+ if (player->has_animation(SceneStringName(RESET))) {
+ return player->get_animation(SceneStringName(RESET));
} else {
Ref<AnimationLibrary> al;
AnimationMixer *mixer = AnimationPlayerEditor::get_singleton()->fetch_mixer_for_library();
@@ -4224,9 +4224,9 @@ Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
reset_anim.instantiate();
reset_anim->set_length(ANIM_MIN_LENGTH);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->add_do_method(al.ptr(), "add_animation", SceneStringNames::get_singleton()->RESET, reset_anim);
+ undo_redo->add_do_method(al.ptr(), "add_animation", SceneStringName(RESET), reset_anim);
undo_redo->add_do_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player);
- undo_redo->add_undo_method(al.ptr(), "remove_animation", SceneStringNames::get_singleton()->RESET);
+ undo_redo->add_undo_method(al.ptr(), "remove_animation", SceneStringName(RESET));
undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player);
return reset_anim;
}
@@ -5024,8 +5024,8 @@ void AnimationTrackEditor::_add_track(int p_type) {
void AnimationTrackEditor::_fetch_value_track_options(const NodePath &p_path, Animation::UpdateMode *r_update_mode, Animation::InterpolationType *r_interpolation_type, bool *r_loop_wrap) {
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
- if (player->has_animation(SceneStringNames::get_singleton()->RESET)) {
- Ref<Animation> reset_anim = player->get_animation(SceneStringNames::get_singleton()->RESET);
+ if (player->has_animation(SceneStringName(RESET))) {
+ Ref<Animation> reset_anim = player->get_animation(SceneStringName(RESET));
int rt = reset_anim->find_track(p_path, Animation::TrackType::TYPE_VALUE);
if (rt >= 0) {
*r_update_mode = reset_anim->value_track_get_update_mode(rt);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index d0ad0e8b11..fd728dc393 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -3760,6 +3760,14 @@ EditorHelpBit::EditorHelpBit(const String &p_symbol) {
/// EditorHelpBitTooltip ///
+void EditorHelpBitTooltip::_safe_queue_free() {
+ if (_pushing_input > 0) {
+ _need_free = true;
+ } else {
+ queue_free();
+ }
+}
+
void EditorHelpBitTooltip::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_WM_MOUSE_ENTER:
@@ -3778,7 +3786,13 @@ void EditorHelpBitTooltip::_input_from_window(const Ref<InputEvent> &p_event) {
} else {
const Ref<InputEventMouse> mouse_event = p_event;
if (mouse_event.is_null()) {
+ // GH-91652. Prevents use-after-free since `ProgressDialog` calls `Main::iteration()`.
+ _pushing_input++;
get_parent_viewport()->push_input(p_event);
+ _pushing_input--;
+ if (_pushing_input <= 0 && _need_free) {
+ queue_free();
+ }
}
}
}
@@ -3839,7 +3853,7 @@ EditorHelpBitTooltip::EditorHelpBitTooltip(Control *p_target) {
timer = memnew(Timer);
timer->set_wait_time(0.2);
- timer->connect("timeout", callable_mp(static_cast<Node *>(this), &Node::queue_free));
+ timer->connect("timeout", callable_mp(this, &EditorHelpBitTooltip::_safe_queue_free));
add_child(timer);
ERR_FAIL_NULL(p_target);
diff --git a/editor/editor_help.h b/editor/editor_help.h
index ca3a05275f..76f9e71931 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -325,6 +325,10 @@ class EditorHelpBitTooltip : public PopupPanel {
GDCLASS(EditorHelpBitTooltip, PopupPanel);
Timer *timer = nullptr;
+ int _pushing_input = 0;
+ bool _need_free = false;
+
+ void _safe_queue_free();
protected:
void _notification(int p_what);
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 266901c938..a9c5586ba2 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -50,6 +50,7 @@
#include "scene/property_utils.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/style_box_flat.h"
+#include "scene/scene_string_names.h"
bool EditorInspector::_property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style) {
if (p_property_path.containsn(p_filter)) {
@@ -390,6 +391,17 @@ void EditorProperty::_notification(int p_what) {
delete_rect = Rect2();
}
} break;
+ case NOTIFICATION_ENTER_TREE: {
+ if (has_borders) {
+ get_parent()->connect(SceneStringName(theme_changed), callable_mp(this, &EditorProperty::_update_property_bg));
+ _update_property_bg();
+ }
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ if (has_borders) {
+ get_parent()->disconnect(SceneStringName(theme_changed), callable_mp(this, &EditorProperty::_update_property_bg));
+ }
+ }
}
}
@@ -810,6 +822,9 @@ void EditorProperty::set_label_reference(Control *p_control) {
void EditorProperty::set_bottom_editor(Control *p_control) {
bottom_editor = p_control;
+ if (has_borders) {
+ _update_property_bg();
+ }
}
Variant EditorProperty::_get_cache_value(const StringName &p_prop, bool &r_valid) const {
@@ -4087,6 +4102,9 @@ void EditorInspector::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
bool needs_update = false;
+ if (EditorThemeManager::is_generated_theme_outdated() && !sub_inspector) {
+ add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
+ }
if (use_settings_name_style && EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_settings_style();
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index b052693524..8fe690fddf 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -136,6 +136,8 @@ private:
void _update_pin_flags();
protected:
+ bool has_borders = false;
+
void _notification(int p_what);
static void _bind_methods();
virtual void _set_read_only(bool p_read_only);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index d7f197b569..e8a0b77184 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -4073,11 +4073,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
EditorDebuggerNode::get_singleton()->update_live_edit_root();
- // Tell everything to edit this object, unless we're in the process of restoring scenes.
- // If we are, we'll edit it after the restoration is done.
- if (!restoring_scenes) {
- push_item(new_scene);
- } else {
+ if (restoring_scenes) {
// Initialize history for restored scenes.
ObjectID id = new_scene->get_instance_id();
if (id != editor_history.get_current()) {
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 816d3d7778..c73bdafb1a 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -3141,7 +3141,7 @@ void EditorPropertyResource::_resource_changed(const Ref<Resource> &p_resource)
// Changing the value of Script-type exported variables of the main script should not trigger saving/reloading properties.
bool is_script = false;
Ref<Script> s = p_resource;
- if (get_edited_object() && s.is_valid() && get_edited_property() == CoreStringNames::get_singleton()->_script) {
+ if (get_edited_object() && s.is_valid() && get_edited_property() == CoreStringName(script)) {
is_script = true;
InspectorDock::get_singleton()->store_script_properties(get_edited_object());
s->call("set_instance_base_type", get_edited_object()->get_class());
@@ -3364,8 +3364,6 @@ void EditorPropertyResource::update_property() {
EditorNode::get_singleton()->hide_unused_editors();
opened_editor = false;
}
-
- _update_property_bg();
}
}
}
@@ -3422,12 +3420,6 @@ bool EditorPropertyResource::is_colored(ColorationMode p_mode) {
void EditorPropertyResource::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_THEME_CHANGED: {
- if (EditorThemeManager::is_generated_theme_outdated()) {
- _update_property_bg();
- }
- } break;
-
case NOTIFICATION_EXIT_TREE: {
const EditorInspector *ei = get_parent_inspector();
if (ei && !ei->is_main_editor_inspector()) {
@@ -3439,6 +3431,7 @@ void EditorPropertyResource::_notification(int p_what) {
EditorPropertyResource::EditorPropertyResource() {
use_sub_inspector = bool(EDITOR_GET("interface/inspector/open_resources_in_current_inspector"));
+ has_borders = true;
}
////////////// DEFAULT PLUGIN //////////////////////
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index c3142b4cd0..e338c5c8bd 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -391,8 +391,6 @@ void EditorPropertyArray::update_property() {
paginator->connect("page_changed", callable_mp(this, &EditorPropertyArray::_page_changed));
vbox->add_child(paginator);
- _update_property_bg();
-
for (int i = 0; i < page_length; i++) {
_create_new_property_slot();
}
@@ -454,7 +452,6 @@ void EditorPropertyArray::update_property() {
memdelete(container);
button_add_item = nullptr;
container = nullptr;
- _update_property_bg();
slots.clear();
}
}
@@ -628,10 +625,6 @@ Node *EditorPropertyArray::get_base_node() {
void EditorPropertyArray::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
- if (EditorThemeManager::is_generated_theme_outdated()) {
- _update_property_bg();
- }
- [[fallthrough]];
case NOTIFICATION_ENTER_TREE: {
change_type->clear();
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
@@ -851,6 +844,7 @@ EditorPropertyArray::EditorPropertyArray() {
subtype = Variant::NIL;
subtype_hint = PROPERTY_HINT_NONE;
subtype_hint_string = "";
+ has_borders = true;
}
///////////////////// DICTIONARY ///////////////////////////
@@ -1000,7 +994,6 @@ void EditorPropertyDictionary::update_property() {
paginator = memnew(EditorPaginator);
paginator->connect("page_changed", callable_mp(this, &EditorPropertyDictionary::_page_changed));
vbox->add_child(paginator);
- _update_property_bg();
for (int i = 0; i < page_length; i++) {
_create_new_property_slot(slots.size());
@@ -1075,7 +1068,6 @@ void EditorPropertyDictionary::update_property() {
memdelete(container);
button_add_item = nullptr;
container = nullptr;
- _update_property_bg();
add_panel = nullptr;
slots.clear();
}
@@ -1089,10 +1081,6 @@ void EditorPropertyDictionary::_object_id_selected(const StringName &p_property,
void EditorPropertyDictionary::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
- if (EditorThemeManager::is_generated_theme_outdated()) {
- _update_property_bg();
- }
- [[fallthrough]];
case NOTIFICATION_ENTER_TREE: {
change_type->clear();
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
@@ -1109,6 +1097,7 @@ void EditorPropertyDictionary::_notification(int p_what) {
if (button_add_item) {
button_add_item->set_icon(get_editor_theme_icon(SNAME("Add")));
+ add_panel->add_theme_style_override(SNAME("panel"), get_theme_stylebox(SNAME("DictionaryAddItem")));
}
} break;
}
@@ -1166,6 +1155,7 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
add_child(change_type);
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu));
changing_type_index = -1;
+ has_borders = true;
}
///////////////////// LOCALIZABLE STRING ///////////////////////////
diff --git a/editor/gui/editor_scene_tabs.cpp b/editor/gui/editor_scene_tabs.cpp
index 94fac59b9b..b824a90170 100644
--- a/editor/gui/editor_scene_tabs.cpp
+++ b/editor/gui/editor_scene_tabs.cpp
@@ -63,6 +63,7 @@ void EditorSceneTabs::_notification(int p_what) {
if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/scene_tabs")) {
scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int());
scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE);
+ _scene_tabs_resized();
}
} break;
}
diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp
index 5f42bb828f..c454ebc6eb 100644
--- a/editor/import/resource_importer_imagefont.cpp
+++ b/editor/import/resource_importer_imagefont.cpp
@@ -62,8 +62,8 @@ bool ResourceImporterImageFont::get_option_visibility(const String &p_path, cons
void ResourceImporterImageFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "character_ranges"), Vector<String>()));
r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "kerning_pairs"), Vector<String>()));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns"), 1));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows"), 1));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns", PROPERTY_HINT_RANGE, "1,1024,1,or_greater"), 1));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows", PROPERTY_HINT_RANGE, "1,1024,1,or_greater"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::RECT2I, "image_margin"), Rect2i()));
r_options->push_back(ImportOption(PropertyInfo(Variant::RECT2I, "character_margin"), Rect2i()));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "ascent"), 0));
@@ -94,6 +94,8 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
Error err = ImageLoader::load_image(p_source_file, img);
ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, vformat("Can't load font texture: \"%s\".", p_source_file));
+ ERR_FAIL_COND_V_MSG(columns <= 0, ERR_FILE_CANT_READ, vformat("Columns (%d) must be positive.", columns));
+ ERR_FAIL_COND_V_MSG(rows <= 0, ERR_FILE_CANT_READ, vformat("Rows (%d) must be positive.", rows));
int count = columns * rows;
int chr_cell_width = (img->get_width() - img_margin.position.x - img_margin.size.x) / columns;
int chr_cell_height = (img->get_height() - img_margin.position.y - img_margin.size.y) / rows;
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 8de00dfcd1..43d8bc332c 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -984,12 +984,12 @@ void AnimationPlayerEditor::_update_animation_list_icons() {
Ref<Texture2D> icon;
if (anim_name == player->get_autoplay()) {
- if (anim_name == SceneStringNames::get_singleton()->RESET) {
+ if (anim_name == SceneStringName(RESET)) {
icon = autoplay_reset_icon;
} else {
icon = autoplay_icon;
}
- } else if (anim_name == SceneStringNames::get_singleton()->RESET) {
+ } else if (anim_name == SceneStringName(RESET)) {
icon = reset_icon;
}
@@ -1459,7 +1459,7 @@ void AnimationPlayerEditor::_onion_skinning_menu(int p_option) {
onion.enabled = !onion.enabled;
if (onion.enabled) {
- if (get_player() && !get_player()->has_animation(SceneStringNames::get_singleton()->RESET)) {
+ if (get_player() && !get_player()->has_animation(SceneStringName(RESET))) {
EditorNode::get_singleton()->show_warning(TTR("Onion skinning requires a RESET animation."));
}
_start_onion_skinning(); // It will check for RESET animation anyway.
@@ -1592,7 +1592,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_1() {
return;
}
- if (!onion.enabled || !is_visible() || !get_player() || !get_player()->has_animation(SceneStringNames::get_singleton()->RESET)) {
+ if (!onion.enabled || !is_visible() || !get_player() || !get_player()->has_animation(SceneStringName(RESET))) {
_stop_onion_skinning();
return;
}
@@ -1783,7 +1783,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2_epilog() {
}
void AnimationPlayerEditor::_start_onion_skinning() {
- if (get_player() && !get_player()->has_animation(SceneStringNames::get_singleton()->RESET)) {
+ if (get_player() && !get_player()->has_animation(SceneStringName(RESET))) {
onion.enabled = false;
onion_toggle->set_pressed_no_signal(false);
return;
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index f24747d903..1314b26b1a 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -119,7 +119,7 @@ String AnimationNodeStateMachineEditor::_get_root_playback_path(String &r_node_d
if (node_directory_path.size()) {
r_node_directory += "/";
}
- base_path = !edited_path.size() ? String(SceneStringNames::get_singleton()->parameters_base_path) + "playback" : String(SceneStringNames::get_singleton()->parameters_base_path) + base_path + "/playback";
+ base_path = !edited_path.size() ? String(SceneStringName(parameters_base_path)) + "playback" : String(SceneStringName(parameters_base_path)) + base_path + "/playback";
} else {
// Hmmm, we have to return Grouped state machine playback...
// It will give the user the error that Root/Nested state machine should be retrieved, that would be kind :-)
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index c7f132bec1..08e3cb34a4 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -221,7 +221,7 @@ void AnimationTreeEditor::remove_plugin(AnimationTreeNodeEditorPlugin *p_editor)
}
String AnimationTreeEditor::get_base_path() {
- String path = SceneStringNames::get_singleton()->parameters_base_path;
+ String path = SceneStringName(parameters_base_path);
for (int i = 0; i < edited_path.size(); i++) {
path += edited_path[i] + "/";
}
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 258396ff31..b2ff03a6d3 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -387,7 +387,7 @@ void CollisionShape2DEditor::_shape_changed() {
canvas_item_editor->update_viewport();
if (current_shape.is_valid()) {
- current_shape->disconnect(SceneStringNames::get_singleton()->changed, callable_mp(canvas_item_editor, &CanvasItemEditor::update_viewport));
+ current_shape->disconnect_changed(callable_mp(canvas_item_editor, &CanvasItemEditor::update_viewport));
current_shape = Ref<Shape2D>();
shape_type = -1;
}
@@ -399,7 +399,7 @@ void CollisionShape2DEditor::_shape_changed() {
current_shape = node->get_shape();
if (current_shape.is_valid()) {
- current_shape->connect(SceneStringNames::get_singleton()->changed, callable_mp(canvas_item_editor, &CanvasItemEditor::update_viewport));
+ current_shape->connect_changed(callable_mp(canvas_item_editor, &CanvasItemEditor::update_viewport));
} else {
return;
}
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 92c9572a02..ce99b87a60 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -172,14 +172,14 @@ void MeshInstance3DEditor::_create_collision_shape() {
ur->add_do_method(instance, "add_child", body, true);
ur->add_do_method(body, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), body);
for (Ref<Shape3D> shape : shapes) {
CollisionShape3D *cshape = memnew(CollisionShape3D);
cshape->set_shape(shape);
body->add_child(cshape, true);
ur->add_do_method(cshape, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), cshape);
}
ur->add_do_reference(body);
ur->add_undo_method(instance, "remove_child", body);
@@ -191,7 +191,7 @@ void MeshInstance3DEditor::_create_collision_shape() {
cshape->set_transform(node->get_transform());
ur->add_do_method(E, "add_sibling", cshape, true);
ur->add_do_method(cshape, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), cshape);
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
}
@@ -232,7 +232,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(node, "add_child", nmi, true);
ur->add_do_method(nmi, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, nmi);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), nmi);
ur->add_do_reference(nmi);
ur->add_undo_method(node, "remove_child", nmi);
@@ -509,7 +509,7 @@ void MeshInstance3DEditor::_create_outline_mesh() {
ur->add_do_method(node, "add_child", mi, true);
ur->add_do_method(mi, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, mi);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), mi);
ur->add_do_reference(mi);
ur->add_undo_method(node, "remove_child", mi);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 723dbf5d6c..23937fa330 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -973,7 +973,7 @@ void ScriptEditor::_queue_close_tabs() {
// Maybe there are unsaved changes.
if (se->is_unsaved()) {
_ask_close_current_unsaved_tab(se);
- erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), CONNECT_ONE_SHOT);
+ erase_tab_confirm->connect(SceneStringName(visibility_changed), callable_mp(this, &ScriptEditor::_queue_close_tabs), CONNECT_ONE_SHOT);
break;
}
}
@@ -4238,7 +4238,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) {
autosave_timer = memnew(Timer);
autosave_timer->set_one_shot(false);
- autosave_timer->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &ScriptEditor::_update_autosave_timer));
+ autosave_timer->connect(SceneStringName(tree_entered), callable_mp(this, &ScriptEditor::_update_autosave_timer));
autosave_timer->connect("timeout", callable_mp(this, &ScriptEditor::_autosave_scripts));
add_child(autosave_timer);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 1bd6b4e5b1..c80dc1ea77 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -410,8 +410,8 @@ void Skeleton3DEditor::create_physical_skeleton() {
ur->add_do_method(physical_bone, "set_joint_type", PhysicalBone3D::JOINT_TYPE_PIN);
}
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, physical_bone);
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, collision_shape);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), physical_bone);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), collision_shape);
ur->add_do_reference(physical_bone);
ur->add_undo_method(simulator, "remove_child", physical_bone);
@@ -842,10 +842,10 @@ void Skeleton3DEditor::_notification(int p_what) {
joint_tree->connect("item_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_selection_changed));
joint_tree->connect("item_mouse_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_rmb_select));
#ifdef TOOLS_ENABLED
- skeleton->connect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_draw_gizmo));
- skeleton->connect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_update_properties));
- skeleton->connect(SceneStringNames::get_singleton()->bone_enabled_changed, callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed));
- skeleton->connect(SceneStringNames::get_singleton()->show_rest_only_changed, callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible));
+ skeleton->connect(SceneStringName(pose_updated), callable_mp(this, &Skeleton3DEditor::_draw_gizmo));
+ skeleton->connect(SceneStringName(pose_updated), callable_mp(this, &Skeleton3DEditor::_update_properties));
+ skeleton->connect(SceneStringName(bone_enabled_changed), callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed));
+ skeleton->connect(SceneStringName(show_rest_only_changed), callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible));
#endif
get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Object::CONNECT_ONE_SHOT);
@@ -870,10 +870,10 @@ void Skeleton3DEditor::_notification(int p_what) {
if (skeleton) {
select_bone(-1); // Requires that the joint_tree has not been deleted.
#ifdef TOOLS_ENABLED
- skeleton->disconnect(SceneStringNames::get_singleton()->show_rest_only_changed, callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible));
- skeleton->disconnect(SceneStringNames::get_singleton()->bone_enabled_changed, callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed));
- skeleton->disconnect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_draw_gizmo));
- skeleton->disconnect(SceneStringNames::get_singleton()->pose_updated, callable_mp(this, &Skeleton3DEditor::_update_properties));
+ skeleton->disconnect(SceneStringName(show_rest_only_changed), callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible));
+ skeleton->disconnect(SceneStringName(bone_enabled_changed), callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed));
+ skeleton->disconnect(SceneStringName(pose_updated), callable_mp(this, &Skeleton3DEditor::_draw_gizmo));
+ skeleton->disconnect(SceneStringName(pose_updated), callable_mp(this, &Skeleton3DEditor::_update_properties));
skeleton->set_transform_gizmo_visible(true);
#endif
if (handles_mesh_instance->get_parent()) {
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index eef9557ca8..2d77c932c7 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -1733,7 +1733,7 @@ void SpriteFramesEditor::_autoplay_pressed() {
if (animated_sprite) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Toggle Autoplay"), UndoRedo::MERGE_DISABLE, frames.ptr());
+ undo_redo->create_action(TTR("Toggle Autoplay"), UndoRedo::MERGE_DISABLE, animated_sprite);
String current = animated_sprite->call("get_animation");
String current_auto = animated_sprite->call("get_autoplay");
if (current == current_auto) {
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index 1d32965b4a..f52c89e736 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -49,6 +49,11 @@ Dictionary GDShaderSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
for (const Point2i &region : disabled_branch_regions) {
if (p_line >= region.x && p_line <= region.y) {
+ // When "color_regions[0].p_start_key.length() > 2",
+ // disabled_branch_region causes color_region to break.
+ // This should be seen as a temporary solution.
+ CodeHighlighter::_get_line_syntax_highlighting_impl(p_line);
+
Dictionary highlighter_info;
highlighter_info["color"] = disabled_branch_color;
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 1a1b14bb84..2878472c7b 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -135,7 +135,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::edit(Ref<TileSet>
// Disconnect to changes.
if (tile_set_atlas_source.is_valid()) {
- tile_set_atlas_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ tile_set_atlas_source->disconnect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
tile_set = p_tile_set;
@@ -144,8 +144,8 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::edit(Ref<TileSet>
// Connect to changes.
if (tile_set_atlas_source.is_valid()) {
- if (!tile_set_atlas_source->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
- tile_set_atlas_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ if (!tile_set_atlas_source->is_connected(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed))) {
+ tile_set_atlas_source->connect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
}
@@ -522,8 +522,8 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(Ref<TileSetAtlasSource
if (tile_set_atlas_source.is_valid() && tile_set_atlas_source->has_tile(coords) && tile_set_atlas_source->has_alternative_tile(coords, alternative)) {
TileData *tile_data = tile_set_atlas_source->get_tile_data(coords, alternative);
- if (tile_data->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
- tile_data->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ if (tile_data->is_connected(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed))) {
+ tile_data->disconnect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
}
}
@@ -538,8 +538,8 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(Ref<TileSetAtlasSource
if (tile_set_atlas_source->has_tile(coords) && tile_set_atlas_source->has_alternative_tile(coords, alternative)) {
TileData *tile_data = tile_set_atlas_source->get_tile_data(coords, alternative);
- if (!tile_data->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
- tile_data->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ if (!tile_data->is_connected(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed))) {
+ tile_data->connect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
}
}
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index e0151351b5..f42fac6d59 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -117,7 +117,7 @@ void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::ed
// Disconnect to changes.
if (tile_set_scenes_collection_source) {
- tile_set_scenes_collection_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ tile_set_scenes_collection_source->disconnect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
tile_set = p_tile_set;
@@ -126,8 +126,8 @@ void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::ed
// Connect to changes.
if (tile_set_scenes_collection_source) {
- if (!tile_set_scenes_collection_source->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
- tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ if (!tile_set_scenes_collection_source->is_connected(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed))) {
+ tile_set_scenes_collection_source->connect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
}
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 35db52a42e..5cb5f5660e 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -45,6 +45,7 @@
#include "editor/plugins/curve_editor_plugin.h"
#include "editor/plugins/shader_editor_plugin.h"
#include "editor/themes/editor_scale.h"
+#include "scene/animation/tween.h"
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
#include "scene/gui/code_edit.h"
@@ -104,6 +105,83 @@ void VisualShaderNodePlugin::_bind_methods() {
///////////////////
+void VSGraphNode::_draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color, const Color &p_rim_color) {
+ Ref<Texture2D> port_icon = p_left ? get_slot_custom_icon_left(p_slot_index) : get_slot_custom_icon_right(p_slot_index);
+
+ Point2 icon_offset;
+ if (!port_icon.is_valid()) {
+ port_icon = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
+ }
+
+ icon_offset = -port_icon->get_size() * 0.5;
+
+ // Draw "shadow"/outline in the connection rim color.
+ draw_texture_rect(port_icon, Rect2(p_pos + icon_offset - Size2(2, 2), port_icon->get_size() + Size2(4, 4)), false, p_rim_color);
+ draw_texture(port_icon, p_pos + icon_offset, p_color);
+}
+
+void VSGraphNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) {
+ Color rim_color = get_theme_color(SNAME("connection_rim_color"), SNAME("GraphEdit"));
+ _draw_port(p_slot_index, p_pos, p_left, p_color, rim_color);
+}
+
+///////////////////
+
+void VSRerouteNode::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ connect("mouse_entered", callable_mp(this, &VSRerouteNode::_on_mouse_entered));
+ connect("mouse_exited", callable_mp(this, &VSRerouteNode::_on_mouse_exited));
+ } break;
+ case NOTIFICATION_DRAW: {
+ Vector2 offset = Vector2(0, -16);
+ Color drag_bg_color = get_theme_color(SNAME("drag_background"), SNAME("VSRerouteNode"));
+ draw_circle(get_size() * 0.5 + offset, 16, Color(drag_bg_color, selected ? 1 : icon_opacity));
+
+ Ref<Texture2D> icon = get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons"));
+ Point2 icon_offset = -icon->get_size() * 0.5 + get_size() * 0.5 + offset;
+ draw_texture(icon, icon_offset, Color(1, 1, 1, selected ? 1 : icon_opacity));
+ } break;
+ }
+}
+
+void VSRerouteNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) {
+ Color rim_color = selected ? get_theme_color("selected_rim_color", "VSRerouteNode") : get_theme_color("connection_rim_color", "GraphEdit");
+ _draw_port(p_slot_index, p_pos, p_left, p_color, rim_color);
+}
+
+VSRerouteNode::VSRerouteNode() {
+ Label *title_lbl = Object::cast_to<Label>(get_titlebar_hbox()->get_child(0));
+ title_lbl->hide();
+
+ const Size2 size = Size2(32, 32) * EDSCALE;
+
+ Control *slot_area = memnew(Control);
+ slot_area->set_custom_minimum_size(size);
+ slot_area->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ add_child(slot_area);
+
+ // Lay the input and output ports on top of each other to create the illusion of a single port.
+ add_theme_constant_override("port_h_offset", size.width / 2);
+}
+
+void VSRerouteNode::set_icon_opacity(float p_opacity) {
+ icon_opacity = p_opacity;
+ queue_redraw();
+}
+
+void VSRerouteNode::_on_mouse_entered() {
+ Ref<Tween> tween = create_tween();
+ tween->tween_method(callable_mp(this, &VSRerouteNode::set_icon_opacity), 0.0, 1.0, FADE_ANIMATION_LENGTH_SEC);
+}
+
+void VSRerouteNode::_on_mouse_exited() {
+ Ref<Tween> tween = create_tween();
+ tween->tween_method(callable_mp(this, &VSRerouteNode::set_icon_opacity), 1.0, 0.0, FADE_ANIMATION_LENGTH_SEC);
+}
+
+///////////////////
+
VisualShaderGraphPlugin::VisualShaderGraphPlugin() {
vs_msdf_fonts_theme.instantiate();
}
@@ -376,6 +454,15 @@ void VisualShaderGraphPlugin::set_frame_autoshrink_enabled(VisualShader::Type p_
frame->set_autoshrink_enabled(p_enable);
}
+void VisualShaderGraphPlugin::update_reroute_nodes() {
+ for (const KeyValue<int, Link> &E : links) {
+ Ref<VisualShaderNodeReroute> reroute_node = Object::cast_to<VisualShaderNodeReroute>(E.value.visual_node);
+ if (reroute_node.is_valid()) {
+ update_node(visual_shader->get_shader_type(), E.key);
+ }
+ }
+}
+
Ref<Script> VisualShaderGraphPlugin::get_node_script(int p_node_id) const {
if (!links.has(p_node_id)) {
return Ref<Script>();
@@ -572,6 +659,9 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
bool is_expression = expression_node.is_valid();
String expression = "";
+ Ref<VisualShaderNodeReroute> reroute_node = vsnode;
+ bool is_reroute = reroute_node.is_valid();
+
Ref<VisualShaderNodeCustom> custom_node = vsnode;
if (custom_node.is_valid()) {
custom_node->_set_initialized(true);
@@ -582,8 +672,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
GraphFrame *frame = memnew(GraphFrame);
frame->set_title(vsnode->get_caption());
node = frame;
+ } else if (is_reroute) {
+ VSRerouteNode *reroute_gnode = memnew(VSRerouteNode);
+ reroute_gnode->set_ignore_invalid_connection_type(true);
+ node = reroute_gnode;
} else {
- GraphNode *gnode = memnew(GraphNode);
+ VSGraphNode *gnode = memnew(VSGraphNode);
gnode->set_title(vsnode->get_caption());
node = gnode;
}
@@ -598,7 +692,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
node->set_theme(vs_msdf_fonts_theme);
// Set the node's titlebar color based on its category.
- if (vsnode->get_category() != VisualShaderNode::CATEGORY_NONE) {
+ if (vsnode->get_category() != VisualShaderNode::CATEGORY_NONE && !is_frame && !is_reroute) {
Ref<StyleBoxFlat> sb_colored = editor->get_theme_stylebox("titlebar", "GraphNode")->duplicate();
sb_colored->set_bg_color(category_color[vsnode->get_category()]);
node->add_theme_style_override("titlebar", sb_colored);
@@ -685,9 +779,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
return;
}
- Control *content_offset = memnew(Control);
- content_offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
- node->add_child(content_offset);
+ if (!is_reroute) {
+ Control *content_offset = memnew(Control);
+ content_offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
+ node->add_child(content_offset);
+ }
if (is_group) {
port_offset += 1;
@@ -696,7 +792,9 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
// Set the minimum width of a node based on the preview size to avoid a resize when toggling the preview.
Ref<StyleBoxFlat> graph_node_stylebox = graph->get_theme_stylebox("panel", "GraphNode");
int port_preview_size = EDITOR_GET("editors/visual_editors/visual_shader/port_preview_size");
- node->set_custom_minimum_size(Size2((Math::ceil(graph_node_stylebox->get_minimum_size().width) + port_preview_size) * EDSCALE, 0));
+ if (!is_frame && !is_reroute) {
+ node->set_custom_minimum_size(Size2((Math::ceil(graph_node_stylebox->get_minimum_size().width) + port_preview_size) * EDSCALE, 0));
+ }
Ref<VisualShaderNodeParticleEmit> emit = vsnode;
if (emit.is_valid()) {
@@ -1129,7 +1227,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
port_offset++;
}
- if (!is_first_hbox) {
+ if (!is_first_hbox && !is_reroute) {
node->add_child(hb);
if (curve_xyz.is_valid()) {
node->move_child(hb, 1 + expanded_port_counter);
@@ -1140,9 +1238,9 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
continue;
}
- int idx = 1;
- if (!is_first_hbox) {
- idx = i + port_offset;
+ int idx = is_first_hbox ? 1 : i + port_offset;
+ if (is_reroute) {
+ idx = 0;
}
if (!is_frame) {
GraphNode *graph_node = Object::cast_to<GraphNode>(node);
@@ -1243,7 +1341,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
if (vsnode->get_output_port_for_preview() >= 0) {
has_relative_parameter_instances = is_node_has_parameter_instances_relatively(p_type, p_id);
show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview(), !has_relative_parameter_instances);
- } else {
+ } else if (!is_reroute) {
offset = memnew(Control);
offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE));
node->add_child(offset);
@@ -1342,6 +1440,13 @@ void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_fro
}
if (visual_shader.is_valid() && visual_shader->get_shader_type() == p_type) {
+ // Update reroute nodes since their port type might have changed.
+ Ref<VisualShaderNodeReroute> reroute_to = visual_shader->get_node(p_type, p_to_node);
+ Ref<VisualShaderNodeReroute> reroute_from = visual_shader->get_node(p_type, p_from_node);
+ if (reroute_to.is_valid() || reroute_from.is_valid()) {
+ update_reroute_nodes();
+ }
+
graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
connections.push_back({ p_from_node, p_from_port, p_to_node, p_to_port });
@@ -1954,6 +2059,7 @@ void VisualShaderEditor::_update_options_menu() {
static Vector<String> type_filter_exceptions;
if (type_filter_exceptions.is_empty()) {
type_filter_exceptions.append("VisualShaderNodeExpression");
+ type_filter_exceptions.append("VisualShaderNodeReroute");
}
for (int i = 0; i < add_options.size(); i++) {
@@ -3478,6 +3584,8 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
frame->set_size(Size2(320 * EDSCALE, 180 * EDSCALE));
}
+ Ref<VisualShaderNodeReroute> reroute = vsnode;
+
bool created_expression_port = false;
// A node is inserted in an already present connection.
@@ -3488,6 +3596,61 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, to_node, to_slot);
}
+ // Create a connection from the output port of an existing node to the new one.
+ if (from_node != -1 && from_slot != -1) {
+ VisualShaderNode::PortType output_port_type = visual_shader->get_node(type, from_node)->get_output_port_type(from_slot);
+
+ if (expr && expr->is_editable()) {
+ expr->add_input_port(0, output_port_type, "input0");
+ created_expression_port = true;
+ }
+
+ if (vsnode->get_input_port_count() > 0 || created_expression_port) {
+ int _to_node = id_to_use;
+
+ if (created_expression_port) {
+ int _to_slot = 0;
+ undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ } else {
+ int _to_slot = -1;
+
+ // Attempting to connect to the default input port or to the first correct port (if it's not found).
+ for (int i = 0; i < vsnode->get_input_port_count(); i++) {
+ if (visual_shader->is_port_types_compatible(output_port_type, vsnode->get_input_port_type(i)) || reroute.is_valid()) {
+ if (i == vsnode->get_default_input_port(output_port_type)) {
+ _to_slot = i;
+ break;
+ } else if (_to_slot == -1) {
+ _to_slot = i;
+ }
+ }
+ }
+
+ if (_to_slot >= 0) {
+ undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
+ }
+ }
+
+ if (output_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
+ if (is_texture2d) {
+ undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeTexture::SOURCE_PORT);
+ }
+ if (is_texture3d || is_texture2d_array) {
+ undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeSample3D::SOURCE_PORT);
+ }
+ if (is_cubemap) {
+ undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeCubemap::SOURCE_PORT);
+ }
+ }
+ }
+ }
+
// Create a connection from the new node to an input port of an existing one.
if (to_node != -1 && to_slot != -1) {
VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
@@ -3548,7 +3711,7 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
// Attempting to connect to the first correct port.
for (int i = 0; i < vsnode->get_output_port_count(); i++) {
- if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(i), input_port_type)) {
+ if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(i), input_port_type) || reroute.is_valid()) {
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, i, to_node, to_slot);
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, i, to_node, to_slot);
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, i, to_node, to_slot);
@@ -3560,60 +3723,6 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
}
}
- // Create a connection from the output port of an existing node to the new one.
- if (from_node != -1 && from_slot != -1) {
- VisualShaderNode::PortType output_port_type = visual_shader->get_node(type, from_node)->get_output_port_type(from_slot);
-
- if (expr && expr->is_editable()) {
- expr->add_input_port(0, output_port_type, "input0");
- created_expression_port = true;
- }
-
- if (vsnode->get_input_port_count() > 0 || created_expression_port) {
- int _to_node = id_to_use;
-
- if (created_expression_port) {
- int _to_slot = 0;
- undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- } else {
- int _to_slot = -1;
-
- // Attempting to connect to the default input port or to the first correct port (if it's not found).
- for (int i = 0; i < vsnode->get_input_port_count(); i++) {
- if (visual_shader->is_port_types_compatible(output_port_type, vsnode->get_input_port_type(i))) {
- if (i == vsnode->get_default_input_port(output_port_type)) {
- _to_slot = i;
- break;
- } else if (_to_slot == -1) {
- _to_slot = i;
- }
- }
- }
-
- if (_to_slot >= 0) {
- undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
- }
- }
-
- if (output_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
- if (is_texture2d) {
- undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeTexture::SOURCE_PORT);
- }
- if (is_texture3d || is_texture2d_array) {
- undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeSample3D::SOURCE_PORT);
- }
- if (is_cubemap) {
- undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeCubemap::SOURCE_PORT);
- }
- }
- }
- }
_member_cancel();
if (is_parameter) {
@@ -3836,6 +3945,9 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, from);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, from);
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, to);
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, to);
undo_redo->commit_action();
@@ -3931,10 +4043,12 @@ bool VisualShaderEditor::_check_node_drop_on_connection(const Vector2 &p_positio
VisualShaderNode::PortType original_port_type_from = visual_shader->get_node(shader_type, String(intersecting_connection->from_node).to_int())->get_output_port_type(intersecting_connection->from_port);
VisualShaderNode::PortType original_port_type_to = visual_shader->get_node(shader_type, String(intersecting_connection->to_node).to_int())->get_input_port_type(intersecting_connection->to_port);
+ Ref<VisualShaderNodeReroute> reroute_node = selected_vsnode;
+
// Searching for the default port or the first compatible input port of the node to insert.
int _to_port = -1;
for (int i = 0; i < selected_vsnode->get_input_port_count(); i++) {
- if (visual_shader->is_port_types_compatible(original_port_type_from, selected_vsnode->get_input_port_type(i))) {
+ if (visual_shader->is_port_types_compatible(original_port_type_from, selected_vsnode->get_input_port_type(i)) || reroute_node.is_valid()) {
if (i == selected_vsnode->get_default_input_port(original_port_type_from)) {
_to_port = i;
break;
@@ -3947,7 +4061,7 @@ bool VisualShaderEditor::_check_node_drop_on_connection(const Vector2 &p_positio
// Searching for the first compatible output port of the node to insert.
int _from_port = -1;
for (int i = 0; i < selected_vsnode->get_output_port_count(); i++) {
- if (visual_shader->is_port_types_compatible(selected_vsnode->get_output_port_type(i), original_port_type_to)) {
+ if (visual_shader->is_port_types_compatible(selected_vsnode->get_output_port_type(i), original_port_type_to) || reroute_node.is_valid()) {
_from_port = i;
break;
}
@@ -4529,6 +4643,8 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
Ref<GraphEdit::Connection> closest_connection = graph->get_closest_connection_at_point(menu_point);
if (closest_connection.is_valid()) {
clicked_connection = closest_connection;
+ saved_node_pos = graph->get_local_mouse_position();
+ saved_node_pos_dirty = true;
connection_popup_menu->set_position(gpos);
connection_popup_menu->reset_size();
connection_popup_menu->popup();
@@ -5628,6 +5744,25 @@ void VisualShaderEditor::_connection_menu_id_pressed(int p_idx) {
connection_node_insert_requested = true;
_show_members_dialog(true, input_port_type, output_port_type);
} break;
+ case ConnectionMenuOptions::INSERT_NEW_REROUTE: {
+ from_node = String(clicked_connection->from_node).to_int();
+ from_slot = clicked_connection->from_port;
+ to_node = String(clicked_connection->to_node).to_int();
+ to_slot = clicked_connection->to_port;
+
+ // Manual offset to place the port exactly at the mouse position.
+ saved_node_pos -= Vector2(11 * EDSCALE * graph->get_zoom(), 50 * EDSCALE * graph->get_zoom());
+
+ // Find reroute addoptions.
+ int idx = -1;
+ for (int i = 0; i < add_options.size(); i++) {
+ if (add_options[i].name == "Reroute") {
+ idx = i;
+ break;
+ }
+ }
+ _add_node(idx, add_options[idx].ops);
+ } break;
default:
break;
}
@@ -6123,6 +6258,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_child(connection_popup_menu);
connection_popup_menu->add_item(TTR("Disconnect"), ConnectionMenuOptions::DISCONNECT);
connection_popup_menu->add_item(TTR("Insert New Node"), ConnectionMenuOptions::INSERT_NEW_NODE);
+ connection_popup_menu->add_item(TTR("Insert New Reroute"), ConnectionMenuOptions::INSERT_NEW_REROUTE);
connection_popup_menu->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_connection_menu_id_pressed));
///////////////////////////////////////
@@ -6962,6 +7098,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("VaryingSetter", "Special", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("VaryingGetter", "Special", "VisualShaderNodeVaryingGetter", TTR("Get varying parameter."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("VaryingSetter", "Special", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Reroute", "Special", "VisualShaderNodeReroute", TTR("Reroute connections freely, can be used to connect multiple input ports to single output port.")));
custom_node_option_idx = add_options.size();
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 246e44a40d..ee2bf605d9 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -66,6 +66,34 @@ public:
virtual Control *create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node);
};
+class VSGraphNode : public GraphNode {
+ GDCLASS(VSGraphNode, GraphNode);
+
+protected:
+ void _draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color, const Color &p_rim_color);
+ virtual void draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) override;
+};
+
+class VSRerouteNode : public VSGraphNode {
+ GDCLASS(VSRerouteNode, GraphNode);
+
+ const float FADE_ANIMATION_LENGTH_SEC = 0.3;
+
+ float icon_opacity = 0.0;
+
+protected:
+ void _notification(int p_what);
+
+ virtual void draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) override;
+
+public:
+ VSRerouteNode();
+ void set_icon_opacity(float p_opacity);
+
+ void _on_mouse_entered();
+ void _on_mouse_exited();
+};
+
class VisualShaderGraphPlugin : public RefCounted {
GDCLASS(VisualShaderGraphPlugin, RefCounted);
@@ -140,6 +168,7 @@ public:
void set_frame_color_enabled(VisualShader::Type p_type, int p_node_id, bool p_enable);
void set_frame_color(VisualShader::Type p_type, int p_node_id, const Color &p_color);
void set_frame_autoshrink_enabled(VisualShader::Type p_type, int p_node_id, bool p_enable);
+ void update_reroute_nodes();
int get_constant_index(float p_constant) const;
Ref<Script> get_node_script(int p_node_id) const;
void update_theme();
@@ -297,6 +326,7 @@ class VisualShaderEditor : public VBoxContainer {
enum ConnectionMenuOptions {
INSERT_NEW_NODE,
+ INSERT_NEW_REROUTE,
DISCONNECT,
};
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 6f0a8bc909..cb379c198f 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -4357,7 +4357,6 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
scene_tree->set_v_size_flags(SIZE_EXPAND | SIZE_FILL);
scene_tree->connect("rmb_pressed", callable_mp(this, &SceneTreeDock::_tree_rmb));
- scene_tree->connect("node_selected", callable_mp(this, &SceneTreeDock::_node_selected), CONNECT_DEFERRED);
scene_tree->connect("node_renamed", callable_mp(this, &SceneTreeDock::_node_renamed), CONNECT_DEFERRED);
scene_tree->connect("node_prerename", callable_mp(this, &SceneTreeDock::_node_prerenamed));
scene_tree->connect("open", callable_mp(this, &SceneTreeDock::_load_request));
diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp
index 2ef62c60a2..7417d14bf3 100644
--- a/editor/themes/editor_theme_manager.cpp
+++ b/editor/themes/editor_theme_manager.cpp
@@ -1650,7 +1650,7 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
p_theme->set_stylebox("titlebar_selected", "GraphFrame", make_empty_stylebox(4, 4, 4, 4));
p_theme->set_color("resizer_color", "GraphFrame", gn_decoration_color);
- // GraphFrame's title Label
+ // GraphFrame's title Label.
p_theme->set_type_variation("GraphFrameTitleLabel", "Label");
p_theme->set_stylebox("normal", "GraphFrameTitleLabel", memnew(StyleBoxEmpty));
p_theme->set_font_size("font_size", "GraphFrameTitleLabel", 22);
@@ -1663,6 +1663,21 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
p_theme->set_constant("shadow_outline_size", "GraphFrameTitleLabel", 1 * EDSCALE);
p_theme->set_constant("line_spacing", "GraphFrameTitleLabel", 3 * EDSCALE);
}
+
+ // VisualShader reroute node.
+ {
+ Ref<StyleBox> vs_reroute_panel_style = make_empty_stylebox();
+ Ref<StyleBox> vs_reroute_titlebar_style = vs_reroute_panel_style->duplicate();
+ vs_reroute_titlebar_style->set_content_margin_all(16);
+ p_theme->set_stylebox("panel", "VSRerouteNode", vs_reroute_panel_style);
+ p_theme->set_stylebox("panel_selected", "VSRerouteNode", vs_reroute_panel_style);
+ p_theme->set_stylebox("titlebar", "VSRerouteNode", vs_reroute_titlebar_style);
+ p_theme->set_stylebox("titlebar_selected", "VSRerouteNode", vs_reroute_titlebar_style);
+ p_theme->set_stylebox("slot", "VSRerouteNode", make_empty_stylebox());
+
+ p_theme->set_color("drag_background", "VSRerouteNode", p_config.dark_theme ? Color(0.19, 0.21, 0.24) : Color(0.8, 0.8, 0.8));
+ p_theme->set_color("selected_rim_color", "VSRerouteNode", p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0));
+ }
}
// ColorPicker and related nodes.
diff --git a/main/SCsub b/main/SCsub
index 3e7680bf89..27b746a937 100644
--- a/main/SCsub
+++ b/main/SCsub
@@ -20,7 +20,7 @@ env_main.CommandNoCache(
env.Run(main_builders.make_splash),
)
-if not env_main["no_editor_splash"]:
+if env_main.editor_build and not env_main["no_editor_splash"]:
env_main.Depends("#main/splash_editor.gen.h", "#main/splash_editor.png")
env_main.CommandNoCache(
"#main/splash_editor.gen.h",
diff --git a/main/main.cpp b/main/main.cpp
index 1ba336221f..bcd7d8df22 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -104,7 +104,7 @@
#include "editor/project_manager.h"
#include "editor/register_editor_types.h"
-#ifndef NO_EDITOR_SPLASH
+#if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
#include "main/splash_editor.gen.h"
#endif
diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html
index 874fe2695e..fc34164368 100644
--- a/misc/dist/html/full-size.html
+++ b/misc/dist/html/full-size.html
@@ -38,7 +38,7 @@ body {
}
#status {
- background-color: #38363A;
+ background-color: #242424;
display: flex;
flex-direction: column;
justify-content: center;
diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected
index d7bb67cfbc..6761512c15 100644
--- a/misc/extension_api_validation/4.2-stable.expected
+++ b/misc/extension_api_validation/4.2-stable.expected
@@ -344,3 +344,16 @@ GH-91143
Validate extension JSON: Error: Field 'classes/Input/methods/vibrate_handheld/arguments': size changed value in new API, from 1 to 2.
Added optional argument. Compatibility method registered.
+
+
+GH-84523
+--------
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_dashed_line/arguments': size changed value in new API, from 6 to 7.
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_multiline/arguments': size changed value in new API, from 3 to 4.
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_multiline_colors/arguments': size changed value in new API, from 3 to 4.
+Validate extension JSON: Error: Field 'classes/CanvasItem/methods/draw_rect/arguments': size changed value in new API, from 4 to 5.
+Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_circle/arguments': size changed value in new API, from 4 to 5.
+Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_multiline/arguments': size changed value in new API, from 4 to 5.
+Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_rect/arguments': size changed value in new API, from 3 to 4.
+
+Optional arguments added. Compatibility methods registered.
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 19b264d764..c7862e23a9 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -2038,15 +2038,15 @@ void GDScriptInstance::notification(int p_notification, bool p_reversed) {
}
String GDScriptInstance::to_string(bool *r_valid) {
- if (has_method(CoreStringNames::get_singleton()->_to_string)) {
+ if (has_method(CoreStringName(_to_string))) {
Callable::CallError ce;
- Variant ret = callp(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce);
+ Variant ret = callp(CoreStringName(_to_string), nullptr, 0, ce);
if (ce.error == Callable::CallError::CALL_OK) {
if (ret.get_type() != Variant::STRING) {
if (r_valid) {
*r_valid = false;
}
- ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String.");
+ ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringName(_to_string) + ", must be a String.");
}
if (r_valid) {
*r_valid = true;
@@ -2919,7 +2919,7 @@ String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) con
return "";
}
-void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *r_dependencies, bool p_add_types) {
+void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'.");
@@ -2933,13 +2933,8 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S
return;
}
- GDScriptAnalyzer analyzer(&parser);
- if (OK != analyzer.analyze()) {
- return;
- }
-
for (const String &E : parser.get_dependencies()) {
- r_dependencies->push_back(E);
+ p_dependencies->push_back(E);
}
}
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index f63b0da745..728459de44 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -638,7 +638,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
- virtual void get_dependencies(const String &p_path, List<String> *r_dependencies, bool p_add_types = false) override;
+ virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override;
};
class ResourceFormatSaverGDScript : public ResourceFormatSaver {
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 4b6cc47218..46b34e4977 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -231,7 +231,7 @@ bool GDScriptAnalyzer::has_member_name_conflict_in_native_type(const StringName
if (ClassDB::has_integer_constant(p_native_type_string, p_member_name)) {
return true;
}
- if (p_member_name == CoreStringNames::get_singleton()->_script) {
+ if (p_member_name == CoreStringName(script)) {
return true;
}
@@ -562,11 +562,6 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
class_type.native_type = result.native_type;
p_class->set_datatype(class_type);
- // Add base class to the list of dependencies.
- if (result.kind == GDScriptParser::DataType::CLASS) {
- parser->add_dependency(result.script_path);
- }
-
// Apply annotations.
for (GDScriptParser::AnnotationNode *&E : p_class->annotations) {
resolve_annotation(E);
@@ -873,11 +868,6 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
}
p_type->set_datatype(result);
-
- if (result.kind == GDScriptParser::DataType::CLASS || result.kind == GDScriptParser::DataType::SCRIPT) {
- parser->add_dependency(result.script_path);
- }
-
return result;
}
@@ -2172,7 +2162,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
List<GDScriptParser::DataType> par_types;
int default_arg_count = 0;
BitField<MethodFlags> method_flags;
- if (get_function_signature(p_for->list, false, list_type, CoreStringNames::get_singleton()->_iter_get, return_type, par_types, default_arg_count, method_flags)) {
+ if (get_function_signature(p_for->list, false, list_type, CoreStringName(_iter_get), return_type, par_types, default_arg_count, method_flags)) {
variable_type = return_type;
variable_type.type_source = list_type.type_source;
} else if (!list_type.is_hard_type()) {
@@ -4112,7 +4102,6 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
if (ScriptServer::is_global_class(name)) {
p_identifier->set_datatype(make_global_class_meta_type(name, p_identifier));
- parser->add_dependency(p_identifier->get_datatype().script_path);
return;
}
@@ -4155,7 +4144,6 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
}
result.is_constant = true;
p_identifier->set_datatype(result);
- parser->add_dependency(autoload.path);
return;
}
}
@@ -4275,6 +4263,7 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
push_error("Preloaded path must be a constant string.", p_preload->path);
} else {
p_preload->resolved_path = p_preload->path->reduced_value;
+ // TODO: Save this as script dependency.
if (p_preload->resolved_path.is_relative_path()) {
p_preload->resolved_path = parser->script_path.get_base_dir().path_join(p_preload->resolved_path);
}
@@ -4305,8 +4294,6 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
}
}
-
- parser->add_dependency(p_preload->resolved_path);
}
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 01e5751dc8..4f8a554ce1 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -346,7 +346,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
scr = scr->_base;
}
- if (nc && (identifier == CoreStringNames::get_singleton()->_free || ClassDB::has_signal(nc->get_name(), identifier) || ClassDB::has_method(nc->get_name(), identifier))) {
+ if (nc && (identifier == CoreStringName(free_) || ClassDB::has_signal(nc->get_name(), identifier) || ClassDB::has_method(nc->get_name(), identifier))) {
// Get like it was a property.
GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 1e67e2d496..4c11fa7f8b 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -1432,8 +1432,6 @@ private:
void reset_extents(Node *p_node, GDScriptTokenizer::Token p_token);
void reset_extents(Node *p_node, Node *p_from);
- HashSet<String> dependencies;
-
template <typename T>
T *alloc_node() {
T *node = memnew(T);
@@ -1577,11 +1575,9 @@ public:
bool annotation_exists(const String &p_annotation_name) const;
const List<ParserError> &get_errors() const { return errors; }
- const HashSet<String> &get_dependencies() const {
- return dependencies;
- }
- void add_dependency(const String &p_dependency) {
- dependencies.insert(p_dependency);
+ const List<String> get_dependencies() const {
+ // TODO: Keep track of deps.
+ return List<String>();
}
#ifdef DEBUG_ENABLED
const List<GDScriptWarning> &get_warnings() const { return warnings; }
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 11bd1d224a..1efa9ece0d 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -1741,7 +1741,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (base_type == Variant::OBJECT) {
if (base_obj) {
MethodBind *method = ClassDB::get_method(base_class, *methodname);
- if (*methodname == CoreStringNames::get_singleton()->_free || (method && !method->has_return())) {
+ if (*methodname == CoreStringName(free_) || (method && !method->has_return())) {
err_text = R"(Trying to get a return value of a method that returns "void")";
OPCODE_BREAK;
}
@@ -3097,7 +3097,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
const Variant *args[] = { &vref };
Callable::CallError ce;
- Variant has_next = obj->callp(CoreStringNames::get_singleton()->_iter_init, args, 1, ce);
+ Variant has_next = obj->callp(CoreStringName(_iter_init), args, 1, ce);
#ifdef DEBUG_ENABLED
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
@@ -3113,7 +3113,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
*counter = ref[0];
GET_VARIANT_PTR(iterator, 2);
- *iterator = obj->callp(CoreStringNames::get_singleton()->_iter_get, (const Variant **)&counter, 1, ce);
+ *iterator = obj->callp(CoreStringName(_iter_get), (const Variant **)&counter, 1, ce);
#ifdef DEBUG_ENABLED
if (ce.error != Callable::CallError::CALL_OK) {
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
@@ -3431,7 +3431,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
const Variant *args[] = { &vref };
Callable::CallError ce;
- Variant has_next = obj->callp(CoreStringNames::get_singleton()->_iter_next, args, 1, ce);
+ Variant has_next = obj->callp(CoreStringName(_iter_next), args, 1, ce);
#ifdef DEBUG_ENABLED
if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
@@ -3447,7 +3447,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
*counter = ref[0];
GET_VARIANT_PTR(iterator, 2);
- *iterator = obj->callp(CoreStringNames::get_singleton()->_iter_get, (const Variant **)&counter, 1, ce);
+ *iterator = obj->callp(CoreStringName(_iter_get), (const Variant **)&counter, 1, ce);
#ifdef DEBUG_ENABLED
if (ce.error != Callable::CallError::CALL_OK) {
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 575702bc54..b92176a63a 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -105,10 +105,6 @@ static Ref<ImporterMesh> _mesh_to_importer_mesh(Ref<Mesh> p_mesh) {
}
Error GLTFDocument::_serialize(Ref<GLTFState> p_state) {
- if (!p_state->buffers.size()) {
- p_state->buffers.push_back(Vector<uint8_t>());
- }
-
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
Error err = ext->export_preserialize(p_state);
@@ -243,7 +239,6 @@ Error GLTFDocument::_serialize_gltf_extensions(Ref<GLTFState> p_state) const {
}
Error GLTFDocument::_serialize_scenes(Ref<GLTFState> p_state) {
- ERR_FAIL_COND_V_MSG(p_state->root_nodes.is_empty(), ERR_INVALID_DATA, "GLTF export: The scene must have at least one root node.");
// Godot only supports one scene per glTF file.
Array scenes;
Dictionary scene_dict;
@@ -251,7 +246,9 @@ Error GLTFDocument::_serialize_scenes(Ref<GLTFState> p_state) {
p_state->json["scenes"] = scenes;
p_state->json["scene"] = 0;
// Add nodes to the scene dict.
- scene_dict["nodes"] = p_state->root_nodes;
+ if (!p_state->root_nodes.is_empty()) {
+ scene_dict["nodes"] = p_state->root_nodes;
+ }
if (!p_state->scene_name.is_empty()) {
scene_dict["name"] = p_state->scene_name;
}
@@ -458,9 +455,15 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) {
ERR_CONTINUE(err != OK);
}
+ if (extensions.is_empty()) {
+ node.erase("extensions");
+ }
+
nodes.push_back(node);
}
- p_state->json["nodes"] = nodes;
+ if (!nodes.is_empty()) {
+ p_state->json["nodes"] = nodes;
+ }
return OK;
}
@@ -691,11 +694,11 @@ static Vector<uint8_t> _parse_base64_uri(const String &p_uri) {
Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> p_state, const String &p_path) {
print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
- if (!p_state->buffers.size()) {
+ if (p_state->buffers.is_empty()) {
return OK;
}
Array buffers;
- if (p_state->buffers.size()) {
+ if (!p_state->buffers.is_empty()) {
Vector<uint8_t> buffer_data = p_state->buffers[0];
Dictionary gltf_buffer;
@@ -730,7 +733,7 @@ Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> p_state, const String &p_p
Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> p_state, const String &p_path) {
print_verbose("glTF: Total buffers: " + itos(p_state->buffers.size()));
- if (!p_state->buffers.size()) {
+ if (p_state->buffers.is_empty()) {
return OK;
}
Array buffers;
@@ -1543,6 +1546,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> p_state,
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_SCALAR;
int component_type;
@@ -1654,6 +1660,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> p_state,
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC2;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1704,6 +1713,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> p_state
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1768,6 +1780,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> p_sta
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1816,6 +1831,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> p_stat
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT;
@@ -1866,6 +1884,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> p
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1938,6 +1959,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> p_stat
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_SCALAR;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -1985,6 +2009,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> p_state,
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC3;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -2058,6 +2085,9 @@ GLTFAccessorIndex GLTFDocument::_encode_sparse_accessor_as_vec3(Ref<GLTFState> p
Ref<GLTFAccessor> sparse_accessor;
sparse_accessor.instantiate();
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_VEC3;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -2160,6 +2190,9 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> p_state
Ref<GLTFAccessor> accessor;
accessor.instantiate();
GLTFBufferIndex buffer_view_i;
+ if (p_state->buffers.is_empty()) {
+ p_state->buffers.push_back(Vector<uint8_t>());
+ }
int64_t size = p_state->buffers[0].size();
const GLTFType type = GLTFType::TYPE_MAT4;
const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT;
@@ -6944,7 +6977,7 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path)
const uint32_t text_chunk_type = 0x4E4F534A; //JSON
uint32_t binary_data_length = 0;
- if (p_state->buffers.size()) {
+ if (p_state->buffers.size() > 0) {
binary_data_length = p_state->buffers[0].size();
}
const uint32_t binary_chunk_length = ((binary_data_length + 3) & (~3));
@@ -6953,20 +6986,28 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> p_state, const String p_path)
file->create(FileAccess::ACCESS_RESOURCES);
file->store_32(magic);
file->store_32(p_state->major_version); // version
- file->store_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_chunk_length); // length
+ uint32_t total_length = header_size + chunk_header_size + text_chunk_length;
+ if (binary_chunk_length) {
+ total_length += chunk_header_size + binary_chunk_length;
+ }
+ file->store_32(total_length);
+
+ // Write the JSON text chunk.
file->store_32(text_chunk_length);
file->store_32(text_chunk_type);
file->store_buffer((uint8_t *)&cs[0], cs.length());
for (uint32_t pad_i = text_data_length; pad_i < text_chunk_length; pad_i++) {
file->store_8(' ');
}
+
+ // Write a single binary chunk.
if (binary_chunk_length) {
file->store_32(binary_chunk_length);
file->store_32(binary_chunk_type);
file->store_buffer(p_state->buffers[0].ptr(), binary_data_length);
- }
- for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) {
- file->store_8(0);
+ for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) {
+ file->store_8(0);
+ }
}
} else {
err = _encode_buffer_bins(p_state, p_path);
@@ -7073,7 +7114,7 @@ PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> p_state, Erro
const uint32_t text_chunk_type = 0x4E4F534A; //JSON
int32_t binary_data_length = 0;
- if (p_state->buffers.size()) {
+ if (p_state->buffers.size() > 0) {
binary_data_length = p_state->buffers[0].size();
}
const int32_t binary_chunk_length = binary_data_length;
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index d53bf7f7ec..49c90cc775 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -949,7 +949,7 @@ void GridMapEditor::_update_mesh_library() {
void GridMapEditor::edit(GridMap *p_gridmap) {
if (node) {
node->disconnect(SNAME("cell_size_changed"), callable_mp(this, &GridMapEditor::_draw_grids));
- node->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GridMapEditor::_update_mesh_library));
+ node->disconnect(CoreStringName(changed), callable_mp(this, &GridMapEditor::_update_mesh_library));
if (mesh_library.is_valid()) {
mesh_library->disconnect_changed(callable_mp(this, &GridMapEditor::update_palette));
mesh_library = Ref<MeshLibrary>();
@@ -987,7 +987,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
update_grid();
node->connect(SNAME("cell_size_changed"), callable_mp(this, &GridMapEditor::_draw_grids));
- node->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GridMapEditor::_update_mesh_library));
+ node->connect(CoreStringName(changed), callable_mp(this, &GridMapEditor::_update_mesh_library));
_update_mesh_library();
}
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 25519c6e3c..abfbfebc02 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -266,7 +266,7 @@ void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) {
}
_recreate_octant_data();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
Ref<MeshLibrary> GridMap::get_mesh_library() const {
@@ -1136,7 +1136,7 @@ void GridMap::_bind_methods() {
BIND_CONSTANT(INVALID_CELL_ITEM);
ADD_SIGNAL(MethodInfo("cell_size_changed", PropertyInfo(Variant::VECTOR3, "cell_size")));
- ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed));
+ ADD_SIGNAL(MethodInfo(CoreStringName(changed)));
}
void GridMap::set_cell_scale(float p_scale) {
diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp
index 6c0669b2f3..b871025491 100644
--- a/modules/multiplayer/multiplayer_spawner.cpp
+++ b/modules/multiplayer/multiplayer_spawner.cpp
@@ -216,7 +216,7 @@ void MultiplayerSpawner::_notification(int p_what) {
for (const KeyValue<ObjectID, SpawnInfo> &E : tracked_nodes) {
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E.key));
ERR_CONTINUE(!node);
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &MultiplayerSpawner::_node_exit));
get_multiplayer()->object_configuration_remove(node, this);
}
tracked_nodes.clear();
@@ -258,7 +258,7 @@ void MultiplayerSpawner::_track(Node *p_node, const Variant &p_argument, int p_s
ObjectID oid = p_node->get_instance_id();
if (!tracked_nodes.has(oid)) {
tracked_nodes[oid] = SpawnInfo(p_argument.duplicate(true), p_scene_id);
- p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit).bind(p_node->get_instance_id()), CONNECT_ONE_SHOT);
+ p_node->connect(SceneStringName(tree_exiting), callable_mp(this, &MultiplayerSpawner::_node_exit).bind(p_node->get_instance_id()), CONNECT_ONE_SHOT);
_spawn_notify(p_node->get_instance_id());
}
}
diff --git a/modules/multiplayer/scene_cache_interface.cpp b/modules/multiplayer/scene_cache_interface.cpp
index c08ccbe4cc..39443029d3 100644
--- a/modules/multiplayer/scene_cache_interface.cpp
+++ b/modules/multiplayer/scene_cache_interface.cpp
@@ -42,7 +42,7 @@ SceneCacheInterface::NodeCache &SceneCacheInterface::_track(Node *p_node) {
NodeCache *nc = nodes_cache.getptr(oid);
if (!nc) {
nodes_cache[oid] = NodeCache();
- p_node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneCacheInterface::_remove_node_cache).bind(oid), Object::CONNECT_ONE_SHOT);
+ p_node->connect(SceneStringName(tree_exited), callable_mp(this, &SceneCacheInterface::_remove_node_cache).bind(oid), Object::CONNECT_ONE_SHOT);
}
return nodes_cache[oid];
}
@@ -286,7 +286,7 @@ void SceneCacheInterface::clear() {
for (KeyValue<ObjectID, NodeCache> &E : nodes_cache) {
Object *obj = ObjectDB::get_instance(E.key);
ERR_CONTINUE(!obj);
- obj->disconnect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneCacheInterface::_remove_node_cache));
+ obj->disconnect(SceneStringName(tree_exited), callable_mp(this, &SceneCacheInterface::_remove_node_cache));
}
peers_info.clear();
nodes_cache.clear();
diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp
index 182e9b455c..f1a43a68b9 100644
--- a/modules/multiplayer/scene_replication_interface.cpp
+++ b/modules/multiplayer/scene_replication_interface.cpp
@@ -57,7 +57,7 @@ SceneReplicationInterface::TrackedNode &SceneReplicationInterface::_track(const
if (!tracked_nodes.has(p_id)) {
tracked_nodes[p_id] = TrackedNode(p_id);
Node *node = get_id_as<Node>(p_id);
- node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationInterface::_untrack).bind(p_id), Node::CONNECT_ONE_SHOT);
+ node->connect(SceneStringName(tree_exited), callable_mp(this, &SceneReplicationInterface::_untrack).bind(p_id), Node::CONNECT_ONE_SHOT);
}
return tracked_nodes[p_id];
}
@@ -135,8 +135,8 @@ void SceneReplicationInterface::on_network_process() {
for (const ObjectID &oid : spawn_queue) {
Node *node = get_id_as<Node>(oid);
ERR_CONTINUE(!node);
- if (node->is_connected(SceneStringNames::get_singleton()->ready, callable_mp(this, &SceneReplicationInterface::_node_ready))) {
- node->disconnect(SceneStringNames::get_singleton()->ready, callable_mp(this, &SceneReplicationInterface::_node_ready));
+ if (node->is_connected(SceneStringName(ready), callable_mp(this, &SceneReplicationInterface::_node_ready))) {
+ node->disconnect(SceneStringName(ready), callable_mp(this, &SceneReplicationInterface::_node_ready));
}
}
spawn_queue.clear();
@@ -168,7 +168,7 @@ Error SceneReplicationInterface::on_spawn(Object *p_obj, Variant p_config) {
ERR_FAIL_COND_V(tobj.spawner != ObjectID(), ERR_ALREADY_IN_USE);
tobj.spawner = spawner->get_instance_id();
spawn_queue.insert(oid);
- node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &SceneReplicationInterface::_node_ready).bind(oid), Node::CONNECT_ONE_SHOT);
+ node->connect(SceneStringName(ready), callable_mp(this, &SceneReplicationInterface::_node_ready).bind(oid), Node::CONNECT_ONE_SHOT);
return OK;
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
index fbdf07e6c2..290be727ab 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -38,7 +38,6 @@ import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
-import android.graphics.Rect
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
@@ -46,10 +45,12 @@ import android.hardware.SensorManager
import android.os.*
import android.util.Log
import android.view.*
-import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.widget.FrameLayout
import androidx.annotation.Keep
import androidx.annotation.StringRes
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsAnimationCompat
+import androidx.core.view.WindowInsetsCompat
import com.google.android.vending.expansion.downloader.*
import org.godotengine.godot.input.GodotEditText
import org.godotengine.godot.io.directory.DirectoryAccessHandler
@@ -418,58 +419,42 @@ class Godot(private val context: Context) : SensorEventListener {
io?.setEdit(editText)
// Listeners for keyboard height.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- // Report the height of virtual keyboard as it changes during the animation.
- val decorView = activity.window.decorView
- decorView.setWindowInsetsAnimationCallback(object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
- var startBottom = 0
- var endBottom = 0
- override fun onPrepare(animation: WindowInsetsAnimation) {
- startBottom = decorView.rootWindowInsets.getInsets(WindowInsets.Type.ime()).bottom
- }
+ val decorView = activity.window.decorView
+ // Report the height of virtual keyboard as it changes during the animation.
+ ViewCompat.setWindowInsetsAnimationCallback(decorView, object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {
+ var startBottom = 0
+ var endBottom = 0
+ override fun onPrepare(animation: WindowInsetsAnimationCompat) {
+ startBottom = ViewCompat.getRootWindowInsets(decorView)?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
+ }
- override fun onStart(animation: WindowInsetsAnimation, bounds: WindowInsetsAnimation.Bounds): WindowInsetsAnimation.Bounds {
- endBottom = decorView.rootWindowInsets.getInsets(WindowInsets.Type.ime()).bottom
- return bounds
- }
+ override fun onStart(animation: WindowInsetsAnimationCompat, bounds: WindowInsetsAnimationCompat.BoundsCompat): WindowInsetsAnimationCompat.BoundsCompat {
+ endBottom = ViewCompat.getRootWindowInsets(decorView)?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
+ return bounds
+ }
- override fun onProgress(windowInsets: WindowInsets, list: List<WindowInsetsAnimation>): WindowInsets {
- // Find the IME animation.
- var imeAnimation: WindowInsetsAnimation? = null
- for (animation in list) {
- if (animation.typeMask and WindowInsets.Type.ime() != 0) {
- imeAnimation = animation
- break
- }
- }
- // Update keyboard height based on IME animation.
- if (imeAnimation != null) {
- val interpolatedFraction = imeAnimation.interpolatedFraction
- // Linear interpolation between start and end values.
- val keyboardHeight = startBottom * (1.0f - interpolatedFraction) + endBottom * interpolatedFraction
- GodotLib.setVirtualKeyboardHeight(keyboardHeight.toInt())
+ override fun onProgress(windowInsets: WindowInsetsCompat, animationsList: List<WindowInsetsAnimationCompat>): WindowInsetsCompat {
+ // Find the IME animation.
+ var imeAnimation: WindowInsetsAnimationCompat? = null
+ for (animation in animationsList) {
+ if (animation.typeMask and WindowInsetsCompat.Type.ime() != 0) {
+ imeAnimation = animation
+ break
}
- return windowInsets
}
- override fun onEnd(animation: WindowInsetsAnimation) {}
- })
- } else {
- // Infer the virtual keyboard height using visible area.
- renderView?.view?.viewTreeObserver?.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
- // Don't allocate a new Rect every time the callback is called.
- val visibleSize = Rect()
- override fun onGlobalLayout() {
- renderView?.let {
- val surfaceView = it.view
-
- surfaceView.getWindowVisibleDisplayFrame(visibleSize)
- val keyboardHeight = surfaceView.height - visibleSize.bottom
- GodotLib.setVirtualKeyboardHeight(keyboardHeight)
- }
+ // Update keyboard height based on IME animation.
+ if (imeAnimation != null) {
+ val interpolatedFraction = imeAnimation.interpolatedFraction
+ // Linear interpolation between start and end values.
+ val keyboardHeight = startBottom * (1.0f - interpolatedFraction) + endBottom * interpolatedFraction
+ GodotLib.setVirtualKeyboardHeight(keyboardHeight.toInt())
}
- })
- }
+ return windowInsets
+ }
+
+ override fun onEnd(animation: WindowInsetsAnimationCompat) {}
+ })
if (host == primaryHost) {
renderView?.queueOnRenderThread {
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index d42303ad25..0bf3927e14 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -154,11 +154,11 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito
String head_include;
if (p_preset->get("html/export_icon")) {
- head_include += "<link id='-gd-engine-icon' rel='icon' type='image/png' href='" + p_name + ".icon.png' />\n";
- head_include += "<link rel='apple-touch-icon' href='" + p_name + ".apple-touch-icon.png'/>\n";
+ head_include += "<link id=\"-gd-engine-icon\" rel=\"icon\" type=\"image/png\" href=\"" + p_name + ".icon.png\" />\n";
+ head_include += "<link rel=\"apple-touch-icon\" href=\"" + p_name + ".apple-touch-icon.png\"/>\n";
}
if (p_preset->get("progressive_web_app/enabled")) {
- head_include += "<link rel='manifest' href='" + p_name + ".manifest.json'>\n";
+ head_include += "<link rel=\"manifest\" href=\"" + p_name + ".manifest.json\">\n";
config["serviceWorker"] = p_name + ".service.worker.js";
}
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index 37e9d1f8c1..f543412962 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -202,7 +202,7 @@ void AnimatedSprite2D::_notification(int p_what) {
} else {
frame = last_frame;
pause();
- emit_signal(SceneStringNames::get_singleton()->animation_finished);
+ emit_signal(SceneStringName(animation_finished));
return;
}
} else {
@@ -211,7 +211,7 @@ void AnimatedSprite2D::_notification(int p_what) {
_calc_frame_speed_scale();
frame_progress = 0.0;
queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
double to_process = MIN((1.0 - frame_progress) / abs_speed, remaining);
frame_progress += to_process * abs_speed;
@@ -226,7 +226,7 @@ void AnimatedSprite2D::_notification(int p_what) {
} else {
frame = 0;
pause();
- emit_signal(SceneStringNames::get_singleton()->animation_finished);
+ emit_signal(SceneStringName(animation_finished));
return;
}
} else {
@@ -235,7 +235,7 @@ void AnimatedSprite2D::_notification(int p_what) {
_calc_frame_speed_scale();
frame_progress = 1.0;
queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
double to_process = MIN(frame_progress / abs_speed, remaining);
frame_progress -= to_process * abs_speed;
@@ -291,12 +291,12 @@ void AnimatedSprite2D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
}
if (frames.is_valid()) {
- frames->disconnect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite2D::_res_changed));
+ frames->disconnect(SceneStringName(changed), callable_mp(this, &AnimatedSprite2D::_res_changed));
}
stop();
frames = p_frames;
if (frames.is_valid()) {
- frames->connect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite2D::_res_changed));
+ frames->connect(SceneStringName(changed), callable_mp(this, &AnimatedSprite2D::_res_changed));
List<StringName> al;
frames->get_animation_list(&al);
@@ -363,7 +363,7 @@ void AnimatedSprite2D::set_frame_and_progress(int p_frame, real_t p_progress) {
return; // No change, don't redraw.
}
queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
void AnimatedSprite2D::set_speed_scale(float p_speed_scale) {
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 4fc0fe0268..fb632e8f64 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -81,10 +81,10 @@ StringName AudioStreamPlayer2D::_get_actual_bus() {
//check if any area is diverting sound into a bus
Ref<World2D> world_2d = get_world_2d();
- ERR_FAIL_COND_V(world_2d.is_null(), SceneStringNames::get_singleton()->Master);
+ ERR_FAIL_COND_V(world_2d.is_null(), SceneStringName(Master));
PhysicsDirectSpaceState2D *space_state = PhysicsServer2D::get_singleton()->space_get_direct_state(world_2d->get_space());
- ERR_FAIL_NULL_V(space_state, SceneStringNames::get_singleton()->Master);
+ ERR_FAIL_COND_V(space_state, SceneStringName(Master));
PhysicsDirectSpaceState2D::ShapeResult sr[MAX_INTERSECT_AREAS];
PhysicsDirectSpaceState2D::PointParameters point_params;
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index 2cd59776ec..3df635d75a 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -997,7 +997,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
}
if (!Math::is_equal_approx(time, 0.0) && active && !should_be_active) {
active = false;
- emit_signal(SceneStringNames::get_singleton()->finished);
+ emit_signal(SceneStringName(finished));
}
}
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index bc39513c03..caac564500 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -731,7 +731,7 @@ void GPUParticles2D::_notification(int p_what) {
}
if (time > active_time) {
if (active && !signal_canceled) {
- emit_signal(SceneStringNames::get_singleton()->finished);
+ emit_signal(SceneStringName(finished));
}
active = false;
if (!emitting) {
diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp
index 4fc375ff8d..28af4184ca 100644
--- a/scene/2d/mesh_instance_2d.cpp
+++ b/scene/2d/mesh_instance_2d.cpp
@@ -70,7 +70,7 @@ void MeshInstance2D::set_texture(const Ref<Texture2D> &p_texture) {
}
texture = p_texture;
queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->texture_changed);
+ emit_signal(SceneStringName(texture_changed));
}
Ref<Texture2D> MeshInstance2D::get_texture() const {
diff --git a/scene/2d/multimesh_instance_2d.cpp b/scene/2d/multimesh_instance_2d.cpp
index 9631b2cc4e..695e44664e 100644
--- a/scene/2d/multimesh_instance_2d.cpp
+++ b/scene/2d/multimesh_instance_2d.cpp
@@ -79,7 +79,7 @@ void MultiMeshInstance2D::set_texture(const Ref<Texture2D> &p_texture) {
}
texture = p_texture;
queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->texture_changed);
+ emit_signal(SceneStringName(texture_changed));
}
Ref<Texture2D> MultiMeshInstance2D::get_texture() const {
diff --git a/scene/2d/physics/area_2d.cpp b/scene/2d/physics/area_2d.cpp
index b1ff94dda4..3ed579b3b1 100644
--- a/scene/2d/physics/area_2d.cpp
+++ b/scene/2d/physics/area_2d.cpp
@@ -142,9 +142,9 @@ void Area2D::_body_enter_tree(ObjectID p_id) {
ERR_FAIL_COND(E->value.in_tree);
E->value.in_tree = true;
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
+ emit_signal(SceneStringName(body_shape_entered), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
}
}
@@ -156,9 +156,9 @@ void Area2D::_body_exit_tree(ObjectID p_id) {
ERR_FAIL_COND(!E);
ERR_FAIL_COND(!E->value.in_tree);
E->value.in_tree = false;
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ emit_signal(SceneStringName(body_exited), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
+ emit_signal(SceneStringName(body_shape_exited), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
}
}
@@ -172,9 +172,9 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
lock_callback();
locked = true;
if (body_in) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_entered), p_body, (Node *)nullptr, p_body_shape, p_area_shape);
} else {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_exited), p_body, (Node *)nullptr, p_body_shape, p_area_shape);
}
locked = false;
unlock_callback();
@@ -200,10 +200,10 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree).bind(objid));
+ node->connect(SceneStringName(tree_entered), callable_mp(this, &Area2D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringName(tree_exiting), callable_mp(this, &Area2D::_body_exit_tree).bind(objid));
if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
}
}
}
@@ -213,7 +213,7 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
if (!node || E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_entered), p_body, node, p_body_shape, p_area_shape);
}
} else {
@@ -227,15 +227,15 @@ void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
if (E->value.rc == 0) {
body_map.remove(E);
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area2D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area2D::_body_exit_tree));
if (in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
+ emit_signal(SceneStringName(body_exited), obj);
}
}
}
if (!node || in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_exited), p_body, obj, p_body_shape, p_area_shape);
}
}
@@ -253,9 +253,9 @@ void Area2D::_area_enter_tree(ObjectID p_id) {
ERR_FAIL_COND(E->value.in_tree);
E->value.in_tree = true;
- emit_signal(SceneStringNames::get_singleton()->area_entered, node);
+ emit_signal(SceneStringName(area_entered), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
+ emit_signal(SceneStringName(area_shape_entered), E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
}
}
@@ -267,9 +267,9 @@ void Area2D::_area_exit_tree(ObjectID p_id) {
ERR_FAIL_COND(!E);
ERR_FAIL_COND(!E->value.in_tree);
E->value.in_tree = false;
- emit_signal(SceneStringNames::get_singleton()->area_exited, node);
+ emit_signal(SceneStringName(area_exited), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
+ emit_signal(SceneStringName(area_shape_exited), E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
}
}
@@ -283,9 +283,9 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
lock_callback();
locked = true;
if (area_in) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_entered), p_area, (Node *)nullptr, p_area_shape, p_self_shape);
} else {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_exited), p_area, (Node *)nullptr, p_area_shape, p_self_shape);
}
locked = false;
unlock_callback();
@@ -311,10 +311,10 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree).bind(objid));
+ node->connect(SceneStringName(tree_entered), callable_mp(this, &Area2D::_area_enter_tree).bind(objid));
+ node->connect(SceneStringName(tree_exiting), callable_mp(this, &Area2D::_area_exit_tree).bind(objid));
if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_entered, node);
+ emit_signal(SceneStringName(area_entered), node);
}
}
}
@@ -324,7 +324,7 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
}
if (!node || E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_entered), p_area, node, p_area_shape, p_self_shape);
}
} else {
@@ -338,15 +338,15 @@ void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
if (E->value.rc == 0) {
area_map.remove(E);
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area2D::_area_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area2D::_area_exit_tree));
if (in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
+ emit_signal(SceneStringName(area_exited), obj);
}
}
}
if (!node || in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, obj, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_exited), p_area, obj, p_area_shape, p_self_shape);
}
}
@@ -370,18 +370,18 @@ void Area2D::_clear_monitoring() {
continue;
}
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area2D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area2D::_body_exit_tree));
if (!E.value.in_tree) {
continue;
}
for (int i = 0; i < E.value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E.value.rid, node, E.value.shapes[i].body_shape, E.value.shapes[i].area_shape);
+ emit_signal(SceneStringName(body_shape_exited), E.value.rid, node, E.value.shapes[i].body_shape, E.value.shapes[i].area_shape);
}
- emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
+ emit_signal(SceneStringName(body_exited), obj);
}
}
@@ -398,18 +398,18 @@ void Area2D::_clear_monitoring() {
continue;
}
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area2D::_area_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area2D::_area_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area2D::_area_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area2D::_area_exit_tree));
if (!E.value.in_tree) {
continue;
}
for (int i = 0; i < E.value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E.value.rid, node, E.value.shapes[i].area_shape, E.value.shapes[i].self_shape);
+ emit_signal(SceneStringName(area_shape_exited), E.value.rid, node, E.value.shapes[i].area_shape, E.value.shapes[i].self_shape);
}
- emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
+ emit_signal(SceneStringName(area_exited), obj);
}
}
}
@@ -538,7 +538,7 @@ StringName Area2D::get_audio_bus_name() const {
return audio_bus;
}
}
- return SceneStringNames::get_singleton()->Master;
+ return SceneStringName(Master);
}
void Area2D::_validate_property(PropertyInfo &p_property) const {
diff --git a/scene/2d/physics/collision_object_2d.cpp b/scene/2d/physics/collision_object_2d.cpp
index 4e5852984b..35704ae382 100644
--- a/scene/2d/physics/collision_object_2d.cpp
+++ b/scene/2d/physics/collision_object_2d.cpp
@@ -519,27 +519,27 @@ bool CollisionObject2D::is_pickable() const {
void CollisionObject2D::_input_event_call(Viewport *p_viewport, const Ref<InputEvent> &p_input_event, int p_shape) {
GDVIRTUAL_CALL(_input_event, p_viewport, p_input_event, p_shape);
- emit_signal(SceneStringNames::get_singleton()->input_event, p_viewport, p_input_event, p_shape);
+ emit_signal(SceneStringName(input_event), p_viewport, p_input_event, p_shape);
}
void CollisionObject2D::_mouse_enter() {
GDVIRTUAL_CALL(_mouse_enter);
- emit_signal(SceneStringNames::get_singleton()->mouse_entered);
+ emit_signal(SceneStringName(mouse_entered));
}
void CollisionObject2D::_mouse_exit() {
GDVIRTUAL_CALL(_mouse_exit);
- emit_signal(SceneStringNames::get_singleton()->mouse_exited);
+ emit_signal(SceneStringName(mouse_exited));
}
void CollisionObject2D::_mouse_shape_enter(int p_shape) {
GDVIRTUAL_CALL(_mouse_shape_enter, p_shape);
- emit_signal(SceneStringNames::get_singleton()->mouse_shape_entered, p_shape);
+ emit_signal(SceneStringName(mouse_shape_entered), p_shape);
}
void CollisionObject2D::_mouse_shape_exit(int p_shape) {
GDVIRTUAL_CALL(_mouse_shape_exit, p_shape);
- emit_signal(SceneStringNames::get_singleton()->mouse_shape_exited, p_shape);
+ emit_signal(SceneStringName(mouse_shape_exited), p_shape);
}
void CollisionObject2D::set_only_update_transform_changes(bool p_enable) {
diff --git a/scene/2d/physics/joints/joint_2d.cpp b/scene/2d/physics/joints/joint_2d.cpp
index 1afac7c150..5f61bebbb1 100644
--- a/scene/2d/physics/joints/joint_2d.cpp
+++ b/scene/2d/physics/joints/joint_2d.cpp
@@ -37,13 +37,13 @@ void Joint2D::_disconnect_signals() {
Node *node_a = get_node_or_null(a);
PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
if (body_a) {
- body_a->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+ body_a->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Joint2D::_body_exit_tree));
}
Node *node_b = get_node_or_null(b);
PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
if (body_b) {
- body_b->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+ body_b->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Joint2D::_body_exit_tree));
}
}
@@ -117,8 +117,8 @@ void Joint2D::_update_joint(bool p_only_free) {
ba = body_a->get_rid();
bb = body_b->get_rid();
- body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
- body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint2D::_body_exit_tree));
+ body_a->connect(SceneStringName(tree_exiting), callable_mp(this, &Joint2D::_body_exit_tree));
+ body_b->connect(SceneStringName(tree_exiting), callable_mp(this, &Joint2D::_body_exit_tree));
PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
}
diff --git a/scene/2d/physics/rigid_body_2d.cpp b/scene/2d/physics/rigid_body_2d.cpp
index 5e05c563a4..2495e7bc18 100644
--- a/scene/2d/physics/rigid_body_2d.cpp
+++ b/scene/2d/physics/rigid_body_2d.cpp
@@ -44,10 +44,10 @@ void RigidBody2D::_body_enter_tree(ObjectID p_id) {
contact_monitor->locked = true;
E->value.in_scene = true;
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ emit_signal(SceneStringName(body_shape_entered), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
}
contact_monitor->locked = false;
@@ -65,10 +65,10 @@ void RigidBody2D::_body_exit_tree(ObjectID p_id) {
contact_monitor->locked = true;
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ emit_signal(SceneStringName(body_exited), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ emit_signal(SceneStringName(body_shape_exited), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
}
contact_monitor->locked = false;
@@ -93,10 +93,10 @@ void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instan
//E->value.rc=0;
E->value.in_scene = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid));
+ node->connect(SceneStringName(tree_entered), callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid));
if (E->value.in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
}
}
@@ -108,7 +108,7 @@ void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instan
}
if (E->value.in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
+ emit_signal(SceneStringName(body_shape_entered), p_body, node, p_body_shape, p_local_shape);
}
} else {
@@ -122,17 +122,17 @@ void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instan
if (E->value.shapes.is_empty()) {
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &RigidBody2D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody2D::_body_exit_tree));
if (in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ emit_signal(SceneStringName(body_exited), node);
}
}
contact_monitor->body_map.remove(E);
}
if (node && in_scene) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, node, p_body_shape, p_local_shape);
+ emit_signal(SceneStringName(body_shape_exited), p_body, node, p_body_shape, p_local_shape);
}
}
}
@@ -158,7 +158,7 @@ void RigidBody2D::_sync_body_state(PhysicsDirectBodyState2D *p_state) {
if (sleeping != p_state->is_sleeping()) {
sleeping = p_state->is_sleeping();
- emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
+ emit_signal(SceneStringName(sleeping_state_changed));
}
}
@@ -605,8 +605,8 @@ void RigidBody2D::set_contact_monitor(bool p_enabled) {
Node *node = Object::cast_to<Node>(obj);
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &RigidBody2D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody2D::_body_exit_tree));
}
}
diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp
index 5745a59297..af40de1dd1 100644
--- a/scene/2d/sprite_2d.cpp
+++ b/scene/2d/sprite_2d.cpp
@@ -146,7 +146,7 @@ void Sprite2D::set_texture(const Ref<Texture2D> &p_texture) {
}
queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->texture_changed);
+ emit_signal(SceneStringName(texture_changed));
item_rect_changed();
}
@@ -260,7 +260,7 @@ void Sprite2D::set_frame(int p_frame) {
frame = p_frame;
item_rect_changed();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
int Sprite2D::get_frame() const {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index fbe7563e6b..3ea69fe17e 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -54,7 +54,7 @@ void TileMap::_tile_set_changed() {
}
void TileMap::_emit_changed() {
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMap::_set_tile_map_data_using_compatibility_format(int p_layer, TileMapDataFormat p_format, const Vector<int> &p_data) {
@@ -360,7 +360,7 @@ void TileMap::add_layer(int p_to_pos) {
for (uint32_t i = 0; i < layers.size(); i++) {
layers[i]->set_as_tile_map_internal_node(i);
}
- new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
+ new_layer->connect(CoreStringName(changed), callable_mp(this, &TileMap::_emit_changed));
notify_property_list_changed();
@@ -768,7 +768,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
new_layer->set_as_tile_map_internal_node(index);
new_layer->set_name(vformat("Layer%d", index));
new_layer->set_tile_set(tile_set);
- new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
+ new_layer->connect(CoreStringName(changed), callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
}
@@ -1051,7 +1051,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY_DEFAULT("format", TileMapDataFormat::TILE_MAP_DATA_FORMAT_1);
- ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed));
+ ADD_SIGNAL(MethodInfo(CoreStringName(changed)));
BIND_ENUM_CONSTANT(VISIBILITY_MODE_DEFAULT);
BIND_ENUM_CONSTANT(VISIBILITY_MODE_FORCE_HIDE);
@@ -1064,7 +1064,7 @@ TileMap::TileMap() {
new_layer->set_as_tile_map_internal_node(0);
new_layer->set_name("Layer0");
new_layer->set_tile_set(tile_set);
- new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
+ new_layer->connect(CoreStringName(changed), callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
if (!base_property_helper.is_initialized()) {
diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp
index fd1a638b58..e3abbea43a 100644
--- a/scene/2d/tile_map_layer.cpp
+++ b/scene/2d/tile_map_layer.cpp
@@ -1598,11 +1598,11 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cel
void TileMapLayer::_tile_set_changed() {
dirty.flags[DIRTY_FLAGS_TILE_SET] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMapLayer::_renamed() {
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMapLayer::_update_notify_local_transform() {
@@ -1805,7 +1805,7 @@ void TileMapLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "navigation_enabled"), "set_navigation_enabled", "is_navigation_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_navigation_visibility_mode", "get_navigation_visibility_mode");
- ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed));
+ ADD_SIGNAL(MethodInfo(CoreStringName(changed)));
ADD_PROPERTY_DEFAULT("tile_map_data_format", TileMapDataFormat::TILE_MAP_DATA_FORMAT_1);
@@ -1819,7 +1819,7 @@ void TileMapLayer::_update_self_texture_filter(RS::CanvasItemTextureFilter p_tex
CanvasItem::_update_self_texture_filter(p_texture_filter);
dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_FILTER] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMapLayer::_update_self_texture_repeat(RS::CanvasItemTextureRepeat p_texture_repeat) {
@@ -1827,7 +1827,7 @@ void TileMapLayer::_update_self_texture_repeat(RS::CanvasItemTextureRepeat p_tex
CanvasItem::_update_self_texture_repeat(p_texture_repeat);
dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_REPEAT] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMapLayer::set_as_tile_map_internal_node(int p_index) {
@@ -2502,7 +2502,7 @@ void TileMapLayer::update_internals() {
void TileMapLayer::notify_runtime_tile_data_update() {
dirty.flags[TileMapLayer::DIRTY_FLAGS_LAYER_RUNTIME_UPDATE] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
Vector2i TileMapLayer::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
@@ -2537,7 +2537,7 @@ void TileMapLayer::set_enabled(bool p_enabled) {
enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_ENABLED] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
bool TileMapLayer::is_enabled() const {
@@ -2563,7 +2563,7 @@ void TileMapLayer::set_tile_set(const Ref<TileSet> &p_tile_set) {
tile_set->connect_changed(callable_mp(this, &TileMapLayer::_tile_set_changed));
}
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
// Trigger updates for TileSet's read-only status.
notify_property_list_changed();
@@ -2675,7 +2675,7 @@ void TileMapLayer::set_self_modulate(const Color &p_self_modulate) {
CanvasItem::set_self_modulate(p_self_modulate);
dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
@@ -2685,7 +2685,7 @@ void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
CanvasItem::set_y_sort_enabled(p_y_sort_enabled);
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
_update_notify_local_transform();
}
@@ -2697,7 +2697,7 @@ void TileMapLayer::set_y_sort_origin(int p_y_sort_origin) {
y_sort_origin = p_y_sort_origin;
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
int TileMapLayer::get_y_sort_origin() const {
@@ -2711,7 +2711,7 @@ void TileMapLayer::set_z_index(int p_z_index) {
CanvasItem::set_z_index(p_z_index);
dirty.flags[DIRTY_FLAGS_LAYER_Z_INDEX] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMapLayer::set_light_mask(int p_light_mask) {
@@ -2721,7 +2721,7 @@ void TileMapLayer::set_light_mask(int p_light_mask) {
CanvasItem::set_light_mask(p_light_mask);
dirty.flags[DIRTY_FLAGS_LAYER_LIGHT_MASK] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
void TileMapLayer::set_rendering_quadrant_size(int p_size) {
@@ -2733,7 +2733,7 @@ void TileMapLayer::set_rendering_quadrant_size(int p_size) {
rendering_quadrant_size = p_size;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
int TileMapLayer::get_rendering_quadrant_size() const {
@@ -2747,7 +2747,7 @@ void TileMapLayer::set_collision_enabled(bool p_enabled) {
collision_enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_COLLISION_ENABLED] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
bool TileMapLayer::is_collision_enabled() const {
@@ -2758,7 +2758,7 @@ void TileMapLayer::set_use_kinematic_bodies(bool p_use_kinematic_bodies) {
use_kinematic_bodies = p_use_kinematic_bodies;
dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] = p_use_kinematic_bodies;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
bool TileMapLayer::is_using_kinematic_bodies() const {
@@ -2772,7 +2772,7 @@ void TileMapLayer::set_collision_visibility_mode(TileMapLayer::DebugVisibilityMo
collision_visibility_mode = p_show_collision;
dirty.flags[DIRTY_FLAGS_LAYER_COLLISION_VISIBILITY_MODE] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
TileMapLayer::DebugVisibilityMode TileMapLayer::get_collision_visibility_mode() const {
@@ -2786,7 +2786,7 @@ void TileMapLayer::set_navigation_enabled(bool p_enabled) {
navigation_enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
bool TileMapLayer::is_navigation_enabled() const {
@@ -2800,7 +2800,7 @@ void TileMapLayer::set_navigation_map(RID p_map) {
navigation_map_override = p_map;
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_MAP] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
RID TileMapLayer::get_navigation_map() const {
@@ -2819,7 +2819,7 @@ void TileMapLayer::set_navigation_visibility_mode(TileMapLayer::DebugVisibilityM
navigation_visibility_mode = p_show_navigation;
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_VISIBILITY_MODE] = true;
_queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringName(changed));
}
TileMapLayer::DebugVisibilityMode TileMapLayer::get_navigation_visibility_mode() const {
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 5ed7fadb2a..b7a47e8723 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -38,11 +38,11 @@ void TouchScreenButton::set_texture_normal(const Ref<Texture2D> &p_texture) {
return;
}
if (texture_normal.is_valid()) {
- texture_normal->disconnect(SceneStringNames::get_singleton()->changed, callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
+ texture_normal->disconnect(SceneStringName(changed), callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
}
texture_normal = p_texture;
if (texture_normal.is_valid()) {
- texture_normal->connect(SceneStringNames::get_singleton()->changed, callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw), CONNECT_REFERENCE_COUNTED);
+ texture_normal->connect(SceneStringName(changed), callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw), CONNECT_REFERENCE_COUNTED);
}
queue_redraw();
}
@@ -56,11 +56,11 @@ void TouchScreenButton::set_texture_pressed(const Ref<Texture2D> &p_texture_pres
return;
}
if (texture_pressed.is_valid()) {
- texture_pressed->disconnect(SceneStringNames::get_singleton()->changed, callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
+ texture_pressed->disconnect(SceneStringName(changed), callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
}
texture_pressed = p_texture_pressed;
if (texture_pressed.is_valid()) {
- texture_pressed->connect(SceneStringNames::get_singleton()->changed, callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw), CONNECT_REFERENCE_COUNTED);
+ texture_pressed->connect(SceneStringName(changed), callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw), CONNECT_REFERENCE_COUNTED);
}
queue_redraw();
}
diff --git a/scene/2d/visible_on_screen_notifier_2d.cpp b/scene/2d/visible_on_screen_notifier_2d.cpp
index 89b2c20b20..fd0f3a461e 100644
--- a/scene/2d/visible_on_screen_notifier_2d.cpp
+++ b/scene/2d/visible_on_screen_notifier_2d.cpp
@@ -48,7 +48,7 @@ void VisibleOnScreenNotifier2D::_visibility_enter() {
}
on_screen = true;
- emit_signal(SceneStringNames::get_singleton()->screen_entered);
+ emit_signal(SceneStringName(screen_entered));
_screen_enter();
}
void VisibleOnScreenNotifier2D::_visibility_exit() {
@@ -57,7 +57,7 @@ void VisibleOnScreenNotifier2D::_visibility_exit() {
}
on_screen = false;
- emit_signal(SceneStringNames::get_singleton()->screen_exited);
+ emit_signal(SceneStringName(screen_exited));
_screen_exit();
}
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 5aa50a4a21..71b96fc8ce 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -1156,7 +1156,7 @@ void CPUParticles3D::_particles_process(double p_delta) {
}
if (!Math::is_equal_approx(time, 0.0) && active && !should_be_active) {
active = false;
- emit_signal(SceneStringNames::get_singleton()->finished);
+ emit_signal(SceneStringName(finished));
}
}
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 16813b9017..865d91e4cc 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -478,7 +478,7 @@ void GPUParticles3D::_notification(int p_what) {
}
if (time > active_time) {
if (active && !signal_canceled) {
- emit_signal(SceneStringNames::get_singleton()->finished);
+ emit_signal(SceneStringName(finished));
}
active = false;
if (!emitting) {
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 98a5134283..9bc5dc09df 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -193,12 +193,12 @@ void Node3D::_notification(int p_what) {
ERR_FAIL_NULL(data.viewport);
if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_enter_world);
+ get_script_instance()->call(SceneStringName(_enter_world));
}
#ifdef TOOLS_ENABLED
if (is_part_of_edited_scene()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SNAME("_request_gizmo_for_id"), get_instance_id());
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringName(_spatial_editor_group), SNAME("_request_gizmo_for_id"), get_instance_id());
}
#endif
} break;
@@ -211,7 +211,7 @@ void Node3D::_notification(int p_what) {
#endif
if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_exit_world);
+ get_script_instance()->call(SceneStringName(_exit_world));
}
data.viewport = nullptr;
@@ -564,7 +564,7 @@ void Node3D::update_gizmos() {
}
if (data.gizmos.is_empty()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SNAME("_request_gizmo_for_id"), get_instance_id());
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringName(_spatial_editor_group), SNAME("_request_gizmo_for_id"), get_instance_id());
return;
}
if (data.gizmos_dirty) {
@@ -583,7 +583,7 @@ void Node3D::set_subgizmo_selection(Ref<Node3DGizmo> p_gizmo, int p_id, Transfor
}
if (is_part_of_edited_scene()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_set_subgizmo_selection, this, p_gizmo, p_id, p_transform);
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringName(_spatial_editor_group), SceneStringName(_set_subgizmo_selection), this, p_gizmo, p_id, p_transform);
}
#endif
}
@@ -600,7 +600,7 @@ void Node3D::clear_subgizmo_selection() {
}
if (is_part_of_edited_scene()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_clear_subgizmo_selection, this);
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringName(_spatial_editor_group), SceneStringName(_clear_subgizmo_selection), this);
}
#endif
}
@@ -777,7 +777,7 @@ Ref<World3D> Node3D::get_world_3d() const {
void Node3D::_propagate_visibility_changed() {
notification(NOTIFICATION_VISIBILITY_CHANGED);
- emit_signal(SceneStringNames::get_singleton()->visibility_changed);
+ emit_signal(SceneStringName(visibility_changed));
#ifdef TOOLS_ENABLED
if (!data.gizmos.is_empty()) {
diff --git a/scene/3d/physics/area_3d.cpp b/scene/3d/physics/area_3d.cpp
index 014c33cad0..8cb316a2fe 100644
--- a/scene/3d/physics/area_3d.cpp
+++ b/scene/3d/physics/area_3d.cpp
@@ -199,9 +199,9 @@ void Area3D::_body_enter_tree(ObjectID p_id) {
ERR_FAIL_COND(E->value.in_tree);
E->value.in_tree = true;
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
+ emit_signal(SceneStringName(body_shape_entered), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
}
}
@@ -213,9 +213,9 @@ void Area3D::_body_exit_tree(ObjectID p_id) {
ERR_FAIL_COND(!E);
ERR_FAIL_COND(!E->value.in_tree);
E->value.in_tree = false;
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ emit_signal(SceneStringName(body_exited), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
+ emit_signal(SceneStringName(body_shape_exited), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].area_shape);
}
}
@@ -229,9 +229,9 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
locked = true;
// Emit the appropriate signals.
if (body_in) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_entered), p_body, (Node *)nullptr, p_body_shape, p_area_shape);
} else {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, (Node *)nullptr, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_exited), p_body, (Node *)nullptr, p_body_shape, p_area_shape);
}
locked = false;
unlock_callback();
@@ -257,10 +257,10 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree).bind(objid));
+ node->connect(SceneStringName(tree_entered), callable_mp(this, &Area3D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringName(tree_exiting), callable_mp(this, &Area3D::_body_exit_tree).bind(objid));
if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
}
}
}
@@ -270,7 +270,7 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
}
if (!node || E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_entered), p_body, node, p_body_shape, p_area_shape);
}
} else {
@@ -284,15 +284,15 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i
if (E->value.rc == 0) {
body_map.remove(E);
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area3D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area3D::_body_exit_tree));
if (in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
+ emit_signal(SceneStringName(body_exited), obj);
}
}
}
if (!node || in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_area_shape);
+ emit_signal(SceneStringName(body_shape_exited), p_body, obj, p_body_shape, p_area_shape);
}
}
@@ -317,18 +317,18 @@ void Area3D::_clear_monitoring() {
}
//ERR_CONTINUE(!node);
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area3D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area3D::_body_exit_tree));
if (!E.value.in_tree) {
continue;
}
for (int i = 0; i < E.value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E.value.rid, node, E.value.shapes[i].body_shape, E.value.shapes[i].area_shape);
+ emit_signal(SceneStringName(body_shape_exited), E.value.rid, node, E.value.shapes[i].body_shape, E.value.shapes[i].area_shape);
}
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ emit_signal(SceneStringName(body_exited), node);
}
}
@@ -346,18 +346,18 @@ void Area3D::_clear_monitoring() {
}
//ERR_CONTINUE(!node);
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area3D::_area_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area3D::_area_exit_tree));
if (!E.value.in_tree) {
continue;
}
for (int i = 0; i < E.value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E.value.rid, node, E.value.shapes[i].area_shape, E.value.shapes[i].self_shape);
+ emit_signal(SceneStringName(area_shape_exited), E.value.rid, node, E.value.shapes[i].area_shape, E.value.shapes[i].self_shape);
}
- emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
+ emit_signal(SceneStringName(area_exited), obj);
}
}
}
@@ -405,9 +405,9 @@ void Area3D::_area_enter_tree(ObjectID p_id) {
ERR_FAIL_COND(E->value.in_tree);
E->value.in_tree = true;
- emit_signal(SceneStringNames::get_singleton()->area_entered, node);
+ emit_signal(SceneStringName(area_entered), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
+ emit_signal(SceneStringName(area_shape_entered), E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
}
}
@@ -419,9 +419,9 @@ void Area3D::_area_exit_tree(ObjectID p_id) {
ERR_FAIL_COND(!E);
ERR_FAIL_COND(!E->value.in_tree);
E->value.in_tree = false;
- emit_signal(SceneStringNames::get_singleton()->area_exited, node);
+ emit_signal(SceneStringName(area_exited), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
+ emit_signal(SceneStringName(area_shape_exited), E->value.rid, node, E->value.shapes[i].area_shape, E->value.shapes[i].self_shape);
}
}
@@ -435,9 +435,9 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
locked = true;
// Emit the appropriate signals.
if (area_in) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_entered), p_area, (Node *)nullptr, p_area_shape, p_self_shape);
} else {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, (Node *)nullptr, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_exited), p_area, (Node *)nullptr, p_area_shape, p_self_shape);
}
locked = false;
unlock_callback();
@@ -463,10 +463,10 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
E->value.rc = 0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree).bind(objid));
+ node->connect(SceneStringName(tree_entered), callable_mp(this, &Area3D::_area_enter_tree).bind(objid));
+ node->connect(SceneStringName(tree_exiting), callable_mp(this, &Area3D::_area_exit_tree).bind(objid));
if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_entered, node);
+ emit_signal(SceneStringName(area_entered), node);
}
}
}
@@ -476,7 +476,7 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
}
if (!node || E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_entered, p_area, node, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_entered), p_area, node, p_area_shape, p_self_shape);
}
} else {
@@ -490,15 +490,15 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i
if (E->value.rc == 0) {
area_map.remove(E);
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &Area3D::_area_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Area3D::_area_exit_tree));
if (in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_exited, obj);
+ emit_signal(SceneStringName(area_exited), obj);
}
}
}
if (!node || in_tree) {
- emit_signal(SceneStringNames::get_singleton()->area_shape_exited, p_area, obj, p_area_shape, p_self_shape);
+ emit_signal(SceneStringName(area_shape_exited), p_area, obj, p_area_shape, p_self_shape);
}
}
@@ -605,7 +605,7 @@ StringName Area3D::get_audio_bus_name() const {
return audio_bus;
}
}
- return SceneStringNames::get_singleton()->Master;
+ return SceneStringName(Master);
}
void Area3D::set_use_reverb_bus(bool p_enable) {
@@ -626,7 +626,7 @@ StringName Area3D::get_reverb_bus_name() const {
return reverb_bus;
}
}
- return SceneStringNames::get_singleton()->Master;
+ return SceneStringName(Master);
}
void Area3D::set_reverb_amount(float p_amount) {
@@ -812,6 +812,8 @@ void Area3D::_bind_methods() {
Area3D::Area3D() :
CollisionObject3D(PhysicsServer3D::get_singleton()->area_create(), true) {
+ audio_bus = SceneStringName(Master);
+ reverb_bus = SceneStringName(Master);
set_gravity(9.8);
set_gravity_direction(Vector3(0, -1, 0));
set_monitoring(true);
diff --git a/scene/3d/physics/area_3d.h b/scene/3d/physics/area_3d.h
index 41382b6128..bb3694dff3 100644
--- a/scene/3d/physics/area_3d.h
+++ b/scene/3d/physics/area_3d.h
@@ -135,10 +135,10 @@ private:
void _clear_monitoring();
bool audio_bus_override = false;
- StringName audio_bus = SceneStringNames::get_singleton()->Master;
+ StringName audio_bus;
bool use_reverb_bus = false;
- StringName reverb_bus = SceneStringNames::get_singleton()->Master;
+ StringName reverb_bus;
float reverb_amount = 0.0;
float reverb_uniformity = 0.0;
diff --git a/scene/3d/physics/collision_object_3d.cpp b/scene/3d/physics/collision_object_3d.cpp
index 54752b1281..324620df4f 100644
--- a/scene/3d/physics/collision_object_3d.cpp
+++ b/scene/3d/physics/collision_object_3d.cpp
@@ -291,17 +291,17 @@ void CollisionObject3D::_apply_enabled() {
void CollisionObject3D::_input_event_call(Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
GDVIRTUAL_CALL(_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape);
- emit_signal(SceneStringNames::get_singleton()->input_event, p_camera, p_input_event, p_pos, p_normal, p_shape);
+ emit_signal(SceneStringName(input_event), p_camera, p_input_event, p_pos, p_normal, p_shape);
}
void CollisionObject3D::_mouse_enter() {
GDVIRTUAL_CALL(_mouse_enter);
- emit_signal(SceneStringNames::get_singleton()->mouse_entered);
+ emit_signal(SceneStringName(mouse_entered));
}
void CollisionObject3D::_mouse_exit() {
GDVIRTUAL_CALL(_mouse_exit);
- emit_signal(SceneStringNames::get_singleton()->mouse_exited);
+ emit_signal(SceneStringName(mouse_exited));
}
void CollisionObject3D::set_body_mode(PhysicsServer3D::BodyMode p_mode) {
diff --git a/scene/3d/physics/joints/joint_3d.cpp b/scene/3d/physics/joints/joint_3d.cpp
index a9c2526bd0..dac52a4dd8 100644
--- a/scene/3d/physics/joints/joint_3d.cpp
+++ b/scene/3d/physics/joints/joint_3d.cpp
@@ -36,13 +36,13 @@ void Joint3D::_disconnect_signals() {
Node *node_a = get_node_or_null(a);
PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a);
if (body_a) {
- body_a->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ body_a->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Joint3D::_body_exit_tree));
}
Node *node_b = get_node_or_null(b);
PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
if (body_b) {
- body_b->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ body_b->disconnect(SceneStringName(tree_exiting), callable_mp(this, &Joint3D::_body_exit_tree));
}
}
@@ -108,12 +108,12 @@ void Joint3D::_update_joint(bool p_only_free) {
if (body_a) {
ba = body_a->get_rid();
- body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ body_a->connect(SceneStringName(tree_exiting), callable_mp(this, &Joint3D::_body_exit_tree));
}
if (body_b) {
bb = body_b->get_rid();
- body_b->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree));
+ body_b->connect(SceneStringName(tree_exiting), callable_mp(this, &Joint3D::_body_exit_tree));
}
PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision);
diff --git a/scene/3d/physics/rigid_body_3d.cpp b/scene/3d/physics/rigid_body_3d.cpp
index 6cd621c1c7..a06680767c 100644
--- a/scene/3d/physics/rigid_body_3d.cpp
+++ b/scene/3d/physics/rigid_body_3d.cpp
@@ -45,10 +45,10 @@ void RigidBody3D::_body_enter_tree(ObjectID p_id) {
contact_monitor->locked = true;
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ emit_signal(SceneStringName(body_shape_entered), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
}
contact_monitor->locked = false;
@@ -66,10 +66,10 @@ void RigidBody3D::_body_exit_tree(ObjectID p_id) {
contact_monitor->locked = true;
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ emit_signal(SceneStringName(body_exited), node);
for (int i = 0; i < E->value.shapes.size(); i++) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
+ emit_signal(SceneStringName(body_shape_exited), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
}
contact_monitor->locked = false;
@@ -94,10 +94,10 @@ void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instan
//E->value.rc=0;
E->value.in_tree = node && node->is_inside_tree();
if (node) {
- node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree).bind(objid));
- node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree).bind(objid));
+ node->connect(SceneStringName(tree_entered), callable_mp(this, &RigidBody3D::_body_enter_tree).bind(objid));
+ node->connect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody3D::_body_exit_tree).bind(objid));
if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_entered, node);
+ emit_signal(SceneStringName(body_entered), node);
}
}
}
@@ -107,7 +107,7 @@ void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instan
}
if (E->value.in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
+ emit_signal(SceneStringName(body_shape_entered), p_body, node, p_body_shape, p_local_shape);
}
} else {
@@ -121,17 +121,17 @@ void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instan
if (E->value.shapes.is_empty()) {
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &RigidBody3D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody3D::_body_exit_tree));
if (in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_exited, node);
+ emit_signal(SceneStringName(body_exited), node);
}
}
contact_monitor->body_map.remove(E);
}
if (node && in_tree) {
- emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, obj, p_body_shape, p_local_shape);
+ emit_signal(SceneStringName(body_shape_exited), p_body, obj, p_body_shape, p_local_shape);
}
}
}
@@ -157,7 +157,7 @@ void RigidBody3D::_sync_body_state(PhysicsDirectBodyState3D *p_state) {
if (sleeping != p_state->is_sleeping()) {
sleeping = p_state->is_sleeping();
- emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
+ emit_signal(SceneStringName(sleeping_state_changed));
}
}
@@ -613,8 +613,8 @@ void RigidBody3D::set_contact_monitor(bool p_enabled) {
Node *node = Object::cast_to<Node>(obj);
if (node) {
- node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree));
- node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree));
+ node->disconnect(SceneStringName(tree_entered), callable_mp(this, &RigidBody3D::_body_enter_tree));
+ node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody3D::_body_exit_tree));
}
}
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 72b5b53b19..cd0aafbf29 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -314,7 +314,7 @@ void Skeleton3D::_notification(int p_what) {
_process_modifiers();
}
- emit_signal(SceneStringNames::get_singleton()->skeleton_updated);
+ emit_signal(SceneStringName(skeleton_updated));
// Update skins.
RenderingServer *rs = RenderingServer::get_singleton();
@@ -605,7 +605,7 @@ void Skeleton3D::set_bone_enabled(int p_bone, bool p_enabled) {
ERR_FAIL_INDEX(p_bone, bone_size);
bones.write[p_bone].enabled = p_enabled;
- emit_signal(SceneStringNames::get_singleton()->bone_enabled_changed, p_bone);
+ emit_signal(SceneStringName(bone_enabled_changed), p_bone);
_make_dirty();
}
@@ -617,7 +617,7 @@ bool Skeleton3D::is_bone_enabled(int p_bone) const {
void Skeleton3D::set_show_rest_only(bool p_enabled) {
show_rest_only = p_enabled;
- emit_signal(SceneStringNames::get_singleton()->show_rest_only_changed);
+ emit_signal(SceneStringName(show_rest_only_changed));
_make_dirty();
}
@@ -840,7 +840,7 @@ void Skeleton3D::force_update_all_bone_transforms() {
if (updating) {
return;
}
- emit_signal(SceneStringNames::get_singleton()->pose_updated);
+ emit_signal(SceneStringName(pose_updated));
}
void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) {
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 7d2a821d16..6ccb0ee134 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -796,15 +796,15 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
return;
}
if (texture.is_valid()) {
- texture->disconnect(SceneStringNames::get_singleton()->changed, callable_mp((SpriteBase3D *)this, &Sprite3D::_queue_redraw));
+ texture->disconnect(SceneStringName(changed), callable_mp((SpriteBase3D *)this, &Sprite3D::_queue_redraw));
}
texture = p_texture;
if (texture.is_valid()) {
- texture->connect(SceneStringNames::get_singleton()->changed, callable_mp((SpriteBase3D *)this, &Sprite3D::_queue_redraw));
+ texture->connect(SceneStringName(changed), callable_mp((SpriteBase3D *)this, &Sprite3D::_queue_redraw));
}
_queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->texture_changed);
+ emit_signal(SceneStringName(texture_changed));
}
Ref<Texture2D> Sprite3D::get_texture() const {
@@ -849,7 +849,7 @@ void Sprite3D::set_frame(int p_frame) {
frame = p_frame;
_queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
int Sprite3D::get_frame() const {
@@ -1122,7 +1122,7 @@ void AnimatedSprite3D::_notification(int p_what) {
} else {
frame = last_frame;
pause();
- emit_signal(SceneStringNames::get_singleton()->animation_finished);
+ emit_signal(SceneStringName(animation_finished));
return;
}
} else {
@@ -1131,7 +1131,7 @@ void AnimatedSprite3D::_notification(int p_what) {
_calc_frame_speed_scale();
frame_progress = 0.0;
_queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
double to_process = MIN((1.0 - frame_progress) / abs_speed, remaining);
frame_progress += to_process * abs_speed;
@@ -1146,7 +1146,7 @@ void AnimatedSprite3D::_notification(int p_what) {
} else {
frame = 0;
pause();
- emit_signal(SceneStringNames::get_singleton()->animation_finished);
+ emit_signal(SceneStringName(animation_finished));
return;
}
} else {
@@ -1155,7 +1155,7 @@ void AnimatedSprite3D::_notification(int p_what) {
_calc_frame_speed_scale();
frame_progress = 1.0;
_queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
double to_process = MIN(frame_progress / abs_speed, remaining);
frame_progress -= to_process * abs_speed;
@@ -1177,12 +1177,12 @@ void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
}
if (frames.is_valid()) {
- frames->disconnect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite3D::_res_changed));
+ frames->disconnect(SceneStringName(changed), callable_mp(this, &AnimatedSprite3D::_res_changed));
}
stop();
frames = p_frames;
if (frames.is_valid()) {
- frames->connect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite3D::_res_changed));
+ frames->connect(SceneStringName(changed), callable_mp(this, &AnimatedSprite3D::_res_changed));
List<StringName> al;
frames->get_animation_list(&al);
@@ -1249,7 +1249,7 @@ void AnimatedSprite3D::set_frame_and_progress(int p_frame, real_t p_progress) {
return; // No change, don't redraw.
}
_queue_redraw();
- emit_signal(SceneStringNames::get_singleton()->frame_changed);
+ emit_signal(SceneStringName(frame_changed));
}
void AnimatedSprite3D::set_speed_scale(float p_speed_scale) {
diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp
index 272852e8fa..36a1771b96 100644
--- a/scene/3d/visible_on_screen_notifier_3d.cpp
+++ b/scene/3d/visible_on_screen_notifier_3d.cpp
@@ -38,7 +38,7 @@ void VisibleOnScreenNotifier3D::_visibility_enter() {
}
on_screen = true;
- emit_signal(SceneStringNames::get_singleton()->screen_entered);
+ emit_signal(SceneStringName(screen_entered));
_screen_enter();
}
void VisibleOnScreenNotifier3D::_visibility_exit() {
@@ -47,7 +47,7 @@ void VisibleOnScreenNotifier3D::_visibility_exit() {
}
on_screen = false;
- emit_signal(SceneStringNames::get_singleton()->screen_exited);
+ emit_signal(SceneStringName(screen_exited));
_screen_exit();
}
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index e0dc300a6b..84ae8f1f4f 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -169,11 +169,11 @@ VisualInstance3D::~VisualInstance3D() {
void GeometryInstance3D::set_material_override(const Ref<Material> &p_material) {
if (material_override.is_valid()) {
- material_override->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ material_override->disconnect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
material_override = p_material;
if (material_override.is_valid()) {
- material_override->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ material_override->connect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
}
RS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
}
@@ -279,12 +279,12 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value)
return true;
}
#ifndef DISABLE_DEPRECATED
- if (p_name == SceneStringNames::get_singleton()->use_in_baked_light && bool(p_value)) {
+ if (p_name == SceneStringName(use_in_baked_light) && bool(p_value)) {
set_gi_mode(GI_MODE_STATIC);
return true;
}
- if (p_name == SceneStringNames::get_singleton()->use_dynamic_gi && bool(p_value)) {
+ if (p_name == SceneStringName(use_dynamic_gi) && bool(p_value)) {
set_gi_mode(GI_MODE_DYNAMIC);
return true;
}
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 1cf235a807..e0b84eb6c7 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -1421,7 +1421,7 @@ AnimationNodeOutput::AnimationNodeOutput() {
void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNode> p_node, const Vector2 &p_position) {
ERR_FAIL_COND(nodes.has(p_name));
ERR_FAIL_COND(p_node.is_null());
- ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output);
+ ERR_FAIL_COND(p_name == SceneStringName(output));
ERR_FAIL_COND(String(p_name).contains("/"));
Node n;
@@ -1491,7 +1491,7 @@ Vector<StringName> AnimationNodeBlendTree::get_node_connection_array(const Strin
void AnimationNodeBlendTree::remove_node(const StringName &p_name) {
ERR_FAIL_COND(!nodes.has(p_name));
- ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output); //can't delete output
+ ERR_FAIL_COND(p_name == SceneStringName(output)); //can't delete output
{
Ref<AnimationNode> node = nodes[p_name].node;
@@ -1520,8 +1520,8 @@ void AnimationNodeBlendTree::remove_node(const StringName &p_name) {
void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringName &p_new_name) {
ERR_FAIL_COND(!nodes.has(p_name));
ERR_FAIL_COND(nodes.has(p_new_name));
- ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output);
- ERR_FAIL_COND(p_new_name == SceneStringNames::get_singleton()->output);
+ ERR_FAIL_COND(p_name == SceneStringName(output));
+ ERR_FAIL_COND(p_new_name == SceneStringName(output));
nodes[p_name].node->disconnect_changed(callable_mp(this, &AnimationNodeBlendTree::_node_changed));
@@ -1546,7 +1546,7 @@ void AnimationNodeBlendTree::rename_node(const StringName &p_name, const StringN
void AnimationNodeBlendTree::connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) {
ERR_FAIL_COND(!nodes.has(p_output_node));
ERR_FAIL_COND(!nodes.has(p_input_node));
- ERR_FAIL_COND(p_output_node == SceneStringNames::get_singleton()->output);
+ ERR_FAIL_COND(p_output_node == SceneStringName(output));
ERR_FAIL_COND(p_input_node == p_output_node);
Ref<AnimationNode> input = nodes[p_input_node].node;
@@ -1574,7 +1574,7 @@ void AnimationNodeBlendTree::disconnect_node(const StringName &p_node, int p_inp
}
AnimationNodeBlendTree::ConnectionError AnimationNodeBlendTree::can_connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) const {
- if (!nodes.has(p_output_node) || p_output_node == SceneStringNames::get_singleton()->output) {
+ if (!nodes.has(p_output_node) || p_output_node == SceneStringName(output)) {
return CONNECTION_ERROR_NO_OUTPUT;
}
@@ -1627,8 +1627,8 @@ String AnimationNodeBlendTree::get_caption() const {
}
AnimationNode::NodeTimeInfo AnimationNodeBlendTree::_process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) {
- Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node;
- node_state.connections = nodes[SceneStringNames::get_singleton()->output].connections;
+ Ref<AnimationNodeOutput> output = nodes[SceneStringName(output)].node;
+ node_state.connections = nodes[SceneStringName(output)].connections;
ERR_FAIL_COND_V(output.is_null(), NodeTimeInfo());
AnimationMixer::PlaybackInfo pi = p_playback_info;
diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp
index d22b58346f..1671192fd9 100644
--- a/scene/animation/animation_mixer.cpp
+++ b/scene/animation/animation_mixer.cpp
@@ -628,9 +628,9 @@ bool AnimationMixer::_update_caches() {
#endif
Ref<Animation> reset_anim;
- bool has_reset_anim = has_animation(SceneStringNames::get_singleton()->RESET);
+ bool has_reset_anim = has_animation(SceneStringName(RESET));
if (has_reset_anim) {
- reset_anim = get_animation(SceneStringNames::get_singleton()->RESET);
+ reset_anim = get_animation(SceneStringName(RESET));
}
for (const StringName &E : sname) {
Ref<Animation> anim = get_animation(E);
@@ -1926,7 +1926,7 @@ bool AnimationMixer::is_reset_on_save_enabled() const {
}
bool AnimationMixer::can_apply_reset() const {
- return has_animation(SceneStringNames::get_singleton()->RESET);
+ return has_animation(SceneStringName(RESET));
}
void AnimationMixer::_build_backup_track_cache() {
@@ -2013,7 +2013,7 @@ Ref<AnimatedValuesBackup> AnimationMixer::make_backup() {
Ref<AnimatedValuesBackup> backup;
backup.instantiate();
- Ref<Animation> reset_anim = animation_set[SceneStringNames::get_singleton()->RESET].animation;
+ Ref<Animation> reset_anim = animation_set[SceneStringName(RESET)].animation;
ERR_FAIL_COND_V(reset_anim.is_null(), Ref<AnimatedValuesBackup>());
_blend_init();
@@ -2022,7 +2022,7 @@ Ref<AnimatedValuesBackup> AnimationMixer::make_backup() {
pi.delta = 0;
pi.seeked = true;
pi.weight = 1.0;
- make_animation_instance(SceneStringNames::get_singleton()->RESET, pi);
+ make_animation_instance(SceneStringName(RESET), pi);
_build_backup_track_cache();
backup->set_data(track_cache);
@@ -2034,7 +2034,7 @@ Ref<AnimatedValuesBackup> AnimationMixer::make_backup() {
void AnimationMixer::reset() {
ERR_FAIL_COND(!can_apply_reset());
- Ref<Animation> reset_anim = animation_set[SceneStringNames::get_singleton()->RESET].animation;
+ Ref<Animation> reset_anim = animation_set[SceneStringName(RESET)].animation;
ERR_FAIL_COND(reset_anim.is_null());
Node *root_node_object = get_node_or_null(root_node);
@@ -2044,11 +2044,11 @@ void AnimationMixer::reset() {
root_node_object->add_child(aux_player);
Ref<AnimationLibrary> al;
al.instantiate();
- al->add_animation(SceneStringNames::get_singleton()->RESET, reset_anim);
+ al->add_animation(SceneStringName(RESET), reset_anim);
aux_player->set_reset_on_save_enabled(false);
aux_player->set_root_node(aux_player->get_path_to(root_node_object));
aux_player->add_animation_library("", al);
- aux_player->set_assigned_animation(SceneStringNames::get_singleton()->RESET);
+ aux_player->set_assigned_animation(SceneStringName(RESET));
aux_player->seek(0.0f, true);
aux_player->queue_free();
}
@@ -2068,7 +2068,7 @@ Ref<AnimatedValuesBackup> AnimationMixer::apply_reset(bool p_user_initiated) {
}
ERR_FAIL_COND_V(!can_apply_reset(), Ref<AnimatedValuesBackup>());
- Ref<Animation> reset_anim = animation_set[SceneStringNames::get_singleton()->RESET].animation;
+ Ref<Animation> reset_anim = animation_set[SceneStringName(RESET)].animation;
ERR_FAIL_COND_V(reset_anim.is_null(), Ref<AnimatedValuesBackup>());
Ref<AnimatedValuesBackup> backup_current = make_backup();
@@ -2286,7 +2286,7 @@ void AnimationMixer::_bind_methods() {
}
AnimationMixer::AnimationMixer() {
- root_node = SceneStringNames::get_singleton()->path_pp;
+ root_node = SceneStringName(path_pp);
}
AnimationMixer::~AnimationMixer() {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 2213800476..2b6c9a335d 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -41,7 +41,7 @@ bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) {
} else if (name.begins_with("next/")) {
String which = name.get_slicec('/', 1);
animation_set_next(which, p_value);
- } else if (p_name == SceneStringNames::get_singleton()->blend_times) {
+ } else if (p_name == SceneStringName(blend_times)) {
Array array = p_value;
int len = array.size();
ERR_FAIL_COND_V(len % 3, false);
@@ -326,14 +326,14 @@ void AnimationPlayer::_blend_post_process() {
String new_name = playback.assigned;
playback_queue.pop_front();
if (end_notify) {
- emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name);
+ emit_signal(SceneStringName(animation_changed), old, new_name);
}
} else {
_clear_caches();
playing = false;
_set_process(false);
if (end_notify) {
- emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned);
+ emit_signal(SceneStringName(animation_finished), playback.assigned);
if (movie_quit_on_finish && OS::get_singleton()->has_feature("movie")) {
print_line(vformat("Movie Maker mode is enabled. Quitting on animation finish as requested by: %s", get_path()));
get_tree()->quit();
@@ -463,7 +463,7 @@ void AnimationPlayer::_play(const StringName &p_name, double p_custom_blend, flo
_set_process(true); // Always process when starting an animation.
playing = true;
- emit_signal(SceneStringNames::get_singleton()->animation_started, c.assigned);
+ emit_signal(SceneStringName(animation_started), c.assigned);
if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
return; // No next in this case.
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 28a163768f..8fe05d9d1f 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -627,7 +627,7 @@ bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const
for (int i = 0; i < p_track_count; i++) {
src_blendsw[i] = 1.0; // By default all go to 1 for the root input.
}
- root_animation_node->node_state.base_path = SceneStringNames::get_singleton()->parameters_base_path;
+ root_animation_node->node_state.base_path = SceneStringName(parameters_base_path);
root_animation_node->node_state.parent = nullptr;
}
@@ -788,7 +788,7 @@ void AnimationTree::_update_properties() {
input_activity_map_get.clear();
if (root_animation_node.is_valid()) {
- _update_properties_for_node(SceneStringNames::get_singleton()->parameters_base_path, root_animation_node);
+ _update_properties_for_node(SceneStringName(parameters_base_path), root_animation_node);
}
properties_dirty = false;
@@ -810,7 +810,7 @@ void AnimationTree::_notification(int p_what) {
void AnimationTree::set_animation_player(const NodePath &p_path) {
animation_player = p_path;
if (p_path.is_empty()) {
- set_root_node(SceneStringNames::get_singleton()->path_pp);
+ set_root_node(SceneStringName(path_pp));
while (animation_libraries.size()) {
remove_animation_library(animation_libraries[0].name);
}
diff --git a/scene/audio/audio_stream_player_internal.cpp b/scene/audio/audio_stream_player_internal.cpp
index 19b3ec481b..ed3c43818e 100644
--- a/scene/audio/audio_stream_player_internal.cpp
+++ b/scene/audio/audio_stream_player_internal.cpp
@@ -307,14 +307,14 @@ StringName AudioStreamPlayerInternal::get_bus() const {
return bus;
}
}
- return SceneStringNames::get_singleton()->Master;
+ return SceneStringName(Master);
}
AudioStreamPlayerInternal::AudioStreamPlayerInternal(Node *p_node, const Callable &p_play_callable, bool p_physical) {
node = p_node;
play_callable = p_play_callable;
physical = p_physical;
- bus = SceneStringNames::get_singleton()->Master;
+ bus = SceneStringName(Master);
AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp((Object *)node, &Object::notify_property_list_changed));
AudioServer::get_singleton()->connect("bus_renamed", callable_mp((Object *)node, &Object::notify_property_list_changed).unbind(3));
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index ad3f607661..15b7f62036 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -298,6 +298,7 @@ void Button::_notification(int p_what) {
icon_size = Size2(icon_width, icon_height);
}
icon_size = _fit_icon_size(icon_size);
+ icon_size = icon_size.round();
}
if (icon_size.width > 0.0f) {
@@ -336,6 +337,7 @@ void Button::_notification(int p_what) {
icon_ofs.y = size.y - style_margin_bottom - icon_size.height;
} break;
}
+ icon_ofs = icon_ofs.floor();
Rect2 icon_region = Rect2(icon_ofs, icon_size);
draw_texture_rect(_icon, icon_region, false, icon_modulate_color);
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 5db8d69eef..625964c5e3 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -86,10 +86,10 @@ void Container::_sort_children() {
}
notification(NOTIFICATION_PRE_SORT_CHILDREN);
- emit_signal(SceneStringNames::get_singleton()->pre_sort_children);
+ emit_signal(SceneStringName(pre_sort_children));
notification(NOTIFICATION_SORT_CHILDREN);
- emit_signal(SceneStringNames::get_singleton()->sort_children);
+ emit_signal(SceneStringName(sort_children));
pending_sort = false;
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 2dd12b92f3..9c27f46467 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1606,7 +1606,7 @@ void Control::_update_minimum_size() {
if (minsize != data.last_minimum_size) {
data.last_minimum_size = minsize;
_size_changed();
- emit_signal(SceneStringNames::get_singleton()->minimum_size_changed);
+ emit_signal(SceneStringName(minimum_size_changed));
}
}
@@ -1770,7 +1770,7 @@ void Control::set_h_size_flags(BitField<SizeFlags> p_flags) {
return;
}
data.h_size_flags = p_flags;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+ emit_signal(SceneStringName(size_flags_changed));
}
BitField<Control::SizeFlags> Control::get_h_size_flags() const {
@@ -1784,7 +1784,7 @@ void Control::set_v_size_flags(BitField<SizeFlags> p_flags) {
return;
}
data.v_size_flags = p_flags;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+ emit_signal(SceneStringName(size_flags_changed));
}
BitField<Control::SizeFlags> Control::get_v_size_flags() const {
@@ -1799,7 +1799,7 @@ void Control::set_stretch_ratio(real_t p_ratio) {
}
data.expand = p_ratio;
- emit_signal(SceneStringNames::get_singleton()->size_flags_changed);
+ emit_signal(SceneStringName(size_flags_changed));
}
real_t Control::get_stretch_ratio() const {
@@ -1811,7 +1811,7 @@ real_t Control::get_stretch_ratio() const {
void Control::_call_gui_input(const Ref<InputEvent> &p_event) {
if (p_event->get_device() != InputEvent::DEVICE_ID_INTERNAL) {
- emit_signal(SceneStringNames::get_singleton()->gui_input, p_event); // Signal should be first, so it's possible to override an event (and then accept it).
+ emit_signal(SceneStringName(gui_input), p_event); // Signal should be first, so it's possible to override an event (and then accept it).
}
if (!is_inside_tree() || get_viewport()->is_input_handled()) {
return; // Input was handled, abort.
@@ -3299,7 +3299,7 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_RESIZED: {
- emit_signal(SceneStringNames::get_singleton()->resized);
+ emit_signal(SceneStringName(resized));
} break;
case NOTIFICATION_DRAW: {
@@ -3309,25 +3309,25 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_MOUSE_ENTER: {
- emit_signal(SceneStringNames::get_singleton()->mouse_entered);
+ emit_signal(SceneStringName(mouse_entered));
} break;
case NOTIFICATION_MOUSE_EXIT: {
- emit_signal(SceneStringNames::get_singleton()->mouse_exited);
+ emit_signal(SceneStringName(mouse_exited));
} break;
case NOTIFICATION_FOCUS_ENTER: {
- emit_signal(SceneStringNames::get_singleton()->focus_entered);
+ emit_signal(SceneStringName(focus_entered));
queue_redraw();
} break;
case NOTIFICATION_FOCUS_EXIT: {
- emit_signal(SceneStringNames::get_singleton()->focus_exited);
+ emit_signal(SceneStringName(focus_exited));
queue_redraw();
} break;
case NOTIFICATION_THEME_CHANGED: {
- emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ emit_signal(SceneStringName(theme_changed));
_invalidate_theme_cache();
_update_theme_item_cache();
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 646e45b27a..35d7146d20 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1059,7 +1059,7 @@ void GraphEdit::_top_connection_layer_input(const Ref<InputEvent> &p_ev) {
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
int type = graph_node->get_output_port_type(j);
- if ((type == connecting_type ||
+ if ((type == connecting_type || graph_node->is_ignoring_valid_connection_type() ||
valid_connection_types.has(ConnectionType(type, connecting_type))) &&
is_in_output_hotzone(graph_node, j, mpos, port_size)) {
if (!is_node_hover_valid(graph_node->get_name(), j, connecting_from_node, connecting_from_port_index)) {
@@ -1084,7 +1084,7 @@ void GraphEdit::_top_connection_layer_input(const Ref<InputEvent> &p_ev) {
port_size.height = MAX(port_size.height, child ? child->get_size().y : 0);
int type = graph_node->get_input_port_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnectionType(connecting_type, type))) &&
+ if ((type == connecting_type || graph_node->is_ignoring_valid_connection_type() || valid_connection_types.has(ConnectionType(connecting_type, type))) &&
is_in_input_hotzone(graph_node, j, mpos, port_size)) {
if (!is_node_hover_valid(connecting_from_node, connecting_from_port_index, graph_node->get_name(), j)) {
continue;
@@ -1117,6 +1117,8 @@ void GraphEdit::_top_connection_layer_input(const Ref<InputEvent> &p_ev) {
emit_signal(SNAME("connection_from_empty"), connecting_from_node, connecting_from_port_index, mb->get_position());
}
}
+ } else {
+ set_selected(get_node_or_null(NodePath(connecting_from_node)));
}
if (connecting) {
@@ -1636,12 +1638,12 @@ void GraphEdit::_draw_grid() {
void GraphEdit::set_selected(Node *p_child) {
for (int i = get_child_count() - 1; i >= 0; i--) {
- GraphNode *graph_node = Object::cast_to<GraphNode>(get_child(i));
- if (!graph_node) {
+ GraphElement *graph_element = Object::cast_to<GraphElement>(get_child(i));
+ if (!graph_element) {
continue;
}
- graph_node->set_selected(graph_node == p_child);
+ graph_element->set_selected(graph_element == p_child);
}
}
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 75ac5c5135..d804f83e1c 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -604,6 +604,14 @@ void GraphNode::set_slot_draw_stylebox(int p_slot_index, bool p_enable) {
emit_signal(SNAME("slot_updated"), p_slot_index);
}
+void GraphNode::set_ignore_invalid_connection_type(bool p_ignore) {
+ ignore_invalid_connection_type = p_ignore;
+}
+
+bool GraphNode::is_ignoring_valid_connection_type() const {
+ return ignore_invalid_connection_type;
+}
+
Size2 GraphNode::get_minimum_size() const {
Ref<StyleBox> sb_panel = theme_cache.panel;
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
@@ -859,6 +867,9 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_slot_draw_stylebox", "slot_index"), &GraphNode::is_slot_draw_stylebox);
ClassDB::bind_method(D_METHOD("set_slot_draw_stylebox", "slot_index", "enable"), &GraphNode::set_slot_draw_stylebox);
+ ClassDB::bind_method(D_METHOD("set_ignore_invalid_connection_type", "ignore"), &GraphNode::set_ignore_invalid_connection_type);
+ ClassDB::bind_method(D_METHOD("is_ignoring_valid_connection_type"), &GraphNode::is_ignoring_valid_connection_type);
+
ClassDB::bind_method(D_METHOD("get_input_port_count"), &GraphNode::get_input_port_count);
ClassDB::bind_method(D_METHOD("get_input_port_position", "port_idx"), &GraphNode::get_input_port_position);
ClassDB::bind_method(D_METHOD("get_input_port_type", "port_idx"), &GraphNode::get_input_port_type);
@@ -874,6 +885,8 @@ void GraphNode::_bind_methods() {
GDVIRTUAL_BIND(_draw_port, "slot_index", "position", "left", "color")
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_invalid_connection_type"), "set_ignore_invalid_connection_type", "is_ignoring_valid_connection_type");
+
ADD_SIGNAL(MethodInfo("slot_updated", PropertyInfo(Variant::INT, "slot_index")));
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphNode, panel);
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index 71cc322baa..27af3192c8 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -95,6 +95,8 @@ class GraphNode : public GraphElement {
bool port_pos_dirty = true;
+ bool ignore_invalid_connection_type = false;
+
void _port_pos_update();
protected:
@@ -147,6 +149,9 @@ public:
bool is_slot_draw_stylebox(int p_slot_index) const;
void set_slot_draw_stylebox(int p_slot_index, bool p_enable);
+ void set_ignore_invalid_connection_type(bool p_ignore);
+ bool is_ignoring_valid_connection_type() const;
+
int get_input_port_count();
Vector2 get_input_port_position(int p_port_idx);
int get_input_port_type(int p_port_idx);
diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp
index e2ae824e60..7ebf8a63c2 100644
--- a/scene/gui/nine_patch_rect.cpp
+++ b/scene/gui/nine_patch_rect.cpp
@@ -111,7 +111,7 @@ void NinePatchRect::set_texture(const Ref<Texture2D> &p_tex) {
queue_redraw();
update_minimum_size();
- emit_signal(SceneStringNames::get_singleton()->texture_changed);
+ emit_signal(SceneStringName(texture_changed));
}
Ref<Texture2D> NinePatchRect::get_texture() const {
diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp
index 687a9e46a0..e581d0b5db 100644
--- a/scene/gui/video_stream_player.cpp
+++ b/scene/gui/video_stream_player.cpp
@@ -163,7 +163,7 @@ void VideoStreamPlayer::_notification(int p_notification) {
play();
return;
}
- emit_signal(SceneStringNames::get_singleton()->finished);
+ emit_signal(SceneStringName(finished));
}
} break;
@@ -460,7 +460,7 @@ StringName VideoStreamPlayer::get_bus() const {
return bus;
}
}
- return SceneStringNames::get_singleton()->Master;
+ return SceneStringName(Master);
}
void VideoStreamPlayer::_validate_property(PropertyInfo &p_property) const {
diff --git a/scene/main/canvas_item.compat.inc b/scene/main/canvas_item.compat.inc
index 7136fded15..9bc3d01a69 100644
--- a/scene/main/canvas_item.compat.inc
+++ b/scene/main/canvas_item.compat.inc
@@ -30,12 +30,32 @@
#ifndef DISABLE_DEPRECATED
-void CanvasItem::_draw_circle_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
+void CanvasItem::_draw_circle_bind_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color) {
draw_circle(p_pos, p_radius, p_color, true, -1.0, false);
}
+void CanvasItem::_draw_rect_bind_compat_84523(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) {
+ draw_rect(p_rect, p_color, p_filled, p_width, false);
+}
+
+void CanvasItem::_draw_dashed_line_bind_compat_84523(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
+ draw_dashed_line(p_from, p_to, p_color, p_width, p_dash, p_aligned, false);
+}
+
+void CanvasItem::_draw_multiline_bind_compat_84523(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) {
+ draw_multiline(p_points, p_color, p_width, false);
+}
+
+void CanvasItem::_draw_multiline_colors_bind_compat_84523(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) {
+ draw_multiline_colors(p_points, p_colors, p_width, false);
+}
+
void CanvasItem::_bind_compatibility_methods() {
- ClassDB::bind_compatibility_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::_draw_circle_compat_84472);
+ ClassDB::bind_compatibility_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::_draw_circle_bind_compat_84472);
+ ClassDB::bind_compatibility_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::_draw_rect_bind_compat_84523, DEFVAL(true), DEFVAL(-1.0));
+ ClassDB::bind_compatibility_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::_draw_dashed_line_bind_compat_84523, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true));
+ ClassDB::bind_compatibility_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::_draw_multiline_bind_compat_84523, DEFVAL(-1.0));
+ ClassDB::bind_compatibility_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::_draw_multiline_colors_bind_compat_84523, DEFVAL(-1.0));
}
#endif
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index cabba0f2ed..dca116086d 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -95,7 +95,7 @@ void CanvasItem::_handle_visibility_change(bool p_visible) {
if (p_visible) {
queue_redraw();
} else {
- emit_signal(SceneStringNames::get_singleton()->hidden);
+ emit_signal(SceneStringName(hidden));
}
_block();
@@ -141,7 +141,7 @@ void CanvasItem::_redraw_callback() {
drawing = true;
current_item_drawn = this;
notification(NOTIFICATION_DRAW);
- emit_signal(SceneStringNames::get_singleton()->draw);
+ emit_signal(SceneStringName(draw));
GDVIRTUAL_CALL(_draw);
current_item_drawn = nullptr;
drawing = false;
@@ -309,7 +309,7 @@ void CanvasItem::_notification(int p_what) {
window = Object::cast_to<Window>(viewport);
if (window) {
- window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
+ window->connect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed));
parent_visible_in_tree = window->is_visible();
} else {
parent_visible_in_tree = true;
@@ -363,7 +363,7 @@ void CanvasItem::_notification(int p_what) {
C = nullptr;
}
if (window) {
- window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
+ window->disconnect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed));
window = nullptr;
}
_set_global_invalid(true);
@@ -383,7 +383,7 @@ void CanvasItem::_notification(int p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
ERR_MAIN_THREAD_GUARD;
- emit_signal(SceneStringNames::get_singleton()->visibility_changed);
+ emit_signal(SceneStringName(visibility_changed));
} break;
case NOTIFICATION_WORLD_2D_CHANGED: {
ERR_MAIN_THREAD_GUARD;
@@ -555,7 +555,7 @@ void CanvasItem::item_rect_changed(bool p_size_changed) {
if (p_size_changed) {
queue_redraw();
}
- emit_signal(SceneStringNames::get_singleton()->item_rect_changed);
+ emit_signal(SceneStringName(item_rect_changed));
}
void CanvasItem::set_z_index(int p_z) {
@@ -609,7 +609,7 @@ bool CanvasItem::is_y_sort_enabled() const {
return y_sort_enabled;
}
-void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
+void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
ERR_FAIL_COND(p_dash <= 0.0);
@@ -618,7 +618,7 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
Vector2 step = p_dash * (p_to - p_from).normalized();
if (length < p_dash || step == Vector2()) {
- RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
return;
}
@@ -642,7 +642,7 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
Vector<Color> colors = { p_color };
- RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width, p_antialiased);
}
void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) {
@@ -683,22 +683,22 @@ void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_sta
draw_polyline(points, p_color, p_width, p_antialiased);
}
-void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) {
+void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
Vector<Color> colors = { p_color };
- RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width, p_antialiased);
}
-void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) {
+void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
- RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased);
}
-void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) {
+void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width, bool p_antialiased) {
ERR_THREAD_GUARD;
ERR_DRAW_GUARD;
@@ -709,9 +709,9 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\".");
}
- RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect, p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect, p_color, p_antialiased);
} else if (p_width >= rect.size.width || p_width >= rect.size.height) {
- RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color, p_antialiased);
} else {
Vector<Vector2> points;
points.resize(5);
@@ -723,7 +723,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
Vector<Color> colors = { p_color };
- RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width, p_antialiased);
}
}
@@ -736,9 +736,9 @@ void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &
WARN_PRINT("The draw_circle() \"width\" argument has no effect when \"filled\" is \"true\".");
}
- RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color);
+ RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color, p_antialiased);
} else if (p_width >= 2.0 * p_radius) {
- RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius + 0.5 * p_width, p_color);
+ RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius + 0.5 * p_width, p_color, p_antialiased);
} else {
// Tessellation count is hardcoded. Keep in sync with the same variable in `RendererCanvasCull::canvas_item_add_circle()`.
const int circle_segments = 64;
@@ -1186,13 +1186,13 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(-1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned", "antialiased"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(-1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::draw_multiline, DEFVAL(-1.0));
- ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0));
- ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0));
+ ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width", "antialiased"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color", "filled", "width", "antialiased"), &CanvasItem::draw_circle, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index ae7b195ead..028c2cb2cf 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -168,7 +168,11 @@ protected:
static void _bind_methods();
#ifndef DISABLE_DEPRECATED
- void _draw_circle_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color);
+ void _draw_circle_bind_compat_84472(const Point2 &p_pos, real_t p_radius, const Color &p_color);
+ void _draw_rect_bind_compat_84523(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width);
+ void _draw_dashed_line_bind_compat_84523(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned);
+ void _draw_multiline_bind_compat_84523(const Vector<Point2> &p_points, const Color &p_color, real_t p_width);
+ void _draw_multiline_colors_bind_compat_84523(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width);
static void _bind_compatibility_methods();
#endif
@@ -271,14 +275,14 @@ public:
/* DRAWING API */
- void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, real_t p_dash = 2.0, bool p_aligned = true);
+ void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, real_t p_dash = 2.0, bool p_aligned = true, bool p_antialiased = false);
void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = -1.0, bool p_antialiased = false);
void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
- void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0);
- void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = -1.0);
- void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = -1.0);
+ void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
+ void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = -1.0, bool p_antialiased = false);
+ void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = -1.0, bool p_antialiased = false);
void draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color, bool p_filled = true, real_t p_width = -1.0, bool p_antialiased = false);
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1));
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index e54209c1dd..15b4186aa1 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -266,7 +266,7 @@ void Node::_propagate_ready() {
if (data.ready_first) {
data.ready_first = false;
notification(NOTIFICATION_READY);
- emit_signal(SceneStringNames::get_singleton()->ready);
+ emit_signal(SceneStringName(ready));
}
}
@@ -295,7 +295,7 @@ void Node::_propagate_enter_tree() {
GDVIRTUAL_CALL(_enter_tree);
- emit_signal(SceneStringNames::get_singleton()->tree_entered);
+ emit_signal(SceneStringName(tree_entered));
data.tree->node_added(this);
@@ -350,7 +350,7 @@ void Node::_propagate_after_exit_tree() {
data.blocked--;
- emit_signal(SceneStringNames::get_singleton()->tree_exited);
+ emit_signal(SceneStringName(tree_exited));
}
void Node::_propagate_exit_tree() {
@@ -372,7 +372,7 @@ void Node::_propagate_exit_tree() {
GDVIRTUAL_CALL(_exit_tree);
- emit_signal(SceneStringNames::get_singleton()->tree_exiting);
+ emit_signal(SceneStringName(tree_exiting));
notification(NOTIFICATION_EXIT_TREE, true);
if (data.tree) {
@@ -1738,11 +1738,11 @@ Node *Node::get_node_or_null(const NodePath &p_path) const {
StringName name = p_path.get_name(i);
Node *next = nullptr;
- if (name == SceneStringNames::get_singleton()->dot) { // .
+ if (name == SceneStringName(dot)) { // .
next = current;
- } else if (name == SceneStringNames::get_singleton()->doubledot) { // ..
+ } else if (name == SceneStringName(doubledot)) { // ..
if (current == nullptr || !current->data.parent) {
return nullptr;
@@ -2667,8 +2667,6 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
node->data.editable_instance = data.editable_instance;
}
- StringName script_property_name = CoreStringNames::get_singleton()->_script;
-
List<const Node *> hidden_roots;
List<const Node *> node_tree;
node_tree.push_front(this);
@@ -2770,45 +2768,6 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
parent->move_child(dup, pos);
}
}
-
- for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
- Node *current_node = node->get_node(get_path_to(N->get()));
- ERR_CONTINUE(!current_node);
-
- if (p_flags & DUPLICATE_SCRIPTS) {
- bool is_valid = false;
- Variant scr = N->get()->get(script_property_name, &is_valid);
- if (is_valid) {
- current_node->set(script_property_name, scr);
- }
- }
-
- List<PropertyInfo> plist;
- N->get()->get_property_list(&plist);
-
- for (const PropertyInfo &E : plist) {
- if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
- continue;
- }
- String name = E.name;
- if (name == script_property_name) {
- continue;
- }
-
- Variant value = N->get()->get(name).duplicate(true);
-
- if (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE) {
- Resource *res = Object::cast_to<Resource>(value);
- if (res) { // Duplicate only if it's a resource
- current_node->set(name, res->duplicate());
- }
-
- } else {
- current_node->set(name, value);
- }
- }
- }
-
return node;
}
@@ -2820,7 +2779,7 @@ Node *Node::duplicate(int p_flags) const {
_duplicate_signals(this, dupe);
}
- _duplicate_properties_node(this, this, dupe);
+ _duplicate_properties(this, this, dupe, p_flags);
return dupe;
}
@@ -2831,7 +2790,8 @@ Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap) con
}
Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, const HashMap<Ref<Resource>, Ref<Resource>> &p_resource_remap) const {
- Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANTIATION | DUPLICATE_FROM_EDITOR, &r_duplimap);
+ int flags = DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANTIATION | DUPLICATE_FROM_EDITOR;
+ Node *dupe = _duplicate(flags, &r_duplimap);
// This is used by SceneTreeDock's paste functionality. When pasting to foreign scene, resources are duplicated.
if (!p_resource_remap.is_empty()) {
@@ -2843,7 +2803,7 @@ Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, con
// if the emitter node comes later in tree order than the receiver
_duplicate_signals(this, dupe);
- _duplicate_properties_node(this, this, dupe);
+ _duplicate_properties(this, this, dupe, flags);
return dupe;
}
@@ -2897,34 +2857,58 @@ void Node::remap_nested_resources(Ref<Resource> p_resource, const HashMap<Ref<Re
}
#endif
-// Duplicates properties that store a Node.
-// This has to be called after nodes have been duplicated since
-// only then do we get a full picture of how the duplicated node tree looks like.
-void Node::_duplicate_properties_node(const Node *p_root, const Node *p_original, Node *p_copy) const {
+// Duplicate node's properties.
+// This has to be called after nodes have been duplicated since there might be properties
+// of type Node that can be updated properly only if duplicated node tree is complete.
+void Node::_duplicate_properties(const Node *p_root, const Node *p_original, Node *p_copy, int p_flags) const {
List<PropertyInfo> props;
- p_copy->get_property_list(&props);
+ p_original->get_property_list(&props);
+ const StringName &script_property_name = CoreStringName(script);
+ if (p_flags & DUPLICATE_SCRIPTS) {
+ bool is_valid = false;
+ Variant scr = p_original->get(script_property_name, &is_valid);
+ if (is_valid) {
+ p_copy->set(script_property_name, scr);
+ }
+ }
for (const PropertyInfo &E : props) {
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- String name = E.name;
+ const StringName name = E.name;
+
+ if (name == script_property_name) {
+ continue;
+ }
+
Variant value = p_original->get(name).duplicate(true);
- if (value.get_type() == Variant::OBJECT) {
- Node *property_node = Object::cast_to<Node>(value);
- if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) {
- value = p_copy->get_node_or_null(p_original->get_path_to(property_node));
- p_copy->set(name, value);
+
+ if (E.usage & PROPERTY_USAGE_ALWAYS_DUPLICATE) {
+ Resource *res = Object::cast_to<Resource>(value);
+ if (res) { // Duplicate only if it's a resource
+ p_copy->set(name, res->duplicate());
}
- } else if (value.get_type() == Variant::ARRAY) {
- Array arr = value;
- if (arr.get_typed_builtin() == Variant::OBJECT) {
- for (int i = 0; i < arr.size(); i++) {
- Node *property_node = Object::cast_to<Node>(arr[i]);
- if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) {
- arr[i] = p_copy->get_node_or_null(p_original->get_path_to(property_node));
+ } else {
+ if (value.get_type() == Variant::OBJECT) {
+ Node *property_node = Object::cast_to<Node>(value);
+ Variant out_value = value;
+ if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) {
+ out_value = p_copy->get_node_or_null(p_original->get_path_to(property_node));
+ }
+ p_copy->set(name, out_value);
+ } else if (value.get_type() == Variant::ARRAY) {
+ Array arr = value;
+ if (arr.get_typed_builtin() == Variant::OBJECT) {
+ for (int i = 0; i < arr.size(); i++) {
+ Node *property_node = Object::cast_to<Node>(arr[i]);
+ if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) {
+ arr[i] = p_copy->get_node_or_null(p_original->get_path_to(property_node));
+ }
}
+ value = arr;
+ p_copy->set(name, value);
}
- value = arr;
+ } else {
p_copy->set(name, value);
}
}
@@ -2933,7 +2917,7 @@ void Node::_duplicate_properties_node(const Node *p_root, const Node *p_original
for (int i = 0; i < p_original->get_child_count(); i++) {
Node *copy_child = p_copy->get_child(i);
ERR_FAIL_NULL_MSG(copy_child, "Child node disappeared while duplicating.");
- _duplicate_properties_node(p_root, p_original->get_child(i), copy_child);
+ _duplicate_properties(p_root, p_original->get_child(i), copy_child, p_flags);
}
}
@@ -3323,7 +3307,7 @@ void Node::update_configuration_warnings() {
return;
}
if (get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
- get_tree()->emit_signal(SceneStringNames::get_singleton()->node_configuration_warning_changed, this);
+ get_tree()->emit_signal(SceneStringName(node_configuration_warning_changed), this);
}
#endif
}
diff --git a/scene/main/node.h b/scene/main/node.h
index fe212ae0f7..65cbd2f2c0 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -266,7 +266,7 @@ private:
void _propagate_groups_dirty();
Array _get_node_and_resource(const NodePath &p_path);
- void _duplicate_properties_node(const Node *p_root, const Node *p_original, Node *p_copy) const;
+ void _duplicate_properties(const Node *p_root, const Node *p_original, Node *p_copy, int p_flags) const;
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
Node *_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap = nullptr) const;
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index 091e6249bf..372d4c6640 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -223,11 +223,11 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
void ShaderGlobalsOverride::_activate() {
ERR_FAIL_NULL(get_tree());
List<Node *> nodes;
- get_tree()->get_nodes_in_group(SceneStringNames::get_singleton()->shader_overrides_group_active, &nodes);
+ get_tree()->get_nodes_in_group(SceneStringName(shader_overrides_group_active), &nodes);
if (nodes.size() == 0) {
//good we are the only override, enable all
active = true;
- add_to_group(SceneStringNames::get_singleton()->shader_overrides_group_active);
+ add_to_group(SceneStringName(shader_overrides_group_active));
for (const KeyValue<StringName, Override> &E : overrides) {
const Override *o = &E.value;
@@ -248,7 +248,7 @@ void ShaderGlobalsOverride::_activate() {
void ShaderGlobalsOverride::_notification(int p_what) {
switch (p_what) {
case Node::NOTIFICATION_ENTER_TREE: {
- add_to_group(SceneStringNames::get_singleton()->shader_overrides_group);
+ add_to_group(SceneStringName(shader_overrides_group));
_activate();
} break;
@@ -263,9 +263,9 @@ void ShaderGlobalsOverride::_notification(int p_what) {
}
}
- remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group_active);
- remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group);
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->shader_overrides_group, "_activate"); //another may want to activate when this is removed
+ remove_from_group(SceneStringName(shader_overrides_group_active));
+ remove_from_group(SceneStringName(shader_overrides_group));
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringName(shader_overrides_group), "_activate"); //another may want to activate when this is removed
active = false;
} break;
}
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 929720fcf4..5ec300faee 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -846,7 +846,7 @@ void Window::set_visible(bool p_visible) {
focused = false;
}
notification(NOTIFICATION_VISIBILITY_CHANGED);
- emit_signal(SceneStringNames::get_singleton()->visibility_changed);
+ emit_signal(SceneStringName(visibility_changed));
RS::get_singleton()->viewport_set_active(get_viewport_rid(), visible);
@@ -1321,7 +1321,7 @@ void Window::_notification(int p_what) {
}
if (visible) {
notification(NOTIFICATION_VISIBILITY_CHANGED);
- emit_signal(SceneStringNames::get_singleton()->visibility_changed);
+ emit_signal(SceneStringName(visibility_changed));
RS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
}
@@ -1337,7 +1337,7 @@ void Window::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ emit_signal(SceneStringName(theme_changed));
_invalidate_theme_cache();
_update_theme_item_cache();
} break;
@@ -1404,11 +1404,11 @@ void Window::_notification(int p_what) {
} break;
case NOTIFICATION_VP_MOUSE_ENTER: {
- emit_signal(SceneStringNames::get_singleton()->mouse_entered);
+ emit_signal(SceneStringName(mouse_entered));
} break;
case NOTIFICATION_VP_MOUSE_EXIT: {
- emit_signal(SceneStringNames::get_singleton()->mouse_exited);
+ emit_signal(SceneStringName(mouse_exited));
} break;
}
}
@@ -1622,7 +1622,7 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
_input_from_window(p_ev);
if (p_ev->get_device() != InputEvent::DEVICE_ID_INTERNAL && is_inside_tree()) {
- emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
+ emit_signal(SceneStringName(window_input), p_ev);
}
if (is_inside_tree()) {
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index de94327d79..a5b0ac24b9 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -744,6 +744,7 @@ void register_scene_types() {
GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeVarying);
GDREGISTER_CLASS(VisualShaderNodeVaryingSetter);
GDREGISTER_CLASS(VisualShaderNodeVaryingGetter);
+ GDREGISTER_CLASS(VisualShaderNodeReroute);
GDREGISTER_CLASS(VisualShaderNodeSDFToScreenUV);
GDREGISTER_CLASS(VisualShaderNodeScreenUVToSDF);
diff --git a/scene/resources/canvas_item_material.cpp b/scene/resources/canvas_item_material.cpp
index 31c8e68ea5..76e99aca92 100644
--- a/scene/resources/canvas_item_material.cpp
+++ b/scene/resources/canvas_item_material.cpp
@@ -33,13 +33,11 @@
#include "core/version.h"
Mutex CanvasItemMaterial::material_mutex;
-SelfList<CanvasItemMaterial>::List *CanvasItemMaterial::dirty_materials = nullptr;
+SelfList<CanvasItemMaterial>::List CanvasItemMaterial::dirty_materials;
HashMap<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData, CanvasItemMaterial::MaterialKey> 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";
@@ -48,14 +46,13 @@ void CanvasItemMaterial::init_shaders() {
}
void CanvasItemMaterial::finish_shaders() {
- memdelete(dirty_materials);
+ dirty_materials.clear();
+
memdelete(shader_names);
- dirty_materials = nullptr;
+ shader_names = 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
@@ -153,8 +150,9 @@ void CanvasItemMaterial::_update_shader() {
void CanvasItemMaterial::flush_changes() {
MutexLock lock(material_mutex);
- while (dirty_materials->first()) {
- dirty_materials->first()->self()->_update_shader();
+ while (dirty_materials.first()) {
+ dirty_materials.first()->self()->_update_shader();
+ dirty_materials.first()->remove_from_list();
}
}
@@ -162,16 +160,10 @@ void CanvasItemMaterial::_queue_shader_change() {
MutexLock lock(material_mutex);
if (_is_initialized() && !element.in_list()) {
- dirty_materials->add(&element);
+ 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();
@@ -288,7 +280,7 @@ CanvasItemMaterial::CanvasItemMaterial() :
current_key.invalid_key = 1;
- _mark_initialized(callable_mp(this, &CanvasItemMaterial::_queue_shader_change));
+ _mark_initialized(callable_mp(this, &CanvasItemMaterial::_queue_shader_change), callable_mp(this, &CanvasItemMaterial::_update_shader));
}
CanvasItemMaterial::~CanvasItemMaterial() {
diff --git a/scene/resources/canvas_item_material.h b/scene/resources/canvas_item_material.h
index 7dddd74a31..ef498c2ff6 100644
--- a/scene/resources/canvas_item_material.h
+++ b/scene/resources/canvas_item_material.h
@@ -98,12 +98,11 @@ private:
}
static Mutex material_mutex;
- static SelfList<CanvasItemMaterial>::List *dirty_materials;
+ 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;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 15b40e776c..3784aa3da0 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -82,24 +82,25 @@ void Material::_validate_property(PropertyInfo &p_property) const {
}
}
-void Material::_mark_initialized(const Callable &p_queue_shader_change_callable) {
+void Material::_mark_ready() {
+ init_state = INIT_STATE_INITIALIZING;
+}
+
+void Material::_mark_initialized(const Callable &p_add_to_dirty_list, const Callable &p_update_shader) {
// If this is happening as part of resource loading, it is not safe to queue the update
- // as an addition to the dirty list, unless the load is happening on the main thread.
- if (ResourceLoader::is_within_load() && Thread::get_caller_id() != Thread::get_main_id()) {
+ // as an addition to the dirty list. It would be if the load is happening on the main thread,
+ // but even so we'd rather perform the update directly instead of using the dirty list.
+ if (ResourceLoader::is_within_load()) {
DEV_ASSERT(init_state != INIT_STATE_READY);
if (init_state == INIT_STATE_UNINITIALIZED) { // Prevent queueing twice.
- // Let's mark this material as being initialized.
init_state = INIT_STATE_INITIALIZING;
- // Knowing that the ResourceLoader will eventually feed deferred calls into the main message queue, let's do these:
- // 1. Queue setting the init state to INIT_STATE_READY finally.
- callable_mp(this, &Material::_mark_initialized).bind(p_queue_shader_change_callable).call_deferred();
- // 2. Queue an individual update of this material.
- p_queue_shader_change_callable.call_deferred();
+ callable_mp(this, &Material::_mark_ready).call_deferred();
+ p_update_shader.call_deferred();
}
} else {
// Straightforward conditions.
init_state = INIT_STATE_READY;
- p_queue_shader_change_callable.callv(Array());
+ p_add_to_dirty_list.call();
}
}
@@ -603,8 +604,6 @@ void BaseMaterial3D::finish_shaders() {
}
void BaseMaterial3D::_update_shader() {
- dirty_materials.remove(&element);
-
MaterialKey mk = _compute_key();
if (mk == current_key) {
return; //no update required in the end
@@ -1855,6 +1854,7 @@ void BaseMaterial3D::flush_changes() {
while (dirty_materials.first()) {
dirty_materials.first()->self()->_update_shader();
+ dirty_materials.first()->remove_from_list();
}
}
@@ -1866,12 +1866,6 @@ void BaseMaterial3D::_queue_shader_change() {
}
}
-bool BaseMaterial3D::_is_shader_dirty() const {
- MutexLock lock(material_mutex);
-
- return element.in_list();
-}
-
void BaseMaterial3D::set_albedo(const Color &p_albedo) {
albedo = p_albedo;
@@ -2824,7 +2818,7 @@ BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const {
RID BaseMaterial3D::get_shader_rid() const {
MutexLock lock(material_mutex);
- if (element.in_list()) { // _is_shader_dirty() would create anoder mutex lock
+ if (element.in_list()) {
((BaseMaterial3D *)this)->_update_shader();
}
ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
@@ -3412,7 +3406,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
current_key.invalid_key = 1;
- _mark_initialized(callable_mp(this, &BaseMaterial3D::_queue_shader_change));
+ _mark_initialized(callable_mp(this, &BaseMaterial3D::_queue_shader_change), callable_mp(this, &BaseMaterial3D::_update_shader));
}
BaseMaterial3D::~BaseMaterial3D() {
diff --git a/scene/resources/material.h b/scene/resources/material.h
index ecf79c581b..50a774e961 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -62,7 +62,8 @@ protected:
void _validate_property(PropertyInfo &p_property) const;
- void _mark_initialized(const Callable &p_queue_shader_change_callable);
+ void _mark_ready();
+ void _mark_initialized(const Callable &p_add_to_dirty_list, const Callable &p_update_shader);
bool _is_initialized() { return init_state == INIT_STATE_READY; }
GDVIRTUAL0RC(RID, _get_shader_rid)
@@ -466,7 +467,6 @@ private:
void _update_shader();
_FORCE_INLINE_ void _queue_shader_change();
- _FORCE_INLINE_ bool _is_shader_dirty() const;
bool orm;
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 407b12d72f..4158b178aa 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -328,7 +328,7 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
ERR_FAIL_INDEX_V(nprops[j].name, sname_count, nullptr);
- if (snames[nprops[j].name] == CoreStringNames::get_singleton()->_script) {
+ if (snames[nprops[j].name] == CoreStringName(script)) {
//work around to avoid old script variables from disappearing, should be the proper fix to:
//https://github.com/godotengine/godot/issues/2958
diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp
index 0b65b33240..81476eaa0f 100644
--- a/scene/resources/particle_process_material.cpp
+++ b/scene/resources/particle_process_material.cpp
@@ -33,14 +33,12 @@
#include "core/version.h"
Mutex ParticleProcessMaterial::material_mutex;
-SelfList<ParticleProcessMaterial>::List *ParticleProcessMaterial::dirty_materials = nullptr;
+SelfList<ParticleProcessMaterial>::List ParticleProcessMaterial::dirty_materials;
HashMap<ParticleProcessMaterial::MaterialKey, ParticleProcessMaterial::ShaderData, ParticleProcessMaterial::MaterialKey> ParticleProcessMaterial::shader_map;
RBSet<String> ParticleProcessMaterial::min_max_properties;
ParticleProcessMaterial::ShaderNames *ParticleProcessMaterial::shader_names = nullptr;
void ParticleProcessMaterial::init_shaders() {
- dirty_materials = memnew(SelfList<ParticleProcessMaterial>::List);
-
shader_names = memnew(ShaderNames);
shader_names->direction = "direction";
@@ -140,15 +138,13 @@ void ParticleProcessMaterial::init_shaders() {
}
void ParticleProcessMaterial::finish_shaders() {
- memdelete(dirty_materials);
- dirty_materials = nullptr;
+ dirty_materials.clear();
memdelete(shader_names);
+ shader_names = nullptr;
}
void ParticleProcessMaterial::_update_shader() {
- dirty_materials->remove(&element);
-
MaterialKey mk = _compute_key();
if (mk == current_key) {
return; //no update required in the end
@@ -1170,8 +1166,9 @@ void ParticleProcessMaterial::_update_shader() {
void ParticleProcessMaterial::flush_changes() {
MutexLock lock(material_mutex);
- while (dirty_materials->first()) {
- dirty_materials->first()->self()->_update_shader();
+ while (dirty_materials.first()) {
+ dirty_materials.first()->self()->_update_shader();
+ dirty_materials.first()->remove_from_list();
}
}
@@ -1179,16 +1176,10 @@ void ParticleProcessMaterial::_queue_shader_change() {
MutexLock lock(material_mutex);
if (_is_initialized() && !element.in_list()) {
- dirty_materials->add(&element);
+ dirty_materials.add(&element);
}
}
-bool ParticleProcessMaterial::_is_shader_dirty() const {
- MutexLock lock(material_mutex);
-
- return element.in_list();
-}
-
bool ParticleProcessMaterial::has_min_max_property(const String &p_name) {
return min_max_properties.has(p_name);
}
@@ -2330,7 +2321,7 @@ ParticleProcessMaterial::ParticleProcessMaterial() :
current_key.invalid_key = 1;
- _mark_initialized(callable_mp(this, &ParticleProcessMaterial::_queue_shader_change));
+ _mark_initialized(callable_mp(this, &ParticleProcessMaterial::_queue_shader_change), callable_mp(this, &ParticleProcessMaterial::_update_shader));
}
ParticleProcessMaterial::~ParticleProcessMaterial() {
diff --git a/scene/resources/particle_process_material.h b/scene/resources/particle_process_material.h
index 94b2009654..25046b51cd 100644
--- a/scene/resources/particle_process_material.h
+++ b/scene/resources/particle_process_material.h
@@ -186,7 +186,7 @@ private:
}
static Mutex material_mutex;
- static SelfList<ParticleProcessMaterial>::List *dirty_materials;
+ static SelfList<ParticleProcessMaterial>::List dirty_materials;
struct ShaderNames {
StringName direction;
@@ -293,7 +293,6 @@ private:
void _update_shader();
_FORCE_INLINE_ void _queue_shader_change();
- _FORCE_INLINE_ bool _is_shader_dirty() const;
Vector3 direction;
float spread = 0.0f;
diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp
index 42ffa2d25a..6e43ea9b17 100644
--- a/scene/resources/sprite_frames.cpp
+++ b/scene/resources/sprite_frames.cpp
@@ -277,5 +277,5 @@ void SpriteFrames::_bind_methods() {
}
SpriteFrames::SpriteFrames() {
- add_animation(SceneStringNames::get_singleton()->_default);
+ add_animation(SceneStringName(default_));
}
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index a57af6886d..5a1b453a13 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -1101,6 +1101,42 @@ bool VisualShader::is_nodes_connected_relatively(const Graph *p_graph, int p_nod
return result;
}
+bool VisualShader::_check_reroute_subgraph(Type p_type, int p_target_port_type, int p_reroute_node, List<int> *r_visited_reroute_nodes) const {
+ const Graph *g = &graph[p_type];
+
+ // BFS to check whether connecting to the given subgraph (rooted at p_reroute_node) is valid.
+ List<int> queue;
+ queue.push_back(p_reroute_node);
+ if (r_visited_reroute_nodes != nullptr) {
+ r_visited_reroute_nodes->push_back(p_reroute_node);
+ }
+ while (!queue.is_empty()) {
+ int current_node_id = queue.front()->get();
+ VisualShader::Node current_node = g->nodes[current_node_id];
+ queue.pop_front();
+ for (const int &next_node_id : current_node.next_connected_nodes) {
+ Ref<VisualShaderNodeReroute> next_vsnode = g->nodes[next_node_id].node;
+ if (next_vsnode.is_valid()) {
+ queue.push_back(next_node_id);
+ if (r_visited_reroute_nodes != nullptr) {
+ r_visited_reroute_nodes->push_back(next_node_id);
+ }
+ continue;
+ }
+ // Check whether all ports connected with the reroute node are compatible.
+ for (const Connection &c : g->connections) {
+ VisualShaderNode::PortType to_port_type = g->nodes[next_node_id].node->get_input_port_type(c.to_port);
+ if (c.from_node == current_node_id &&
+ c.to_node == next_node_id &&
+ !is_port_types_compatible(p_target_port_type, to_port_type)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const {
ERR_FAIL_INDEX_V(p_type, TYPE_MAX, false);
const Graph *g = &graph[p_type];
@@ -1128,7 +1164,12 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
- if (!is_port_types_compatible(from_port_type, to_port_type)) {
+ Ref<VisualShaderNodeReroute> to_node_reroute = g->nodes[p_to_node].node;
+ if (to_node_reroute.is_valid()) {
+ if (!_check_reroute_subgraph(p_type, from_port_type, p_to_node)) {
+ return false;
+ }
+ } else if (!is_port_types_compatible(from_port_type, to_port_type)) {
return false;
}
@@ -1141,7 +1182,6 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
if (is_nodes_connected_relatively(g, p_from_node, p_to_node)) {
return false;
}
-
return true;
}
@@ -1179,6 +1219,28 @@ void VisualShader::detach_node_from_frame(Type p_type, int p_node) {
g->nodes[p_node].node->set_frame(-1);
}
+String VisualShader::get_reroute_parameter_name(Type p_type, int p_reroute_node) const {
+ ERR_FAIL_INDEX_V(p_type, TYPE_MAX, "");
+ const Graph *g = &graph[p_type];
+
+ ERR_FAIL_COND_V(!g->nodes.has(p_reroute_node), "");
+
+ const VisualShader::Node *node = &g->nodes[p_reroute_node];
+ while (node->prev_connected_nodes.size() > 0) {
+ int connected_node_id = node->prev_connected_nodes[0];
+ node = &g->nodes[connected_node_id];
+ Ref<VisualShaderNodeParameter> parameter_node = node->node;
+ if (parameter_node.is_valid() && parameter_node->get_output_port_type(0) == VisualShaderNode::PORT_TYPE_SAMPLER) {
+ return parameter_node->get_parameter_name();
+ }
+ Ref<VisualShaderNodeInput> input_node = node->node;
+ if (input_node.is_valid() && input_node->get_output_port_type(0) == VisualShaderNode::PORT_TYPE_SAMPLER) {
+ return input_node->get_input_real_name();
+ }
+ }
+ return "";
+}
+
void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
ERR_FAIL_INDEX(p_type, TYPE_MAX);
Graph *g = &graph[p_type];
@@ -1217,10 +1279,30 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
ERR_FAIL_COND_V(!g->nodes.has(p_to_node), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_to_port, g->nodes[p_to_node].node->get_input_port_count(), ERR_INVALID_PARAMETER);
+ Ref<VisualShaderNodeReroute> from_node_reroute = g->nodes[p_from_node].node;
+ Ref<VisualShaderNodeReroute> to_node_reroute = g->nodes[p_to_node].node;
+
+ // Allow connection with incompatible port types only if the reroute node isn't connected to anything.
VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
+ bool port_types_are_compatible = is_port_types_compatible(from_port_type, to_port_type);
+
+ if (to_node_reroute.is_valid()) {
+ List<int> visited_reroute_nodes;
+ port_types_are_compatible = _check_reroute_subgraph(p_type, from_port_type, p_to_node, &visited_reroute_nodes);
+ if (port_types_are_compatible) {
+ // Set the port type of all reroute nodes.
+ for (const int &E : visited_reroute_nodes) {
+ Ref<VisualShaderNodeReroute> reroute_node = g->nodes[E].node;
+ reroute_node->_set_port_type(from_port_type);
+ }
+ }
+ } else if (from_node_reroute.is_valid() && !from_node_reroute->is_input_port_connected(0)) {
+ from_node_reroute->_set_port_type(to_port_type);
+ port_types_are_compatible = true;
+ }
- ERR_FAIL_COND_V_MSG(!is_port_types_compatible(from_port_type, to_port_type), ERR_INVALID_PARAMETER, "Incompatible port types (scalar/vec/bool) with transform.");
+ ERR_FAIL_COND_V_MSG(!port_types_are_compatible, ERR_INVALID_PARAMETER, "Incompatible port types.");
for (const Connection &E : g->connections) {
if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
@@ -1904,12 +1986,18 @@ Error VisualShader::_write_node(Type type, StringBuilder *p_global_code, StringB
if (in_type == VisualShaderNode::PORT_TYPE_SAMPLER && out_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
VisualShaderNode *ptr = const_cast<VisualShaderNode *>(graph[type].nodes[from_node].node.ptr());
+ // FIXME: This needs to be refactored at some point.
if (ptr->has_method("get_input_real_name")) {
inputs[i] = ptr->call("get_input_real_name");
} else if (ptr->has_method("get_parameter_name")) {
inputs[i] = ptr->call("get_parameter_name");
} else {
- inputs[i] = "";
+ Ref<VisualShaderNodeReroute> reroute = graph[type].nodes[from_node].node;
+ if (reroute.is_valid()) {
+ inputs[i] = get_reroute_parameter_name(type, from_node);
+ } else {
+ inputs[i] = "";
+ }
}
} else if (in_type == out_type) {
inputs[i] = src_var;
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index d32e2465b9..18cdc8342b 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -163,6 +163,8 @@ private:
void _input_type_changed(Type p_type, int p_id);
bool has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const;
+ bool _check_reroute_subgraph(Type p_type, int p_target_port_type, int p_reroute_node, List<int> *r_visited_reroute_nodes = nullptr) const;
+
protected:
virtual void _update_shader() const override;
static void _bind_methods();
@@ -229,6 +231,8 @@ public: // internal methods
void attach_node_to_frame(Type p_type, int p_node, int p_frame);
void detach_node_from_frame(Type p_type, int p_node);
+ String get_reroute_parameter_name(Type p_type, int p_reroute_node) const;
+
void rebuild();
void get_node_connections(Type p_type, List<Connection> *r_connections) const;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index ccd730eef2..d5394c8af5 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -8150,3 +8150,82 @@ VisualShaderNodeRotationByAxis::VisualShaderNodeRotationByAxis() {
simple_decl = false;
}
+
+String VisualShaderNodeReroute::get_caption() const {
+ return "Reroute";
+}
+
+int VisualShaderNodeReroute::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeReroute::PortType VisualShaderNodeReroute::get_input_port_type(int p_port) const {
+ return input_port_type;
+}
+
+String VisualShaderNodeReroute::get_input_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeReroute::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeReroute::PortType VisualShaderNodeReroute::get_output_port_type(int p_port) const {
+ return input_port_type;
+}
+
+String VisualShaderNodeReroute::get_output_port_name(int p_port) const {
+ return String();
+}
+
+String VisualShaderNodeReroute::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ for (int i = 0; i < get_output_port_count(); i++) {
+ if (input_port_type == PORT_TYPE_SAMPLER) {
+ continue;
+ }
+
+ String input = p_input_vars[0];
+ if (input.is_empty()) {
+ code += vformat(" %s;\n", p_output_vars[i]);
+ continue;
+ }
+ code += vformat(" %s = %s;\n", p_output_vars[i], input);
+ }
+ return code;
+}
+
+void VisualShaderNodeReroute::_set_port_type(PortType p_type) {
+ input_port_type = p_type;
+ switch (p_type) {
+ case PORT_TYPE_SCALAR:
+ set_input_port_default_value(0, 0.0);
+ break;
+ case PORT_TYPE_VECTOR_2D:
+ set_input_port_default_value(0, Vector2());
+ break;
+ case PORT_TYPE_VECTOR_3D:
+ set_input_port_default_value(0, Vector3());
+ break;
+ case PORT_TYPE_VECTOR_4D:
+ set_input_port_default_value(0, Vector4());
+ break;
+ case PORT_TYPE_TRANSFORM:
+ set_input_port_default_value(0, Transform3D());
+ break;
+ default:
+ break;
+ }
+}
+
+void VisualShaderNodeReroute::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_set_port_type", "port_type"), &VisualShaderNodeReroute::_set_port_type);
+ ClassDB::bind_method(D_METHOD("get_port_type"), &VisualShaderNodeReroute::get_port_type);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "port_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_port_type", "get_port_type");
+}
+
+VisualShaderNodeReroute::VisualShaderNodeReroute() {
+ set_input_port_default_value(0, 0.0);
+}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 0bd0c631b8..a23ae72def 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -3092,4 +3092,35 @@ public:
VisualShaderNodeRotationByAxis();
};
+class VisualShaderNodeReroute : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeReroute, VisualShaderNode);
+
+ PortType input_port_type = PORT_TYPE_SCALAR;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+ virtual bool has_output_port_preview(int p_port) const override { return false; }
+ virtual bool is_output_port_expandable(int p_port) const override { return false; }
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ virtual Category get_category() const override { return CATEGORY_SPECIAL; }
+
+ void _set_port_type(PortType p_type);
+ PortType get_port_type() const { return input_port_type; }
+
+ VisualShaderNodeReroute();
+};
+
#endif // VISUAL_SHADER_NODES_H
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 5610b2f642..d40cb9ab6c 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -196,7 +196,7 @@ SceneStringNames::SceneStringNames() {
// Audio bus name.
Master = StaticCString::create("Master");
- _default = StaticCString::create("default");
+ default_ = StaticCString::create("default");
_window_group = StaticCString::create("_window_group");
_window_input = StaticCString::create("_window_input");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 60254e3006..0e3a2a403e 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -198,7 +198,7 @@ public:
NodePath path_pp;
- StringName _default;
+ StringName default_; // "default", conflict with C++ keyword.
StringName node_configuration_warning_changed;
@@ -224,4 +224,6 @@ public:
#endif
};
+#define SceneStringName(m_name) SceneStringNames::get_singleton()->m_name
+
#endif // SCENE_STRING_NAMES_H
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 820e0bbeb6..d37836ed96 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -762,7 +762,7 @@ void AudioServer::set_bus_count(int p_count) {
buses[i]->bypass = false;
buses[i]->volume_db = 0;
if (i > 0) {
- buses[i]->send = SceneStringNames::get_singleton()->Master;
+ buses[i]->send = SceneStringName(Master);
}
bus_map[attempt] = buses[i];
@@ -1600,7 +1600,7 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
for (int i = 0; i < p_bus_layout->buses.size(); i++) {
Bus *bus = memnew(Bus);
if (i == 0) {
- bus->name = SceneStringNames::get_singleton()->Master;
+ bus->name = SceneStringName(Master);
} else {
bus->name = p_bus_layout->buses[i].name;
bus->send = p_bus_layout->buses[i].send;
@@ -1923,5 +1923,5 @@ void AudioBusLayout::_get_property_list(List<PropertyInfo> *p_list) const {
AudioBusLayout::AudioBusLayout() {
buses.resize(1);
- buses.write[0].name = SceneStringNames::get_singleton()->Master;
+ buses.write[0].name = SceneStringName(Master);
}
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index 7a44645b1e..38baa6a4fa 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -57,6 +57,9 @@ public:
bool has_feature(Feature p_feature) const override { return false; }
String get_name() const override { return "headless"; }
+ // Stub implementations to prevent warnings from being printed for methods
+ // that don't affect the project's behavior in headless mode.
+
int get_screen_count() const override { return 0; }
int get_primary_screen() const override { return 0; };
Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Point2i(); }
@@ -66,6 +69,8 @@ public:
float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return 1; }
float screen_get_max_scale() const override { return 1; }
float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return SCREEN_REFRESH_RATE_FALLBACK; }
+ void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override {}
+ void screen_set_keep_on(bool p_enable) override {}
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
@@ -130,10 +135,47 @@ public:
void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override {}
void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override {}
+ int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override { return 0; }
+
void process_events() override {}
+ void set_native_icon(const String &p_filename) override {}
void set_icon(const Ref<Image> &p_icon) override {}
+ void help_set_search_callbacks(const Callable &p_search_callback = Callable(), const Callable &p_action_callback = Callable()) override {}
+
+ bool tts_is_speaking() const override { return false; }
+ bool tts_is_paused() const override { return false; }
+ TypedArray<Dictionary> tts_get_voices() const override { return TypedArray<Dictionary>(); }
+ void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.0f, float p_rate = 1.0f, int p_utterance_id = 0, bool p_interrupt = false) override {}
+ void tts_pause() override {}
+ void tts_resume() override {}
+ void tts_stop() override {}
+
+ void mouse_set_mode(MouseMode p_mode) override {}
+ void clipboard_set(const String &p_text) override {}
+ void clipboard_set_primary(const String &p_text) override {}
+
+ void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override {}
+ void virtual_keyboard_hide() override {}
+
+ void cursor_set_shape(CursorShape p_shape) override {}
+ void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override {}
+
+ Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+ Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+ Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+ Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+
+ void release_rendering_thread() override {}
+ void swap_buffers() override {}
+
+ IndicatorID create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) override { return INVALID_INDICATOR_ID; }
+ void status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) override {}
+ void status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip) override {}
+ void status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) override {}
+ void delete_status_indicator(IndicatorID p_id) override {}
+
DisplayServerHeadless() {
native_menu = memnew(NativeMenu);
}
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index fd9141f46e..7284076a47 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -140,7 +140,12 @@ void GodotSoftBody3D::set_mesh(RID p_mesh) {
Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0);
ERR_FAIL_COND(arrays.is_empty());
- bool success = create_from_trimesh(arrays[RenderingServer::ARRAY_INDEX], arrays[RenderingServer::ARRAY_VERTEX]);
+ const Vector<int> &indices = arrays[RenderingServer::ARRAY_INDEX];
+ const Vector<Vector3> &vertices = arrays[RenderingServer::ARRAY_VERTEX];
+ ERR_FAIL_COND_MSG(indices.is_empty(), "Soft body's mesh needs to have indices");
+ ERR_FAIL_COND_MSG(vertices.is_empty(), "Soft body's mesh needs to have vertices");
+
+ bool success = create_from_trimesh(indices, vertices);
if (!success) {
destroy();
}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index e48c72cec7..42de831e7a 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -38,6 +38,12 @@
#include "rendering_server_globals.h"
#include "servers/rendering/storage/texture_storage.h"
+// Use the same antialiasing feather size as StyleBoxFlat's default
+// (but doubled, as it's specified for both sides here).
+// This value is empirically determined to provide good antialiasing quality
+// while not making lines appear too soft.
+const static float FEATHER_SIZE = 1.25f;
+
void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
@@ -638,11 +644,8 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
}
if (p_antialiased) {
- // Use the same antialiasing feather size as StyleBoxFlat's default
- // (but doubled, as it's specified for both sides here).
- // This value is empirically determined to provide good antialiasing quality
- // while not making lines appear too soft.
- float border_size = 1.25f;
+ float border_size = FEATHER_SIZE;
+
if (0.0f <= p_width && p_width < 1.0f) {
border_size *= p_width;
}
@@ -651,7 +654,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
Vector2 border = dir * border_size;
Vector2 border2 = dir2 * border_size;
- Color transparent = Color(p_color.r, p_color.g, p_color.b, 0.0);
+ Color transparent = Color(p_color, 0.0);
{
Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
@@ -903,11 +906,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_ptr = colors.ptrw();
if (p_antialiased) {
- // Use the same antialiasing feather size as StyleBoxFlat's default
- // (but doubled, as it's specified for both sides here).
- // This value is empirically determined to provide good antialiasing quality
- // while not making lines appear too soft.
- float border_size = 1.25f;
+ float border_size = FEATHER_SIZE;
if (p_width < 1.0f) {
border_size *= p_width;
}
@@ -1094,12 +1093,15 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
pline->polygon.create(indices, points, colors);
}
-void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
ERR_FAIL_COND(p_points.is_empty() || p_points.size() % 2 != 0);
ERR_FAIL_COND(p_colors.size() != 1 && p_colors.size() * 2 != p_points.size());
// TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out.
if (p_width < 0) {
+ if (p_antialiased) {
+ WARN_PRINT("Antialiasing is not supported for thin multilines drawn using line strips (`p_width < 0`).");
+ }
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -1127,7 +1129,7 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
Vector2 from = p_points[i * 2 + 0];
Vector2 to = p_points[i * 2 + 1];
- canvas_item_add_line(p_item, from, to, color, p_width);
+ canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);
}
} else { //} else if (p_colors.size() << 1 == p_points.size()) {
for (int i = 0; i < p_colors.size(); i++) {
@@ -1135,13 +1137,13 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
Vector2 from = p_points[i * 2 + 0];
Vector2 to = p_points[i * 2 + 1];
- canvas_item_add_line(p_item, from, to, color, p_width);
+ canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);
}
}
}
}
-void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) {
+void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -1149,45 +1151,251 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
ERR_FAIL_NULL(rect);
rect->modulate = p_color;
rect->rect = p_rect;
+
+ // Add feathers.
+ if (p_antialiased) {
+ float border_size = FEATHER_SIZE;
+
+ const real_t size = MIN(p_rect.size.width, p_rect.size.height);
+ if (0.0f <= size && size < 1.0f) {
+ border_size *= size;
+ }
+
+ const Vector2 vec_down = Vector2(0.0f, p_rect.size.height);
+ const Vector2 vec_right = Vector2(p_rect.size.width, 0.0f);
+
+ const Vector2 begin_left = p_rect.position;
+ const Vector2 begin_right = p_rect.position + vec_down;
+ const Vector2 end_left = p_rect.position + vec_right;
+ const Vector2 end_right = p_rect.position + p_rect.size;
+
+ const Vector2 dir = Vector2(0.0f, -1.0f);
+ const Vector2 dir2 = Vector2(-1.0f, 0.0f);
+ const Vector2 border = dir * border_size;
+ const Vector2 border2 = dir2 * border_size;
+
+ Color transparent = Color(p_color, 0.0);
+
+ {
+ Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(left_border);
+
+ left_border->points[0] = begin_left;
+ left_border->points[1] = begin_left + border;
+ left_border->points[2] = end_left + border;
+ left_border->points[3] = end_left;
+
+ left_border->colors[0] = p_color;
+ left_border->colors[1] = transparent;
+ left_border->colors[2] = transparent;
+ left_border->colors[3] = p_color;
+
+ left_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(right_border);
+
+ right_border->points[0] = begin_right;
+ right_border->points[1] = begin_right - border;
+ right_border->points[2] = end_right - border;
+ right_border->points[3] = end_right;
+
+ right_border->colors[0] = p_color;
+ right_border->colors[1] = transparent;
+ right_border->colors[2] = transparent;
+ right_border->colors[3] = p_color;
+
+ right_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_border);
+
+ top_border->points[0] = begin_left;
+ top_border->points[1] = begin_left + border2;
+ top_border->points[2] = begin_right + border2;
+ top_border->points[3] = begin_right;
+
+ top_border->colors[0] = p_color;
+ top_border->colors[1] = transparent;
+ top_border->colors[2] = transparent;
+ top_border->colors[3] = p_color;
+
+ top_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_border);
+
+ bottom_border->points[0] = end_left;
+ bottom_border->points[1] = end_left - border2;
+ bottom_border->points[2] = end_right - border2;
+ bottom_border->points[3] = end_right;
+
+ bottom_border->colors[0] = p_color;
+ bottom_border->colors[1] = transparent;
+ bottom_border->colors[2] = transparent;
+ bottom_border->colors[3] = p_color;
+
+ bottom_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_left_corner);
+
+ top_left_corner->points[0] = begin_left;
+ top_left_corner->points[1] = begin_left + border2;
+ top_left_corner->points[2] = begin_left + border + border2;
+ top_left_corner->points[3] = begin_left + border;
+
+ top_left_corner->colors[0] = p_color;
+ top_left_corner->colors[1] = transparent;
+ top_left_corner->colors[2] = transparent;
+ top_left_corner->colors[3] = transparent;
+
+ top_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_right_corner);
+
+ top_right_corner->points[0] = begin_right;
+ top_right_corner->points[1] = begin_right + border2;
+ top_right_corner->points[2] = begin_right - border + border2;
+ top_right_corner->points[3] = begin_right - border;
+
+ top_right_corner->colors[0] = p_color;
+ top_right_corner->colors[1] = transparent;
+ top_right_corner->colors[2] = transparent;
+ top_right_corner->colors[3] = transparent;
+
+ top_right_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_left_corner);
+
+ bottom_left_corner->points[0] = end_left;
+ bottom_left_corner->points[1] = end_left - border2;
+ bottom_left_corner->points[2] = end_left + border - border2;
+ bottom_left_corner->points[3] = end_left + border;
+
+ bottom_left_corner->colors[0] = p_color;
+ bottom_left_corner->colors[1] = transparent;
+ bottom_left_corner->colors[2] = transparent;
+ bottom_left_corner->colors[3] = transparent;
+
+ bottom_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_right_corner);
+
+ bottom_right_corner->points[0] = end_right;
+ bottom_right_corner->points[1] = end_right - border2;
+ bottom_right_corner->points[2] = end_right - border - border2;
+ bottom_right_corner->points[3] = end_right - border;
+
+ bottom_right_corner->colors[0] = p_color;
+ bottom_right_corner->colors[1] = transparent;
+ bottom_right_corner->colors[2] = transparent;
+ bottom_right_corner->colors[3] = transparent;
+
+ bottom_right_corner->point_count = 4;
+ }
+ }
}
-void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
+void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
- Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_NULL(circle);
+ static const int circle_segments = 64;
- circle->primitive = RS::PRIMITIVE_TRIANGLES;
+ {
+ Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_NULL(circle);
- Vector<int> indices;
- Vector<Vector2> points;
+ circle->primitive = RS::PRIMITIVE_TRIANGLES;
- static const int circle_points = 64;
+ Vector<int> indices;
+ Vector<Vector2> points;
- points.resize(circle_points);
- Vector2 *points_ptr = points.ptrw();
- const real_t circle_point_step = Math_TAU / circle_points;
+ points.resize(circle_segments + 2);
+ Vector2 *points_ptr = points.ptrw();
- for (int i = 0; i < circle_points; i++) {
- float angle = i * circle_point_step;
- points_ptr[i].x = Math::cos(angle) * p_radius;
- points_ptr[i].y = Math::sin(angle) * p_radius;
- points_ptr[i] += p_pos;
- }
+ // Store circle center in the last point.
+ points_ptr[circle_segments + 1] = p_pos;
- indices.resize((circle_points - 2) * 3);
- int *indices_ptr = indices.ptrw();
+ const real_t circle_point_step = Math_TAU / circle_segments;
+
+ for (int i = 0; i < circle_segments + 1; i++) {
+ float angle = i * circle_point_step;
+ points_ptr[i].x = Math::cos(angle) * p_radius;
+ points_ptr[i].y = Math::sin(angle) * p_radius;
+ points_ptr[i] += p_pos;
+ }
- for (int i = 0; i < circle_points - 2; i++) {
- indices_ptr[i * 3 + 0] = 0;
- indices_ptr[i * 3 + 1] = i + 1;
- indices_ptr[i * 3 + 2] = i + 2;
+ indices.resize(circle_segments * 3);
+ int *indices_ptr = indices.ptrw();
+
+ for (int i = 0; i < circle_segments; i++) {
+ indices_ptr[i * 3 + 0] = circle_segments + 1;
+ indices_ptr[i * 3 + 1] = i;
+ indices_ptr[i * 3 + 2] = i + 1;
+ }
+
+ Vector<Color> color;
+ color.push_back(p_color);
+ circle->polygon.create(indices, points, color);
}
- Vector<Color> color;
- color.push_back(p_color);
- circle->polygon.create(indices, points, color);
+ if (p_antialiased) {
+ float border_size = FEATHER_SIZE;
+
+ const float diameter = p_radius * 2.0f;
+ if (0.0f <= diameter && diameter < 1.0f) {
+ border_size *= p_radius;
+ }
+
+ Item::CommandPolygon *feather = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_NULL(feather);
+ feather->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+
+ Color transparent = Color(p_color, 0.0);
+
+ Vector<int> indices;
+ Vector<Color> colors;
+ Vector<Vector2> points;
+
+ points.resize(2 * circle_segments + 2);
+ colors.resize(2 * circle_segments + 2);
+
+ const real_t circle_point_step = Math_TAU / circle_segments;
+
+ Vector2 *points_ptr = points.ptrw();
+ Color *colors_ptr = colors.ptrw();
+
+ for (int i = 0; i < circle_segments + 1; i++) {
+ const float angle = i * circle_point_step;
+ const float c = Math::cos(angle);
+ const float s = Math::sin(angle);
+
+ points_ptr[i * 2].x = c * p_radius;
+ points_ptr[i * 2].y = s * p_radius;
+ points_ptr[i * 2] += p_pos;
+
+ points_ptr[i * 2 + 1].x = c * (p_radius + border_size);
+ points_ptr[i * 2 + 1].y = s * (p_radius + border_size);
+ points_ptr[i * 2 + 1] += p_pos;
+
+ colors_ptr[i * 2] = p_color;
+ colors_ptr[i * 2 + 1] = transparent;
+ }
+
+ feather->polygon.create(indices, points, colors);
+ }
}
void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) {
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 961506ca28..9f8cbea2e9 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -233,9 +233,9 @@ public:
void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false);
void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
- void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0);
- void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
- void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
+ void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
+ void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased);
+ void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 8175010caf..068f9d9ef2 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -1812,6 +1812,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+ RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment);
if (p_render_data->camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
@@ -1823,7 +1824,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1833,13 +1834,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
- draw_sky = true;
+ draw_sky = !p_render_data->transparent_bg;
} break;
case RS::ENV_BG_CANVAS: {
if (!is_reflection_probe) {
@@ -1859,7 +1860,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
@@ -3578,11 +3579,11 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RID RenderForwardClustered::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
- return p_render_buffers->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? rb_data->get_normal_roughness() : rb_data->get_normal_roughness_msaa();
+ return rb_data->get_normal_roughness();
}
RID RenderForwardClustered::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
- return p_render_buffers->get_velocity_buffer(p_render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED);
+ return p_render_buffers->get_velocity_buffer(false);
}
void RenderForwardClustered::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 5715d94d95..878ea7bcfb 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -830,6 +830,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+ RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment);
if (p_render_data->camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
@@ -841,7 +842,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if (environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -851,13 +852,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if (environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
- draw_sky = true;
+ draw_sky = !p_render_data->transparent_bg;
} break;
case RS::ENV_BG_CANVAS: {
if (rb_data.is_valid()) {
@@ -874,7 +875,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 6cb03871c9..1e4880e67a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -1149,6 +1149,10 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
render_data.sdfgi_update_data = p_sdfgi_update_data;
render_data.render_info = r_render_info;
+
+ if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
+ render_data.transparent_bg = texture_storage->render_target_get_transparent(rb->get_render_target());
+ }
}
PagedArray<RID> empty;
diff --git a/servers/rendering/renderer_rd/storage_rd/render_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h
index 2f61899a18..3cd397b8ed 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_data_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h
@@ -78,6 +78,9 @@ public:
RenderingMethod::RenderInfo *render_info = nullptr;
+ /* Viewport data */
+ bool transparent_bg = false;
+
/* Shadow data */
const RendererSceneRender::RenderShadowData *render_shadows = nullptr;
int render_shadow_count = 0;
diff --git a/servers/rendering/rendering_context_driver.h b/servers/rendering/rendering_context_driver.h
index df1424da95..539b3814a0 100644
--- a/servers/rendering/rendering_context_driver.h
+++ b/servers/rendering/rendering_context_driver.h
@@ -73,10 +73,15 @@ public:
DEVICE_TYPE_MAX = 0x5
};
+ struct Workarounds {
+ bool avoid_compute_after_draw = false;
+ };
+
struct Device {
String name = "Unknown";
Vendor vendor = VENDOR_UNKNOWN;
DeviceType type = DEVICE_TYPE_OTHER;
+ Workarounds workarounds;
};
virtual ~RenderingContextDriver();
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 31fc51efaa..6746a1dde1 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -4877,25 +4877,78 @@ void RenderingDevice::_end_frame() {
ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work).");
}
- draw_graph.end(frames[frame].draw_command_buffer, RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS);
driver->command_buffer_end(frames[frame].setup_command_buffer);
- driver->command_buffer_end(frames[frame].draw_command_buffer);
+
+ // The command buffer must be copied into a stack variable as the driver workarounds can change the command buffer in use.
+ RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer;
+ draw_graph.end(RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS, command_buffer, frames[frame].command_buffer_pool);
+ driver->command_buffer_end(command_buffer);
driver->end_segment();
}
void RenderingDevice::_execute_frame(bool p_present) {
+ // Check whether this frame should present the swap chains and in which queue.
const bool frame_can_present = p_present && !frames[frame].swap_chains_to_present.is_empty();
const bool separate_present_queue = main_queue != present_queue;
- const VectorView<RDD::SemaphoreID> execute_draw_semaphore = frame_can_present && separate_present_queue ? frames[frame].draw_semaphore : VectorView<RDD::SemaphoreID>();
- const VectorView<RDD::SwapChainID> execute_draw_swap_chains = frame_can_present && !separate_present_queue ? frames[frame].swap_chains_to_present : VectorView<RDD::SwapChainID>();
+ thread_local LocalVector<RDD::SwapChainID> swap_chains;
+ swap_chains.clear();
+
+ // Execute the setup command buffer.
driver->command_queue_execute_and_present(main_queue, {}, frames[frame].setup_command_buffer, frames[frame].setup_semaphore, {}, {});
- driver->command_queue_execute_and_present(main_queue, frames[frame].setup_semaphore, frames[frame].draw_command_buffer, execute_draw_semaphore, frames[frame].draw_fence, execute_draw_swap_chains);
+
+ // Execute command buffers and use semaphores to wait on the execution of the previous one. Normally there's only one command buffer,
+ // but driver workarounds can force situations where there'll be more.
+ uint32_t command_buffer_count = 1;
+ RDG::CommandBufferPool &buffer_pool = frames[frame].command_buffer_pool;
+ if (buffer_pool.buffers_used > 0) {
+ command_buffer_count += buffer_pool.buffers_used;
+ buffer_pool.buffers_used = 0;
+ }
+
+ RDD::SemaphoreID wait_semaphore = frames[frame].setup_semaphore;
+ for (uint32_t i = 0; i < command_buffer_count; i++) {
+ RDD::CommandBufferID command_buffer;
+ RDD::SemaphoreID signal_semaphore;
+ RDD::FenceID signal_fence;
+ if (i > 0) {
+ command_buffer = buffer_pool.buffers[i - 1];
+ signal_semaphore = buffer_pool.semaphores[i - 1];
+ } else {
+ command_buffer = frames[frame].draw_command_buffer;
+ signal_semaphore = frames[frame].draw_semaphore;
+ }
+
+ bool signal_semaphore_valid;
+ if (i == (command_buffer_count - 1)) {
+ // This is the last command buffer, it should signal the fence.
+ signal_fence = frames[frame].draw_fence;
+ signal_semaphore_valid = false;
+
+ if (frame_can_present && separate_present_queue) {
+ // The semaphore is required if the frame can be presented and a separate present queue is used.
+ signal_semaphore_valid = true;
+ } else if (frame_can_present) {
+ // Just present the swap chains as part of the last command execution.
+ swap_chains = frames[frame].swap_chains_to_present;
+ }
+ } else {
+ // Semaphores always need to be signaled if it's not the last command buffer.
+ signal_semaphore_valid = true;
+ }
+
+ driver->command_queue_execute_and_present(main_queue, wait_semaphore, command_buffer, signal_semaphore_valid ? signal_semaphore : VectorView<RDD::SemaphoreID>(), signal_fence, swap_chains);
+
+ // Make the next command buffer wait on the semaphore signaled by this one.
+ wait_semaphore = signal_semaphore;
+ }
+
+ // Indicate the fence has been signaled so the next time the frame's contents need to be used, the CPU needs to wait on the work to be completed.
frames[frame].draw_fence_signaled = true;
if (frame_can_present) {
if (separate_present_queue) {
// Issue the presentation separately if the presentation queue is different from the main queue.
- driver->command_queue_execute_and_present(present_queue, frames[frame].draw_semaphore, {}, {}, {}, frames[frame].swap_chains_to_present);
+ driver->command_queue_execute_and_present(present_queue, wait_semaphore, {}, {}, {}, frames[frame].swap_chains_to_present);
}
frames[frame].swap_chains_to_present.clear();
@@ -5044,6 +5097,9 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
frames[i].timestamp_cpu_result_values.resize(max_timestamp_query_elements);
frames[i].timestamp_result_values.resize(max_timestamp_query_elements);
frames[i].timestamp_result_count = 0;
+
+ // Assign the main queue family and command pool to the command buffer pool.
+ frames[i].command_buffer_pool.pool = frames[i].command_pool;
}
// Start from frame count, so everything else is immediately old.
@@ -5055,7 +5111,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
driver->command_buffer_begin(frames[0].draw_command_buffer);
// Create draw graph and start it initialized as well.
- draw_graph.initialize(driver, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME);
+ draw_graph.initialize(driver, device, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME);
draw_graph.begin();
for (uint32_t i = 0; i < frames.size(); i++) {
@@ -5388,6 +5444,11 @@ void RenderingDevice::finalize() {
driver->semaphore_free(frames[i].setup_semaphore);
driver->semaphore_free(frames[i].draw_semaphore);
driver->fence_free(frames[i].draw_fence);
+
+ RDG::CommandBufferPool &buffer_pool = frames[i].command_buffer_pool;
+ for (uint32_t j = 0; j < buffer_pool.buffers.size(); j++) {
+ driver->semaphore_free(buffer_pool.semaphores[j]);
+ }
}
if (pipeline_cache_enabled) {
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 9db2fdfbf4..020be6be18 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1261,6 +1261,9 @@ private:
// Swap chains prepared for drawing during the frame that must be presented.
LocalVector<RDD::SwapChainID> swap_chains_to_present;
+ // Extra command buffer pool used for driver workarounds.
+ RDG::CommandBufferPool command_buffer_pool;
+
struct Timestamp {
String description;
uint64_t value = 0;
diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp
index b04f2ebbaa..c7de5c67cb 100644
--- a/servers/rendering/rendering_device_graph.cpp
+++ b/servers/rendering/rendering_device_graph.cpp
@@ -753,71 +753,96 @@ void RenderingDeviceGraph::_wait_for_secondary_command_buffer_tasks() {
}
}
-void RenderingDeviceGraph::_run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level) {
+void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level) {
for (uint32_t i = 0; i < p_sorted_commands_count; i++) {
const uint32_t command_index = p_sorted_commands[i].index;
const uint32_t command_data_offset = command_data_offsets[command_index];
const RecordedCommand *command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]);
- _run_label_command_change(p_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level);
+ _run_label_command_change(r_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level);
switch (command->type) {
case RecordedCommand::TYPE_BUFFER_CLEAR: {
const RecordedBufferClearCommand *buffer_clear_command = reinterpret_cast<const RecordedBufferClearCommand *>(command);
- driver->command_clear_buffer(p_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size);
+ driver->command_clear_buffer(r_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size);
} break;
case RecordedCommand::TYPE_BUFFER_COPY: {
const RecordedBufferCopyCommand *buffer_copy_command = reinterpret_cast<const RecordedBufferCopyCommand *>(command);
- driver->command_copy_buffer(p_command_buffer, buffer_copy_command->source, buffer_copy_command->destination, buffer_copy_command->region);
+ driver->command_copy_buffer(r_command_buffer, buffer_copy_command->source, buffer_copy_command->destination, buffer_copy_command->region);
} break;
case RecordedCommand::TYPE_BUFFER_GET_DATA: {
const RecordedBufferGetDataCommand *buffer_get_data_command = reinterpret_cast<const RecordedBufferGetDataCommand *>(command);
- driver->command_copy_buffer(p_command_buffer, buffer_get_data_command->source, buffer_get_data_command->destination, buffer_get_data_command->region);
+ driver->command_copy_buffer(r_command_buffer, buffer_get_data_command->source, buffer_get_data_command->destination, buffer_get_data_command->region);
} break;
case RecordedCommand::TYPE_BUFFER_UPDATE: {
const RecordedBufferUpdateCommand *buffer_update_command = reinterpret_cast<const RecordedBufferUpdateCommand *>(command);
const RecordedBufferCopy *command_buffer_copies = buffer_update_command->buffer_copies();
for (uint32_t j = 0; j < buffer_update_command->buffer_copies_count; j++) {
- driver->command_copy_buffer(p_command_buffer, command_buffer_copies[j].source, buffer_update_command->destination, command_buffer_copies[j].region);
+ driver->command_copy_buffer(r_command_buffer, command_buffer_copies[j].source, buffer_update_command->destination, command_buffer_copies[j].region);
}
} break;
case RecordedCommand::TYPE_COMPUTE_LIST: {
+ if (device.workarounds.avoid_compute_after_draw && workarounds_state.draw_list_found) {
+ // Avoid compute after draw workaround. Refer to the comment that enables this in the Vulkan driver for more information.
+ workarounds_state.draw_list_found = false;
+
+ // Create or reuse a command buffer and finish recording the current one.
+ driver->command_buffer_end(r_command_buffer);
+
+ while (r_command_buffer_pool.buffers_used >= r_command_buffer_pool.buffers.size()) {
+ RDD::CommandBufferID command_buffer = driver->command_buffer_create(r_command_buffer_pool.pool);
+ RDD::SemaphoreID command_semaphore = driver->semaphore_create();
+ r_command_buffer_pool.buffers.push_back(command_buffer);
+ r_command_buffer_pool.semaphores.push_back(command_semaphore);
+ }
+
+ // Start recording on the next usable command buffer from the pool.
+ uint32_t command_buffer_index = r_command_buffer_pool.buffers_used++;
+ r_command_buffer = r_command_buffer_pool.buffers[command_buffer_index];
+ driver->command_buffer_begin(r_command_buffer);
+ }
+
const RecordedComputeListCommand *compute_list_command = reinterpret_cast<const RecordedComputeListCommand *>(command);
- _run_compute_list_command(p_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size);
+ _run_compute_list_command(r_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size);
} break;
case RecordedCommand::TYPE_DRAW_LIST: {
+ if (device.workarounds.avoid_compute_after_draw) {
+ // Indicate that a draw list was encountered for the workaround.
+ workarounds_state.draw_list_found = true;
+ }
+
const RecordedDrawListCommand *draw_list_command = reinterpret_cast<const RecordedDrawListCommand *>(command);
const VectorView clear_values(draw_list_command->clear_values(), draw_list_command->clear_values_count);
- driver->command_begin_render_pass(p_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values);
- _run_draw_list_command(p_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size);
- driver->command_end_render_pass(p_command_buffer);
+ driver->command_begin_render_pass(r_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values);
+ _run_draw_list_command(r_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size);
+ driver->command_end_render_pass(r_command_buffer);
} break;
case RecordedCommand::TYPE_TEXTURE_CLEAR: {
const RecordedTextureClearCommand *texture_clear_command = reinterpret_cast<const RecordedTextureClearCommand *>(command);
- driver->command_clear_color_texture(p_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range);
+ driver->command_clear_color_texture(r_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range);
} break;
case RecordedCommand::TYPE_TEXTURE_COPY: {
const RecordedTextureCopyCommand *texture_copy_command = reinterpret_cast<const RecordedTextureCopyCommand *>(command);
- driver->command_copy_texture(p_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region);
+ driver->command_copy_texture(r_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region);
} break;
case RecordedCommand::TYPE_TEXTURE_GET_DATA: {
const RecordedTextureGetDataCommand *texture_get_data_command = reinterpret_cast<const RecordedTextureGetDataCommand *>(command);
const VectorView<RDD::BufferTextureCopyRegion> command_buffer_texture_copy_regions_view(texture_get_data_command->buffer_texture_copy_regions(), texture_get_data_command->buffer_texture_copy_regions_count);
- driver->command_copy_texture_to_buffer(p_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view);
+ driver->command_copy_texture_to_buffer(r_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view);
} break;
case RecordedCommand::TYPE_TEXTURE_RESOLVE: {
const RecordedTextureResolveCommand *texture_resolve_command = reinterpret_cast<const RecordedTextureResolveCommand *>(command);
- driver->command_resolve_texture(p_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap);
+ driver->command_resolve_texture(r_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap);
} break;
case RecordedCommand::TYPE_TEXTURE_UPDATE: {
const RecordedTextureUpdateCommand *texture_update_command = reinterpret_cast<const RecordedTextureUpdateCommand *>(command);
const RecordedBufferToTextureCopy *command_buffer_to_texture_copies = texture_update_command->buffer_to_texture_copies();
for (uint32_t j = 0; j < texture_update_command->buffer_to_texture_copies_count; j++) {
- driver->command_copy_buffer_to_texture(p_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region);
+ driver->command_copy_buffer_to_texture(r_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region);
}
} break;
case RecordedCommand::TYPE_CAPTURE_TIMESTAMP: {
const RecordedCaptureTimestampCommand *texture_capture_timestamp_command = reinterpret_cast<const RecordedCaptureTimestampCommand *>(command);
- driver->command_timestamp_write(p_command_buffer, texture_capture_timestamp_command->pool, texture_capture_timestamp_command->index);
+ driver->command_timestamp_write(r_command_buffer, texture_capture_timestamp_command->pool, texture_capture_timestamp_command->index);
} break;
default: {
DEV_ASSERT(false && "Unknown recorded command type.");
@@ -1229,8 +1254,9 @@ void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data
}
}
-void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) {
+void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) {
driver = p_driver;
+ device = p_device;
frames.resize(p_frame_count);
for (uint32_t i = 0; i < p_frame_count; i++) {
@@ -1805,7 +1831,7 @@ void RenderingDeviceGraph::end_label() {
command_label_index = -1;
}
-void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers) {
+void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool) {
if (command_count == 0) {
// No commands have been logged, do nothing.
return;
@@ -1919,7 +1945,12 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo
if (command_count > 0) {
int32_t current_label_index = -1;
int32_t current_label_level = -1;
- _run_label_command_change(p_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level);
+ _run_label_command_change(r_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level);
+
+ if (device.workarounds.avoid_compute_after_draw) {
+ // Reset the state of the workaround.
+ workarounds_state.draw_list_found = false;
+ }
if (p_reorder_commands) {
#if PRINT_RENDER_GRAPH
@@ -1946,8 +1977,8 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo
RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start];
uint32_t level_command_count = i - current_level_start;
_boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority);
- _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
- _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level);
+ _group_barriers_for_render_commands(r_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
+ _run_render_commands(current_level, level_command_ptr, level_command_count, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level);
current_level = commands_sorted[i].level;
current_level_start = i;
}
@@ -1956,20 +1987,20 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo
RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start];
uint32_t level_command_count = command_count - current_level_start;
_boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority);
- _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
- _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level);
+ _group_barriers_for_render_commands(r_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
+ _run_render_commands(current_level, level_command_ptr, level_command_count, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level);
#if PRINT_RENDER_GRAPH
print_line("COMMANDS", command_count, "LEVELS", current_level + 1);
#endif
} else {
for (uint32_t i = 0; i < command_count; i++) {
- _group_barriers_for_render_commands(p_command_buffer, &commands_sorted[i], 1, p_full_barriers);
- _run_render_commands(p_command_buffer, i, &commands_sorted[i], 1, current_label_index, current_label_level);
+ _group_barriers_for_render_commands(r_command_buffer, &commands_sorted[i], 1, p_full_barriers);
+ _run_render_commands(i, &commands_sorted[i], 1, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level);
}
}
- _run_label_command_change(p_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level);
+ _run_label_command_change(r_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level);
#if PRINT_COMMAND_RECORDING
print_line(vformat("Recorded %d commands", command_count));
diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h
index 3bc63bb297..a96382e0cc 100644
--- a/servers/rendering/rendering_device_graph.h
+++ b/servers/rendering/rendering_device_graph.h
@@ -184,6 +184,20 @@ public:
}
};
+ struct CommandBufferPool {
+ // Provided by RenderingDevice.
+ RDD::CommandPoolID pool;
+
+ // Created internally by RenderingDeviceGraph.
+ LocalVector<RDD::CommandBufferID> buffers;
+ LocalVector<RDD::SemaphoreID> semaphores;
+ uint32_t buffers_used = 0;
+ };
+
+ struct WorkaroundsState {
+ bool draw_list_found = false;
+ };
+
private:
struct InstructionList {
LocalVector<uint8_t> data;
@@ -560,6 +574,7 @@ private:
};
RDD *driver = nullptr;
+ RenderingContextDriver::Device device;
int64_t tracking_frame = 0;
LocalVector<uint8_t> command_data;
LocalVector<uint32_t> command_data_offsets;
@@ -582,6 +597,7 @@ private:
bool command_synchronization_pending = false;
BarrierGroup barrier_group;
bool driver_honors_barriers = false;
+ WorkaroundsState workarounds_state;
TightLocalVector<Frame> frames;
uint32_t frame = 0;
@@ -608,7 +624,7 @@ private:
void _run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size);
void _run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary);
void _wait_for_secondary_command_buffer_tasks();
- void _run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level);
+ void _run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level);
void _run_label_command_change(RDD::CommandBufferID p_command_buffer, int32_t p_new_label_index, int32_t p_new_level, bool p_ignore_previous_value, bool p_use_label_for_empty, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level);
void _boost_priority_for_render_commands(RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, uint32_t &r_boosted_priority);
void _group_barriers_for_render_commands(RDD::CommandBufferID p_command_buffer, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, bool p_full_memory_barrier);
@@ -619,7 +635,7 @@ private:
public:
RenderingDeviceGraph();
~RenderingDeviceGraph();
- void initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame);
+ void initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame);
void finalize();
void begin();
void add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size);
@@ -664,7 +680,7 @@ public:
void add_synchronization();
void begin_label(const String &p_label_name, const Color &p_color);
void end_label();
- void end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers);
+ void end(bool p_reorder_commands, bool p_full_barriers, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool);
static ResourceTracker *resource_tracker_create();
static void resource_tracker_free(ResourceTracker *tracker);
};
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index d0b6bc492d..164ec3cc09 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -885,9 +885,9 @@ public:
FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
- FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
- FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
- FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
+ FUNC5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
+ FUNC4(canvas_item_add_rect, RID, const Rect2 &, const Color &, bool)
+ FUNC5(canvas_item_add_circle, RID, const Point2 &, float, const Color &, bool)
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float)
diff --git a/servers/rendering_server.compat.inc b/servers/rendering_server.compat.inc
index 0cef3c906c..99f2de9a9a 100644
--- a/servers/rendering_server.compat.inc
+++ b/servers/rendering_server.compat.inc
@@ -34,8 +34,23 @@ void RenderingServer::_environment_set_fog_bind_compat_84792(RID p_env, bool p_e
environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL);
}
+void RenderingServer::_canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+ canvas_item_add_multiline(p_item, p_points, p_colors, p_width, false);
+}
+
+void RenderingServer::_canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color) {
+ canvas_item_add_rect(p_item, p_rect, p_color, false);
+}
+
+void RenderingServer::_canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
+ canvas_item_add_circle(p_item, p_pos, p_radius, p_color, false);
+}
+
void RenderingServer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792);
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::_canvas_item_add_multiline_bind_compat_84523, DEFVAL(-1.0));
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::_canvas_item_add_rect_bind_compat_84523);
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::_canvas_item_add_circle_bind_compat_84523);
}
#endif
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index ab82e42f43..5cfd8d3cd2 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -3229,9 +3229,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(-1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0));
- ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
- ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color", "antialiased"), &RenderingServer::canvas_item_add_rect, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color", "antialiased"), &RenderingServer::canvas_item_add_circle, DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range", "scale"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 5bc028dfdd..e15dba4353 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -99,6 +99,10 @@ protected:
#ifndef DISABLE_DEPRECATED
void _environment_set_fog_bind_compat_84792(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ void _canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0);
+ void _canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color);
+ void _canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
+
static void _bind_compatibility_methods();
#endif
@@ -1465,9 +1469,9 @@ public:
virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0;
- virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0) = 0;
- virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
- virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
+ virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased = false) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0) = 0;
diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h
index d714d71416..2a629642d4 100644
--- a/tests/core/object/test_object.h
+++ b/tests/core/object/test_object.h
@@ -251,7 +251,7 @@ TEST_CASE("[Object] Script property setter") {
Variant script;
bool valid = false;
- object.set(CoreStringNames::get_singleton()->_script, script, &valid);
+ object.set(CoreStringName(script), script, &valid);
CHECK(valid);
CHECK_MESSAGE(
object.get_script() == script,
@@ -264,7 +264,7 @@ TEST_CASE("[Object] Script property getter") {
object.set_script(script);
bool valid = false;
- const Variant &actual_value = object.get(CoreStringNames::get_singleton()->_script, &valid);
+ const Variant &actual_value = object.get(CoreStringName(script), &valid);
CHECK(valid);
CHECK_MESSAGE(
actual_value == script,
diff --git a/tests/scene/test_curve_2d.h b/tests/scene/test_curve_2d.h
index 099f6fefa9..1248632630 100644
--- a/tests/scene/test_curve_2d.h
+++ b/tests/scene/test_curve_2d.h
@@ -147,13 +147,19 @@ TEST_CASE("[Curve2D] Sampling") {
CHECK(curve->samplef(1) == Vector2(0, 50));
}
- SUBCASE("sample_baked") {
+ SUBCASE("sample_baked, cubic = false") {
CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 0))) == Vector2(0, 0));
CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 25))) == Vector2(0, 25));
CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 50))) == Vector2(0, 50));
}
- SUBCASE("sample_baked_with_rotation") {
+ SUBCASE("sample_baked, cubic = true") {
+ CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 0)), true) == Vector2(0, 0));
+ CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 25)), true) == Vector2(0, 25));
+ CHECK(curve->sample_baked(curve->get_closest_offset(Vector2(0, 50)), true) == Vector2(0, 50));
+ }
+
+ SUBCASE("sample_baked_with_rotation, cubic = false") {
const real_t pi = 3.14159;
const real_t half_pi = pi * 0.5;
Ref<Curve2D> rot_curve = memnew(Curve2D);
@@ -188,6 +194,41 @@ TEST_CASE("[Curve2D] Sampling") {
CHECK(Math::is_equal_approx(t.get_rotation(), -half_pi));
}
+ SUBCASE("sample_baked_with_rotation, cubic = true") {
+ const real_t pi = 3.14159;
+ const real_t half_pi = pi * 0.5;
+ Ref<Curve2D> rot_curve = memnew(Curve2D);
+ Transform2D t;
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(50, 0));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(25, 0));
+ CHECK(Math::is_equal_approx(t.get_rotation(), 0));
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(0, 50));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(0, 25));
+ CHECK(Math::is_equal_approx(t.get_rotation(), half_pi));
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(-50, 0));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(-25, 0));
+ CHECK(Math::is_equal_approx(t.get_rotation(), pi));
+
+ rot_curve->clear_points();
+ rot_curve->add_point(Vector2());
+ rot_curve->add_point(Vector2(0, -50));
+ t = rot_curve->sample_baked_with_rotation(25, true);
+ CHECK(t.get_origin() == Vector2(0, -25));
+ CHECK(Math::is_equal_approx(t.get_rotation(), -half_pi));
+ }
+
SUBCASE("get_closest_point") {
CHECK(curve->get_closest_point(Vector2(0, 0)) == Vector2(0, 0));
CHECK(curve->get_closest_point(Vector2(0, 25)) == Vector2(0, 25));
diff --git a/tests/scene/test_curve_3d.h b/tests/scene/test_curve_3d.h
index d73bb1ad35..2e60a9c6e6 100644
--- a/tests/scene/test_curve_3d.h
+++ b/tests/scene/test_curve_3d.h
@@ -177,12 +177,30 @@ TEST_CASE("[Curve3D] Sampling") {
CHECK(curve->sample_baked(curve->get_closest_offset(Vector3(0, 50, 0)), true) == Vector3(0, 50, 0));
}
- SUBCASE("sample_baked_with_rotation") {
+ SUBCASE("sample_baked_with_rotation, cubic = false, p_apply_tilt = false") {
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
}
+ SUBCASE("sample_baked_with_rotation, cubic = false, p_apply_tilt = true") {
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0)), false, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0)), false, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0)), false, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
+ }
+
+ SUBCASE("sample_baked_with_rotation, cubic = true, p_apply_tilt = false") {
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0)), true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0)), true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0)), true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
+ }
+
+ SUBCASE("sample_baked_with_rotation, cubic = true, p_apply_tilt = true") {
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0)), true, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0)), true, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
+ CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0)), true, true) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
+ }
+
SUBCASE("sample_baked_tilt") {
CHECK(curve->sample_baked_tilt(curve->get_closest_offset(Vector3(0, 0, 0))) == 0);
CHECK(curve->sample_baked_tilt(curve->get_closest_offset(Vector3(0, 25, 0))) == 0);
diff --git a/version.py b/version.py
index e915a6e530..d5ea5cfd91 100644
--- a/version.py
+++ b/version.py
@@ -3,7 +3,7 @@ name = "Godot Engine"
major = 4
minor = 3
patch = 0
-status = "dev"
+status = "beta"
module_config = ""
website = "https://godotengine.org"
docs = "latest"