diff options
58 files changed, 717 insertions, 441 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index de0037d5e8..820a85c3fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -227,6 +227,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - More information in the [progress report](https://godotengine.org/article/improvements-shaders-visual-shaders-godot-4). - [Add Billboard mode to visual shaders.](https://github.com/godotengine/godot/pull/49157) - [The constants `PI`, `TAU` and `E` are now available in the shader language.](https://github.com/godotengine/godot/pull/48837) +- Uniform hints to control textures (`repeat_enabled`, `repeat_disabled`, `filter_linear`, `filter_nearest`, `hint_screen_texture`, etc.). #### Miscellaneous @@ -401,6 +402,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - [Removed support for 16× MSAA due to driver bugs and low performance.](https://github.com/godotengine/godot/pull/49063) - For high-quality offline rendering, using supersampling together with 8× MSAA is a better option anyway. +#### Shaders + +- Removed `SCREEN_TEXTURE` and `DEPTH_TEXTURE` in favour of uniform hints `hint_screen_texture` and `hint_depth_texture`. + ### Fixed #### Core diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index bd4fa61bd5..4df3df160f 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -31,8 +31,11 @@ #include "gdextension_interface.h" #include "core/config/engine.h" +#include "core/io/file_access.h" +#include "core/io/xml_parser.h" #include "core/object/class_db.h" #include "core/object/script_language_extension.h" +#include "core/object/worker_thread_pool.h" #include "core/os/memory.h" #include "core/variant/variant.h" #include "core/version.h" @@ -678,6 +681,59 @@ static const char32_t *gdextension_string_operator_index_const(GDExtensionConstS return &self->ptr()[p_index]; } +static void gdextension_string_operator_plus_eq_string(GDExtensionStringPtr p_self, GDExtensionConstStringPtr p_b) { + String *self = (String *)p_self; + const String *b = (const String *)p_b; + *self += *b; +} + +static void gdextension_string_operator_plus_eq_char(GDExtensionStringPtr p_self, char32_t p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static void gdextension_string_operator_plus_eq_cstr(GDExtensionStringPtr p_self, const char *p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static void gdextension_string_operator_plus_eq_wcstr(GDExtensionStringPtr p_self, const wchar_t *p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static void gdextension_string_operator_plus_eq_c32str(GDExtensionStringPtr p_self, const char32_t *p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static GDExtensionInt gdextension_xml_parser_open_buffer(GDExtensionObjectPtr p_instance, const uint8_t *p_buffer, size_t p_size) { + XMLParser *xml = (XMLParser *)p_instance; + return (GDExtensionInt)xml->_open_buffer(p_buffer, p_size); +} + +static void gdextension_file_access_store_buffer(GDExtensionObjectPtr p_instance, const uint8_t *p_src, uint64_t p_length) { + FileAccess *fa = (FileAccess *)p_instance; + fa->store_buffer(p_src, p_length); +} + +static uint64_t gdextension_file_access_get_buffer(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length) { + const FileAccess *fa = (FileAccess *)p_instance; + return fa->get_buffer(p_dst, p_length); +} + +static int64_t gdextension_worker_thread_pool_add_native_group_task(GDExtensionObjectPtr p_instance, void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, bool p_high_priority, GDExtensionConstStringPtr p_description) { + WorkerThreadPool *p = (WorkerThreadPool *)p_instance; + const String *description = (const String *)p_description; + return (int64_t)p->add_native_group_task(p_func, p_userdata, p_elements, p_tasks, p_high_priority, *description); +} + +static int64_t gdextension_worker_thread_pool_add_native_task(GDExtensionObjectPtr p_instance, void (*p_func)(void *), void *p_userdata, bool p_high_priority, GDExtensionConstStringPtr p_description) { + WorkerThreadPool *p = (WorkerThreadPool *)p_instance; + const String *description = (const String *)p_description; + return (int64_t)p->add_native_task(p_func, p_userdata, p_high_priority, *description); +} + /* Packed array functions */ static uint8_t *gdextension_packed_byte_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { @@ -1025,6 +1081,25 @@ void gdextension_setup_interface(GDExtensionInterface *p_interface) { gde_interface.string_to_wide_chars = gdextension_string_to_wide_chars; gde_interface.string_operator_index = gdextension_string_operator_index; gde_interface.string_operator_index_const = gdextension_string_operator_index_const; + gde_interface.string_operator_plus_eq_string = gdextension_string_operator_plus_eq_string; + gde_interface.string_operator_plus_eq_char = gdextension_string_operator_plus_eq_char; + gde_interface.string_operator_plus_eq_cstr = gdextension_string_operator_plus_eq_cstr; + gde_interface.string_operator_plus_eq_wcstr = gdextension_string_operator_plus_eq_wcstr; + gde_interface.string_operator_plus_eq_c32str = gdextension_string_operator_plus_eq_c32str; + + /* XMLParser extra utilities */ + + gde_interface.xml_parser_open_buffer = gdextension_xml_parser_open_buffer; + + /* FileAccess extra utilities */ + + gde_interface.file_access_store_buffer = gdextension_file_access_store_buffer; + gde_interface.file_access_get_buffer = gdextension_file_access_get_buffer; + + /* WorkerThreadPool extra utilities */ + + gde_interface.worker_thread_pool_add_native_group_task = gdextension_worker_thread_pool_add_native_group_task; + gde_interface.worker_thread_pool_add_native_task = gdextension_worker_thread_pool_add_native_task; /* Packed array functions */ diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 190298ee8a..a16eef2fcf 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -503,6 +503,26 @@ typedef struct { char32_t *(*string_operator_index)(GDExtensionStringPtr p_self, GDExtensionInt p_index); const char32_t *(*string_operator_index_const)(GDExtensionConstStringPtr p_self, GDExtensionInt p_index); + void (*string_operator_plus_eq_string)(GDExtensionStringPtr p_self, GDExtensionConstStringPtr p_b); + void (*string_operator_plus_eq_char)(GDExtensionStringPtr p_self, char32_t p_b); + void (*string_operator_plus_eq_cstr)(GDExtensionStringPtr p_self, const char *p_b); + void (*string_operator_plus_eq_wcstr)(GDExtensionStringPtr p_self, const wchar_t *p_b); + void (*string_operator_plus_eq_c32str)(GDExtensionStringPtr p_self, const char32_t *p_b); + + /* XMLParser extra utilities */ + + GDExtensionInt (*xml_parser_open_buffer)(GDExtensionObjectPtr p_instance, const uint8_t *p_buffer, size_t p_size); + + /* FileAccess extra utilities */ + + void (*file_access_store_buffer)(GDExtensionObjectPtr p_instance, const uint8_t *p_src, uint64_t p_length); + uint64_t (*file_access_get_buffer)(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length); + + /* WorkerThreadPool extra utilities */ + + int64_t (*worker_thread_pool_add_native_group_task)(GDExtensionObjectPtr p_instance, void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, bool p_high_priority, GDExtensionConstStringPtr p_description); + int64_t (*worker_thread_pool_add_native_task)(GDExtensionObjectPtr p_instance, void (*p_func)(void *), void *p_userdata, bool p_high_priority, GDExtensionConstStringPtr p_description); + /* Packed array functions */ uint8_t *(*packed_byte_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index 77d1bdcc5c..cacbcb28a4 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -292,7 +292,7 @@ real_t FileAccess::get_real() const { Variant FileAccess::get_var(bool p_allow_objects) const { uint32_t len = get_32(); - Vector<uint8_t> buff = _get_buffer(len); + Vector<uint8_t> buff = get_buffer(len); ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant()); const uint8_t *r = buff.ptr(); @@ -469,7 +469,7 @@ uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const { return i; } -Vector<uint8_t> FileAccess::_get_buffer(int64_t p_length) const { +Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const { Vector<uint8_t> data; ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0."); @@ -663,7 +663,7 @@ void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) { } } -void FileAccess::_store_buffer(const Vector<uint8_t> &p_buffer) { +void FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) { uint64_t len = p_buffer.size(); if (len == 0) { return; @@ -687,7 +687,7 @@ void FileAccess::store_var(const Variant &p_var, bool p_full_objects) { ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant."); store_32(len); - _store_buffer(buff); + store_buffer(buff); } Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) { @@ -829,7 +829,7 @@ void FileAccess::_bind_methods() { ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float); ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double); ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real); - ClassDB::bind_method(D_METHOD("get_buffer", "length"), &FileAccess::_get_buffer); + ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t>(FileAccess::*)(int64_t) const) & FileAccess::get_buffer); ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line); ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(",")); ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false)); @@ -847,7 +847,7 @@ void FileAccess::_bind_methods() { ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float); ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double); ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real); - ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &FileAccess::_store_buffer); + ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (void(FileAccess::*)(const Vector<uint8_t> &)) & FileAccess::store_buffer); ClassDB::bind_method(D_METHOD("store_line", "line"), &FileAccess::store_line); ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(",")); ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string); diff --git a/core/io/file_access.h b/core/io/file_access.h index 3116ed521f..3e51ba11ed 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -127,7 +127,7 @@ public: Variant get_var(bool p_allow_objects = false) const; virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes - Vector<uint8_t> _get_buffer(int64_t p_length) const; + Vector<uint8_t> get_buffer(int64_t p_length) const; virtual String get_line() const; virtual String get_token() const; virtual Vector<String> get_csv_line(const String &p_delim = ",") const; @@ -162,7 +162,7 @@ public: virtual String get_pascal_string(); virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes - void _store_buffer(const Vector<uint8_t> &p_buffer); + void store_buffer(const Vector<uint8_t> &p_buffer); void store_var(const Variant &p_var, bool p_full_objects = false); diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 09836419be..5c0a017bfc 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -354,10 +354,10 @@ void XMLParser::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node_offset"), &XMLParser::get_node_offset); ClassDB::bind_method(D_METHOD("get_attribute_count"), &XMLParser::get_attribute_count); ClassDB::bind_method(D_METHOD("get_attribute_name", "idx"), &XMLParser::get_attribute_name); - ClassDB::bind_method(D_METHOD("get_attribute_value", "idx"), (String(XMLParser::*)(int) const) & XMLParser::get_attribute_value); + ClassDB::bind_method(D_METHOD("get_attribute_value", "idx"), &XMLParser::get_attribute_value); ClassDB::bind_method(D_METHOD("has_attribute", "name"), &XMLParser::has_attribute); - ClassDB::bind_method(D_METHOD("get_named_attribute_value", "name"), (String(XMLParser::*)(const String &) const) & XMLParser::get_attribute_value); - ClassDB::bind_method(D_METHOD("get_named_attribute_value_safe", "name"), &XMLParser::get_attribute_value_safe); + ClassDB::bind_method(D_METHOD("get_named_attribute_value", "name"), &XMLParser::get_named_attribute_value); + ClassDB::bind_method(D_METHOD("get_named_attribute_value_safe", "name"), &XMLParser::get_named_attribute_value_safe); ClassDB::bind_method(D_METHOD("is_empty"), &XMLParser::is_empty); ClassDB::bind_method(D_METHOD("get_current_line"), &XMLParser::get_current_line); ClassDB::bind_method(D_METHOD("skip_section"), &XMLParser::skip_section); @@ -422,7 +422,7 @@ bool XMLParser::has_attribute(const String &p_name) const { return false; } -String XMLParser::get_attribute_value(const String &p_name) const { +String XMLParser::get_named_attribute_value(const String &p_name) const { int idx = -1; for (int i = 0; i < attributes.size(); i++) { if (attributes[i].name == p_name) { @@ -436,7 +436,7 @@ String XMLParser::get_attribute_value(const String &p_name) const { return attributes[idx].value; } -String XMLParser::get_attribute_value_safe(const String &p_name) const { +String XMLParser::get_named_attribute_value_safe(const String &p_name) const { int idx = -1; for (int i = 0; i < attributes.size(); i++) { if (attributes[i].name == p_name) { diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h index b4ae5c93b6..b96478c7a5 100644 --- a/core/io/xml_parser.h +++ b/core/io/xml_parser.h @@ -109,8 +109,8 @@ public: String get_attribute_name(int p_idx) const; String get_attribute_value(int p_idx) const; bool has_attribute(const String &p_name) const; - String get_attribute_value(const String &p_name) const; - String get_attribute_value_safe(const String &p_name) const; // do not print error if doesn't exist + String get_named_attribute_value(const String &p_name) const; + String get_named_attribute_value_safe(const String &p_name) const; // do not print error if doesn't exist bool is_empty() const; int get_current_line() const; diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index c9cfbdd4cb..66ef418e42 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -263,6 +263,15 @@ void ScriptServer::remove_global_class(const StringName &p_class) { global_classes.erase(p_class); } +void ScriptServer::remove_global_class_by_path(const String &p_path) { + for (const KeyValue<StringName, GlobalScriptClass> &kv : global_classes) { + if (kv.value.path == p_path) { + global_classes.erase(kv.key); + return; + } + } +} + bool ScriptServer::is_global_class(const StringName &p_class) { return global_classes.has(p_class); } diff --git a/core/object/script_language.h b/core/object/script_language.h index ff678bcd25..02d1880dc2 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -80,6 +80,7 @@ public: static void global_classes_clear(); static void add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path); static void remove_global_class(const StringName &p_class); + static void remove_global_class_by_path(const String &p_path); static bool is_global_class(const StringName &p_class); static StringName get_global_class_language(const StringName &p_class); static String get_global_class_path(const String &p_class); diff --git a/doc/classes/BackBufferCopy.xml b/doc/classes/BackBufferCopy.xml index b2c5a1756f..be4a649b50 100644 --- a/doc/classes/BackBufferCopy.xml +++ b/doc/classes/BackBufferCopy.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="BackBufferCopy" inherits="Node2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Copies a region of the screen (or the whole screen) to a buffer so it can be accessed in your shader scripts through the [code]texture(SCREEN_TEXTURE, ...)[/code] function. + Copies a region of the screen (or the whole screen) to a buffer so it can be accessed in your shader scripts using the screen texture (i.e. a uniform sampler with ``hint_screen_texture``). </brief_description> <description> - Node for back-buffering the currently-displayed screen. The region defined in the [BackBufferCopy] node is buffered with the content of the screen it covers, or the entire screen according to the copy mode set. Use the [code]texture(SCREEN_TEXTURE, ...)[/code] function in your shader scripts to access the buffer. + Node for back-buffering the currently-displayed screen. The region defined in the [BackBufferCopy] node is buffered with the content of the screen it covers, or the entire screen according to the copy mode set. Use the screen texture in your shader scripts to access the buffer. [b]Note:[/b] Since this node inherits from [Node2D] (and not [Control]), anchors and margins won't apply to child [Control]-derived nodes. This can be problematic when resizing the window. To avoid this, add [Control]-derived nodes as [i]siblings[/i] to the [BackBufferCopy] node instead of adding them as children. </description> <tutorials> diff --git a/doc/classes/CanvasGroup.xml b/doc/classes/CanvasGroup.xml index 37827defec..6eeff8fef3 100644 --- a/doc/classes/CanvasGroup.xml +++ b/doc/classes/CanvasGroup.xml @@ -9,8 +9,10 @@ [codeblock] shader_type canvas_item; + uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; + void fragment() { - vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0); if (c.a > 0.0001) { c.rgb /= c.a; diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml index cddf3662aa..5f33c68a7d 100644 --- a/doc/classes/EditorFileSystem.xml +++ b/doc/classes/EditorFileSystem.xml @@ -71,12 +71,6 @@ This will not import the file. To reimport, call [method reimport_files] or [method scan] methods. </description> </method> - <method name="update_script_classes"> - <return type="void" /> - <description> - Scans the script files and updates the list of custom class names. - </description> - </method> </methods> <signals> <signal name="filesystem_changed"> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 2124a97751..370be8e9f3 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -467,6 +467,14 @@ See [method add_inspector_plugin] for an example of how to register a plugin. </description> </method> + <method name="add_resource_conversion_plugin"> + <return type="void" /> + <param index="0" name="plugin" type="EditorResourceConversionPlugin" /> + <description> + Registers a new [EditorResourceConversionPlugin]. Resource conversion plugins are used to add custom resource converters to the editor inspector. + See [EditorResourceConversionPlugin] for an example of how to create a resource conversion plugin. + </description> + </method> <method name="add_scene_format_importer_plugin"> <return type="void" /> <param index="0" name="scene_format_importer" type="EditorSceneFormatImporter" /> @@ -632,6 +640,13 @@ Removes a gizmo plugin registered by [method add_node_3d_gizmo_plugin]. </description> </method> + <method name="remove_resource_conversion_plugin"> + <return type="void" /> + <param index="0" name="plugin" type="EditorResourceConversionPlugin" /> + <description> + Removes a resource conversion plugin registered by [method add_resource_conversion_plugin]. + </description> + </method> <method name="remove_scene_format_importer_plugin"> <return type="void" /> <param index="0" name="scene_format_importer" type="EditorSceneFormatImporter" /> diff --git a/doc/classes/EditorResourceConversionPlugin.xml b/doc/classes/EditorResourceConversionPlugin.xml index c40bb1d91e..6bdfbbe40c 100644 --- a/doc/classes/EditorResourceConversionPlugin.xml +++ b/doc/classes/EditorResourceConversionPlugin.xml @@ -1,8 +1,28 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="EditorResourceConversionPlugin" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Plugin for adding custom converters from one resource format to another in the editor resource picker context menu; for example, converting a [StandardMaterial3D] to a [ShaderMaterial]. </brief_description> <description> + [EditorResourceConversionPlugin] is invoked when the context menu is brought up for a resource in the editor inspector. Relevant conversion plugins will appear as menu options to convert the given resource to a target type. + Below shows an example of a basic plugin that will convert an [ImageTexture] to a [PortableCompressedTexture2D]. + [codeblocks] + [gdscript] + extends EditorResourceConversionPlugin + + func _handles(resource : Resource): + return resource is ImageTexture + + func _converts_to(): + return "PortableCompressedTexture2D" + + func _convert(itex : Resource): + var ptex = PortableCompressedTexture2D.new() + ptex.create_from_image(itex.get_image(), PortableCompressedTexture2D.COMPRESSION_MODE_LOSSLESS) + return ptex + [/gdscript] + [/codeblocks] + To use an [EditorResourceConversionPlugin], register it using the [method EditorPlugin.add_resource_conversion_plugin] method first. </description> <tutorials> </tutorials> @@ -11,17 +31,20 @@ <return type="Resource" /> <param index="0" name="resource" type="Resource" /> <description> + Takes an input [Resource] and converts it to the type given in [method _converts_to]. The returned [Resource] is the result of the conversion, and the input [Resource] remains unchanged. </description> </method> <method name="_converts_to" qualifiers="virtual const"> <return type="String" /> <description> + Returns the class name of the target type of [Resource] that this plugin converts source resources to. </description> </method> <method name="_handles" qualifiers="virtual const"> <return type="bool" /> <param index="0" name="resource" type="Resource" /> <description> + Called to determine whether a particular [Resource] can be converted to the target resource type by this plugin. </description> </method> </methods> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 32281953b2..33170e6606 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -3336,7 +3336,7 @@ <param index="0" name="viewport" type="RID" /> <param index="1" name="enabled" type="bool" /> <description> - If [code]true[/code], render the contents of the viewport directly to screen. This allows a low-level optimization where you can skip drawing a viewport to the root viewport. While this optimization can result in a significant increase in speed (especially on older devices), it comes at a cost of usability. When this is enabled, you cannot read from the viewport or from the [code]SCREEN_TEXTURE[/code]. You also lose the benefit of certain window settings, such as the various stretch modes. Another consequence to be aware of is that in 2D the rendering happens in window coordinates, so if you have a viewport that is double the size of the window, and you set this, then only the portion that fits within the window will be drawn, no automatic scaling is possible, even if your game scene is significantly larger than the window size. + If [code]true[/code], render the contents of the viewport directly to screen. This allows a low-level optimization where you can skip drawing a viewport to the root viewport. While this optimization can result in a significant increase in speed (especially on older devices), it comes at a cost of usability. When this is enabled, you cannot read from the viewport or from the screen_texture. You also lose the benefit of certain window settings, such as the various stretch modes. Another consequence to be aware of is that in 2D the rendering happens in window coordinates, so if you have a viewport that is double the size of the window, and you set this, then only the portion that fits within the window will be drawn, no automatic scaling is possible, even if your game scene is significantly larger than the window size. </description> </method> <method name="viewport_set_scaling_3d_mode"> diff --git a/doc/classes/VisualShaderNodeTexture.xml b/doc/classes/VisualShaderNodeTexture.xml index 72a7fadf1a..38fa98b21e 100644 --- a/doc/classes/VisualShaderNodeTexture.xml +++ b/doc/classes/VisualShaderNodeTexture.xml @@ -33,12 +33,18 @@ Use the texture from this shader's normal map built-in. </constant> <constant name="SOURCE_DEPTH" value="4" enum="Source"> - Use the depth texture available for this shader. + Use the depth texture captured during the depth prepass. Only available when the depth prepass is used (i.e. in spatial shaders and in the forward_plus or gl_compatibility renderers). </constant> <constant name="SOURCE_PORT" value="5" enum="Source"> Use the texture provided in the input port for this function. </constant> - <constant name="SOURCE_MAX" value="6" enum="Source"> + <constant name="SOURCE_3D_NORMAL" value="6" enum="Source"> + Use the normal buffer captured during the depth prepass. Only available when the normal-roughness buffer is available (i.e. in spatial shaders and in the forward_plus renderer). + </constant> + <constant name="SOURCE_ROUGHNESS" value="7" enum="Source"> + Use the roughness buffer captured during the depth prepass. Only available when the normal-roughness buffer is available (i.e. in spatial shaders and in the forward_plus renderer). + </constant> + <constant name="SOURCE_MAX" value="8" enum="Source"> Represents the size of the [enum Source] enum. </constant> <constant name="TYPE_DATA" value="0" enum="TextureType"> diff --git a/doc/classes/VisualShaderNodeTextureParameter.xml b/doc/classes/VisualShaderNodeTextureParameter.xml index 333226dc58..8a08bea659 100644 --- a/doc/classes/VisualShaderNodeTextureParameter.xml +++ b/doc/classes/VisualShaderNodeTextureParameter.xml @@ -18,6 +18,9 @@ <member name="texture_repeat" type="int" setter="set_texture_repeat" getter="get_texture_repeat" enum="VisualShaderNodeTextureParameter.TextureRepeat" default="0"> Sets the texture repeating mode. See [enum TextureRepeat] for options. </member> + <member name="texture_source" type="int" setter="set_texture_source" getter="get_texture_source" enum="VisualShaderNodeTextureParameter.TextureSource" default="0"> + Sets the texture source mode. Used for reading from the screen, depth, or normal_roughness texture. see [enum TextureSource] for options. + </member> <member name="texture_type" type="int" setter="set_texture_type" getter="get_texture_type" enum="VisualShaderNodeTextureParameter.TextureType" default="0"> Defines the type of data provided by the source texture. See [enum TextureType] for options. </member> @@ -88,5 +91,20 @@ <constant name="REPEAT_MAX" value="3" enum="TextureRepeat"> Represents the size of the [enum TextureRepeat] enum. </constant> + <constant name="SOURCE_NONE" value="0" enum="TextureSource"> + The texture source is not specified in the shader. + </constant> + <constant name="SOURCE_SCREEN" value="1" enum="TextureSource"> + The texture source is the screen texture which captures all opaque objects drawn this frame. + </constant> + <constant name="SOURCE_DEPTH" value="2" enum="TextureSource"> + The texture source is the depth texture from the depth prepass. + </constant> + <constant name="SOURCE_NORMAL_ROUGHNESS" value="3" enum="TextureSource"> + The texture source is the normal-roughness buffer from the depth prepass. + </constant> + <constant name="SOURCE_MAX" value="4" enum="TextureSource"> + Represents the size of the [enum TextureSource] enum. + </constant> </constants> </class> diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index a946a2ceb5..fb338b9849 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -2654,8 +2654,10 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() { shader_type canvas_item; +uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; + void fragment() { - vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0); if (c.a > 0.0001) { c.rgb /= c.a; @@ -2679,8 +2681,10 @@ void fragment() { shader_type canvas_item; +uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; + void fragment() { - vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0); COLOR.rgb = c.rgb; } )"); diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 8c53ab6529..1631c65385 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -277,7 +277,7 @@ flat in uvec4 varying_G; uniform sampler2D atlas_texture; //texunit:-2 uniform sampler2D shadow_atlas_texture; //texunit:-3 #endif // DISABLE_LIGHTING -uniform sampler2D screen_texture; //texunit:-4 +uniform sampler2D color_buffer; //texunit:-4 uniform sampler2D sdf_texture; //texunit:-5 uniform sampler2D normal_texture; //texunit:-6 uniform sampler2D specular_texture; //texunit:-7 diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 1b922fa726..951155e287 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -564,10 +564,10 @@ uniform highp samplerCubeShadow positional_shadow; // texunit:-4 #ifdef USE_MULTIVIEW uniform highp sampler2DArray depth_buffer; // texunit:-6 -uniform highp sampler2DArray screen_texture; // texunit:-5 +uniform highp sampler2DArray color_buffer; // texunit:-5 #else uniform highp sampler2D depth_buffer; // texunit:-6 -uniform highp sampler2D screen_texture; // texunit:-5 +uniform highp sampler2D color_buffer; // texunit:-5 #endif uniform highp mat4 world_transform; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 2d81771898..50e5c868d3 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1515,7 +1515,6 @@ MaterialStorage::MaterialStorage() { actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture"; actions.renames["SPECULAR_SHININESS"] = "specular_shininess"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "screen_texture"; actions.renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; actions.renames["POINT_COORD"] = "gl_PointCoord"; @@ -1536,7 +1535,6 @@ MaterialStorage::MaterialStorage() { actions.renames["screen_uv_to_sdf"] = "screen_uv_to_sdf"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; @@ -1617,9 +1615,6 @@ MaterialStorage::MaterialStorage() { actions.renames["POINT_COORD"] = "gl_PointCoord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; - //actions.renames["SCREEN_TEXTURE"] = "color_buffer"; //Not implemented in 3D yet. - //actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; // Not implemented in 3D yet. - //actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; // Not implemented in 3D yet actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; actions.renames["FOG"] = "fog"; @@ -1684,7 +1679,6 @@ MaterialStorage::MaterialStorage() { actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; @@ -2960,7 +2954,6 @@ void CanvasShaderData::set_code(const String &p_code) { actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_modei, BLEND_MODE_PMALPHA); actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_modei, BLEND_MODE_DISABLED); - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; actions.usage_flag_pointers["texture_sdf"] = &uses_sdf; actions.usage_flag_pointers["TIME"] = &uses_time; @@ -2974,6 +2967,7 @@ void CanvasShaderData::set_code(const String &p_code) { blend_mode = BlendMode(blend_modei); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; #if 0 print_line("**compiling shader:"); @@ -3309,9 +3303,6 @@ void SceneShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; - actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; actions.usage_flag_pointers["DISCARD"] = &uses_discard; actions.usage_flag_pointers["TIME"] = &uses_time; actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; @@ -3364,6 +3355,9 @@ void SceneShaderData::set_code(const String &p_code) { vertex_input_mask |= uses_bones << 9; vertex_input_mask |= uses_weights << 10; uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; + uses_depth_texture = gen_code.uses_depth_texture; + uses_normal_texture = gen_code.uses_normal_roughness_texture; uses_vertex_time = gen_code.uses_vertex_time; uses_fragment_time = gen_code.uses_fragment_time; diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 85adc312f2..c675060b2b 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -1021,15 +1021,15 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> & if (parser->get_node_name() == element) { DocData::MethodDoc method; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - method.name = parser->get_attribute_value("name"); + method.name = parser->get_named_attribute_value("name"); if (parser->has_attribute("qualifiers")) { - method.qualifiers = parser->get_attribute_value("qualifiers"); + method.qualifiers = parser->get_named_attribute_value("qualifiers"); } if (parser->has_attribute("is_deprecated")) { - method.is_deprecated = parser->get_attribute_value("is_deprecated").to_lower() == "true"; + method.is_deprecated = parser->get_named_attribute_value("is_deprecated").to_lower() == "true"; } if (parser->has_attribute("is_experimental")) { - method.is_experimental = parser->get_attribute_value("is_experimental").to_lower() == "true"; + method.is_experimental = parser->get_named_attribute_value("is_experimental").to_lower() == "true"; } while (parser->read() == OK) { @@ -1037,21 +1037,21 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> & String name = parser->get_node_name(); if (name == "return") { ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT); - method.return_type = parser->get_attribute_value("type"); + method.return_type = parser->get_named_attribute_value("type"); if (parser->has_attribute("enum")) { - method.return_enum = parser->get_attribute_value("enum"); + method.return_enum = parser->get_named_attribute_value("enum"); } } else if (name == "returns_error") { ERR_FAIL_COND_V(!parser->has_attribute("number"), ERR_FILE_CORRUPT); - method.errors_returned.push_back(parser->get_attribute_value("number").to_int()); + method.errors_returned.push_back(parser->get_named_attribute_value("number").to_int()); } else if (name == "param") { DocData::ArgumentDoc argument; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - argument.name = parser->get_attribute_value("name"); + argument.name = parser->get_named_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT); - argument.type = parser->get_attribute_value("type"); + argument.type = parser->get_named_attribute_value("type"); if (parser->has_attribute("enum")) { - argument.enumeration = parser->get_attribute_value("enum"); + argument.enumeration = parser->get_named_attribute_value("enum"); } method.arguments.push_back(argument); @@ -1153,21 +1153,21 @@ Error DocTools::_load(Ref<XMLParser> parser) { ERR_FAIL_COND_V(parser->get_node_name() != "class", ERR_FILE_CORRUPT); ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - String name = parser->get_attribute_value("name"); + String name = parser->get_named_attribute_value("name"); class_list[name] = DocData::ClassDoc(); DocData::ClassDoc &c = class_list[name]; c.name = name; if (parser->has_attribute("inherits")) { - c.inherits = parser->get_attribute_value("inherits"); + c.inherits = parser->get_named_attribute_value("inherits"); } if (parser->has_attribute("is_deprecated")) { - c.is_deprecated = parser->get_attribute_value("is_deprecated").to_lower() == "true"; + c.is_deprecated = parser->get_named_attribute_value("is_deprecated").to_lower() == "true"; } if (parser->has_attribute("is_experimental")) { - c.is_experimental = parser->get_attribute_value("is_experimental").to_lower() == "true"; + c.is_experimental = parser->get_named_attribute_value("is_experimental").to_lower() == "true"; } while (parser->read() == OK) { @@ -1193,7 +1193,7 @@ Error DocTools::_load(Ref<XMLParser> parser) { if (name3 == "link") { DocData::TutorialDoc tutorial; if (parser->has_attribute("title")) { - tutorial.title = parser->get_attribute_value("title"); + tutorial.title = parser->get_named_attribute_value("title"); } parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) { @@ -1231,23 +1231,23 @@ Error DocTools::_load(Ref<XMLParser> parser) { DocData::PropertyDoc prop2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - prop2.name = parser->get_attribute_value("name"); + prop2.name = parser->get_named_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT); - prop2.type = parser->get_attribute_value("type"); + prop2.type = parser->get_named_attribute_value("type"); if (parser->has_attribute("setter")) { - prop2.setter = parser->get_attribute_value("setter"); + prop2.setter = parser->get_named_attribute_value("setter"); } if (parser->has_attribute("getter")) { - prop2.getter = parser->get_attribute_value("getter"); + prop2.getter = parser->get_named_attribute_value("getter"); } if (parser->has_attribute("enum")) { - prop2.enumeration = parser->get_attribute_value("enum"); + prop2.enumeration = parser->get_named_attribute_value("enum"); } if (parser->has_attribute("is_deprecated")) { - prop2.is_deprecated = parser->get_attribute_value("is_deprecated").to_lower() == "true"; + prop2.is_deprecated = parser->get_named_attribute_value("is_deprecated").to_lower() == "true"; } if (parser->has_attribute("is_experimental")) { - prop2.is_experimental = parser->get_attribute_value("is_experimental").to_lower() == "true"; + prop2.is_experimental = parser->get_named_attribute_value("is_experimental").to_lower() == "true"; } if (!parser->is_empty()) { parser->read(); @@ -1274,11 +1274,11 @@ Error DocTools::_load(Ref<XMLParser> parser) { DocData::ThemeItemDoc prop2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - prop2.name = parser->get_attribute_value("name"); + prop2.name = parser->get_named_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT); - prop2.type = parser->get_attribute_value("type"); + prop2.type = parser->get_named_attribute_value("type"); ERR_FAIL_COND_V(!parser->has_attribute("data_type"), ERR_FILE_CORRUPT); - prop2.data_type = parser->get_attribute_value("data_type"); + prop2.data_type = parser->get_named_attribute_value("data_type"); if (!parser->is_empty()) { parser->read(); if (parser->get_node_type() == XMLParser::NODE_TEXT) { @@ -1303,21 +1303,21 @@ Error DocTools::_load(Ref<XMLParser> parser) { if (name3 == "constant") { DocData::ConstantDoc constant2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); - constant2.name = parser->get_attribute_value("name"); + constant2.name = parser->get_named_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("value"), ERR_FILE_CORRUPT); - constant2.value = parser->get_attribute_value("value"); + constant2.value = parser->get_named_attribute_value("value"); constant2.is_value_valid = true; if (parser->has_attribute("enum")) { - constant2.enumeration = parser->get_attribute_value("enum"); + constant2.enumeration = parser->get_named_attribute_value("enum"); } if (parser->has_attribute("is_bitfield")) { - constant2.is_bitfield = parser->get_attribute_value("is_bitfield").to_lower() == "true"; + constant2.is_bitfield = parser->get_named_attribute_value("is_bitfield").to_lower() == "true"; } if (parser->has_attribute("is_deprecated")) { - constant2.is_deprecated = parser->get_attribute_value("is_deprecated").to_lower() == "true"; + constant2.is_deprecated = parser->get_named_attribute_value("is_deprecated").to_lower() == "true"; } if (parser->has_attribute("is_experimental")) { - constant2.is_experimental = parser->get_attribute_value("is_experimental").to_lower() == "true"; + constant2.is_experimental = parser->get_named_attribute_value("is_experimental").to_lower() == "true"; } if (!parser->is_empty()) { parser->read(); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 9c056ffdd9..63008ec65c 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -602,10 +602,19 @@ bool EditorFileSystem::_update_scan_actions() { fs_changed = true; + if (ClassDB::is_parent_class(ia.new_file->type, SNAME("Script"))) { + _queue_update_script_class(ia.dir->get_file_path(idx)); + } + } break; case ItemAction::ACTION_FILE_REMOVE: { int idx = ia.dir->find_file_index(ia.file); ERR_CONTINUE(idx == -1); + + if (ClassDB::is_parent_class(ia.dir->files[idx]->type, SNAME("Script"))) { + _queue_update_script_class(ia.dir->get_file_path(idx)); + } + _delete_internal_files(ia.dir->files[idx]->file); memdelete(ia.dir->files[idx]); ia.dir->files.remove_at(idx); @@ -640,6 +649,10 @@ bool EditorFileSystem::_update_scan_actions() { ERR_CONTINUE(idx == -1); String full_path = ia.dir->get_file_path(idx); + if (ClassDB::is_parent_class(ia.dir->files[idx]->type, SNAME("Script"))) { + _queue_update_script_class(full_path); + } + reloads.push_back(full_path); } break; @@ -710,7 +723,6 @@ void EditorFileSystem::scan() { scanning = false; emit_signal(SNAME("filesystem_changed")); emit_signal(SNAME("sources_changed"), sources_changed.size() > 0); - _queue_update_script_classes(); first_scan = false; } else { ERR_FAIL_COND(thread.is_started()); @@ -922,20 +934,6 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc } } - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptLanguage *lang = ScriptServer::get_language(i); - if (lang->supports_documentation() && fi->type == lang->get_type()) { - Ref<Script> scr = ResourceLoader::load(path); - if (scr == nullptr) { - continue; - } - Vector<DocData::ClassDoc> docs = scr->get_documentation(); - for (int j = 0; j < docs.size(); j++) { - EditorHelp::get_doc_data()->add_doc(docs[j]); - } - } - } - p_dir->files.push_back(fi); p_progress.update(idx, total); } @@ -1229,7 +1227,6 @@ void EditorFileSystem::_notification(int p_what) { emit_signal(SNAME("filesystem_changed")); } emit_signal(SNAME("sources_changed"), sources_changed.size() > 0); - _queue_update_script_classes(); first_scan = false; } } else if (!scanning && thread.is_started()) { @@ -1244,7 +1241,6 @@ void EditorFileSystem::_notification(int p_what) { _update_scan_actions(); emit_signal(SNAME("filesystem_changed")); emit_signal(SNAME("sources_changed"), sources_changed.size() > 0); - _queue_update_script_classes(); first_scan = false; } @@ -1491,39 +1487,50 @@ String EditorFileSystem::_get_global_script_class(const String &p_type, const St return String(); } -void EditorFileSystem::_scan_script_classes(EditorFileSystemDirectory *p_dir) { - int filecount = p_dir->files.size(); - const EditorFileSystemDirectory::FileInfo *const *files = p_dir->files.ptr(); - for (int i = 0; i < filecount; i++) { - if (files[i]->script_class_name.is_empty()) { +void EditorFileSystem::_update_script_classes() { + update_script_mutex.lock(); + + for (const String &path : update_script_paths) { + ScriptServer::remove_global_class_by_path(path); // First remove, just in case it changed + + int index = -1; + EditorFileSystemDirectory *efd = find_file(path, &index); + + if (!efd || index < 0) { + // The file was removed continue; } - String lang; - for (int j = 0; j < ScriptServer::get_language_count(); j++) { - if (ScriptServer::get_language(j)->handles_global_class_type(files[i]->type)) { - lang = ScriptServer::get_language(j)->get_name(); + if (!efd->files[index]->script_class_name.is_empty()) { + String lang; + for (int j = 0; j < ScriptServer::get_language_count(); j++) { + if (ScriptServer::get_language(j)->handles_global_class_type(efd->files[index]->type)) { + lang = ScriptServer::get_language(j)->get_name(); + } } + + ScriptServer::add_global_class(efd->files[index]->script_class_name, efd->files[index]->script_class_extends, lang, path); + EditorNode::get_editor_data().script_class_set_icon_path(efd->files[index]->script_class_name, efd->files[index]->script_class_icon_path); + EditorNode::get_editor_data().script_class_set_name(efd->files[index]->file, efd->files[index]->script_class_name); } - ScriptServer::add_global_class(files[i]->script_class_name, files[i]->script_class_extends, lang, p_dir->get_file_path(i)); - EditorNode::get_editor_data().script_class_set_icon_path(files[i]->script_class_name, files[i]->script_class_icon_path); - EditorNode::get_editor_data().script_class_set_name(files[i]->file, files[i]->script_class_name); - } - for (int i = 0; i < p_dir->get_subdir_count(); i++) { - _scan_script_classes(p_dir->get_subdir(i)); - } -} -void EditorFileSystem::update_script_classes() { - if (!update_script_classes_queued.is_set()) { - return; + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptLanguage *lang = ScriptServer::get_language(i); + if (lang->supports_documentation() && efd->files[index]->type == lang->get_type()) { + Ref<Script> scr = ResourceLoader::load(path); + if (scr.is_null()) { + continue; + } + Vector<DocData::ClassDoc> docs = scr->get_documentation(); + for (int j = 0; j < docs.size(); j++) { + EditorHelp::get_doc_data()->add_doc(docs[j]); + } + } + } } - update_script_classes_queued.clear(); - ScriptServer::global_classes_clear(); - if (get_filesystem()) { - _scan_script_classes(get_filesystem()); - } + update_script_paths.clear(); + update_script_mutex.unlock(); ScriptServer::save_global_classes(); EditorNode::get_editor_data().script_class_save_icon_paths(); @@ -1538,13 +1545,14 @@ void EditorFileSystem::update_script_classes() { ResourceSaver::add_custom_savers(); } -void EditorFileSystem::_queue_update_script_classes() { - if (update_script_classes_queued.is_set()) { - return; +void EditorFileSystem::_queue_update_script_class(const String &p_path) { + update_script_mutex.lock(); + bool call_update = update_script_paths.is_empty(); + update_script_paths.insert(p_path); + update_script_mutex.unlock(); + if (call_update) { + call_deferred(SNAME("_update_script_classes")); } - - update_script_classes_queued.set(); - call_deferred(SNAME("update_script_classes")); } void EditorFileSystem::update_file(const String &p_file) { @@ -1566,12 +1574,15 @@ void EditorFileSystem::update_file(const String &p_file) { ResourceUID::get_singleton()->remove_id(fs->files[cpos]->uid); } } + if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) { + _queue_update_script_class(p_file); + } + memdelete(fs->files[cpos]); fs->files.remove_at(cpos); } call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later - _queue_update_script_classes(); return; } @@ -1631,8 +1642,11 @@ void EditorFileSystem::update_file(const String &p_file) { // Update preview EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); + if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) { + _queue_update_script_class(p_file); + } + call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later - _queue_update_script_classes(); } HashSet<String> EditorFileSystem::get_valid_extensions() const { @@ -2414,7 +2428,7 @@ void EditorFileSystem::_bind_methods() { ClassDB::bind_method(D_METHOD("update_file", "path"), &EditorFileSystem::update_file); ClassDB::bind_method(D_METHOD("get_filesystem_path", "path"), &EditorFileSystem::get_filesystem_path); ClassDB::bind_method(D_METHOD("get_file_type", "path"), &EditorFileSystem::get_file_type); - ClassDB::bind_method(D_METHOD("update_script_classes"), &EditorFileSystem::update_script_classes); + ClassDB::bind_method(D_METHOD("_update_script_classes"), &EditorFileSystem::_update_script_classes); ClassDB::bind_method(D_METHOD("reimport_files", "files"), &EditorFileSystem::reimport_files); ADD_SIGNAL(MethodInfo("filesystem_changed")); @@ -2474,7 +2488,6 @@ EditorFileSystem::EditorFileSystem() { using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT"); scan_total = 0; - update_script_classes_queued.clear(); MessageQueue::get_singleton()->push_callable(callable_mp(ResourceUID::get_singleton(), &ResourceUID::clear)); // Will be updated on scan. ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path); } diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 2985134093..1a0c8e2f78 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -257,9 +257,10 @@ class EditorFileSystem : public Node { } }; - void _scan_script_classes(EditorFileSystemDirectory *p_dir); - SafeFlag update_script_classes_queued; - void _queue_update_script_classes(); + Mutex update_script_mutex; + HashSet<String> update_script_paths; + void _queue_update_script_class(const String &p_path); + void _update_script_classes(); String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const; @@ -312,8 +313,6 @@ public: void reimport_file_with_custom_parameters(const String &p_file, const String &p_importer, const HashMap<StringName, Variant> &p_custom_params); - void update_script_classes(); - bool is_group_file(const String &p_path) const; void move_group_file(const String &p_path, const String &p_new_path); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index ec866ad999..d508638acd 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -45,6 +45,7 @@ #include "editor/inspector_dock.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/editor_debugger_plugin.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/project_settings_editor.h" @@ -856,6 +857,14 @@ void EditorPlugin::remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plu EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_plugin); } +void EditorPlugin::add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin) { + EditorNode::get_singleton()->add_resource_conversion_plugin(p_plugin); +} + +void EditorPlugin::remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin) { + EditorNode::get_singleton()->remove_resource_conversion_plugin(p_plugin); +} + void EditorPlugin::_editor_project_settings_changed() { emit_signal(SNAME("project_settings_changed")); } @@ -911,6 +920,8 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_node_3d_gizmo_plugin", "plugin"), &EditorPlugin::remove_node_3d_gizmo_plugin); ClassDB::bind_method(D_METHOD("add_inspector_plugin", "plugin"), &EditorPlugin::add_inspector_plugin); ClassDB::bind_method(D_METHOD("remove_inspector_plugin", "plugin"), &EditorPlugin::remove_inspector_plugin); + ClassDB::bind_method(D_METHOD("add_resource_conversion_plugin", "plugin"), &EditorPlugin::add_resource_conversion_plugin); + ClassDB::bind_method(D_METHOD("remove_resource_conversion_plugin", "plugin"), &EditorPlugin::remove_resource_conversion_plugin); ClassDB::bind_method(D_METHOD("set_input_event_forwarding_always_enabled"), &EditorPlugin::set_input_event_forwarding_always_enabled); ClassDB::bind_method(D_METHOD("set_force_draw_over_forwarding_enabled"), &EditorPlugin::set_force_draw_over_forwarding_enabled); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 21eb4b89ef..b79d2de035 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -48,6 +48,7 @@ class EditorInspector; class EditorInspectorPlugin; class EditorNode3DGizmoPlugin; class EditorPaths; +class EditorResourceConversionPlugin; class EditorResourcePreview; class EditorSceneFormatImporter; class EditorScenePostImportPlugin; @@ -307,6 +308,9 @@ public: void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); + void add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin); + void remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin); + void enable_plugin(); void disable_plugin(); diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index fcd706627d..a8d746fde6 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -262,7 +262,7 @@ void Collada::_parse_asset(XMLParser &parser) { COLLADA_PRINT("up axis: " + parser.get_node_data()); } else if (name == "unit") { - state.unit_scale = parser.get_attribute_value("meter").to_float(); + state.unit_scale = parser.get_named_attribute_value("meter").to_float(); COLLADA_PRINT("unit scale: " + rtos(state.unit_scale)); } @@ -273,7 +273,7 @@ void Collada::_parse_asset(XMLParser &parser) { } void Collada::_parse_image(XMLParser &parser) { - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); if (!(state.import_flags & IMPORT_FLAG_SCENE)) { if (!parser.is_empty()) { @@ -286,7 +286,7 @@ void Collada::_parse_image(XMLParser &parser) { if (state.version < State::Version(1, 4, 0)) { /* <1.4 */ - String path = parser.get_attribute_value("source").strip_edges(); + String path = parser.get_named_attribute_value("source").strip_edges(); if (!path.contains("://") && path.is_relative_path()) { // path is relative to file being loaded, so convert to a resource path image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().path_join(path.uri_decode())); @@ -337,9 +337,9 @@ void Collada::_parse_material(XMLParser &parser) { Material material; - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); if (parser.has_attribute("name")) { - material.name = parser.get_attribute_value("name"); + material.name = parser.get_named_attribute_value("name"); } if (state.version < State::Version(1, 4, 0)) { @@ -348,7 +348,7 @@ void Collada::_parse_material(XMLParser &parser) { } else { while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT && parser.get_node_name() == "instance_effect") { - material.instance_effect = _uri_to_id(parser.get_attribute_value("url")); + material.instance_effect = _uri_to_id(parser.get_named_attribute_value("url")); } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "material") { break; //end of <asset> } @@ -549,7 +549,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & _parse_effect_material(parser, effect, id); // try again } else if (parser.get_node_name() == "newparam") { - String name = parser.get_attribute_value("sid"); + String name = parser.get_named_attribute_value("sid"); Variant value = _parse_param(parser); effect.params[name] = value; COLLADA_PRINT("param: " + name + " value:" + String(value)); @@ -591,7 +591,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & } } else if (parser.get_node_name() == "texture") { - String sampler = parser.get_attribute_value("texture"); + String sampler = parser.get_named_attribute_value("texture"); if (!effect.params.has(sampler)) { ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data()); } else { @@ -609,7 +609,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & } else if (what == "emission") { effect.emission.texture = uri; } else if (what == "bump") { - if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") { + if (parser.has_attribute("bumptype") && parser.get_named_attribute_value("bumptype") != "NORMALMAP") { WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported."); } @@ -654,7 +654,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "texture") { - String sampler = parser.get_attribute_value("texture"); + String sampler = parser.get_named_attribute_value("texture"); if (!effect.params.has(sampler)) { ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data()); } else { @@ -665,7 +665,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String & } else { String uri = effect.params[surface]; - if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") { + if (parser.has_attribute("bumptype") && parser.get_named_attribute_value("bumptype") != "NORMALMAP") { WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported."); } @@ -703,11 +703,11 @@ void Collada::_parse_effect(XMLParser &parser) { return; } - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); Effect effect; if (parser.has_attribute("name")) { - effect.name = parser.get_attribute_value("name"); + effect.name = parser.get_named_attribute_value("name"); } _parse_effect_material(parser, effect, id); @@ -724,7 +724,7 @@ void Collada::_parse_camera(XMLParser &parser) { return; } - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); state.camera_data_map[id] = CameraData(); CameraData &camera = state.camera_data_map[id]; @@ -780,7 +780,7 @@ void Collada::_parse_light(XMLParser &parser) { return; } - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); state.light_data_map[id] = LightData(); LightData &light = state.light_data_map[id]; @@ -848,7 +848,7 @@ void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_nam CurveData &curvedata = state.curve_data_map[p_id]; curvedata.name = p_name; - String closed = parser.get_attribute_value_safe("closed").to_lower(); + String closed = parser.get_named_attribute_value_safe("closed").to_lower(); curvedata.closed = closed == "true" || closed == "1"; COLLADA_PRINT("curve name: " + p_name); @@ -865,7 +865,7 @@ void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_nam String section = parser.get_node_name(); if (section == "source") { - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); curvedata.sources[id] = CurveData::Source(); current_source = id; COLLADA_PRINT("source data: " + id); @@ -888,15 +888,15 @@ void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_nam } else if (section == "accessor") { // child of source (below a technique tag) if (curvedata.sources.has(current_source)) { - curvedata.sources[current_source].stride = parser.get_attribute_value("stride").to_int(); + curvedata.sources[current_source].stride = parser.get_named_attribute_value("stride").to_int(); COLLADA_PRINT("section: " + current_source + " stride " + itos(curvedata.sources[current_source].stride)); } } else if (section == "control_vertices") { while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "input") { - String semantic = parser.get_attribute_value("semantic"); - String source = _uri_to_id(parser.get_attribute_value("source")); + String semantic = parser.get_named_attribute_value("semantic"); + String source = _uri_to_id(parser.get_named_attribute_value("source")); curvedata.control_vertices[semantic] = source; @@ -945,7 +945,7 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name String section = parser.get_node_name(); if (section == "source") { - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); meshdata.sources[id] = MeshData::Source(); current_source = id; COLLADA_PRINT("source data: " + id); @@ -961,19 +961,19 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name } else if (section == "accessor") { // child of source (below a technique tag) if (meshdata.sources.has(current_source)) { - meshdata.sources[current_source].stride = parser.get_attribute_value("stride").to_int(); + meshdata.sources[current_source].stride = parser.get_named_attribute_value("stride").to_int(); COLLADA_PRINT("section: " + current_source + " stride " + itos(meshdata.sources[current_source].stride)); } } else if (section == "vertices") { MeshData::Vertices vert; - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); int last_ref = 0; while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "input") { - String semantic = parser.get_attribute_value("semantic"); - String source = _uri_to_id(parser.get_attribute_value("source")); + String semantic = parser.get_named_attribute_value("semantic"); + String source = _uri_to_id(parser.get_named_attribute_value("source")); if (semantic == "TEXCOORD") { semantic = "TEXCOORD" + itos(last_ref++); @@ -998,22 +998,22 @@ void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name MeshData::Primitives prim; if (parser.has_attribute("material")) { - prim.material = parser.get_attribute_value("material"); + prim.material = parser.get_named_attribute_value("material"); } - prim.count = parser.get_attribute_value("count").to_int(); + prim.count = parser.get_named_attribute_value("count").to_int(); prim.vertex_size = 0; int last_ref = 0; while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "input") { - String semantic = parser.get_attribute_value("semantic"); - String source = _uri_to_id(parser.get_attribute_value("source")); + String semantic = parser.get_named_attribute_value("semantic"); + String source = _uri_to_id(parser.get_named_attribute_value("source")); if (semantic == "TEXCOORD") { semantic = "TEXCOORD" + itos(last_ref++); } - int offset = parser.get_attribute_value("offset").to_int(); + int offset = parser.get_named_attribute_value("offset").to_int(); MeshData::Primitives::SourceRef sref; sref.source = source; @@ -1074,7 +1074,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { state.skin_controller_data_map[p_id] = SkinControllerData(); SkinControllerData &skindata = state.skin_controller_data_map[p_id]; - skindata.base = _uri_to_id(parser.get_attribute_value("source")); + skindata.base = _uri_to_id(parser.get_named_attribute_value("source")); String current_source; @@ -1091,7 +1091,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { COLLADA_PRINT("skeleton bind shape transform: " + skindata.bind_shape); } else if (section == "source") { - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); skindata.sources[id] = SkinControllerData::Source(); current_source = id; COLLADA_PRINT("source data: " + id); @@ -1125,7 +1125,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { if (skindata.sources.has(current_source)) { int stride = 1; if (parser.has_attribute("stride")) { - stride = parser.get_attribute_value("stride").to_int(); + stride = parser.get_named_attribute_value("stride").to_int(); } skindata.sources[current_source].stride = stride; @@ -1138,8 +1138,8 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "input") { - String semantic = parser.get_attribute_value("semantic"); - String source = _uri_to_id(parser.get_attribute_value("source")); + String semantic = parser.get_named_attribute_value("semantic"); + String source = _uri_to_id(parser.get_named_attribute_value("source")); joint.sources[semantic] = source; @@ -1155,15 +1155,15 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { } else if (section == "vertex_weights") { SkinControllerData::Weights weights; - weights.count = parser.get_attribute_value("count").to_int(); + weights.count = parser.get_named_attribute_value("count").to_int(); while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "input") { - String semantic = parser.get_attribute_value("semantic"); - String source = _uri_to_id(parser.get_attribute_value("source")); + String semantic = parser.get_named_attribute_value("semantic"); + String source = _uri_to_id(parser.get_named_attribute_value("source")); - int offset = parser.get_attribute_value("offset").to_int(); + int offset = parser.get_named_attribute_value("offset").to_int(); SkinControllerData::Weights::SourceRef sref; sref.source = source; @@ -1228,8 +1228,8 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) { state.morph_controller_data_map[p_id] = MorphControllerData(); MorphControllerData &morphdata = state.morph_controller_data_map[p_id]; - morphdata.mesh = _uri_to_id(parser.get_attribute_value("source")); - morphdata.mode = parser.get_attribute_value("method"); + morphdata.mesh = _uri_to_id(parser.get_named_attribute_value("source")); + morphdata.mode = parser.get_named_attribute_value("method"); String current_source; while (parser.read() == OK) { @@ -1237,7 +1237,7 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) { String section = parser.get_node_name(); if (section == "source") { - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); morphdata.sources[id] = MorphControllerData::Source(); current_source = id; COLLADA_PRINT("source data: " + id); @@ -1261,7 +1261,7 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) { if (morphdata.sources.has(current_source)) { int stride = 1; if (parser.has_attribute("stride")) { - stride = parser.get_attribute_value("stride").to_int(); + stride = parser.get_named_attribute_value("stride").to_int(); } morphdata.sources[current_source].stride = stride; @@ -1272,8 +1272,8 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) { while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "input") { - String semantic = parser.get_attribute_value("semantic"); - String source = _uri_to_id(parser.get_attribute_value("source")); + String semantic = parser.get_named_attribute_value("semantic"); + String source = _uri_to_id(parser.get_named_attribute_value("source")); morphdata.targets[semantic] = source; @@ -1295,7 +1295,7 @@ void Collada::_parse_morph_controller(XMLParser &parser, String p_id) { } void Collada::_parse_controller(XMLParser &parser) { - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); if (parser.is_empty()) { return; @@ -1320,7 +1320,7 @@ Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) { String type = parser.get_node_name(); NodeGeometry *geom = memnew(NodeGeometry); geom->controller = type == "instance_controller"; - geom->source = _uri_to_id(parser.get_attribute_value_safe("url")); + geom->source = _uri_to_id(parser.get_named_attribute_value_safe("url")); if (parser.is_empty()) { //nothing else to parse... return geom; @@ -1329,8 +1329,8 @@ Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) { while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "instance_material") { - String symbol = parser.get_attribute_value("symbol"); - String target = _uri_to_id(parser.get_attribute_value("target")); + String symbol = parser.get_named_attribute_value("symbol"); + String target = _uri_to_id(parser.get_named_attribute_value("target")); NodeGeometry::Material mat; mat.target = target; @@ -1370,7 +1370,7 @@ Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) { Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &parser) { NodeCamera *cam = memnew(NodeCamera); - cam->camera = _uri_to_id(parser.get_attribute_value_safe("url")); + cam->camera = _uri_to_id(parser.get_named_attribute_value_safe("url")); if (state.up_axis == Vector3::AXIS_Z) { //collada weirdness cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5); @@ -1391,7 +1391,7 @@ Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &parser) { Collada::Node *Collada::_parse_visual_instance_light(XMLParser &parser) { NodeLight *cam = memnew(NodeLight); - cam->light = _uri_to_id(parser.get_attribute_value_safe("url")); + cam->light = _uri_to_id(parser.get_named_attribute_value_safe("url")); if (state.up_axis == Vector3::AXIS_Z) { //collada weirdness cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5); @@ -1437,7 +1437,7 @@ Collada::Node *Collada::_parse_visual_node_instance_data(XMLParser &parser) { Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { String name; - String id = parser.get_attribute_value_safe("id"); + String id = parser.get_named_attribute_value_safe("id"); bool found_name = false; @@ -1455,25 +1455,25 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { Node *node = nullptr; - name = parser.has_attribute("name") ? parser.get_attribute_value_safe("name") : parser.get_attribute_value_safe("id"); + name = parser.has_attribute("name") ? parser.get_named_attribute_value_safe("name") : parser.get_named_attribute_value_safe("id"); if (name.is_empty()) { name = id; } else { found_name = true; } - if ((parser.has_attribute("type") && parser.get_attribute_value("type") == "JOINT") || state.idref_joints.has(name)) { + if ((parser.has_attribute("type") && parser.get_named_attribute_value("type") == "JOINT") || state.idref_joints.has(name)) { // handle a bone NodeJoint *joint = memnew(NodeJoint); if (parser.has_attribute("sid")) { //bones may not have sid - joint->sid = parser.get_attribute_value("sid"); + joint->sid = parser.get_named_attribute_value("sid"); //state.bone_map[joint->sid]=joint; } else if (state.idref_joints.has(name)) { joint->sid = name; //kind of a cheat but.. } else if (parser.has_attribute("name")) { - joint->sid = parser.get_attribute_value_safe("name"); + joint->sid = parser.get_named_attribute_value_safe("name"); } if (!joint->sid.is_empty()) { @@ -1490,7 +1490,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { if (section == "translate") { Node::XForm xf; if (parser.has_attribute("sid")) { - xf.id = parser.get_attribute_value("sid"); + xf.id = parser.get_named_attribute_value("sid"); } xf.op = Node::XForm::OP_TRANSLATE; @@ -1501,7 +1501,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { } else if (section == "rotate") { Node::XForm xf; if (parser.has_attribute("sid")) { - xf.id = parser.get_attribute_value("sid"); + xf.id = parser.get_named_attribute_value("sid"); } xf.op = Node::XForm::OP_ROTATE; @@ -1513,7 +1513,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { } else if (section == "scale") { Node::XForm xf; if (parser.has_attribute("sid")) { - xf.id = parser.get_attribute_value("sid"); + xf.id = parser.get_named_attribute_value("sid"); } xf.op = Node::XForm::OP_SCALE; @@ -1527,7 +1527,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { } else if (section == "matrix") { Node::XForm xf; if (parser.has_attribute("sid")) { - xf.id = parser.get_attribute_value("sid"); + xf.id = parser.get_named_attribute_value("sid"); } xf.op = Node::XForm::OP_MATRIX; @@ -1544,7 +1544,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { } else if (section == "visibility") { Node::XForm xf; if (parser.has_attribute("sid")) { - xf.id = parser.get_attribute_value("sid"); + xf.id = parser.get_named_attribute_value("sid"); } xf.op = Node::XForm::OP_VISIBILITY; @@ -1609,7 +1609,7 @@ Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { } void Collada::_parse_visual_scene(XMLParser &parser) { - String id = parser.get_attribute_value("id"); + String id = parser.get_named_attribute_value("id"); if (parser.is_empty()) { return; @@ -1619,7 +1619,7 @@ void Collada::_parse_visual_scene(XMLParser &parser) { VisualScene &vscene = state.visual_scene_map[id]; if (parser.has_attribute("name")) { - vscene.name = parser.get_attribute_value("name"); + vscene.name = parser.get_named_attribute_value("name"); } while (parser.read() == OK) { @@ -1656,7 +1656,7 @@ void Collada::_parse_animation(XMLParser &parser) { String id = ""; if (parser.has_attribute("id")) { - id = parser.get_attribute_value("id"); + id = parser.get_named_attribute_value("id"); } String current_source; @@ -1668,7 +1668,7 @@ void Collada::_parse_animation(XMLParser &parser) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { String name = parser.get_node_name(); if (name == "source") { - current_source = parser.get_attribute_value("id"); + current_source = parser.get_named_attribute_value("id"); source_param_names[current_source] = Vector<String>(); source_param_types[current_source] = Vector<String>(); @@ -1683,32 +1683,32 @@ void Collada::_parse_animation(XMLParser &parser) { } } else if (name == "accessor") { if (!current_source.is_empty() && parser.has_attribute("stride")) { - source_strides[current_source] = parser.get_attribute_value("stride").to_int(); + source_strides[current_source] = parser.get_named_attribute_value("stride").to_int(); } } else if (name == "sampler") { - current_sampler = parser.get_attribute_value("id"); + current_sampler = parser.get_named_attribute_value("id"); samplers[current_sampler] = HashMap<String, String>(); } else if (name == "param") { if (parser.has_attribute("name")) { - source_param_names[current_source].push_back(parser.get_attribute_value("name")); + source_param_names[current_source].push_back(parser.get_named_attribute_value("name")); } else { source_param_names[current_source].push_back(""); } if (parser.has_attribute("type")) { - source_param_types[current_source].push_back(parser.get_attribute_value("type")); + source_param_types[current_source].push_back(parser.get_named_attribute_value("type")); } else { source_param_types[current_source].push_back(""); } } else if (name == "input") { if (!current_sampler.is_empty()) { - samplers[current_sampler][parser.get_attribute_value("semantic")] = parser.get_attribute_value("source"); + samplers[current_sampler][parser.get_named_attribute_value("semantic")] = parser.get_named_attribute_value("source"); } } else if (name == "channel") { - channel_sources.push_back(parser.get_attribute_value("source")); - channel_targets.push_back(parser.get_attribute_value("target")); + channel_sources.push_back(parser.get_named_attribute_value("source")); + channel_targets.push_back(parser.get_named_attribute_value("target")); } } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation") { @@ -1857,22 +1857,22 @@ void Collada::_parse_animation_clip(XMLParser &parser) { AnimationClip clip; if (parser.has_attribute("name")) { - clip.name = parser.get_attribute_value("name"); + clip.name = parser.get_named_attribute_value("name"); } else if (parser.has_attribute("id")) { - clip.name = parser.get_attribute_value("id"); + clip.name = parser.get_named_attribute_value("id"); } if (parser.has_attribute("start")) { - clip.begin = parser.get_attribute_value("start").to_float(); + clip.begin = parser.get_named_attribute_value("start").to_float(); } if (parser.has_attribute("end")) { - clip.end = parser.get_attribute_value("end").to_float(); + clip.end = parser.get_named_attribute_value("end").to_float(); } while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { String name = parser.get_node_name(); if (name == "instance_animation") { - String url = _uri_to_id(parser.get_attribute_value("url")); + String url = _uri_to_id(parser.get_named_attribute_value("url")); clip.tracks.push_back(url); } @@ -1894,9 +1894,9 @@ void Collada::_parse_scene(XMLParser &parser) { String name = parser.get_node_name(); if (name == "instance_visual_scene") { - state.root_visual_scene = _uri_to_id(parser.get_attribute_value("url")); + state.root_visual_scene = _uri_to_id(parser.get_named_attribute_value("url")); } else if (name == "instance_physics_scene") { - state.root_physics_scene = _uri_to_id(parser.get_attribute_value("url")); + state.root_physics_scene = _uri_to_id(parser.get_named_attribute_value("url")); } } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "scene") { @@ -1925,8 +1925,8 @@ void Collada::_parse_library(XMLParser &parser) { } else if (name == "light") { _parse_light(parser); } else if (name == "geometry") { - String id = parser.get_attribute_value("id"); - String name2 = parser.get_attribute_value_safe("name"); + String id = parser.get_named_attribute_value("id"); + String name2 = parser.get_named_attribute_value_safe("name"); while (parser.read() == OK) { if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { if (parser.get_node_name() == "mesh") { @@ -2346,7 +2346,7 @@ Error Collada::load(const String &p_path, int p_flags) { { //version - String version = parser.get_attribute_value("version"); + String version = parser.get_named_attribute_value("version"); state.version.major = version.get_slice(".", 0).to_int(); state.version.minor = version.get_slice(".", 1).to_int(); state.version.rev = version.get_slice(".", 2).to_int(); diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index ad6d41e10c..3dd01754a3 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -206,6 +206,20 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path)); + // Avoid trying to load/interpret potential build artifacts from Visual Studio (e.g. when compiling native plugins inside the project tree) + // This should only match, if it's indeed a COFF file header + // https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types + const int first_bytes = f->get_16(); + static const Vector<int> coff_header_machines{ + 0x0, // IMAGE_FILE_MACHINE_UNKNOWN + 0x8664, // IMAGE_FILE_MACHINE_AMD64 + 0x1c0, // IMAGE_FILE_MACHINE_ARM + 0x14c, // IMAGE_FILE_MACHINE_I386 + 0x200, // IMAGE_FILE_MACHINE_IA64 + }; + ERR_FAIL_COND_V_MSG(coff_header_machines.find(first_bytes) != -1, ERR_FILE_CORRUPT, vformat("Couldn't read OBJ file '%s', it seems to be binary, corrupted, or empty.", p_path)); + f->seek(0); + Ref<ArrayMesh> mesh; mesh.instantiate(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 51687eb19a..188abf1f5c 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -2174,6 +2174,8 @@ Error ScriptEditor::_save_text_file(Ref<TextFile> p_text_file, const String &p_p p_text_file->set_last_modified_time(FileAccess::get_modified_time(p_path)); } + EditorFileSystem::get_singleton()->update_file(p_path); + _res_saved_callback(sqscr); return OK; } @@ -2492,7 +2494,6 @@ void ScriptEditor::save_all_scripts() { } _update_script_names(); - EditorFileSystem::get_singleton()->update_script_classes(); } void ScriptEditor::apply_scripts() const { diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index b2542b96fa..96b1ad7ee0 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -5441,11 +5441,9 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Binormal", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Color", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("DepthTexture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture", "DEPTH_TEXTURE"), { "depth_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FragCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FrontFacing", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing", "FRONT_FACING"), { "front_facing" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("PointCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ScreenTexture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture", "SCREEN_TEXTURE"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Tangent", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Vertex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -5488,7 +5486,6 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("NormalTexture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture", "NORMAL_TEXTURE"), { "normal_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("PointCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenPixelSize", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size", "SCREEN_PIXEL_SIZE"), { "screen_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenTexture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture", "SCREEN_TEXTURE"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("SpecularShininess", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("SpecularShininessTexture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE"), { "specular_shininess_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); @@ -5692,7 +5689,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("CurveTexture", "Textures/Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); curve_xyz_node_option_idx = add_options.size(); add_options.push_back(AddOption("CurveXYZTexture", "Textures/Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D)); - add_options.push_back(AddOption("LinearSceneDepth", "Textures/Functions", "VisualShaderNodeLinearSceneDepth", TTR("Returns the depth value of the DEPTH_TEXTURE node in a linear space."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("LinearSceneDepth", "Textures/Functions", "VisualShaderNodeLinearSceneDepth", TTR("Returns the depth value obtained from the depth prepass in a linear space."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); texture2d_node_option_idx = add_options.size(); add_options.push_back(AddOption("Texture2D", "Textures/Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); texture2d_array_node_option_idx = add_options.size(); diff --git a/main/main.cpp b/main/main.cpp index 00c6b1fecd..e5d2ea3922 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1677,10 +1677,21 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", true); OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false); +#ifdef TOOLS_ENABLED if (editor || project_manager) { - // The editor and project manager always detect and use hiDPI if needed + // The editor and project manager always detect and use hiDPI if needed. OS::get_singleton()->_allow_hidpi = true; + // Disable Vulkan overlays in editor, they cause various issues. + OS::get_singleton()->set_environment("DISABLE_MANGOHUD", "1"); // GH-57403. + OS::get_singleton()->set_environment("DISABLE_RTSS_LAYER", "1"); // GH-57937. + OS::get_singleton()->set_environment("DISABLE_VKBASALT", "1"); + } else { + // Re-allow using Vulkan overlays, disabled while using the editor. + OS::get_singleton()->unset_environment("DISABLE_MANGOHUD"); + OS::get_singleton()->unset_environment("DISABLE_RTSS_LAYER"); + OS::get_singleton()->unset_environment("DISABLE_VKBASALT"); } +#endif if (rtm == -1) { rtm = GLOBAL_DEF("rendering/driver/threads/thread_model", OS::RENDER_THREAD_SAFE); @@ -2114,7 +2125,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { #endif } -#ifdef TOOLS_ENABLED +#if defined(TOOLS_ENABLED) && defined(MACOS_ENABLED) if (OS::get_singleton()->get_bundle_icon_path().is_empty()) { Ref<Image> icon = memnew(Image(app_icon_png)); DisplayServer::get_singleton()->set_icon(icon); diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp index 3b789a235f..5b451fbf6b 100644 --- a/modules/bmp/image_loader_bmp.cpp +++ b/modules/bmp/image_loader_bmp.cpp @@ -58,6 +58,13 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, ERR_FAIL_COND_V_MSG(height % 8 != 0, ERR_UNAVAILABLE, vformat("1-bpp BMP images must have a height that is a multiple of 8, but the imported BMP is %d pixels tall.", int(height))); + } else if (bits_per_pixel == 2) { + // Requires bit unpacking... + ERR_FAIL_COND_V_MSG(width % 4 != 0, ERR_UNAVAILABLE, + vformat("2-bpp BMP images must have a width that is a multiple of 4, but the imported BMP is %d pixels wide.", int(width))); + ERR_FAIL_COND_V_MSG(height % 4 != 0, ERR_UNAVAILABLE, + vformat("2-bpp BMP images must have a height that is a multiple of 4, but the imported BMP is %d pixels tall.", int(height))); + } else if (bits_per_pixel == 4) { // Requires bit unpacking... ERR_FAIL_COND_V_MSG(width % 2 != 0, ERR_UNAVAILABLE, @@ -88,7 +95,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, const uint32_t line_width = (width_bytes + 3) & ~3; // The actual data traversal is determined by - // the data width in case of 8/4/1 bit images + // the data width in case of 8/4/2/1 bit images const uint32_t w = bits_per_pixel >= 24 ? width : width_bytes; const uint8_t *line = p_buffer + (line_width * (height - 1)); const uint8_t *end_buffer = p_buffer + p_header.bmp_file_header.bmp_file_size - p_header.bmp_file_header.bmp_file_offset; @@ -114,6 +121,17 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, index += 8; line_ptr += 1; } break; + case 2: { + uint8_t color_index = *line_ptr; + + write_buffer[index + 0] = (color_index >> 6) & 3; + write_buffer[index + 1] = (color_index >> 4) & 3; + write_buffer[index + 2] = (color_index >> 2) & 3; + write_buffer[index + 3] = color_index & 3; + + index += 4; + line_ptr += 1; + } break; case 4: { uint8_t color_index = *line_ptr; diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index fd748ea569..3fe741a582 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -553,6 +553,7 @@ @icon("res://path/to/class/icon.svg") [/codeblock] [b]Note:[/b] Only the script can have a custom icon. Inner classes are not supported. + [b]Note:[/b] As annotations describe their subject, the [code]@icon[/code] annotation must be placed before the class definition and inheritance. </description> </annotation> <annotation name="@onready"> @@ -585,6 +586,7 @@ @tool extends Node [/codeblock] + [b]Note:[/b] As annotations describe their subject, the [code]@tool[/code] annotation must be placed before the class definition and inheritance. </description> </annotation> <annotation name="@warning_ignore" qualifiers="vararg"> diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index d556f475d2..6b8f140923 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -560,6 +560,12 @@ void OpenXRAPI::destroy_instance() { instance = XR_NULL_HANDLE; } enabled_extensions.clear(); + + if (graphics_extension != nullptr) { + unregister_extension_wrapper(graphics_extension); + memdelete(graphics_extension); + graphics_extension = nullptr; + } } bool OpenXRAPI::create_session() { @@ -1347,6 +1353,10 @@ void OpenXRAPI::register_extension_wrapper(OpenXRExtensionWrapper *p_extension_w registered_extension_wrappers.push_back(p_extension_wrapper); } +void OpenXRAPI::unregister_extension_wrapper(OpenXRExtensionWrapper *p_extension_wrapper) { + registered_extension_wrappers.erase(p_extension_wrapper); +} + void OpenXRAPI::register_extension_metadata() { for (OpenXRExtensionWrapper *extension_wrapper : registered_extension_wrappers) { extension_wrapper->on_register_metadata(); diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index 5fb8de660e..52a1af5a09 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -312,6 +312,7 @@ public: void set_xr_interface(OpenXRInterface *p_xr_interface); static void register_extension_wrapper(OpenXRExtensionWrapper *p_extension_wrapper); + static void unregister_extension_wrapper(OpenXRExtensionWrapper *p_extension_wrapper); static void register_extension_metadata(); static void cleanup_extension_wrappers(); diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp index 4e2fe3dab5..1c4d53c43a 100644 --- a/modules/openxr/register_types.cpp +++ b/modules/openxr/register_types.cpp @@ -111,6 +111,10 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) { ERR_FAIL_NULL(openxr_api); if (!openxr_api->initialize(Main::get_rendering_driver_name())) { + OS::get_singleton()->alert("OpenXR was requested but failed to start.\n" + "Please check if your HMD is connected.\n" + "When using Windows MR please note that WMR only has DirectX support, make sure SteamVR is your default OpenXR runtime.\n" + "Godot will start in normal mode.\n"); memdelete(openxr_api); openxr_api = nullptr; return; diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index e52b87741e..8e9ff61ad0 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -423,11 +423,7 @@ bool TextServerAdvanced::_load_support_data(const String &p_filename) { return false; } uint64_t len = f->get_length(); -#ifdef GDEXTENSION PackedByteArray icu_data = f->get_buffer(len); -#else - PackedByteArray icu_data = f->_get_buffer(len); -#endif UErrorCode err = U_ZERO_ERROR; udata_setCommonData(icu_data.ptr(), &err); @@ -476,11 +472,7 @@ bool TextServerAdvanced::_save_support_data(const String &p_filename) const { PackedByteArray icu_data; icu_data.resize(U_ICUDATA_SIZE); memcpy(icu_data.ptrw(), U_ICUDATA_ENTRY_POINT, U_ICUDATA_SIZE); -#ifdef GDEXTENSION f->store_buffer(icu_data); -#else - f->_store_buffer(icu_data); -#endif return true; #else @@ -824,29 +816,17 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_ // Could not find texture to fit, create one. int texsize = MAX(p_data->size.x * p_data->oversampling * 8, 256); -#ifdef GDEXTENSION - texsize = Math::next_power_of_2(texsize); -#else texsize = next_power_of_2(texsize); -#endif if (p_msdf) { texsize = MIN(texsize, 2048); } else { texsize = MIN(texsize, 1024); } if (mw > texsize) { // Special case, adapt to it? -#ifdef GDEXTENSION - texsize = Math::next_power_of_2(mw); -#else texsize = next_power_of_2(mw); -#endif } if (mh > texsize) { // Special case, adapt to it? -#ifdef GDEXTENSION - texsize = Math::next_power_of_2(mh); -#else texsize = next_power_of_2(mh); -#endif } ShelfPackTexture tex = ShelfPackTexture(texsize, texsize); @@ -949,14 +929,14 @@ static int ft_cubic_to(const FT_Vector *control1, const FT_Vector *control2, con return 0; } -void TextServerAdvanced::_generateMTSDF_threaded(uint32_t y, void *p_td) const { +void TextServerAdvanced::_generateMTSDF_threaded(void *p_td, uint32_t p_y) { MSDFThreadData *td = static_cast<MSDFThreadData *>(p_td); msdfgen::ShapeDistanceFinder<msdfgen::OverlappingContourCombiner<msdfgen::MultiAndTrueDistanceSelector>> distanceFinder(*td->shape); - int row = td->shape->inverseYAxis ? td->output->height() - y - 1 : y; + int row = td->shape->inverseYAxis ? td->output->height() - p_y - 1 : p_y; for (int col = 0; col < td->output->width(); ++col) { - int x = (y % 2) ? td->output->width() - col - 1 : col; - msdfgen::Point2 p = td->projection->unproject(msdfgen::Point2(x + .5, y + .5)); + int x = (p_y % 2) ? td->output->width() - col - 1 : col; + msdfgen::Point2 p = td->projection->unproject(msdfgen::Point2(x + .5, p_y + .5)); msdfgen::MultiAndTrueDistance distance = distanceFinder.distance(p); td->distancePixelConversion->operator()(td->output->operator()(x, row), distance); } @@ -1026,14 +1006,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( td.projection = &projection; td.distancePixelConversion = &distancePixelConversion; -#ifdef GDEXTENSION - for (int i = 0; i < h; i++) { - _generateMTSDF_threaded(i, &td); - } -#else - WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerAdvanced::_generateMTSDF_threaded, &td, h, -1, true, SNAME("FontServerRasterizeMSDF")); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_native_group_task(&TextServerAdvanced::_generateMTSDF_threaded, &td, h, -1, true, String("FontServerRasterizeMSDF")); WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); -#endif msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config); diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index e8a3a10ab8..5920ddaa50 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -72,7 +72,6 @@ #include <godot_cpp/templates/hash_map.hpp> #include <godot_cpp/templates/hash_set.hpp> #include <godot_cpp/templates/rid_owner.hpp> - #include <godot_cpp/templates/vector.hpp> using namespace godot; @@ -350,7 +349,7 @@ class TextServerAdvanced : public TextServerExtension { _FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const; _FORCE_INLINE_ void _font_clear_cache(FontAdvanced *p_font_data); - void _generateMTSDF_threaded(uint32_t y, void *p_td) const; + static void _generateMTSDF_threaded(void *p_td, uint32_t p_y); _FORCE_INLINE_ Vector2i _get_size(const FontAdvanced *p_font_data, int p_size) const { if (p_font_data->msdf) { diff --git a/modules/text_server_adv/thorvg_svg_in_ot.cpp b/modules/text_server_adv/thorvg_svg_in_ot.cpp index 9354d3f9b3..1406e3aaa0 100644 --- a/modules/text_server_adv/thorvg_svg_in_ot.cpp +++ b/modules/text_server_adv/thorvg_svg_in_ot.cpp @@ -88,24 +88,13 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin if (!gl_state.ready) { Ref<XMLParser> parser; parser.instantiate(); -#ifdef GDEXTENSION - PackedByteArray data; - data.resize(document->svg_document_length); - memcpy(data.ptrw(), document->svg_document, document->svg_document_length); - parser->open_buffer(data); -#else parser->_open_buffer((const uint8_t *)document->svg_document, document->svg_document_length); -#endif float aspect = 1.0f; String xml_body; while (parser->read() == OK) { if (parser->has_attribute("id")) { -#ifdef GDEXTENSION const String &gl_name = parser->get_named_attribute_value("id"); -#else - const String &gl_name = parser->get_attribute_value("id"); -#endif if (gl_name.begins_with("glyph")) { int dot_pos = gl_name.find("."); int64_t gl_idx = gl_name.substr(5, (dot_pos > 0) ? dot_pos - 5 : -1).to_int(); @@ -117,11 +106,7 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin } if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name() == "svg") { if (parser->has_attribute("viewBox")) { -#ifdef GDEXTENSION PackedStringArray vb = parser->get_named_attribute_value("viewBox").split(" "); -#else - Vector<String> vb = parser->get_attribute_value("viewBox").split(" "); -#endif if (vb.size() == 4) { aspect = vb[2].to_float() / vb[3].to_float(); @@ -129,19 +114,6 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin } continue; } -#ifdef GDEXTENSION - if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { - xml_body = xml_body + "<" + parser->get_node_name(); - for (int i = 0; i < parser->get_attribute_count(); i++) { - xml_body = xml_body + " " + parser->get_attribute_name(i) + "=\"" + parser->get_attribute_value(i) + "\""; - } - xml_body = xml_body + ">"; - } else if (parser->get_node_type() == XMLParser::NODE_TEXT) { - xml_body = xml_body + parser->get_node_data(); - } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) { - xml_body = xml_body + "</" + parser->get_node_name() + ">"; - } -#else if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { xml_body += vformat("<%s", parser->get_node_name()); for (int i = 0; i < parser->get_attribute_count(); i++) { @@ -153,7 +125,6 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) { xml_body += vformat("</%s>", parser->get_node_name()); } -#endif } String temp_xml = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 0 0\">" + xml_body; @@ -175,11 +146,7 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin new_h = (new_w / aspect); } -#ifdef GDEXTENSION gl_state.xml_code = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"" + rtos(min_x) + " " + rtos(min_y) + " " + rtos(new_w) + " " + rtos(new_h) + "\">" + xml_body; -#else - gl_state.xml_code = vformat("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%f %f %f %f\">", min_x, min_y, new_w, new_h) + xml_body; -#endif picture = tvg::Picture::gen(); result = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false); diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 034f88e387..ece34f56d6 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -248,11 +248,7 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_ // Could not find texture to fit, create one. int texsize = MAX(p_data->size.x * p_data->oversampling * 8, 256); -#ifdef GDEXTENSION - texsize = Math::next_power_of_2(texsize); -#else texsize = next_power_of_2(texsize); -#endif if (p_msdf) { texsize = MIN(texsize, 2048); @@ -260,18 +256,10 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_ texsize = MIN(texsize, 1024); } if (mw > texsize) { // Special case, adapt to it? -#ifdef GDEXTENSION - texsize = Math::next_power_of_2(mw); -#else texsize = next_power_of_2(mw); -#endif } if (mh > texsize) { // Special case, adapt to it? -#ifdef GDEXTENSION - texsize = Math::next_power_of_2(mh); -#else texsize = next_power_of_2(mh); -#endif } ShelfPackTexture tex = ShelfPackTexture(texsize, texsize); @@ -374,14 +362,14 @@ static int ft_cubic_to(const FT_Vector *control1, const FT_Vector *control2, con return 0; } -void TextServerFallback::_generateMTSDF_threaded(uint32_t y, void *p_td) const { +void TextServerFallback::_generateMTSDF_threaded(void *p_td, uint32_t p_y) { MSDFThreadData *td = static_cast<MSDFThreadData *>(p_td); msdfgen::ShapeDistanceFinder<msdfgen::OverlappingContourCombiner<msdfgen::MultiAndTrueDistanceSelector>> distanceFinder(*td->shape); - int row = td->shape->inverseYAxis ? td->output->height() - y - 1 : y; + int row = td->shape->inverseYAxis ? td->output->height() - p_y - 1 : p_y; for (int col = 0; col < td->output->width(); ++col) { - int x = (y % 2) ? td->output->width() - col - 1 : col; - msdfgen::Point2 p = td->projection->unproject(msdfgen::Point2(x + .5, y + .5)); + int x = (p_y % 2) ? td->output->width() - col - 1 : col; + msdfgen::Point2 p = td->projection->unproject(msdfgen::Point2(x + .5, p_y + .5)); msdfgen::MultiAndTrueDistance distance = distanceFinder.distance(p); td->distancePixelConversion->operator()(td->output->operator()(x, row), distance); } @@ -451,14 +439,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( td.projection = &projection; td.distancePixelConversion = &distancePixelConversion; -#ifdef GDEXTENSION - for (int i = 0; i < h; i++) { - _generateMTSDF_threaded(i, &td); - } -#else - WorkerThreadPool::GroupID group_id = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerFallback::_generateMTSDF_threaded, &td, h, -1, true, SNAME("TextServerFBRenderMSDF")); - WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_id); -#endif + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_native_group_task(&TextServerFallback::_generateMTSDF_threaded, &td, h, -1, true, String("TextServerFBRenderMSDF")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config); diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index b42f564534..9fb048a581 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -67,11 +67,11 @@ #include <godot_cpp/classes/image.hpp> #include <godot_cpp/classes/image_texture.hpp> #include <godot_cpp/classes/ref.hpp> +#include <godot_cpp/classes/worker_thread_pool.hpp> #include <godot_cpp/templates/hash_map.hpp> #include <godot_cpp/templates/hash_set.hpp> #include <godot_cpp/templates/rid_owner.hpp> -#include <godot_cpp/templates/thread_work_pool.hpp> #include <godot_cpp/templates/vector.hpp> using namespace godot; @@ -303,7 +303,7 @@ class TextServerFallback : public TextServerExtension { _FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const; _FORCE_INLINE_ void _font_clear_cache(FontFallback *p_font_data); - void _generateMTSDF_threaded(uint32_t y, void *p_td) const; + static void _generateMTSDF_threaded(void *p_td, uint32_t p_y); _FORCE_INLINE_ Vector2i _get_size(const FontFallback *p_font_data, int p_size) const { if (p_font_data->msdf) { diff --git a/modules/text_server_fb/thorvg_svg_in_ot.cpp b/modules/text_server_fb/thorvg_svg_in_ot.cpp index 9354d3f9b3..1406e3aaa0 100644 --- a/modules/text_server_fb/thorvg_svg_in_ot.cpp +++ b/modules/text_server_fb/thorvg_svg_in_ot.cpp @@ -88,24 +88,13 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin if (!gl_state.ready) { Ref<XMLParser> parser; parser.instantiate(); -#ifdef GDEXTENSION - PackedByteArray data; - data.resize(document->svg_document_length); - memcpy(data.ptrw(), document->svg_document, document->svg_document_length); - parser->open_buffer(data); -#else parser->_open_buffer((const uint8_t *)document->svg_document, document->svg_document_length); -#endif float aspect = 1.0f; String xml_body; while (parser->read() == OK) { if (parser->has_attribute("id")) { -#ifdef GDEXTENSION const String &gl_name = parser->get_named_attribute_value("id"); -#else - const String &gl_name = parser->get_attribute_value("id"); -#endif if (gl_name.begins_with("glyph")) { int dot_pos = gl_name.find("."); int64_t gl_idx = gl_name.substr(5, (dot_pos > 0) ? dot_pos - 5 : -1).to_int(); @@ -117,11 +106,7 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin } if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name() == "svg") { if (parser->has_attribute("viewBox")) { -#ifdef GDEXTENSION PackedStringArray vb = parser->get_named_attribute_value("viewBox").split(" "); -#else - Vector<String> vb = parser->get_attribute_value("viewBox").split(" "); -#endif if (vb.size() == 4) { aspect = vb[2].to_float() / vb[3].to_float(); @@ -129,19 +114,6 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin } continue; } -#ifdef GDEXTENSION - if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { - xml_body = xml_body + "<" + parser->get_node_name(); - for (int i = 0; i < parser->get_attribute_count(); i++) { - xml_body = xml_body + " " + parser->get_attribute_name(i) + "=\"" + parser->get_attribute_value(i) + "\""; - } - xml_body = xml_body + ">"; - } else if (parser->get_node_type() == XMLParser::NODE_TEXT) { - xml_body = xml_body + parser->get_node_data(); - } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) { - xml_body = xml_body + "</" + parser->get_node_name() + ">"; - } -#else if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { xml_body += vformat("<%s", parser->get_node_name()); for (int i = 0; i < parser->get_attribute_count(); i++) { @@ -153,7 +125,6 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END) { xml_body += vformat("</%s>", parser->get_node_name()); } -#endif } String temp_xml = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 0 0\">" + xml_body; @@ -175,11 +146,7 @@ FT_Error tvg_svg_in_ot_preset_slot(FT_GlyphSlot p_slot, FT_Bool p_cache, FT_Poin new_h = (new_w / aspect); } -#ifdef GDEXTENSION gl_state.xml_code = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"" + rtos(min_x) + " " + rtos(min_y) + " " + rtos(new_w) + " " + rtos(new_h) + "\">" + xml_body; -#else - gl_state.xml_code = vformat("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%f %f %f %f\">", min_x, min_y, new_w, new_h) + xml_body; -#endif picture = tvg::Picture::gen(); result = picture->load(gl_state.xml_code.utf8().get_data(), gl_state.xml_code.utf8().length(), "svg+xml", false); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 376ed89c16..942bf0a904 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -355,20 +355,20 @@ void OS_Android::_load_system_font_config() { if (parser->get_node_type() == XMLParser::NODE_ELEMENT) { in_font_node = false; if (parser->get_node_name() == "familyset") { - int ver = parser->has_attribute("version") ? parser->get_attribute_value("version").to_int() : 0; + int ver = parser->has_attribute("version") ? parser->get_named_attribute_value("version").to_int() : 0; if (ver < 21) { ERR_PRINT(vformat("Unsupported font config version %s", ver)); break; } } else if (parser->get_node_name() == "alias") { - String name = parser->has_attribute("name") ? parser->get_attribute_value("name").strip_edges() : String(); - String to = parser->has_attribute("to") ? parser->get_attribute_value("to").strip_edges() : String(); + String name = parser->has_attribute("name") ? parser->get_named_attribute_value("name").strip_edges() : String(); + String to = parser->has_attribute("to") ? parser->get_named_attribute_value("to").strip_edges() : String(); if (!name.is_empty() && !to.is_empty()) { font_aliases[name] = to; } } else if (parser->get_node_name() == "family") { - fn = parser->has_attribute("name") ? parser->get_attribute_value("name").strip_edges() : String(); - String lang_code = parser->has_attribute("lang") ? parser->get_attribute_value("lang").strip_edges() : String(); + fn = parser->has_attribute("name") ? parser->get_named_attribute_value("name").strip_edges() : String(); + String lang_code = parser->has_attribute("lang") ? parser->get_named_attribute_value("lang").strip_edges() : String(); Vector<String> lang_codes = lang_code.split(","); for (int i = 0; i < lang_codes.size(); i++) { Vector<String> lang_code_elements = lang_codes[i].split("-"); @@ -412,9 +412,9 @@ void OS_Android::_load_system_font_config() { } } else if (parser->get_node_name() == "font") { in_font_node = true; - fb = parser->has_attribute("fallbackFor") ? parser->get_attribute_value("fallbackFor").strip_edges() : String(); - fi.weight = parser->has_attribute("weight") ? parser->get_attribute_value("weight").to_int() : 400; - fi.italic = parser->has_attribute("style") && parser->get_attribute_value("style").strip_edges() == "italic"; + fb = parser->has_attribute("fallbackFor") ? parser->get_named_attribute_value("fallbackFor").strip_edges() : String(); + fi.weight = parser->has_attribute("weight") ? parser->get_named_attribute_value("weight").to_int() : 400; + fi.italic = parser->has_attribute("style") && parser->get_named_attribute_value("style").strip_edges() == "italic"; } } if (parser->get_node_type() == XMLParser::NODE_TEXT) { diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index fa81c81b20..631543763b 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -741,6 +741,17 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod if (p_flags & WINDOW_FLAG_POPUP_BIT) { wd.is_popup = true; } + if (p_flags & WINDOW_FLAG_TRANSPARENT_BIT) { + DWM_BLURBEHIND bb; + ZeroMemory(&bb, sizeof(bb)); + HRGN hRgn = CreateRectRgn(0, 0, -1, -1); + bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; + bb.hRgnBlur = hRgn; + bb.fEnable = TRUE; + DwmEnableBlurBehindWindow(wd.hWnd, &bb); + + wd.layered_window = true; + } // Inherit icons from MAIN_WINDOW for all sub windows. HICON mainwindow_icon = (HICON)SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_GETICON, ICON_SMALL, 0); @@ -778,6 +789,9 @@ void DisplayServerWindows::show_window(WindowID p_id) { SetForegroundWindow(wd.hWnd); // Slightly higher priority. SetFocus(wd.hWnd); // Set keyboard focus. } + if (wd.always_on_top) { + SetWindowPos(wd.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0)); + } } void DisplayServerWindows::delete_sub_window(WindowID p_window) { diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index d5c3f7730b..3e2a952ea7 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -791,6 +791,14 @@ void BaseMaterial3D::_update_shader() { code += "uniform vec4 refraction_texture_channel;\n"; } + if (features[FEATURE_REFRACTION]) { + code += "uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;"; + } + + if (proximity_fade_enabled) { + code += "uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;"; + } + if (features[FEATURE_NORMAL_MAPPING]) { code += "uniform sampler2D texture_normal : hint_roughness_normal," + texfilter_str + ";\n"; code += "uniform float normal_scale : hint_range(-16,16);\n"; @@ -1228,7 +1236,7 @@ void BaseMaterial3D::_update_shader() { code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n"; } code += " float ref_amount = 1.0 - albedo.a * albedo_tex.a;\n"; - code += " EMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n"; + code += " EMISSION += textureLod(screen_texture,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n"; code += " ALBEDO *= 1.0 - ref_amount;\n"; code += " ALPHA = 1.0;\n"; @@ -1246,7 +1254,7 @@ void BaseMaterial3D::_update_shader() { } if (proximity_fade_enabled) { - code += " float depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n"; + code += " float depth_tex = textureLod(depth_texture,SCREEN_UV,0.0).r;\n"; code += " vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex,1.0);\n"; code += " world_pos.xyz/=world_pos.w;\n"; code += " ALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n"; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 4c99563a91..76fb2d1367 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -2734,9 +2734,6 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "front_facing", "FRONT_FACING" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_roughness_texture", "NORMAL_ROUGHNESS_TEXTURE" }, - { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "depth_texture", "DEPTH_TEXTURE" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, @@ -2799,7 +2796,6 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_texture", "NORMAL_TEXTURE" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" }, diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 985bcb442e..ec89c87bd2 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -771,6 +771,23 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade break; } return u + ";\n"; + } else if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) { + String u = "uniform sampler2D " + make_unique_id(p_type, p_id, "screen_tex"); + return u + " : hint_screen_texture;\n"; + } else if (source == SOURCE_DEPTH || source == SOURCE_3D_NORMAL || source == SOURCE_ROUGHNESS) { + String sampler_name = ""; + String hint = " : "; + if (source == SOURCE_DEPTH) { + sampler_name = "depth_tex"; + hint += "hint_depth_texture;\n"; + } else if (source == SOURCE_3D_NORMAL) { + sampler_name = "screen_normal_tex"; + hint += "hint_normal_roughness_texture;\n"; + } else if (source == SOURCE_ROUGHNESS) { + sampler_name = "screen_roughness_tex"; + hint += "hint_normal_roughness_texture;\n"; + } + return "uniform sampler2D " + make_unique_id(p_type, p_id, sampler_name) + hint; } return String(); @@ -824,17 +841,18 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) { + String id = make_unique_id(p_type, p_id, "screen_tex"); if (p_input_vars[0].is_empty() || p_for_preview) { // Use UV by default. if (p_input_vars[1].is_empty()) { - code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0);\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", 0.0);\n"; } else { - code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1].is_empty()) { //no lod - code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", 0.0);\n"; } else { - code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } return code; } @@ -871,23 +889,58 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: return code; } - if (source == SOURCE_DEPTH) { + if (source == SOURCE_DEPTH || source == SOURCE_ROUGHNESS) { if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { + String var_name = ""; + String sampler_name = ""; + + if (source == SOURCE_DEPTH) { + var_name = "_depth"; + sampler_name = "depth_tex"; + } else if (source == SOURCE_ROUGHNESS) { + var_name = "_screen_roughness"; + sampler_name = "screen_roughness_tex"; + } + + String id = make_unique_id(p_type, p_id, sampler_name); code += " {\n"; if (p_input_vars[0].is_empty()) { // Use UV by default. if (p_input_vars[1].is_empty()) { - code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n"; + code += " float " + var_name + " = texture(" + id + ", " + default_uv + ").r;\n"; } else { - code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n"; + code += " float " + var_name + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ").r;\n"; } } else if (p_input_vars[1].is_empty()) { //no lod - code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n"; + code += " float " + var_name + " = texture(" + id + ", " + p_input_vars[0] + ".xy).r;\n"; } else { - code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n"; + code += " float " + var_name + " = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n"; } - code += " " + p_output_vars[0] + " = vec4(_depth, _depth, _depth, 1.0);\n"; + code += " " + p_output_vars[0] + " = vec4(" + var_name + ", " + var_name + ", " + var_name + ", 1.0);\n"; + code += " }\n"; + return code; + } + } + + if (source == SOURCE_3D_NORMAL) { + if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { + String id = make_unique_id(p_type, p_id, "screen_normal_tex"); + code += " {\n"; + if (p_input_vars[0].is_empty()) { // Use UV by default. + if (p_input_vars[1].is_empty()) { + code += " vec3 _screen_normal = texture(" + id + ", " + default_uv + ").xyz;\n"; + } else { + code += " vec3 _screen_normal = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ").xyz;\n"; + } + } else if (p_input_vars[1].is_empty()) { + //no lod + code += " vec3 _screen_normal = texture(" + id + ", " + p_input_vars[0] + ".xy).xyz;\n"; + } else { + code += " vec3 _screen_normal = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").xyz;\n"; + } + + code += " " + p_output_vars[0] + " = vec4(_screen_normal, 1.0);\n"; code += " }\n"; return code; } @@ -921,6 +974,12 @@ void VisualShaderNodeTexture::set_source(Source p_source) { case SOURCE_PORT: simple_decl = false; break; + case SOURCE_3D_NORMAL: + simple_decl = false; + break; + case SOURCE_ROUGHNESS: + simple_decl = false; + break; default: break; } @@ -990,8 +1049,8 @@ String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::T return String(); // all good } - if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { - if (get_output_port_for_preview() == 0) { // DEPTH_TEXTURE is not supported in preview(canvas_item) shader + if ((source == SOURCE_DEPTH || source == SOURCE_3D_NORMAL || source == SOURCE_ROUGHNESS) && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { + if (get_output_port_for_preview() == 0) { // DEPTH_TEXTURE and NORMAL_ROUGHNESS_TEXTURE are not supported in preview(canvas_item) shader return RTR("Invalid source for preview."); } return String(); // all good @@ -1010,7 +1069,7 @@ void VisualShaderNodeTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture_type", "value"), &VisualShaderNodeTexture::set_texture_type); ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeTexture::get_texture_type); - ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort"), "set_source", "get_source"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort,ScreenNormal,Roughness"), "set_source", "get_source"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type"); @@ -1020,6 +1079,8 @@ void VisualShaderNodeTexture::_bind_methods() { BIND_ENUM_CONSTANT(SOURCE_2D_NORMAL); BIND_ENUM_CONSTANT(SOURCE_DEPTH); BIND_ENUM_CONSTANT(SOURCE_PORT); + BIND_ENUM_CONSTANT(SOURCE_3D_NORMAL); + BIND_ENUM_CONSTANT(SOURCE_ROUGHNESS); BIND_ENUM_CONSTANT(SOURCE_MAX); BIND_ENUM_CONSTANT(TYPE_DATA); @@ -1702,11 +1763,15 @@ bool VisualShaderNodeLinearSceneDepth::has_output_port_preview(int p_port) const return false; } +String VisualShaderNodeLinearSceneDepth::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + return "uniform sampler2D " + make_unique_id(p_type, p_id, "depth_tex") + " : hint_depth_texture;\n"; +} + String VisualShaderNodeLinearSceneDepth::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; code += " {\n"; - code += " float __log_depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).x;\n"; + code += " float __log_depth = textureLod(" + make_unique_id(p_type, p_id, "depth_tex") + ", SCREEN_UV, 0.0).x;\n"; code += " vec3 __depth_ndc = vec3(SCREEN_UV * 2.0 - 1.0, __log_depth);\n"; code += " vec4 __depth_view = INV_PROJECTION_MATRIX * vec4(__depth_ndc, 1.0);\n"; code += " __depth_view.xyz /= __depth_view.w;\n"; @@ -6101,7 +6166,7 @@ VisualShaderNodeTransformParameter::VisualShaderNodeTransformParameter() { ////////////// -String get_sampler_hint(VisualShaderNodeTextureParameter::TextureType p_texture_type, VisualShaderNodeTextureParameter::ColorDefault p_color_default, VisualShaderNodeTextureParameter::TextureFilter p_texture_filter, VisualShaderNodeTextureParameter::TextureRepeat p_texture_repeat) { +String get_sampler_hint(VisualShaderNodeTextureParameter::TextureType p_texture_type, VisualShaderNodeTextureParameter::ColorDefault p_color_default, VisualShaderNodeTextureParameter::TextureFilter p_texture_filter, VisualShaderNodeTextureParameter::TextureRepeat p_texture_repeat, VisualShaderNodeTextureParameter::TextureSource p_texture_source) { String code; bool has_colon = false; @@ -6204,6 +6269,33 @@ String get_sampler_hint(VisualShaderNodeTextureParameter::TextureType p_texture_ } } + { + String source_code; + + switch (p_texture_source) { + case VisualShaderNodeTextureParameter::SOURCE_SCREEN: + source_code = "hint_screen_texture"; + break; + case VisualShaderNodeTextureParameter::SOURCE_DEPTH: + source_code = "hint_depth_texture"; + break; + case VisualShaderNodeTextureParameter::SOURCE_NORMAL_ROUGHNESS: + source_code = "hint_normal_roughness_texture"; + break; + default: + break; + } + + if (!source_code.is_empty()) { + if (!has_colon) { + code += " : "; + } else { + code += ", "; + } + code += source_code; + } + } + return code; } @@ -6290,6 +6382,19 @@ VisualShaderNodeTextureParameter::TextureRepeat VisualShaderNodeTextureParameter return texture_repeat; } +void VisualShaderNodeTextureParameter::set_texture_source(TextureSource p_source) { + ERR_FAIL_INDEX(int(p_source), int(SOURCE_MAX)); + if (texture_source == p_source) { + return; + } + texture_source = p_source; + emit_changed(); +} + +VisualShaderNodeTextureParameter::TextureSource VisualShaderNodeTextureParameter::get_texture_source() const { + return texture_source; +} + Vector<StringName> VisualShaderNodeTextureParameter::get_editable_properties() const { Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties(); props.push_back("texture_type"); @@ -6298,6 +6403,7 @@ Vector<StringName> VisualShaderNodeTextureParameter::get_editable_properties() c } props.push_back("texture_filter"); props.push_back("texture_repeat"); + props.push_back("texture_source"); return props; } @@ -6311,6 +6417,7 @@ HashMap<StringName, String> VisualShaderNodeTextureParameter::get_editable_prope names.insert("color_default", RTR("Default Color")); names.insert("texture_filter", RTR("Filter")); names.insert("texture_repeat", RTR("Repeat")); + names.insert("texture_source", RTR("Source")); return names; } @@ -6318,19 +6425,23 @@ void VisualShaderNodeTextureParameter::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture_type", "type"), &VisualShaderNodeTextureParameter::set_texture_type); ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeTextureParameter::get_texture_type); - ClassDB::bind_method(D_METHOD("set_color_default", "type"), &VisualShaderNodeTextureParameter::set_color_default); + ClassDB::bind_method(D_METHOD("set_color_default", "color"), &VisualShaderNodeTextureParameter::set_color_default); ClassDB::bind_method(D_METHOD("get_color_default"), &VisualShaderNodeTextureParameter::get_color_default); ClassDB::bind_method(D_METHOD("set_texture_filter", "filter"), &VisualShaderNodeTextureParameter::set_texture_filter); ClassDB::bind_method(D_METHOD("get_texture_filter"), &VisualShaderNodeTextureParameter::get_texture_filter); - ClassDB::bind_method(D_METHOD("set_texture_repeat", "type"), &VisualShaderNodeTextureParameter::set_texture_repeat); + ClassDB::bind_method(D_METHOD("set_texture_repeat", "repeat"), &VisualShaderNodeTextureParameter::set_texture_repeat); ClassDB::bind_method(D_METHOD("get_texture_repeat"), &VisualShaderNodeTextureParameter::get_texture_repeat); + ClassDB::bind_method(D_METHOD("set_texture_source", "source"), &VisualShaderNodeTextureParameter::set_texture_source); + ClassDB::bind_method(D_METHOD("get_texture_source"), &VisualShaderNodeTextureParameter::get_texture_source); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White,Black,Transparent"), "set_color_default", "get_color_default"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Default,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Default,Enabled,Disabled"), "set_texture_repeat", "get_texture_repeat"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_source", PROPERTY_HINT_ENUM, "None,Screen,Depth,NormalRoughness"), "set_texture_source", "get_texture_source"); BIND_ENUM_CONSTANT(TYPE_DATA); BIND_ENUM_CONSTANT(TYPE_COLOR); @@ -6356,6 +6467,12 @@ void VisualShaderNodeTextureParameter::_bind_methods() { BIND_ENUM_CONSTANT(REPEAT_ENABLED); BIND_ENUM_CONSTANT(REPEAT_DISABLED); BIND_ENUM_CONSTANT(REPEAT_MAX); + + BIND_ENUM_CONSTANT(SOURCE_NONE); + BIND_ENUM_CONSTANT(SOURCE_SCREEN); + BIND_ENUM_CONSTANT(SOURCE_DEPTH); + BIND_ENUM_CONSTANT(SOURCE_NORMAL_ROUGHNESS); + BIND_ENUM_CONSTANT(SOURCE_MAX); } bool VisualShaderNodeTextureParameter::is_qualifier_supported(Qualifier p_qual) const { @@ -6396,7 +6513,7 @@ String VisualShaderNodeTexture2DParameter::get_output_port_name(int p_port) cons String VisualShaderNodeTexture2DParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform sampler2D " + get_parameter_name(); - code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat); + code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source); code += ";\n"; return code; } @@ -6496,7 +6613,7 @@ String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func(Shade String VisualShaderNodeTextureParameterTriplanar::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform sampler2D " + get_parameter_name(); - code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat); + code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source); code += ";\n"; return code; } @@ -6542,7 +6659,7 @@ String VisualShaderNodeTexture2DArrayParameter::get_output_port_name(int p_port) String VisualShaderNodeTexture2DArrayParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform sampler2DArray " + get_parameter_name(); - code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat); + code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source); code += ";\n"; return code; } @@ -6562,7 +6679,7 @@ String VisualShaderNodeTexture3DParameter::get_output_port_name(int p_port) cons String VisualShaderNodeTexture3DParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform sampler3D " + get_parameter_name(); - code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat); + code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source); code += ";\n"; return code; } @@ -6582,7 +6699,7 @@ String VisualShaderNodeCubemapParameter::get_output_port_name(int p_port) const String VisualShaderNodeCubemapParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = _get_qual_str() + "uniform samplerCube " + get_parameter_name(); - code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat); + code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source); code += ";\n"; return code; } diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 07843c0264..8d0f88d83a 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -385,6 +385,8 @@ public: SOURCE_2D_NORMAL, SOURCE_DEPTH, SOURCE_PORT, + SOURCE_3D_NORMAL, + SOURCE_ROUGHNESS, SOURCE_MAX, }; @@ -668,6 +670,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual bool has_output_port_preview(int p_port) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; 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; VisualShaderNodeLinearSceneDepth(); @@ -2362,11 +2365,20 @@ public: REPEAT_MAX, }; + enum TextureSource { + SOURCE_NONE, + SOURCE_SCREEN, + SOURCE_DEPTH, + SOURCE_NORMAL_ROUGHNESS, + SOURCE_MAX, + }; + protected: TextureType texture_type = TYPE_DATA; ColorDefault color_default = COLOR_DEFAULT_WHITE; TextureFilter texture_filter = FILTER_DEFAULT; TextureRepeat texture_repeat = REPEAT_DEFAULT; + TextureSource texture_source = SOURCE_NONE; protected: static void _bind_methods(); @@ -2398,6 +2410,9 @@ public: void set_texture_repeat(TextureRepeat p_repeat); TextureRepeat get_texture_repeat() const; + void set_texture_source(TextureSource p_source); + TextureSource get_texture_source() const; + bool is_qualifier_supported(Qualifier p_qual) const override; bool is_convertible_to_constant() const override; @@ -2408,6 +2423,7 @@ VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureType) VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::ColorDefault) VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureFilter) VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureRepeat) +VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureSource) /////////////////////////////////////// diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 7eabce2f79..412406c0b4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -44,7 +44,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { valid = false; ubo_size = 0; uniforms.clear(); - uses_screen_texture = false; if (code.is_empty()) { return; //just invalid, but no error @@ -73,9 +72,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { uses_position = false; uses_sss = false; uses_transmittance = false; - uses_screen_texture = false; - uses_depth_texture = false; - uses_normal_texture = false; uses_time = false; writes_modelview_or_projection = false; uses_world_coordinates = false; @@ -120,9 +116,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; - actions.usage_flag_pointers["NORMAL_ROUGHNESS_TEXTURE"] = &uses_normal_texture; actions.usage_flag_pointers["DISCARD"] = &uses_discard; actions.usage_flag_pointers["TIME"] = &uses_time; actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; @@ -151,6 +144,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_test = DepthTest(depth_testi); cull_mode = Cull(cull_modei); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; + uses_depth_texture = gen_code.uses_depth_texture; + uses_normal_texture = gen_code.uses_normal_roughness_texture; uses_vertex_time = gen_code.uses_vertex_time; uses_fragment_time = gen_code.uses_fragment_time; @@ -607,9 +603,6 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["POINT_COORD"] = "gl_PointCoord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "color_buffer"; - actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; actions.renames["FOG"] = "fog"; @@ -674,7 +667,6 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; @@ -707,10 +699,6 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps - actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]"; - actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter - actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index ee4c8001eb..3d1d78c63d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -46,7 +46,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { valid = false; ubo_size = 0; uniforms.clear(); - uses_screen_texture = false; if (code.is_empty()) { return; //just invalid, but no error @@ -74,9 +73,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { uses_vertex = false; uses_sss = false; uses_transmittance = false; - uses_screen_texture = false; - uses_depth_texture = false; - uses_normal_texture = false; uses_time = false; writes_modelview_or_projection = false; uses_world_coordinates = false; @@ -121,9 +117,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { // actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; // actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; - actions.usage_flag_pointers["NORMAL_ROUGHNESS_TEXTURE"] = &uses_normal_texture; actions.usage_flag_pointers["DISCARD"] = &uses_discard; actions.usage_flag_pointers["TIME"] = &uses_time; actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; @@ -152,6 +145,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { depth_test = DepthTest(depth_testi); uses_vertex_time = gen_code.uses_vertex_time; uses_fragment_time = gen_code.uses_fragment_time; + uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; + uses_depth_texture = gen_code.uses_depth_texture; + uses_normal_texture = gen_code.uses_normal_roughness_texture; #if 0 print_line("**compiling shader:"); @@ -498,9 +495,6 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["POINT_COORD"] = "gl_PointCoord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "color_buffer"; - actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; actions.renames["FOG"] = "fog"; @@ -565,7 +559,6 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 1f92697ecc..6f1f00cedc 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -128,6 +128,7 @@ public: bool uses_screen_texture = false; bool uses_depth_texture = false; bool uses_normal_texture = false; + bool uses_screen_texture_mipmaps = false; bool uses_time = false; bool uses_vertex_time = false; bool uses_fragment_time = false; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 07557eab81..462b925134 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2036,7 +2036,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA); actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED); - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; actions.usage_flag_pointers["texture_sdf"] = &uses_sdf; actions.usage_flag_pointers["TIME"] = &uses_time; @@ -2048,6 +2047,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; if (version.is_null()) { version = canvas_singleton->shader.canvas_shader.version_create(); @@ -2425,7 +2425,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture"; actions.renames["SPECULAR_SHININESS"] = "specular_shininess"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "screen_texture"; actions.renames["SCREEN_PIXEL_SIZE"] = "canvas_data.screen_pixel_size"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; actions.renames["POINT_COORD"] = "gl_PointCoord"; @@ -2446,7 +2445,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.renames["screen_uv_to_sdf"] = "screen_uv_to_sdf"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; @@ -2461,7 +2459,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.custom_samplers["TEXTURE"] = "texture_sampler"; actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler"; actions.custom_samplers["SPECULAR_SHININESS_TEXTURE"] = "texture_sampler"; - actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; //mipmap and filter for screen texture actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; actions.texture_layout_set = MATERIAL_UNIFORM_SET; @@ -2634,8 +2631,10 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { shader_type canvas_item; +uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; + void fragment() { - vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0); if (c.a > 0.0001) { c.rgb /= c.a; @@ -2659,8 +2658,10 @@ void fragment() { shader_type canvas_item; +uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; + void fragment() { - vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0); COLOR.rgb = c.rgb; } )"); diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index fe4bf4bed0..a904f4e0a6 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -137,7 +137,7 @@ layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture; layout(set = 0, binding = 5) uniform sampler shadow_sampler; -layout(set = 0, binding = 6) uniform texture2D screen_texture; +layout(set = 0, binding = 6) uniform texture2D color_buffer; layout(set = 0, binding = 7) uniform texture2D sdf_texture; layout(set = 0, binding = 8) uniform sampler material_samplers[12]; diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 626da90168..68542f32af 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -909,9 +909,6 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (p_default_actions.renames.has(vnode->name)) { code = p_default_actions.renames[vnode->name]; - if (vnode->name == "SCREEN_TEXTURE") { - r_gen_code.uses_screen_texture_mipmaps = true; - } } else { if (shader->uniforms.has(vnode->name)) { //its a uniform! @@ -919,29 +916,22 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (u.texture_order >= 0) { StringName name = vnode->name; if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) { - name = "SCREEN_TEXTURE"; + name = "color_buffer"; if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) { r_gen_code.uses_screen_texture_mipmaps = true; } + r_gen_code.uses_screen_texture = true; } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) { - name = "NORMAL_ROUGHNESS_TEXTURE"; + name = "normal_roughness_buffer"; + r_gen_code.uses_normal_roughness_texture = true; } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { - name = "DEPTH_TEXTURE"; + name = "depth_buffer"; + r_gen_code.uses_depth_texture = true; } else { name = _mkid(vnode->name); //texture, use as is } - if (p_default_actions.renames.has(name)) { - code = p_default_actions.renames[name]; - } else { - code = name; - } - - if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) { - *p_actions.usage_flag_pointers[name] = true; - used_flag_pointers.insert(name); - } - + code = name; } else { //a scalar or vector if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { @@ -1251,16 +1241,20 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } if (correct_texture_uniform) { - //TODO Needs to detect screen_texture hint as well - is_screen_texture = (texture_uniform == "SCREEN_TEXTURE"); - String sampler_name; + bool is_normal_roughness_texture = false; if (actions.custom_samplers.has(texture_uniform)) { sampler_name = actions.custom_samplers[texture_uniform]; } else { if (shader->uniforms.has(texture_uniform)) { - sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat); + const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform]; + if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) { + is_screen_texture = true; + } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) { + is_normal_roughness_texture = true; + } + sampler_name = _get_sampler_name(u.filter, u.repeat); } else { bool found = false; @@ -1287,7 +1281,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } String data_type_name = ""; - if (texture_uniform == "NORMAL_ROUGHNESS_TEXTURE") { + if (is_normal_roughness_texture) { data_type_name = "multiviewSampler"; normal_roughness_texture_used = true; } else { @@ -1515,6 +1509,9 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident r_gen_code.uses_vertex_time = false; r_gen_code.uses_global_textures = false; r_gen_code.uses_screen_texture_mipmaps = false; + r_gen_code.uses_screen_texture = false; + r_gen_code.uses_depth_texture = false; + r_gen_code.uses_normal_roughness_texture = false; used_name_defines.clear(); used_rmode_defines.clear(); diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h index eeb2916160..43bea213da 100644 --- a/servers/rendering/shader_compiler.h +++ b/servers/rendering/shader_compiler.h @@ -81,6 +81,9 @@ public: bool uses_fragment_time; bool uses_vertex_time; bool uses_screen_texture_mipmaps; + bool uses_screen_texture; + bool uses_depth_texture; + bool uses_normal_roughness_texture; }; struct DefaultIdentifierActions { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 59a2ff66f3..5ecc38a63b 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -5399,6 +5399,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } else { if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { + if (identifier == "SCREEN_TEXTURE" || identifier == "DEPTH_TEXTURE" || identifier == "NORMAL_ROUGHNESS_TEXTURE") { + String name = String(identifier); + String name_lower = name.to_lower(); + _set_error(vformat(RTR("%s has been removed in favor of using hint_%s with a uniform.\nTo continue with minimal code changes add 'uniform sampler2D %s : hint_%s, filter_linear_mipmaps;' near the top of your shader."), name, name_lower, name, name_lower)); + return nullptr; + } _set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier))); return nullptr; } diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 38dc806370..ba39328b2e 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -138,9 +138,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_ROUGHNESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); @@ -267,7 +264,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].main_function = true; diff --git a/tests/core/io/test_xml_parser.h b/tests/core/io/test_xml_parser.h index f4e3f34be2..40cbea2dab 100644 --- a/tests/core/io/test_xml_parser.h +++ b/tests/core/io/test_xml_parser.h @@ -54,7 +54,7 @@ TEST_CASE("[XMLParser] End-to-end") { CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_ELEMENT); CHECK(parser.get_node_name() == "top"); CHECK(parser.has_attribute("attr")); - CHECK(parser.get_attribute_value("attr") == "attr value"); + CHECK(parser.get_named_attribute_value("attr") == "attr value"); CHECK(parser.read() == OK); CHECK(parser.get_node_type() == XMLParser::NodeType::NODE_TEXT); |