diff options
215 files changed, 5194 insertions, 3699 deletions
diff --git a/.gitattributes b/.gitattributes index 45ea6c25e8..8d2fb108ba 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,8 @@ thirdparty/* linguist-vendored * text=auto eol=lf # Except for bat files, which are Windows only files *.bat eol=crlf +# And some test files where the EOL matters +*.test.txt -text # The above only works properly for Git 2.10+, so for older versions # we need to manually list the binary files we don't want modified. diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 341d70d0e7..8c716242e4 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -19,30 +19,15 @@ jobs: fail-fast: false matrix: include: -# Temporarily disabled until Mono is fixed -# -# - name: Editor w Mono (target=release_debug, tools=yes, tests=yes) -# cache-name: linux-editor-mono -# target: release_debug -# tools: true -# tests: false # Disabled due freeze caused by mix Mono build and CI -# sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no -# doc-test: true -# bin: "./bin/godot.linuxbsd.opt.tools.64.mono" -# build-mono: true -# proj-conv: true -# artifact: true - -# Temporary replacement: - - - name: Editor w/o Mono (target=release_debug, tools=yes, tests=yes) + - name: Editor w Mono (target=release_debug, tools=yes, tests=yes) cache-name: linux-editor-mono target: release_debug tools: true tests: false # Disabled due freeze caused by mix Mono build and CI + sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no doc-test: true - bin: "./bin/godot.linuxbsd.opt.tools.64" - build-mono: false + bin: "./bin/godot.linuxbsd.opt.tools.64.mono" + build-mono: true proj-conv: true artifact: true @@ -72,24 +57,12 @@ jobs: # Skip 2GiB artifact speeding up action. artifact: false -# Temporarily disabled: -# -# - name: Template w/ Mono (target=release, tools=no) -# cache-name: linux-template-mono -# target: release -# tools: false -# tests: false -# sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no debug_symbols=no -# build-mono: false -# artifact: true - -# Temporary replacement: - - - name: Template w/o Mono (target=release, tools=no) + - name: Template w/ Mono (target=release, tools=no) cache-name: linux-template-mono target: release tools: false tests: false + sconsflags: module_mono_enabled=yes mono_static=yes mono_glue=no debug_symbols=no build-mono: false artifact: true diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 3852f77bfc..2cf6e8a025 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -46,8 +46,8 @@ namespace core_bind { ResourceLoader *ResourceLoader::singleton = nullptr; -Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads) { - return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads); +Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, CacheMode p_cache_mode) { + return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads, ResourceFormatLoader::CacheMode(p_cache_mode)); } ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) { @@ -121,7 +121,7 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) { } void ResourceLoader::_bind_methods() { - ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads", "cache_mode"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE)); ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &ResourceLoader::load_threaded_get); @@ -331,6 +331,39 @@ Vector<String> OS::get_cmdline_args() { return cmdlinev; } +Vector<String> OS::get_cmdline_user_args() { + List<String> cmdline = ::OS::get_singleton()->get_cmdline_user_args(); + Vector<String> cmdlinev; + for (const String &E : cmdline) { + cmdlinev.push_back(E); + } + + return cmdlinev; +} + +void OS::set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments) { + List<String> args_list; + for (const String &restart_argument : p_restart_arguments) { + args_list.push_back(restart_argument); + } + + ::OS::get_singleton()->set_restart_on_exit(p_restart, args_list); +} + +bool OS::is_restart_on_exit_set() const { + return ::OS::get_singleton()->is_restart_on_exit_set(); +} + +Vector<String> OS::get_restart_on_exit_arguments() const { + List<String> args = ::OS::get_singleton()->get_restart_on_exit_arguments(); + Vector<String> args_vector; + for (List<String>::Element *E = args.front(); E; E = E->next()) { + args_vector.push_back(E->get()); + } + + return args_vector; +} + String OS::get_locale() const { return ::OS::get_singleton()->get_locale(); } @@ -614,6 +647,11 @@ void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name); ClassDB::bind_method(D_METHOD("get_cmdline_args"), &OS::get_cmdline_args); + ClassDB::bind_method(D_METHOD("get_cmdline_user_args"), &OS::get_cmdline_user_args); + + ClassDB::bind_method(D_METHOD("set_restart_on_exit", "restart", "arguments"), &OS::set_restart_on_exit, DEFVAL(Vector<String>())); + ClassDB::bind_method(D_METHOD("is_restart_on_exit_set"), &OS::is_restart_on_exit_set); + ClassDB::bind_method(D_METHOD("get_restart_on_exit_arguments"), &OS::get_restart_on_exit_arguments); ClassDB::bind_method(D_METHOD("delay_usec", "usec"), &OS::delay_usec); ClassDB::bind_method(D_METHOD("delay_msec", "msec"), &OS::delay_msec); @@ -1227,13 +1265,13 @@ Vector<uint8_t> File::get_buffer(int64_t p_length) const { return data; } -String File::get_as_text() const { +String File::get_as_text(bool p_skip_cr) const { ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission."); uint64_t original_pos = f->get_position(); const_cast<FileAccess *>(*f)->seek(0); - String text = f->get_as_utf8_string(); + String text = f->get_as_utf8_string(p_skip_cr); const_cast<FileAccess *>(*f)->seek(original_pos); @@ -1430,7 +1468,7 @@ void File::_bind_methods() { ClassDB::bind_method(D_METHOD("get_buffer", "length"), &File::get_buffer); ClassDB::bind_method(D_METHOD("get_line"), &File::get_line); ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &File::get_csv_line, DEFVAL(",")); - ClassDB::bind_method(D_METHOD("get_as_text"), &File::get_as_text); + ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &File::get_as_text, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_md5", "path"), &File::get_md5); ClassDB::bind_method(D_METHOD("get_sha256", "path"), &File::get_sha256); ClassDB::bind_method(D_METHOD("is_big_endian"), &File::is_big_endian); diff --git a/core/core_bind.h b/core/core_bind.h index 068d2a6dc3..98bf34e07d 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -71,7 +71,7 @@ public: static ResourceLoader *get_singleton() { return singleton; } - Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false); + Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, CacheMode p_cache_mode = CACHE_MODE_REUSE); ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array()); Ref<Resource> load_threaded_get(const String &p_path); @@ -182,12 +182,17 @@ public: bool is_process_running(int p_pid) const; int get_process_id() const; + void set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments = Vector<String>()); + bool is_restart_on_exit_set() const; + Vector<String> get_restart_on_exit_arguments() const; + bool has_environment(const String &p_var) const; String get_environment(const String &p_var) const; bool set_environment(const String &p_var, const String &p_value) const; String get_name() const; Vector<String> get_cmdline_args(); + Vector<String> get_cmdline_user_args(); String get_locale() const; String get_locale_language() const; @@ -411,7 +416,7 @@ public: Vector<uint8_t> get_buffer(int64_t p_length) const; // Get an array of bytes. String get_line() const; Vector<String> get_csv_line(const String &p_delim = ",") const; - String get_as_text() const; + String get_as_text(bool p_skip_cr = false) const; String get_md5(const String &p_path) const; String get_sha256(const String &p_path) const; diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index da25f23917..8ed3d40c22 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -377,7 +377,7 @@ uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const { return i; } -String FileAccess::get_as_utf8_string() const { +String FileAccess::get_as_utf8_string(bool p_skip_cr) const { Vector<uint8_t> sourcef; uint64_t len = get_length(); sourcef.resize(len + 1); @@ -388,7 +388,7 @@ String FileAccess::get_as_utf8_string() const { w[len] = 0; String s; - s.parse_utf8((const char *)w); + s.parse_utf8((const char *)w, -1, p_skip_cr); return s; } diff --git a/core/io/file_access.h b/core/io/file_access.h index e2c11142d7..3386800686 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -113,7 +113,7 @@ public: virtual String get_line() const; virtual String get_token() const; virtual Vector<String> get_csv_line(const String &p_delim = ",") const; - virtual String get_as_utf8_string() const; + virtual String get_as_utf8_string(bool p_skip_cr = false) const; /** * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) diff --git a/core/math/vector4.cpp b/core/math/vector4.cpp index ed42d8bfb9..cc0d0dcf72 100644 --- a/core/math/vector4.cpp +++ b/core/math/vector4.cpp @@ -89,7 +89,7 @@ Vector4::Axis Vector4::min_axis_index() const { uint32_t min_index = 0; real_t min_value = x; for (uint32_t i = 1; i < 4; i++) { - if (operator[](i) < min_value) { + if (operator[](i) <= min_value) { min_index = i; min_value = operator[](i); } diff --git a/core/math/vector4i.cpp b/core/math/vector4i.cpp index 8c571b02e3..2dc5b74202 100644 --- a/core/math/vector4i.cpp +++ b/core/math/vector4i.cpp @@ -47,7 +47,7 @@ Vector4i::Axis Vector4i::min_axis_index() const { uint32_t min_index = 0; int32_t min_value = x; for (uint32_t i = 1; i < 4; i++) { - if (operator[](i) < min_value) { + if (operator[](i) <= min_value) { min_index = i; min_value = operator[](i); } diff --git a/core/object/object.h b/core/object/object.h index f3f89982d9..649f42c9a0 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -50,7 +50,7 @@ enum PropertyHint { PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,no_slider][,radians][,degrees][,exp][,suffix:<keyword>] range. PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_ENUM_SUGGESTION, ///< hint_text= "val1,val2,val3,etc" - PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "full" to also include in/out. (ie: "attenuation,inout") + PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) use "attenuation" hint string to revert (flip h), "positive_only" to exclude in-out and out-in. (ie: "attenuation,positive_only") PROPERTY_HINT_LINK, PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_LAYERS_2D_RENDER, diff --git a/core/os/os.cpp b/core/os/os.cpp index 619e3eb06f..1358c926d1 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -362,9 +362,10 @@ String OS::get_model_name() const { return "GenericDevice"; } -void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) { +void OS::set_cmdline(const char *p_execpath, const List<String> &p_args, const List<String> &p_user_args) { _execpath = String::utf8(p_execpath); _cmdline = p_args; + _user_args = p_user_args; } String OS::get_unique_id() const { diff --git a/core/os/os.h b/core/os/os.h index b9f7328929..9152b797ef 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -46,6 +46,7 @@ class OS { static uint64_t target_ticks; String _execpath; List<String> _cmdline; + List<String> _user_args; bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. bool low_processor_usage_mode = false; int low_processor_usage_mode_sleep_usec = 10000; @@ -106,7 +107,7 @@ protected: virtual void finalize() = 0; virtual void finalize_core() = 0; - virtual void set_cmdline(const char *p_execpath, const List<String> &p_args); + virtual void set_cmdline(const char *p_execpath, const List<String> &p_args, const List<String> &p_user_args); virtual bool _check_internal_feature_support(const String &p_feature) = 0; @@ -162,6 +163,7 @@ public: virtual String get_name() const = 0; virtual List<String> get_cmdline_args() const { return _cmdline; } + virtual List<String> get_cmdline_user_args() const { return _user_args; } virtual List<String> get_cmdline_platform_args() const { return List<String>(); } virtual String get_model_name() const; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index beefe54faf..e93375bff7 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1656,7 +1656,7 @@ String String::utf8(const char *p_utf8, int p_len) { return ret; } -Error String::parse_utf8(const char *p_utf8, int p_len) { +Error String::parse_utf8(const char *p_utf8, int p_len, bool p_skip_cr) { if (!p_utf8) { return ERR_INVALID_DATA; } @@ -1689,6 +1689,10 @@ Error String::parse_utf8(const char *p_utf8, int p_len) { uint8_t c = *ptrtmp >= 0 ? *ptrtmp : uint8_t(256 + *ptrtmp); if (skip == 0) { + if (p_skip_cr && c == '\r') { + ptrtmp++; + continue; + } /* Determine the number of characters in sequence */ if ((c & 0x80) == 0) { skip = 0; @@ -1753,6 +1757,10 @@ Error String::parse_utf8(const char *p_utf8, int p_len) { uint8_t c = *p_utf8 >= 0 ? *p_utf8 : uint8_t(256 + *p_utf8); if (skip == 0) { + if (p_skip_cr && c == '\r') { + p_utf8++; + continue; + } /* Determine the number of characters in sequence */ if ((c & 0x80) == 0) { *(dst++) = c; diff --git a/core/string/ustring.h b/core/string/ustring.h index 7672663964..6c3169f136 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -377,7 +377,7 @@ public: CharString ascii(bool p_allow_extended = false) const; CharString utf8() const; - Error parse_utf8(const char *p_utf8, int p_len = -1); + Error parse_utf8(const char *p_utf8, int p_len = -1, bool p_skip_cr = false); static String utf8(const char *p_utf8, int p_len = -1); Char16String utf16() const; diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index a92b237624..f40f11944d 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -391,13 +391,13 @@ </description> </method> <method name="track_insert_key"> - <return type="void" /> + <return type="int" /> <argument index="0" name="track_idx" type="int" /> <argument index="1" name="time" type="float" /> <argument index="2" name="key" type="Variant" /> <argument index="3" name="transition" type="float" default="1" /> <description> - Insert a generic key in a given track. + Inserts a generic key in a given track. Returns the key index. </description> </method> <method name="track_is_compressed" qualifiers="const"> diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index b24c439432..d3c8bdac3a 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AnimationPlayer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> - Container and player of [Animation] resources. + Player of [Animation] resources. </brief_description> <description> - An animation player is used for general-purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in different channels. - [AnimationPlayer] is more suited than [Tween] for animations where you know the final values in advance. For example, fading a screen in and out is more easily done with an [AnimationPlayer] node thanks to the animation tools provided by the editor. That particular example can also be implemented with a [Tween] node, but it requires doing everything by code. + An animation player is used for general-purpose playback of [Animation] resources. It contains a dictionary of [AnimationLibrary] resources and custom blend times between animation transitions. + Some methods and properties use a single key to refence an animation directly. These keys are formatted as the key for the library, followed by a forward slash, then the key for the animation whithin the library, for example [code]"movement/run"[/code]. If the library's key is an empty string (known as the default library), the forward slash is omitted, being the same key used by the library. + [AnimationPlayer] is more suited than [Tween] for animations where you know the final values in advance. For example, fading a screen in and out is more easily done with an [AnimationPlayer] node thanks to the animation tools provided by the editor. That particular example can also be implemented with a [Tween], but it requires doing everything by code. Updating the target properties of animations occurs at process time. </description> <tutorials> @@ -19,6 +20,7 @@ <argument index="0" name="name" type="StringName" /> <argument index="1" name="library" type="AnimationLibrary" /> <description> + Adds [code]library[/code] to the animation player, under the key [code]name[/code]. </description> </method> <method name="advance"> @@ -32,7 +34,7 @@ <return type="StringName" /> <argument index="0" name="anim_from" type="StringName" /> <description> - Returns the name of the next animation in the queue. + Returns the key of the animation which is queued to play after the [code]anim_from[/code] animation. </description> </method> <method name="animation_set_next"> @@ -59,13 +61,14 @@ <return type="StringName" /> <argument index="0" name="animation" type="Animation" /> <description> - Returns the name of [code]animation[/code] or an empty string if not found. + Returns the key of [code]animation[/code] or an empty [StringName] if not found. </description> </method> <method name="find_animation_library" qualifiers="const"> <return type="StringName" /> <argument index="0" name="animation" type="Animation" /> <description> + Returns the key for the [AnimationLibrary] that contains [code]animation[/code] or an empty [StringName] if not found. </description> </method> <method name="get_animation" qualifiers="const"> @@ -79,17 +82,19 @@ <return type="AnimationLibrary" /> <argument index="0" name="name" type="StringName" /> <description> + Returns the first [AnimationLibrary] with key [code]name[/code] or [code]null[/code] if not found. </description> </method> <method name="get_animation_library_list" qualifiers="const"> <return type="StringName[]" /> <description> + Returns the list of stored library keys. </description> </method> <method name="get_animation_list" qualifiers="const"> <return type="PackedStringArray" /> <description> - Returns the list of stored animation names. + Returns the list of stored animation keys. </description> </method> <method name="get_blend_time" qualifiers="const"> @@ -97,7 +102,7 @@ <argument index="0" name="anim_from" type="StringName" /> <argument index="1" name="anim_to" type="StringName" /> <description> - Gets the blend time (in seconds) between two animations, referenced by their names. + Gets the blend time (in seconds) between two animations, referenced by their keys. </description> </method> <method name="get_playing_speed" qualifiers="const"> @@ -109,7 +114,7 @@ <method name="get_queue"> <return type="PackedStringArray" /> <description> - Returns a list of the animation names that are currently queued to play. + Returns a list of the animation keys that are currently queued to play. </description> </method> <method name="has_animation" qualifiers="const"> @@ -123,6 +128,7 @@ <return type="bool" /> <argument index="0" name="name" type="StringName" /> <description> + Returns [code]true[/code] if the [AnimationPlayer] stores an [AnimationLibrary] with key [code]name[/code]. </description> </method> <method name="is_playing" qualifiers="const"> @@ -164,6 +170,7 @@ <return type="void" /> <argument index="0" name="name" type="StringName" /> <description> + Removes the [AnimationLibrary] assosiated with the key [code]name[/code]. </description> </method> <method name="rename_animation_library"> @@ -171,6 +178,7 @@ <argument index="0" name="name" type="StringName" /> <argument index="1" name="newname" type="StringName" /> <description> + Moves the [AnimationLibrary] associated with the key [code]name[/code] to the key [code]newname[/code]. </description> </method> <method name="seek"> @@ -188,7 +196,7 @@ <argument index="1" name="anim_to" type="StringName" /> <argument index="2" name="sec" type="float" /> <description> - Specifies a blend time (in seconds) between two animations, referenced by their names. + Specifies a blend time (in seconds) between two animations, referenced by their keys. </description> </method> <method name="stop"> @@ -202,17 +210,17 @@ </methods> <members> <member name="assigned_animation" type="String" setter="set_assigned_animation" getter="get_assigned_animation"> - If playing, the current animation; otherwise, the animation last played. When set, would change the animation, but would not play it unless currently playing. See also [member current_animation]. + If playing, the the current animation's key, otherwise, the animation last played. When set, this changes the animation, but will not play it unless already playing. See also [member current_animation]. </member> <member name="autoplay" type="String" setter="set_autoplay" getter="get_autoplay" default=""""> - The name of the animation to play when the scene loads. + The key of the animation to play when the scene loads. </member> <member name="current_animation" type="String" setter="set_current_animation" getter="get_current_animation" default=""""> - The name of the currently playing animation. If no animation is playing, the property's value is an empty string. Changing this value does not restart the animation. See [method play] for more information on playing animations. + The key of the currently playing animation. If no animation is playing, the property's value is an empty string. Changing this value does not restart the animation. See [method play] for more information on playing animations. [b]Note:[/b] while this property appears in the inspector, it's not meant to be edited, and it's not saved in the scene. This property is mainly used to get the currently playing animation, and internally for animation playback tracks. For more information, see [Animation]. </member> <member name="current_animation_length" type="float" setter="" getter="get_current_animation_length"> - The length (in seconds) of the currently being played animation. + The length (in seconds) of the currently playing animation. </member> <member name="current_animation_position" type="float" setter="" getter="get_current_animation_position"> The position (in seconds) of the currently playing animation. @@ -237,8 +245,8 @@ The speed scaling ratio. For instance, if this value is 1, then the animation plays at normal speed. If it's 0.5, then it plays at half speed. If it's 2, then it plays at double speed. </member> <member name="reset_on_save" type="bool" setter="set_reset_on_save_enabled" getter="is_reset_on_save_enabled" default="true"> - This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation applied (as if it had been seeked to time 0), then reverted after saving. - In other words, the saved scene file will contain the "default pose", as defined by the reset animation, if any, with the editor keeping the values that the nodes had before saving. + This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation (the animation with the key [code]"RESET"[/code]) applied as if it had been seeked to time 0, with the editor keeping the values that the scene had before saving. + This makes it more convenient to preview and edit animations in the editor, as changes to the scene will not be saved as long as they are set in the reset animation. </member> <member name="root_node" type="NodePath" setter="set_root" getter="get_root" default="NodePath("..")"> The node from which node path references will travel. @@ -249,8 +257,8 @@ <argument index="0" name="old_name" type="StringName" /> <argument index="1" name="new_name" type="StringName" /> <description> - Emitted when a queued animation plays after the previous animation was finished. See [method queue]. - [b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or from [AnimationTree]. + Emitted when a queued animation plays after the previous animation finished. See [method queue]. + [b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or by an [AnimationTree]. </description> </signal> <signal name="animation_finished"> diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index b3cea7217e..16359108a4 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -241,7 +241,7 @@ A high value makes the material appear more like a metal. Non-metals use their albedo as the diffuse color and add diffuse to the specular reflection. With non-metals, the reflection appears on top of the albedo color. Metals use their albedo as a multiplier to the specular reflection and set the diffuse color to black resulting in a tinted reflection. Materials work better when fully metal or fully non-metal, values between [code]0[/code] and [code]1[/code] should only be used for blending between metal and non-metal sections. To alter the amount of reflection use [member roughness]. </member> <member name="metallic_specular" type="float" setter="set_specular" getter="get_specular" default="0.5"> - Sets the size of the specular lobe. The specular lobe is the bright spot that is reflected from light sources. + Adjusts the strength of specular reflections. Specular reflections are composed of scene reflections and the specular lobe which is the bright spot that is reflected from light sources. When set to [code]0.0[/code], no specular reflections will be visible. This differs from the [constant SPECULAR_DISABLED] [enum SpecularMode] as [constant SPECULAR_DISABLED] only applies to the specular lobe from the light source. [b]Note:[/b] Unlike [member metallic], this is not energy-conserving, so it should be left at [code]0.5[/code] in most cases. See also [member roughness]. </member> <member name="metallic_texture" type="Texture2D" setter="set_texture" getter="get_texture"> diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml index b86104a5e3..3322ab4c66 100644 --- a/doc/classes/Decal.xml +++ b/doc/classes/Decal.xml @@ -58,7 +58,7 @@ </methods> <members> <member name="albedo_mix" type="float" setter="set_albedo_mix" getter="get_albedo_mix" default="1.0"> - Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh. + Blends the albedo [Color] of the decal with albedo [Color] of the underlying mesh. This can be set to [code]0.0[/code] to create a decal that only affects normal or ORM. In this case, an albedo texture is still required as its alpha channel will determine where the normal and ORM will be overridden. See also [member modulate]. </member> <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575"> Specifies which [member VisualInstance3D.layers] this decal will project on. By default, Decals affect all layers. This is used so you can specify which types of objects receive the Decal and which do not. This is especially useful so you can ensure that dynamic objects don't accidentally receive a Decal intended for the terrain under them. @@ -70,22 +70,23 @@ If [code]true[/code], decals will smoothly fade away when far from the active [Camera3D] starting at [member distance_fade_begin]. The Decal will fade out over [member distance_fade_begin] + [member distance_fade_length], after which it will be culled and not sent to the shader at all. Use this to reduce the number of active Decals in a scene and thus improve performance. </member> <member name="distance_fade_length" type="float" setter="set_distance_fade_length" getter="get_distance_fade_length" default="10.0"> - The distance over which the Decal fades (in 3D units). The Decal becomes slowly more transparent over this distance and is completely invisible at the end. + The distance over which the Decal fades (in 3D units). The Decal becomes slowly more transparent over this distance and is completely invisible at the end. Higher values result in a smoother fade-out transition, which is more suited when the camera moves fast. </member> <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0"> - Energy multiplier for the emission texture. This will make the decal emit light at a higher intensity. + Energy multiplier for the emission texture. This will make the decal emit light at a higher or lower intensity, independently of the albedo color. See also [member modulate]. </member> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> Sets the size of the [AABB] used by the decal. The AABB goes from [code]-extents[/code] to [code]extents[/code]. </member> <member name="lower_fade" type="float" setter="set_lower_fade" getter="get_lower_fade" default="0.3"> - Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). + Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). See also [member upper_fade]. </member> <member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)"> - Changes the [Color] of the Decal by multiplying it with this value. + Changes the [Color] of the Decal by multiplying the albedo and emission colors with this value. The alpha component is only taken into account when multiplying the albedo color, not the emission color. See also [member emission_energy] and [member albedo_mix] to change the emission and albedo intensity independently of each other. </member> <member name="normal_fade" type="float" setter="set_normal_fade" getter="get_normal_fade" default="0.0"> Fades the Decal if the angle between the Decal's [AABB] and the target surface becomes too large. A value of [code]0[/code] projects the Decal regardless of angle, a value of [code]1[/code] limits the Decal to surfaces that are nearly perpendicular. + [b]Note:[/b] Setting [member normal_fade] to a value greater than [code]0.0[/code] has a small performance cost due to the added normal angle computations. </member> <member name="texture_albedo" type="Texture2D" setter="set_texture" getter="get_texture"> [Texture2D] with the base [Color] of the Decal. Either this or the [member texture_emission] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object. @@ -98,13 +99,15 @@ <member name="texture_normal" type="Texture2D" setter="set_texture" getter="get_texture"> [Texture2D] with the per-pixel normal map for the decal. Use this to add extra detail to decals. [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter]. + [b]Note:[/b] Setting this texture alone will not result in a visible decal, as [member texture_albedo] must also be set. To create a normal-only decal, load an albedo texture into [member texture_albedo] and set [member albedo_mix] to [code]0.0[/code]. The albedo texture's alpha channel will be used to determine where the underlying surface's normal map should be overridden (and its intensity). </member> <member name="texture_orm" type="Texture2D" setter="set_texture" getter="get_texture"> [Texture2D] storing ambient occlusion, roughness, and metallic for the decal. Use this to add extra detail to decals. [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter]. + [b]Note:[/b] Setting this texture alone will not result in a visible decal, as [member texture_albedo] must also be set. To create a ORM-only decal, load an albedo texture into [member texture_albedo] and set [member albedo_mix] to [code]0.0[/code]. The albedo texture's alpha channel will be used to determine where the underlying surface's ORM map should be overridden (and its intensity). </member> <member name="upper_fade" type="float" setter="set_upper_fade" getter="get_upper_fade" default="0.3"> - Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). + Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). See also [member lower_fade]. </member> </members> <constants> diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 84f8523da3..586458bd28 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -101,6 +101,13 @@ Used by sub-inspectors. Emit it if what was selected was an Object ID. </description> </signal> + <signal name="property_can_revert_changed"> + <argument index="0" name="property" type="StringName" /> + <argument index="1" name="can_revert" type="bool" /> + <description> + Emitted when the revertability (i.e., whether it has a non-default value and thus is displayed with a revert icon) of a property has changed. + </description> + </signal> <signal name="property_changed"> <argument index="0" name="property" type="StringName" /> <argument index="1" name="value" type="Variant" /> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 9da360915b..f662a07825 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -97,7 +97,7 @@ Blend factor between the fog's color and the color of the background [Sky]. Must have [member background_mode] set to [constant BG_SKY]. This is useful to simulate [url=https://en.wikipedia.org/wiki/Aerial_perspective]aerial perspective[/url] in large scenes with low density fog. However, it is not very useful for high-density fog, as the sky will shine through. When set to [code]1.0[/code], the fog color comes completely from the [Sky]. If set to [code]0.0[/code], aerial perspective is disabled. </member> - <member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.001"> + <member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.01"> The exponential fog density to use. Higher values result in a more dense fog. </member> <member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled" default="false"> @@ -109,7 +109,7 @@ <member name="fog_height_density" type="float" setter="set_fog_height_density" getter="get_fog_height_density" default="0.0"> The density used to increase fog as height decreases. To make fog increase as height increases, use a negative value. </member> - <member name="fog_light_color" type="Color" setter="set_fog_light_color" getter="get_fog_light_color" default="Color(0.5, 0.6, 0.7, 1)"> + <member name="fog_light_color" type="Color" setter="set_fog_light_color" getter="get_fog_light_color" default="Color(0.518, 0.553, 0.608, 1)"> The fog's color. </member> <member name="fog_light_energy" type="float" setter="set_fog_light_energy" getter="get_fog_light_energy" default="1.0"> @@ -320,8 +320,9 @@ <member name="volumetric_fog_enabled" type="bool" setter="set_volumetric_fog_enabled" getter="is_volumetric_fog_enabled" default="false"> Enables the volumetric fog effect. Volumetric fog uses a screen-aligned froxel buffer to calculate accurate volumetric scattering in the short to medium range. Volumetric fog interacts with [FogVolume]s and lights to calculate localized and global fog. Volumetric fog uses a PBR single-scattering model based on extinction, scattering, and emission which it exposes to users as density, albedo, and emission. </member> - <member name="volumetric_fog_gi_inject" type="float" setter="set_volumetric_fog_gi_inject" getter="get_volumetric_fog_gi_inject" default="0.0"> - Scales the strength of Global Illumination used in the volumetric fog. A value of [code]0[/code] means that Global Illumination will not impact the volumetric fog. + <member name="volumetric_fog_gi_inject" type="float" setter="set_volumetric_fog_gi_inject" getter="get_volumetric_fog_gi_inject" default="1.0"> + Scales the strength of Global Illumination used in the volumetric fog. A value of [code]0.0[/code] means that Global Illumination will not impact the volumetric fog. + [b]Note:[/b] Only [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) are taken into account when using [member volumetric_fog_gi_inject]. Global illumination from [LightmapGI], [ReflectionProbe] and SSIL (see [member ssil_enabled]) will be ignored by volumetric fog. </member> <member name="volumetric_fog_length" type="float" setter="set_volumetric_fog_length" getter="get_volumetric_fog_length" default="64.0"> The distance over which the volumetric fog is computed. Increase to compute fog over a greater range, decrease to add more detail when a long range is not needed. For best quality fog, keep this as low as possible. diff --git a/doc/classes/File.xml b/doc/classes/File.xml index 0b4a8fa46e..3a2776ff21 100644 --- a/doc/classes/File.xml +++ b/doc/classes/File.xml @@ -115,9 +115,10 @@ </method> <method name="get_as_text" qualifiers="const"> <return type="String" /> + <argument index="0" name="skip_cr" type="bool" default="false" /> <description> - Returns the whole file as a [String]. - Text is interpreted as being UTF-8 encoded. + Returns the whole file as a [String]. Text is interpreted as being UTF-8 encoded. + If [code]skip_cr[/code] is [code]true[/code], carriage return characters ([code]\r[/code], CR) will be ignored when parsing the UTF-8, so that only line feed characters ([code]\n[/code], LF) represent a new line (Unix convention). </description> </method> <method name="get_buffer" qualifiers="const"> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 965dbe7449..33145dccd0 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -55,6 +55,29 @@ [/codeblock] </description> </method> + <method name="_is_node_hover_valid" qualifiers="virtual"> + <return type="bool" /> + <argument index="0" name="from" type="StringName" /> + <argument index="1" name="from_slot" type="int" /> + <argument index="2" name="to" type="StringName" /> + <argument index="3" name="to_slot" type="int" /> + <description> + This virtual method can be used to insert additional error detection while the user is dragging a connection over a valid port. + Return [code]true[/code] if the connection is indeed valid or return [code]false[/code] if the connection is impossible. If the connection is impossible, no snapping to the port and thus no connection request to that port will happen. + In this example a connection to same node is suppressed: + [codeblocks] + [gdscript] + func _is_node_hover_valid(from, from_slot, to, to_slot): + return from != to + [/gdscript] + [csharp] + public override bool _IsNodeHoverValid(String from, int fromSlot, String to, int toSlot) { + return from != to; + } + [/csharp] + [/codeblocks] + </description> + </method> <method name="add_valid_connection_type"> <return type="void" /> <argument index="0" name="from_type" type="int" /> diff --git a/doc/classes/LabelSettings.xml b/doc/classes/LabelSettings.xml index 227313d3b3..aa972f2cf3 100644 --- a/doc/classes/LabelSettings.xml +++ b/doc/classes/LabelSettings.xml @@ -9,21 +9,21 @@ <members> <member name="font" type="Font" setter="set_font" getter="get_font"> </member> - <member name="font_color" type="Color" setter="set_font_color" getter="get_font_color" default="Color(0.875, 0.875, 0.875, 1)"> + <member name="font_color" type="Color" setter="set_font_color" getter="get_font_color" default="Color(1, 1, 1, 1)"> </member> <member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16"> </member> - <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0"> + <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="3.0"> </member> <member name="outline_color" type="Color" setter="set_outline_color" getter="get_outline_color" default="Color(1, 1, 1, 1)"> </member> <member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0"> </member> - <member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color" default="Color(1, 1, 1, 1)"> + <member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color" default="Color(0, 0, 0, 0)"> </member> <member name="shadow_offset" type="Vector2" setter="set_shadow_offset" getter="get_shadow_offset" default="Vector2(1, 1)"> </member> - <member name="shadow_size" type="int" setter="set_shadow_size" getter="get_shadow_size" default="0"> + <member name="shadow_size" type="int" setter="set_shadow_size" getter="get_shadow_size" default="1"> </member> </members> </class> diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml index 966f964b12..33d2535ca2 100644 --- a/doc/classes/NavigationMesh.xml +++ b/doc/classes/NavigationMesh.xml @@ -28,6 +28,7 @@ <argument index="0" name="mesh" type="Mesh" /> <description> Initializes the navigation mesh by setting the vertices and indices according to a [Mesh]. + [b]Note:[/b] The given [code]mesh[/code] must be of type [constant Mesh.PRIMITIVE_TRIANGLES] and have an index array. </description> </method> <method name="get_collision_mask_value" qualifiers="const"> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 5473347cb1..75cd52787a 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -198,6 +198,17 @@ } [/csharp] [/codeblocks] + [b]Note:[/b] Passing custom user arguments directly is not recommended, as the engine may discard or modify them. Instead, the best way is to use the standard UNIX double dash ([code]--[/code]) and then pass custom arguments, which the engine itself will ignore. These can be read via [method get_cmdline_user_args]. + </description> + </method> + <method name="get_cmdline_user_args"> + <return type="PackedStringArray" /> + <description> + Similar to [method get_cmdline_args], but this returns the user arguments (any argument passed after the double dash [code]--[/code] argument). These are left untouched by Godot for the user. + For example, in the command line below, [code]--fullscreen[/code] will not be returned in [method get_cmdline_user_args] and [code]--level 1[/code] will only be returned in [method get_cmdline_user_args]: + [codeblock] + godot --fullscreen -- --level 1 + [/codeblock] </description> </method> <method name="get_config_dir" qualifiers="const"> @@ -363,6 +374,12 @@ [b]Note:[/b] This method is only implemented on Windows, macOS, Linux and iOS. On Android, HTML5 and UWP, [method get_processor_name] returns an empty string. </description> </method> + <method name="get_restart_on_exit_arguments" qualifiers="const"> + <return type="PackedStringArray" /> + <description> + Returns the list of command line arguments that will be used when the project automatically restarts using [method set_restart_on_exit]. See also [method is_restart_on_exit_set]. + </description> + </method> <method name="get_static_memory_peak_usage" qualifiers="const"> <return type="int" /> <description> @@ -470,6 +487,12 @@ [b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows. </description> </method> + <method name="is_restart_on_exit_set" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the project will automatically restart when it exits for any reason, [code]false[/code] otherwise. See also [method set_restart_on_exit] and [method get_restart_on_exit_arguments]. + </description> + </method> <method name="is_stdout_verbose" qualifiers="const"> <return type="bool" /> <description> @@ -561,6 +584,17 @@ [b]Note:[/b] Double-check the casing of [code]variable[/code]. Environment variable names are case-sensitive on all platforms except Windows. </description> </method> + <method name="set_restart_on_exit"> + <return type="void" /> + <argument index="0" name="restart" type="bool" /> + <argument index="1" name="arguments" type="PackedStringArray" default="PackedStringArray()" /> + <description> + If [code]restart[/code] is [code]true[/code], restarts the project automatically when it is exited with [method SceneTree.quit] or [constant Node.NOTIFICATION_WM_CLOSE_REQUEST]. Command line [code]arguments[/code] can be supplied. To restart the project with the same command line arguments as originally used to run the project, pass [method get_cmdline_args] as the value for [code]arguments[/code]. + [method set_restart_on_exit] can be used to apply setting changes that require a restart. See also [method is_restart_on_exit_set] and [method get_restart_on_exit_arguments]. + [b]Note:[/b] This method is only effective on desktop platforms, and only when the project isn't started from the editor. It will have no effect on mobile and Web platforms, or when the project is started from the editor. + [b]Note:[/b] If the project process crashes or is [i]killed[/i] by the user (by sending [code]SIGKILL[/code] instead of the usual [code]SIGTERM[/code]), the project won't restart automatically. + </description> + </method> <method name="set_thread_name"> <return type="int" enum="Error" /> <argument index="0" name="name" type="String" /> diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index 354fbd462c..ef3b94e2a1 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -271,6 +271,42 @@ <member name="tangential_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> Minimum equivalent of [member tangential_accel_max]. </member> + <member name="turbulence_active" type="bool" setter="set_turbulence_active" getter="get_turbulence_active" default="false"> + Enables and disables Turbulence for the particle system. + </member> + <member name="turbulence_influence_max" type="float" setter="set_param_max" getter="get_param_max"> + Minimum turbulence influence on each particle. + The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life]. + </member> + <member name="turbulence_influence_min" type="float" setter="set_param_min" getter="get_param_min"> + Maximum turbulence influence on each particle. + The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life]. + </member> + <member name="turbulence_influence_over_life" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> + Each particle's amount of turbulence will be influenced along this [CurveTexture] over its life time. + </member> + <member name="turbulence_initial_displacement_max" type="float" setter="set_param_max" getter="get_param_max"> + Maximum displacement of each particles spawn position by the turbulence. + The actual amount of displacement will be a factor of the underlying turbulence multiplied by a random value between [member turbulence_initial_displacement_min] and [member turbulence_initial_displacement_max]. + </member> + <member name="turbulence_initial_displacement_min" type="float" setter="set_param_min" getter="get_param_min"> + Minimum displacement of each particles spawn position by the turbulence. + The actual amount of displacement will be a factor of the underlying turbulence multiplied by a random value between [member turbulence_initial_displacement_min] and [member turbulence_initial_displacement_max]. + </member> + <member name="turbulence_noise_scale" type="float" setter="set_turbulence_noise_scale" getter="get_turbulence_noise_scale"> + This value controls the overall scale/frequency of the turbulence noise pattern. + A small scale will result in smaller features with more detail while a high scale will result in smoother noise with larger features. + </member> + <member name="turbulence_noise_speed" type="Vector3" setter="set_turbulence_noise_speed" getter="get_turbulence_noise_speed"> + The movement speed of the turbulence pattern. This changes how quickly the noise changes over time. + A value of [code]Vector3(0.0, 0.0, 0.0)[/code] will freeze the turbulence pattern in place. + </member> + <member name="turbulence_noise_speed_random" type="float" setter="set_turbulence_noise_speed_random" getter="get_turbulence_noise_speed_random"> + Use to influence the noise speed in a random pattern. This helps to break up visible movement patterns. + </member> + <member name="turbulence_noise_strength" type="float" setter="set_turbulence_noise_strength" getter="get_turbulence_noise_strength"> + The turbulence noise strength. Increasing this will result in a stronger, more contrasting, noise pattern. + </member> </members> <constants> <constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0" enum="Parameter"> @@ -309,7 +345,7 @@ <constant name="PARAM_ANIM_OFFSET" value="11" enum="Parameter"> Use with [method set_param_min], [method set_param_max], and [method set_param_texture] to set animation offset properties. </constant> - <constant name="PARAM_MAX" value="12" enum="Parameter"> + <constant name="PARAM_MAX" value="15" enum="Parameter"> Represents the size of the [enum Parameter] enum. </constant> <constant name="PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="ParticleFlags"> @@ -348,6 +384,15 @@ <constant name="EMISSION_SHAPE_MAX" value="7" enum="EmissionShape"> Represents the size of the [enum EmissionShape] enum. </constant> + <constant name="PARAM_TURB_VEL_INFLUENCE" value="13" enum="Parameter"> + Use with [method set_param_min] and [method set_param_max] to set the turbulence minimum und maximum influence on each particles velocity. + </constant> + <constant name="PARAM_TURB_INIT_DISPLACEMENT" value="14" enum="Parameter"> + Use with [method set_param_min] and [method set_param_max] to set the turbulence minimum and maximum displacement of the particles spawn position. + </constant> + <constant name="PARAM_TURB_INFLUENCE_OVER_LIFE" value="12" enum="Parameter"> + Use with [method set_param_texture] to set the turbulence influence over the particles life time. + </constant> <constant name="SUB_EMITTER_DISABLED" value="0" enum="SubEmitterMode"> </constant> <constant name="SUB_EMITTER_CONSTANT" value="1" enum="SubEmitterMode"> @@ -357,6 +402,7 @@ <constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode"> </constant> <constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode"> + Represents the size of the [enum SubEmitterMode] enum. </constant> </constants> </class> diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml index dd52d09750..729058c9b3 100644 --- a/doc/classes/ResourceLoader.xml +++ b/doc/classes/ResourceLoader.xml @@ -95,8 +95,10 @@ <argument index="0" name="path" type="String" /> <argument index="1" name="type_hint" type="String" default="""" /> <argument index="2" name="use_sub_threads" type="bool" default="false" /> + <argument index="3" name="cache_mode" type="int" enum="ResourceLoader.CacheMode" default="1" /> <description> Loads the resource using threads. If [code]use_sub_threads[/code] is [code]true[/code], multiple threads will be used to load the resource, which makes loading faster, but may affect the main thread (and thus cause game slowdowns). + The [code]cache_mode[/code] property defines whether and how the cache should be used or updated when loading the resource. See [enum CacheMode] for details. </description> </method> <method name="remove_resource_format_loader"> diff --git a/doc/classes/VisualShaderNodeTextureUniform.xml b/doc/classes/VisualShaderNodeTextureUniform.xml index bff6f2015d..9014f79f54 100644 --- a/doc/classes/VisualShaderNodeTextureUniform.xml +++ b/doc/classes/VisualShaderNodeTextureUniform.xml @@ -39,12 +39,15 @@ Represents the size of the [enum TextureType] enum. </constant> <constant name="COLOR_DEFAULT_WHITE" value="0" enum="ColorDefault"> - Defaults to white color. + Defaults to fully opaque white color. </constant> <constant name="COLOR_DEFAULT_BLACK" value="1" enum="ColorDefault"> - Defaults to black color. + Defaults to fully opaque black color. </constant> - <constant name="COLOR_DEFAULT_MAX" value="2" enum="ColorDefault"> + <constant name="COLOR_DEFAULT_TRANSPARENT" value="2" enum="ColorDefault"> + Defaults to fully transparent black color. + </constant> + <constant name="COLOR_DEFAULT_MAX" value="3" enum="ColorDefault"> Represents the size of the [enum ColorDefault] enum. </constant> <constant name="FILTER_DEFAULT" value="0" enum="TextureFilter"> diff --git a/doc/classes/VoxelGIData.xml b/doc/classes/VoxelGIData.xml index b8d424b5fe..9198da4bc6 100644 --- a/doc/classes/VoxelGIData.xml +++ b/doc/classes/VoxelGIData.xml @@ -72,10 +72,10 @@ <member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" default="0.0"> The normal bias to use for indirect lighting and reflections. Higher values reduce self-reflections visible in non-rough materials, at the cost of more visible light leaking and flatter-looking indirect lighting. See also [member bias]. To prioritize hiding self-reflections over lighting quality, set [member bias] to [code]0.0[/code] and [member normal_bias] to a value between [code]1.0[/code] and [code]2.0[/code]. </member> - <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.7"> - If indirect lighting looks too flat, try decreasing [member propagation] while increasing [member energy] at the same time. See also [member use_two_bounces] which influences the indirect lighting's effective brightness. + <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" default="0.5"> + The multiplier to use when light bounces off a surface. Higher values result in brighter indirect lighting. If indirect lighting looks too flat, try decreasing [member propagation] while increasing [member energy] at the same time. See also [member use_two_bounces] which influences the indirect lighting's effective brightness. </member> - <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="false"> + <member name="use_two_bounces" type="bool" setter="set_use_two_bounces" getter="is_using_two_bounces" default="true"> If [code]true[/code], performs two bounces of indirect lighting instead of one. This makes indirect lighting look more natural and brighter at a small performance cost. The second bounce is also visible in reflections. If the scene appears too bright after enabling [member use_two_bounces], adjust [member propagation] and [member energy]. </member> </members> diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp index c8e6c2b476..de0181f887 100644 --- a/drivers/gles3/effects/copy_effects.cpp +++ b/drivers/gles3/effects/copy_effects.cpp @@ -111,6 +111,7 @@ CopyEffects::~CopyEffects() { glDeleteVertexArrays(1, &screen_triangle_array); glDeleteBuffers(1, &quad); glDeleteVertexArrays(1, &quad_array); + copy.shader.version_free(copy.shader_version); } void CopyEffects::copy_to_rect(const Rect2i &p_rect) { diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 26d84aa6a3..410cd376a7 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -496,7 +496,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() { while (sky) { if (sky->radiance == 0) { - sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) - 2; + sky->mipmap_count = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBA8) - 1; // Left uninitialized, will attach a texture at render time glGenFramebuffers(1, &sky->radiance_framebuffer); @@ -523,7 +523,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1); glGenTextures(1, &sky->raw_radiance); glBindTexture(GL_TEXTURE_CUBE_MAP, sky->raw_radiance); @@ -544,7 +544,8 @@ void RasterizerSceneGLES3::_update_dirty_skys() { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, sky->mipmap_count - 1); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } @@ -701,6 +702,7 @@ void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const Pag } if (!sky->radiance) { + _invalidate_sky(sky); _update_dirty_skys(); } } @@ -879,7 +881,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p } if (update_single_frame) { - for (int i = 0; i <= max_processing_layer; i++) { + for (int i = 0; i < max_processing_layer; i++) { _filter_sky_radiance(sky, i); } } else { @@ -889,7 +891,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p sky->reflection_dirty = false; } else { - if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer <= max_processing_layer) { + if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) { _filter_sky_radiance(sky, sky->processing_layer); sky->processing_layer++; } @@ -1005,7 +1007,9 @@ void RasterizerSceneGLES3::_filter_sky_radiance(Sky *p_sky, int p_base_layer) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, p_sky->radiance, p_base_layer); #ifdef DEBUG_ENABLED GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); + if (status != GL_FRAMEBUFFER_COMPLETE) { + WARN_PRINT("Could not bind sky radiance face: " + itos(i) + ", status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status)); + } #endif material_storage->shaders.cubemap_filter_shader.version_set_uniform(CubemapFilterShaderGLES3::FACE_ID, i, scene_globals.cubemap_filter_shader_version, mode); @@ -2303,7 +2307,7 @@ void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_ glGenTextures(1, &rb->depth_texture); glBindTexture(GL_TEXTURE_2D, rb->depth_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -2421,6 +2425,8 @@ void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter } RasterizerSceneGLES3::RasterizerSceneGLES3() { + singleton = this; + GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); GLES3::Config *config = GLES3::Config::get_singleton(); @@ -2620,6 +2626,8 @@ RasterizerSceneGLES3::~RasterizerSceneGLES3() { glDeleteBuffers(1, &sky_globals.directional_light_buffer); memdelete_arr(sky_globals.directional_lights); memdelete_arr(sky_globals.last_frame_directional_lights); + + singleton = nullptr; } #endif // GLES3_ENABLED diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index 57f0d7d0b8..88464876f1 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -106,12 +106,12 @@ void main() { T[2] = N; for (int sample_num = 0; sample_num < sample_count; sample_num++) { - vec4 sample = sample_directions_mip[sample_num]; - vec3 L = T * sample.xyz; - vec3 val = textureLod(source_cube, L, sample.w).rgb; + vec4 sample_direction_mip = sample_directions_mip[sample_num]; + vec3 L = T * sample_direction_mip.xyz; + vec3 val = textureLod(source_cube, L, sample_direction_mip.w).rgb; // Mix using linear val = srgb_to_linear(val); - sum.rgb += val * sample.z; + sum.rgb += val * sample_direction_mip.z; } sum /= weight; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index cd88ba6cb7..4081d73ab0 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -686,7 +686,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif // LIGHT_ANISOTROPY_USED // F float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + // Calculate Fresnel using cheap approximate specular occlusion term from Filament: + // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion + float f90 = clamp(50.0 * f0.g, 0.0, 1.0); + vec3 F = f0 + (f90 - f0) * cLdotH5; vec3 specular_brdf_NL = cNdotL * D * F * G; @@ -751,7 +754,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f if (omni_lights[idx].size > 0.0) { float t = omni_lights[idx].size / max(0.001, light_length); - size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t)); } light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha, @@ -800,7 +803,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f if (spot_lights[idx].size > 0.0) { float t = spot_lights[idx].size / max(0.001, light_length); - size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t)); } light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha, @@ -1107,7 +1110,7 @@ void main() { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); #endif } diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 68045930b0..24791b94d0 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1156,6 +1156,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_BLACK); } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: { + gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_TRANSPARENT); + } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_ANISO); } break; @@ -2320,11 +2323,14 @@ void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int ShaderLanguage::TYPE_VEC3, // vec3 ShaderLanguage::TYPE_IVEC3, //vec3i ShaderLanguage::TYPE_MAX, //xform2d not supported here + ShaderLanguage::TYPE_VEC4, //vec4 + ShaderLanguage::TYPE_IVEC4, //vec4i ShaderLanguage::TYPE_VEC4, //plane ShaderLanguage::TYPE_VEC4, //quat ShaderLanguage::TYPE_MAX, //aabb not supported here ShaderLanguage::TYPE_MAX, //basis not supported here ShaderLanguage::TYPE_MAX, //xform not supported here + ShaderLanguage::TYPE_MAX, //projection not supported here ShaderLanguage::TYPE_VEC4 //color }; diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 88b81805fa..667ba4f5e6 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -1347,7 +1347,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b _multimesh_mark_all_dirty(multimesh, false, true); //update AABB } else if (multimesh->mesh.is_valid()) { //if we have a mesh set, we need to re-generate the AABB from the new data - const float *data = multimesh->data_cache.ptr(); + const float *data = p_buffer.ptr(); _multimesh_re_create_aabb(multimesh, data, multimesh->instances); multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index c05f516548..543638e8ff 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -115,6 +115,17 @@ TextureStorage::TextureStorage() { texture_2d_layered_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_CUBEMAP_BLACK], images, RS::TEXTURE_LAYERED_CUBEMAP); } + { // transparent black + Ref<Image> image; + image.instantiate(); + image->create(4, 4, true, Image::FORMAT_RGBA8); + image->fill(Color(0, 0, 0, 0)); + image->generate_mipmaps(); + + default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT] = texture_allocate(); + texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT], image); + } + { Ref<Image> image; image.instantiate(); diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 77ec1da6f5..71f713bc9f 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -103,6 +103,7 @@ namespace GLES3 { enum DefaultGLTexture { DEFAULT_GL_TEXTURE_WHITE, DEFAULT_GL_TEXTURE_BLACK, + DEFAULT_GL_TEXTURE_TRANSPARENT, DEFAULT_GL_TEXTURE_NORMAL, DEFAULT_GL_TEXTURE_ANISO, DEFAULT_GL_TEXTURE_DEPTH, diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index e66aa88eb9..83047caf98 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -37,6 +37,7 @@ #include "editor/editor_scale.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "scene/animation/animation_player.h" +#include "scene/gui/separator.h" #include "scene/gui/view_panner.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 18ce2ded63..cb7d3c7d96 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -33,11 +33,14 @@ #include "editor/editor_data.h" #include "editor/editor_spin_slider.h" -#include "editor/property_editor.h" #include "editor/property_selector.h" +#include "scene/3d/node_3d.h" +#include "scene/gui/check_box.h" #include "scene/gui/control.h" #include "scene/gui/menu_button.h" +#include "scene/gui/option_button.h" +#include "scene/gui/panel_container.h" #include "scene/gui/scroll_bar.h" #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp index 92ea0f15e9..4c445eb766 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp @@ -37,6 +37,7 @@ #include "editor/doc_tools.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" DebugAdapterProtocol *DebugAdapterProtocol::singleton = nullptr; diff --git a/editor/debugger/debug_adapter/debug_adapter_server.cpp b/editor/debugger/debug_adapter/debug_adapter_server.cpp index e9fc7ec913..41e6b1f308 100644 --- a/editor/debugger/debug_adapter/debug_adapter_server.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_server.cpp @@ -33,6 +33,7 @@ #include "core/os/os.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" DebugAdapterServer::DebugAdapterServer() { _EDITOR_DEF("network/debug_adapter/remote_port", remote_port); diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp index bdab1cfecb..dbd2c61d44 100644 --- a/editor/debugger/editor_debugger_tree.cpp +++ b/editor/debugger/editor_debugger_tree.cpp @@ -225,6 +225,39 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int updating_scene_tree = false; } +Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) { + if (get_button_id_at_position(p_point) != -1) { + return Variant(); + } + + TreeItem *selected = get_selected(); + if (!selected) { + return Variant(); + } + + String path = selected->get_text(0); + + HBoxContainer *hb = memnew(HBoxContainer); + TextureRect *tf = memnew(TextureRect); + tf->set_texture(selected->get_icon(0)); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + hb->add_child(tf); + Label *label = memnew(Label(path)); + hb->add_child(label); + set_drag_preview(hb); + + if (!selected->get_parent() || !selected->get_parent()->get_parent()) { + path = "."; + } else { + while (selected->get_parent()->get_parent() != get_root()) { + selected = selected->get_parent(); + path = selected->get_text(0) + "/" + path; + } + } + + return vformat("\"%s\"", path); +} + String EditorDebuggerTree::get_selected_path() { if (!get_selected()) { return ""; diff --git a/editor/debugger/editor_debugger_tree.h b/editor/debugger/editor_debugger_tree.h index 9d163fd548..5b2df8abd5 100644 --- a/editor/debugger/editor_debugger_tree.h +++ b/editor/debugger/editor_debugger_tree.h @@ -65,6 +65,8 @@ protected: void _notification(int p_what); public: + virtual Variant get_drag_data(const Point2 &p_point) override; + String get_selected_path(); ObjectID get_selected_object(); int get_current_debugger(); // Would love to have one tree for every debugger. diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 41095a7267..ac2e958c5b 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -50,7 +50,6 @@ #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" -#include "editor/property_editor.h" #include "main/performance.h" #include "scene/3d/camera_3d.h" #include "scene/debugger/scene_debugger.h" diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 4f89e1b2d1..5b4da0e32b 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -37,6 +37,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/margin_container.h" void DependencyEditor::_searched(const String &p_path) { diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 556a0176cb..b6d7bbc45f 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -37,6 +37,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "filesystem_dock.h" #include "scene/resources/font.h" #include "servers/audio_server.h" diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index 174a97d471..ba1f2fd6af 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -32,6 +32,7 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/control.h" #include "scene/gui/tree.h" diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 424195e4dd..297d1226e3 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -34,6 +34,7 @@ #include "editor/editor_feature_profile.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" void EditorHelpSearch::_update_icons() { search_box->set_right_icon(results_tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 57acc0b2c5..e06e3cbc5f 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -471,6 +471,9 @@ void EditorProperty::update_revert_and_pin_status() { bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property, ¤t) && !is_read_only(); if (new_can_revert != can_revert || new_pinned != pinned) { + if (new_can_revert != can_revert) { + emit_signal(SNAME("property_can_revert_changed"), property, new_can_revert); + } can_revert = new_can_revert; pinned = new_pinned; update(); @@ -784,6 +787,9 @@ void EditorProperty::expand_all_folding() { void EditorProperty::collapse_all_folding() { } +void EditorProperty::expand_revertable() { +} + void EditorProperty::set_selectable(bool p_selectable) { selectable = p_selectable; } @@ -966,6 +972,7 @@ void EditorProperty::_bind_methods() { ADD_SIGNAL(MethodInfo("property_keyed_with_value", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); ADD_SIGNAL(MethodInfo("property_checked", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "checked"))); ADD_SIGNAL(MethodInfo("property_pinned", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "pinned"))); + ADD_SIGNAL(MethodInfo("property_can_revert_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::BOOL, "can_revert"))); ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx"))); @@ -1225,12 +1232,15 @@ void EditorInspectorSection::_notification(int p_what) { // Get the section header font. Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts")); int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts")); + Color font_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); // Get the right direction arrow texture, if the section is foldable. Ref<Texture2D> arrow; + bool folded = foldable; if (foldable) { if (object->editor_is_section_unfolded(section)) { arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree")); + folded = false; } else { if (is_layout_rtl()) { arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree")); @@ -1274,28 +1284,71 @@ void EditorInspectorSection::_notification(int p_what) { } draw_rect(header_rect, c); - // Draw header title and folding arrow. - const int arrow_margin = 2; - const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0; - Color color = get_theme_color(SNAME("font_color")); - float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE) - section_indent; - Point2 text_offset = Point2(0, font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2); - HorizontalAlignment text_align = HORIZONTAL_ALIGNMENT_LEFT; - if (rtl) { - text_align = HORIZONTAL_ALIGNMENT_RIGHT; - } else { - text_offset.x = section_indent + Math::round(arrow_width + arrow_margin * EDSCALE); - } - draw_string(font, text_offset.floor(), label, text_align, text_width, font_size, color); + // Draw header title, folding arrow and coutn of revertable properties. + { + int separation = Math::round(2 * EDSCALE); - if (arrow.is_valid()) { - Point2 arrow_position = Point2(0, (header_height - arrow->get_height()) / 2); + int margin_start = section_indent + separation; + int margin_end = separation; + + // - Arrow. + if (arrow.is_valid()) { + Point2 arrow_position; + if (rtl) { + arrow_position.x = get_size().width - (margin_start + arrow->get_width()); + } else { + arrow_position.x = margin_start; + } + arrow_position.y = (header_height - arrow->get_height()) / 2; + draw_texture(arrow, arrow_position); + margin_start += arrow->get_width(); + } + + int available = get_size().width - (margin_start + margin_end); + + // - Count of revertable properties. + String num_revertable_str; + int num_revertable_width = 0; + if (folded && revertable_properties.size()) { + int label_width = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, available, font_size, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS).x; + + Ref<Font> light_font = get_theme_font(SNAME("main"), SNAME("EditorFonts")); + int light_font_size = get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")); + Color light_font_color = get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")); + + // Can we fit the long version of the revertable count text? + if (revertable_properties.size() == 1) { + num_revertable_str = "(1 change)"; + } else { + num_revertable_str = vformat("(%d changes)", revertable_properties.size()); + } + num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x; + if (label_width + separation + num_revertable_width > available) { + // We'll have to use the short version. + num_revertable_str = vformat("(%d)", revertable_properties.size()); + num_revertable_width = light_font->get_string_size(num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, TextServer::JUSTIFICATION_NONE).x; + } + + Point2 text_offset = Point2( + margin_end, + light_font->get_ascent(light_font_size) + (header_height - light_font->get_height(light_font_size)) / 2); + if (!rtl) { + text_offset.x = get_size().width - (text_offset.x + num_revertable_width); + } + draw_string(light_font, text_offset, num_revertable_str, HORIZONTAL_ALIGNMENT_LEFT, -1.0f, light_font_size, light_font_color, TextServer::JUSTIFICATION_NONE); + margin_end += num_revertable_width + separation; + available -= num_revertable_width + separation; + } + + // - Label. + Point2 text_offset = Point2( + margin_start, + font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2); if (rtl) { - arrow_position.x = get_size().width - section_indent - arrow->get_width() - Math::round(arrow_margin * EDSCALE); - } else { - arrow_position.x = section_indent + Math::round(arrow_margin * EDSCALE); + text_offset.x = margin_end; } - draw_texture(arrow, arrow_position.floor()); + HorizontalAlignment text_align = rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT; + draw_string(font, text_offset, label, text_align, available, font_size, font_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); } // Draw dropping highlight. @@ -1471,6 +1524,22 @@ void EditorInspectorSection::fold() { update(); } +bool EditorInspectorSection::has_revertable_properties() const { + return !revertable_properties.is_empty(); +} + +void EditorInspectorSection::property_can_revert_changed(const String &p_path, bool p_can_revert) { + bool had_revertable_properties = has_revertable_properties(); + if (p_can_revert) { + revertable_properties.insert(p_path); + } else { + revertable_properties.erase(p_path); + } + if (has_revertable_properties() != had_revertable_properties) { + update(); + } +} + void EditorInspectorSection::_bind_methods() { ClassDB::bind_method(D_METHOD("setup", "section", "label", "object", "bg_color", "foldable"), &EditorInspectorSection::setup); ClassDB::bind_method(D_METHOD("get_vbox"), &EditorInspectorSection::get_vbox); @@ -2330,7 +2399,7 @@ String EditorInspector::get_selected_path() const { return property_selected; } -void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped) { +void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped) { for (const EditorInspectorPlugin::AddedEditor &F : ped->added_editors) { EditorProperty *ep = Object::cast_to<EditorProperty>(F.property_editor); current_vbox->add_child(F.property_editor); @@ -2370,6 +2439,10 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit } } + if (p_section) { + ep->connect("property_can_revert_changed", callable_mp(p_section, &EditorInspectorSection::property_can_revert_changed)); + } + ep->set_read_only(read_only); ep->update_property(); ep->_update_pin_flags(); @@ -2476,9 +2549,11 @@ void EditorInspector::update_tree() { // Get the lists of editors to add the beginning. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_begin(object); - _parse_added_editors(main_vbox, ped); + _parse_added_editors(main_vbox, nullptr, ped); } + StringName type_name; + // Get the lists of editors for properties. for (List<PropertyInfo>::Element *E_property = plist.front(); E_property; E_property = E_property->next()) { PropertyInfo &p = E_property->get(); @@ -2549,6 +2624,7 @@ void EditorInspector::update_tree() { category_vbox = nullptr; //reset String type = p.name; + type_name = p.name; // Set the category icon. if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) { @@ -2582,24 +2658,23 @@ void EditorInspector::update_tree() { if (use_doc_hints) { // Sets the category tooltip to show documentation. - StringName type2 = p.name; - if (!class_descr_cache.has(type2)) { + if (!class_descr_cache.has(type_name)) { String descr; DocTools *dd = EditorHelp::get_doc_data(); - HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type2); + HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type_name); if (E) { descr = DTR(E->value.brief_description); } - class_descr_cache[type2] = descr; + class_descr_cache[type_name] = descr; } - category->set_tooltip(p.name + "::" + (class_descr_cache[type2].is_empty() ? "" : class_descr_cache[type2])); + category->set_tooltip(p.name + "::" + (class_descr_cache[type_name].is_empty() ? "" : class_descr_cache[type_name])); } // Add editors at the start of a category. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_category(object, p.name); - _parse_added_editors(main_vbox, ped); + _parse_added_editors(main_vbox, nullptr, ped); } continue; @@ -2791,7 +2866,7 @@ void EditorInspector::update_tree() { // Add editors at the start of a group. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_group(object, path); - _parse_added_editors(section->get_vbox(), ped); + _parse_added_editors(section->get_vbox(), section, ped); } vbox_per_path[root_vbox][acc_path] = section->get_vbox(); @@ -2864,7 +2939,7 @@ void EditorInspector::update_tree() { // Build the doc hint, to use as tooltip. // Get the class name. - StringName classname = object->get_class_name(); + StringName classname = type_name == "" ? object->get_class_name() : type_name; if (!object_class.is_empty()) { classname = object_class; } @@ -2973,6 +3048,12 @@ void EditorInspector::update_tree() { editor_property_map[prop].push_back(ep); } } + + EditorInspectorSection *section = Object::cast_to<EditorInspectorSection>(current_vbox->get_parent()); + if (section) { + ep->connect("property_can_revert_changed", callable_mp(section, &EditorInspectorSection::property_can_revert_changed)); + } + ep->set_draw_warning(draw_warning); ep->set_use_folding(use_folding); ep->set_checkable(checkable); @@ -3025,7 +3106,7 @@ void EditorInspector::update_tree() { // Get the lists of to add at the end. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_end(object); - _parse_added_editors(main_vbox, ped); + _parse_added_editors(main_vbox, nullptr, ped); } } @@ -3178,6 +3259,44 @@ void EditorInspector::expand_all_folding() { } } +void EditorInspector::expand_revertable() { + HashSet<EditorInspectorSection *> sections_to_unfold[2]; + for (EditorInspectorSection *E : sections) { + if (E->has_revertable_properties()) { + sections_to_unfold[0].insert(E); + } + } + + // Climb up the hierachy doing double buffering with the sets. + int a = 0; + int b = 1; + while (sections_to_unfold[a].size()) { + for (EditorInspectorSection *E : sections_to_unfold[a]) { + E->unfold(); + + Node *n = E->get_parent(); + while (n) { + if (Object::cast_to<EditorInspector>(n)) { + break; + } + if (Object::cast_to<EditorInspectorSection>(n) && !sections_to_unfold[a].has((EditorInspectorSection *)n)) { + sections_to_unfold[b].insert((EditorInspectorSection *)n); + } + n = n->get_parent(); + } + } + + sections_to_unfold[a].clear(); + SWAP(a, b); + } + + for (const KeyValue<StringName, List<EditorProperty *>> &F : editor_property_map) { + for (EditorProperty *E : F.value) { + E->expand_revertable(); + } + } +} + void EditorInspector::set_scroll_offset(int p_offset) { set_v_scroll(p_offset); } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 4ec3513da5..54533de960 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -184,6 +184,7 @@ public: virtual void expand_all_folding(); virtual void collapse_all_folding(); + virtual void expand_revertable(); virtual Variant get_drag_data(const Point2 &p_point) override; virtual void update_cache(); @@ -281,6 +282,8 @@ class EditorInspectorSection : public Container { Timer *dropping_unfold_timer = nullptr; bool dropping = false; + HashSet<StringName> revertable_properties; + void _test_unfold(); protected: @@ -299,6 +302,9 @@ public: void unfold(); void fold(); + bool has_revertable_properties() const; + void property_can_revert_changed(const String &p_path, bool p_can_revert); + EditorInspectorSection(); ~EditorInspectorSection(); }; @@ -517,7 +523,7 @@ class EditorInspector : public ScrollContainer { void _edit_request_change(Object *p_object, const String &p_prop); void _filter_changed(const String &p_text); - void _parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped); + void _parse_added_editors(VBoxContainer *current_vbox, EditorInspectorSection *p_section, Ref<EditorInspectorPlugin> ped); void _vscroll_changed(double); @@ -579,6 +585,7 @@ public: void collapse_all_folding(); void expand_all_folding(); + void expand_revertable(); void set_scroll_offset(int p_offset); int get_scroll_offset() const; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 012666d625..38cc85bb4e 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -35,7 +35,9 @@ #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/center_container.h" +#include "scene/gui/separator.h" #include "scene/resources/font.h" void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index e10394a2a8..e9aceb684f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -49,6 +49,7 @@ #include "main/main.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/gui/center_container.h" +#include "scene/gui/color_picker.h" #include "scene/gui/control.h" #include "scene/gui/dialogs.h" #include "scene/gui/file_dialog.h" @@ -149,6 +150,7 @@ #include "editor/plugins/debugger_editor_plugin.h" #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/editor_preview_plugins.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "editor/plugins/font_config_plugin.h" #include "editor/plugins/gdextension_export_plugin.h" #include "editor/plugins/gpu_particles_2d_editor_plugin.h" @@ -6172,7 +6174,14 @@ EditorNode::EditorNode() { EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false); EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true); EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); - EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary"); + + PackedStringArray open_in_new_inspector_defaults; + // Required for the script editor to work. + open_in_new_inspector_defaults.push_back("Script"); + // Required for the GridMap editor to work. + open_in_new_inspector_defaults.push_back("MeshLibrary"); + EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", open_in_new_inspector_defaults); + EDITOR_DEF("interface/inspector/default_color_picker_mode", 0); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW,OKHSL", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("interface/inspector/default_color_picker_shape", (int32_t)ColorPicker::SHAPE_OKHSL_CIRCLE); diff --git a/editor/editor_node.h b/editor/editor_node.h index c521c0fb04..0201e84eaf 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -37,7 +37,6 @@ #include "editor/editor_run.h" #include "editor/export/editor_export.h" #include "editor/inspector_dock.h" -#include "editor/property_editor.h" typedef void (*EditorNodeInitCallback)(); typedef void (*EditorPluginInitializeCallback)(); @@ -48,6 +47,7 @@ class AudioStreamPreviewGenerator; class BackgroundProgress; class Button; class CenterContainer; +class ColorPicker; class ConfirmationDialog; class Control; class DependencyEditor; @@ -67,6 +67,7 @@ class EditorPlugin; class EditorPluginList; class EditorQuickOpen; class EditorResourcePreview; +class EditorResourceConversionPlugin; class EditorRun; class EditorRunNative; class EditorSettingsDialog; diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 3a0b875b8c..5a010a66c1 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -37,6 +37,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "scene/gui/margin_container.h" +#include "scene/gui/tree.h" void EditorPluginSettings::_notification(int p_what) { switch (p_what) { diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h index 7c6d93e6f4..9c619066f2 100644 --- a/editor/editor_plugin_settings.h +++ b/editor/editor_plugin_settings.h @@ -34,8 +34,8 @@ #include "core/object/undo_redo.h" #include "editor/editor_data.h" #include "editor/plugin_config_dialog.h" -#include "property_editor.h" -#include "scene/gui/dialogs.h" + +class Tree; class EditorPluginSettings : public VBoxContainer { GDCLASS(EditorPluginSettings, VBoxContainer); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 215a44482e..5298b818e7 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1580,6 +1580,11 @@ void EditorPropertyEasing::_spin_value_changed(double p_value) { // which can cause crashes and other issues. p_value = CLAMP(p_value, -1'000'000, 1'000'000); + if (positive_only) { + // Force a positive or zero value if a negative value was manually entered by double-clicking. + p_value = MAX(0.0, p_value); + } + emit_changed(get_edited_property(), p_value); _spin_focus_exited(); } @@ -1591,9 +1596,9 @@ void EditorPropertyEasing::_spin_focus_exited() { easing_draw->update(); } -void EditorPropertyEasing::setup(bool p_full, bool p_flip) { +void EditorPropertyEasing::setup(bool p_positive_only, bool p_flip) { flip = p_flip; - full = p_full; + positive_only = p_positive_only; } void EditorPropertyEasing::_notification(int p_what) { @@ -1601,13 +1606,13 @@ void EditorPropertyEasing::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { preset->clear(); - preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO); preset->add_icon_item(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")), "Linear", EASING_LINEAR); - preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "In", EASING_IN); - preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Out", EASING_OUT); - if (full) { - preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "In-Out", EASING_IN_OUT); - preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Out-In", EASING_OUT_IN); + preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "Ease In", EASING_IN); + preset->add_icon_item(get_theme_icon(SNAME("CurveOut"), SNAME("EditorIcons")), "Ease Out", EASING_OUT); + preset->add_icon_item(get_theme_icon(SNAME("CurveConstant"), SNAME("EditorIcons")), "Zero", EASING_ZERO); + if (!positive_only) { + preset->add_icon_item(get_theme_icon(SNAME("CurveInOut"), SNAME("EditorIcons")), "Ease In-Out", EASING_IN_OUT); + preset->add_icon_item(get_theme_icon(SNAME("CurveOutIn"), SNAME("EditorIcons")), "Ease Out-In", EASING_OUT_IN); } easing_draw->set_custom_minimum_size(Size2(0, get_theme_font(SNAME("font"), SNAME("Label"))->get_height(get_theme_font_size(SNAME("font_size"), SNAME("Label"))) * 2)); } break; @@ -3918,6 +3923,12 @@ void EditorPropertyResource::expand_all_folding() { } } +void EditorPropertyResource::expand_revertable() { + if (sub_inspector) { + sub_inspector->expand_revertable(); + } +} + void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { use_sub_inspector = p_enable; } @@ -4099,20 +4110,20 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ case Variant::FLOAT: { if (p_hint == PROPERTY_HINT_EXP_EASING) { EditorPropertyEasing *editor = memnew(EditorPropertyEasing); - bool full = true; + bool positive_only = false; bool flip = false; - Vector<String> hints = p_hint_text.split(","); + const Vector<String> hints = p_hint_text.split(","); for (int i = 0; i < hints.size(); i++) { - String h = hints[i].strip_edges(); - if (h == "attenuation") { + const String hint = hints[i].strip_edges(); + if (hint == "attenuation") { flip = true; } - if (h == "inout") { - full = true; + if (hint == "positive_only") { + positive_only = true; } } - editor->setup(full, flip); + editor->setup(positive_only, flip); return editor; } else { @@ -4356,11 +4367,11 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ editor->setup(p_object, p_path, p_hint == PROPERTY_HINT_RESOURCE_TYPE ? p_hint_text : "Resource"); if (p_hint == PROPERTY_HINT_RESOURCE_TYPE) { - String open_in_new = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); - for (int i = 0; i < open_in_new.get_slice_count(","); i++) { - String type = open_in_new.get_slicec(',', i).strip_edges(); + const PackedStringArray open_in_new_inspector = EDITOR_GET("interface/inspector/resources_to_open_in_new_inspector"); + + for (const String &type : open_in_new_inspector) { for (int j = 0; j < p_hint_text.get_slice_count(","); j++) { - String inherits = p_hint_text.get_slicec(',', j); + const String inherits = p_hint_text.get_slicec(',', j); if (ClassDB::is_parent_class(inherits, type)) { editor->set_use_sub_inspector(false); } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index b3aac6e8ca..6a1360d2ca 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -443,6 +443,7 @@ class EditorPropertyEasing : public EditorProperty { bool dragging = false; bool full = false; bool flip = false; + bool positive_only = false; enum { EASING_ZERO, @@ -471,7 +472,7 @@ protected: public: virtual void update_property() override; - void setup(bool p_full, bool p_flip); + void setup(bool p_positive_only, bool p_flip); EditorPropertyEasing(); }; @@ -856,6 +857,7 @@ public: void collapse_all_folding() override; void expand_all_folding() override; + void expand_revertable() override; void set_use_sub_inspector(bool p_enable); diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 60c091a4b0..d850773a6d 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -38,6 +38,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/filesystem_dock.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/scene_tree_dock.h" diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index ec5edab860..d8b738be17 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -32,6 +32,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/export/editor_export_platform.h" void EditorRunNative::_notification(int p_what) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 37a531299f..4846fd6478 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1051,6 +1051,8 @@ void EditorSettings::set_initial_value(const StringName &p_setting, const Varian } Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_restart_if_changed) { + ERR_FAIL_NULL_V_MSG(EditorSettings::get_singleton(), p_default, "EditorSettings not instantiated yet."); + Variant ret = p_default; if (EditorSettings::get_singleton()->has_setting(p_setting)) { ret = EditorSettings::get_singleton()->get(p_setting); @@ -1067,7 +1069,7 @@ Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_re } Variant _EDITOR_GET(const String &p_setting) { - ERR_FAIL_COND_V(!EditorSettings::get_singleton()->has_setting(p_setting), Variant()); + ERR_FAIL_COND_V(!EditorSettings::get_singleton() || !EditorSettings::get_singleton()->has_setting(p_setting), Variant()); return EditorSettings::get_singleton()->get(p_setting); } @@ -1422,9 +1424,7 @@ void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) { } Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) { - if (!EditorSettings::get_singleton()) { - return nullptr; - } + ERR_FAIL_NULL_V_MSG(EditorSettings::get_singleton(), nullptr, "EditorSettings not instantiated yet."); Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); @@ -1434,6 +1434,8 @@ Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) { } void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode) { + ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet."); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path + "."); @@ -1444,6 +1446,8 @@ void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_k } void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes) { + ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet."); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE_ARRAY with invalid shortcut: " + p_path + "."); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 5d60baf202..02380c4e39 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1660,6 +1660,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_dictionary_add_item->set_expand_margin_size(SIDE_RIGHT, 4 * EDSCALE); theme->set_stylebox("DictionaryAddItem", "EditorStyles", style_dictionary_add_item); + Ref<StyleBoxEmpty> vshader_label_style = make_empty_stylebox(2, 1, 2, 1); + theme->set_stylebox("label_style", "VShaderEditor", vshader_label_style); + // adaptive script theme constants // for comments and elements with lower relevance const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5); @@ -1669,17 +1672,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27); - // editor main color - const Color main_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0.02, 0.5, 1.0); - - const Color symbol_color = Color(0.34, 0.57, 1.0).lerp(mono_color, dark_theme ? 0.5 : 0.3); - const Color keyword_color = Color(1.0, 0.44, 0.52); - const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.8, 0.4, 0.6); - const Color basetype_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0.0, 0.76, 0.38); - const Color type_color = basetype_color.lerp(mono_color, dark_theme ? 0.4 : 0.3); - const Color usertype_color = basetype_color.lerp(mono_color, dark_theme ? 0.7 : 0.5); - const Color comment_color = dim_color; - const Color string_color = (dark_theme ? Color(1.0, 0.85, 0.26) : Color(1.0, 0.82, 0.09)).lerp(mono_color, dark_theme ? 0.5 : 0.3); + const Color symbol_color = dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61); + const Color keyword_color = dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51); + const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8); + const Color base_type_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2); + const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4); + const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4); + const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5); + const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0); // Use the brightest background color on a light theme (which generally uses a negative contrast rate). const Color te_background_color = dark_theme ? background_color : dark_color_3; @@ -1692,24 +1692,24 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color completion_font_color = font_color; const Color text_color = font_color; const Color line_number_color = dim_color; - const Color safe_line_number_color = dim_color * Color(1, 1.2, 1, 1.5); + const Color safe_line_number_color = dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75); const Color caret_color = mono_color; const Color caret_background_color = mono_color.inverted(); const Color text_selected_color = dark_color_3; - const Color brace_mismatch_color = error_color; + const Color brace_mismatch_color = dark_theme ? error_color : Color(1, 0.08, 0, 1); const Color current_line_color = alpha1; const Color line_length_guideline_color = dark_theme ? base_color : background_color; const Color word_highlighted_color = alpha1; - const Color number_color = basetype_color.lerp(mono_color, dark_theme ? 0.5 : 0.3); - const Color function_color = main_color; - const Color member_variable_color = main_color.lerp(mono_color, 0.6); + const Color number_color = dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1); + const Color function_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1); + const Color member_variable_color = dark_theme ? Color(0.34, 0.7, 1.0).lerp(mono_color, 0.6) : Color(0, 0.4, 0.68, 1); const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3); const Color bookmark_color = Color(0.08, 0.49, 0.98); - const Color breakpoint_color = error_color; + const Color breakpoint_color = dark_theme ? error_color : Color(1, 0.27, 0.2, 1); const Color executing_line_color = Color(0.98, 0.89, 0.27); const Color code_folding_color = alpha3; const Color search_result_color = alpha1; - const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38); + const Color search_result_border_color = dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38); EditorSettings *setting = EditorSettings::get_singleton(); String text_editor_color_theme = setting->get("text_editor/theme/color_theme"); @@ -1717,9 +1717,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true); setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true); setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true); - setting->set_initial_value("text_editor/theme/highlighting/base_type_color", basetype_color, true); - setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/user_type_color", usertype_color, true); + setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true); setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true); setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true); setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true); diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 57ae83aeee..34b407779e 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -41,6 +41,7 @@ #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/plugins/script_editor_plugin.h" #include "editor_export_plugin.h" diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp index 7d20081217..a7d9d7f068 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -37,8 +37,10 @@ #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/progress_dialog.h" #include "scene/gui/file_dialog.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" #include "scene/main/http_request.h" diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index a20f19efc8..cb82cefbbb 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -38,6 +38,7 @@ #include "editor/editor_properties.h" #include "editor/editor_scale.h" #include "editor/export/editor_export.h" +#include "scene/gui/check_button.h" #include "scene/gui/link_button.h" #include "scene/gui/tree.h" diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 410f01a9c6..6c12464b5a 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -35,6 +35,7 @@ #include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/importer_mesh.h" diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp index 9d96822aef..a70f5225e9 100644 --- a/editor/import_defaults_editor.cpp +++ b/editor/import_defaults_editor.cpp @@ -36,6 +36,7 @@ #include "editor/editor_autoload_settings.h" #include "editor/editor_plugin_settings.h" #include "editor/editor_sectioned_inspector.h" +#include "editor/editor_settings.h" #include "editor/localization_editor.h" #include "editor/shader_globals_editor.h" #include "scene/gui/center_container.h" diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index f9e5885f9d..087ef48b56 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -34,6 +34,7 @@ #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" class ImportDockParameters : public Object { GDCLASS(ImportDockParameters, Object); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index e0dd5610ee..79d94246ad 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -33,6 +33,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/plugins/script_editor_plugin.h" InspectorDock *InspectorDock::singleton = nullptr; @@ -64,6 +65,9 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { case COLLAPSE_ALL: { _menu_collapseall(); } break; + case EXPAND_REVERTABLE: { + _menu_expand_revertable(); + } break; case RESOURCE_SAVE: { _save_resource(false); @@ -400,6 +404,10 @@ void InspectorDock::_menu_expandall() { inspector->expand_all_folding(); } +void InspectorDock::_menu_expand_revertable() { + inspector->expand_revertable(); +} + void InspectorDock::_warning_pressed() { warning_dialog->popup_centered(); } @@ -518,6 +526,8 @@ void InspectorDock::update(Object *p_object) { p->clear(); p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/expand_all", TTR("Expand All")), EXPAND_ALL); p->add_icon_shortcut(get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse All")), COLLAPSE_ALL); + // Calling it 'revertable' internally, because that's what the implementation is based on, but labeling it as 'non-default' because that's more user friendly, even if not 100% accurate. + p->add_shortcut(ED_SHORTCUT("property_editor/expand_revertable", TTR("Expand Non-Default")), EXPAND_REVERTABLE); p->add_separator(TTR("Property Name Style")); p->add_radio_check_item(TTR("Raw"), PROPERTY_NAME_STYLE_RAW); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index e3d35c2157..e32410151f 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -61,6 +61,7 @@ class InspectorDock : public VBoxContainer { COLLAPSE_ALL, EXPAND_ALL, + EXPAND_REVERTABLE, // Matches `EditorPropertyNameProcessor::Style`. PROPERTY_NAME_STYLE_RAW, @@ -124,6 +125,7 @@ class InspectorDock : public VBoxContainer { void _edit_back(); void _menu_collapseall(); void _menu_expandall(); + void _menu_expand_revertable(); void _select_history(int p_idx); void _prepare_history(); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 9d80e7a193..cb77cd78bf 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -35,6 +35,8 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "scene/gui/separator.h" bool AbstractPolygon2DEditor::Vertex::operator==(const AbstractPolygon2DEditor::Vertex &p_vertex) const { return polygon == p_vertex.polygon && vertex == p_vertex.vertex; diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 7481882cbe..32d97c65a9 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -34,6 +34,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_blend_tree.h" StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const { diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index 3488b4bf30..9b06f3248f 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -33,11 +33,11 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_blend_space_1d.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 14d009f03b..dc764725dd 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -38,6 +38,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index 88b9072599..26471df051 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -33,11 +33,11 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_blend_space_2d.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 561651e5f5..79be2d04b3 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -38,6 +38,7 @@ #include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index b5bf91a1da..18199676b8 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -33,7 +33,6 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_blend_tree.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index fe5a772b0d..473450b292 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -38,6 +38,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index ea16abd64c..165940e639 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -33,7 +33,6 @@ #include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_node_state_machine.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h index ab4ef5a001..a33d97f62f 100644 --- a/editor/plugins/animation_tree_editor_plugin.h +++ b/editor/plugins/animation_tree_editor_plugin.h @@ -32,7 +32,6 @@ #define ANIMATION_TREE_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "editor/property_editor.h" #include "scene/animation/animation_tree.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 964570e1bd..8de1ba326d 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -53,6 +53,7 @@ #include "scene/gui/flow_container.h" #include "scene/gui/grid_container.h" #include "scene/gui/nine_patch_rect.h" +#include "scene/gui/separator.h" #include "scene/gui/subviewport_container.h" #include "scene/gui/view_panner.h" #include "scene/main/canvas_layer.h" diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 5b368de3cc..04fd819dec 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -214,8 +214,8 @@ private: int primary_grid_steps = 8; int grid_step_multiplier = 0; - real_t snap_rotation_step = 0.0; - real_t snap_rotation_offset = Math::deg2rad(15.0); + real_t snap_rotation_step = Math::deg2rad(15.0); + real_t snap_rotation_offset = 0.0; real_t snap_scale_step = 0.1f; bool smart_snap_active = false; bool grid_snap_active = false; diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index ec038174fc..2756e45cf4 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -31,7 +31,9 @@ #include "control_editor_plugin.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "scene/gui/separator.h" void ControlPositioningWarning::_update_warning() { if (!control_node) { diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 2954071054..8aeab684e3 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" CurveEditor::CurveEditor() { _selected_point = -1; diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index 5c90d70982..c572b5b7fe 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -35,6 +35,7 @@ #include "editor/debugger/editor_debugger_server.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/fileserver/editor_file_server.h" #include "editor/plugins/script_editor_plugin.h" #include "scene/gui/menu_button.h" diff --git a/editor/plugins/editor_resource_conversion_plugin.cpp b/editor/plugins/editor_resource_conversion_plugin.cpp new file mode 100644 index 0000000000..91394dbac7 --- /dev/null +++ b/editor/plugins/editor_resource_conversion_plugin.cpp @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* editor_resource_conversion_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor_resource_conversion_plugin.h" + +void EditorResourceConversionPlugin::_bind_methods() { + GDVIRTUAL_BIND(_converts_to); + GDVIRTUAL_BIND(_handles, "resource"); + GDVIRTUAL_BIND(_convert, "resource"); +} + +String EditorResourceConversionPlugin::converts_to() const { + String ret; + if (GDVIRTUAL_CALL(_converts_to, ret)) { + return ret; + } + + return ""; +} + +bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const { + bool ret; + if (GDVIRTUAL_CALL(_handles, p_resource, ret)) { + return ret; + } + + return false; +} + +Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const { + Ref<Resource> ret; + if (GDVIRTUAL_CALL(_convert, p_resource, ret)) { + return ret; + } + + return Ref<Resource>(); +} diff --git a/editor/plugins/editor_resource_conversion_plugin.h b/editor/plugins/editor_resource_conversion_plugin.h new file mode 100644 index 0000000000..34b0837383 --- /dev/null +++ b/editor/plugins/editor_resource_conversion_plugin.h @@ -0,0 +1,54 @@ +/*************************************************************************/ +/* editor_resource_conversion_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef EDITOR_RESOURCE_CONVERSION_PLUGIN_H +#define EDITOR_RESOURCE_CONVERSION_PLUGIN_H + +#include "core/io/resource.h" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/script_language.h" + +class EditorResourceConversionPlugin : public RefCounted { + GDCLASS(EditorResourceConversionPlugin, RefCounted); + +protected: + static void _bind_methods(); + + GDVIRTUAL0RC(String, _converts_to) + GDVIRTUAL1RC(bool, _handles, Ref<Resource>) + GDVIRTUAL1RC(Ref<Resource>, _convert, Ref<Resource>) + +public: + virtual String converts_to() const; + virtual bool handles(const Ref<Resource> &p_resource) const; + virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const; +}; + +#endif // EDITOR_RESOURCE_CONVERSION_PLUGIN_H diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index 4cdca95fca..542aee879b 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -33,6 +33,7 @@ #include "canvas_item_editor_plugin.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "node_3d_editor_plugin.h" Size2 GradientEditor::get_minimum_size() const { diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 4f8f6568d1..00fc8cc7d6 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -32,6 +32,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/subviewport_container.h" #include "scene/resources/fog_material.h" #include "scene/resources/particles_material.h" diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 9c6247d59b..fc3da5fd9f 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -32,7 +32,7 @@ #define MATERIAL_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "editor/property_editor.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "scene/3d/camera_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 2605a60d48..65b15a6001 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -34,6 +34,7 @@ #include "core/math/geometry_3d.h" #include "core/os/keyboard.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "node_3d_editor_plugin.h" #include "scene/resources/curve.h" diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 03de010f28..bbf5ffa462 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -591,7 +591,7 @@ void ScriptEditor::_go_to_tab(int p_idx) { } } - Control *c = Object::cast_to<Control>(tab_container->get_tab_control(p_idx)); + Control *c = tab_container->get_tab_control(p_idx); if (!c) { return; } @@ -813,7 +813,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { if (history_pos >= 0) { idx = tab_container->get_tab_idx_from_control(history[history_pos].control); } - tab_container->set_current_tab(idx); + _go_to_tab(idx); } else { _update_selected_editor_menu(); } @@ -1448,20 +1448,20 @@ void ScriptEditor::_menu_option(int p_option) { case WINDOW_MOVE_UP: { if (tab_container->get_current_tab() > 0) { tab_container->move_child(current, tab_container->get_current_tab() - 1); - tab_container->set_current_tab(tab_container->get_current_tab() - 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; case WINDOW_MOVE_DOWN: { if (tab_container->get_current_tab() < tab_container->get_tab_count() - 1) { tab_container->move_child(current, tab_container->get_current_tab() + 1); - tab_container->set_current_tab(tab_container->get_current_tab() + 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; default: { if (p_option >= WINDOW_SELECT_BASE) { - tab_container->set_current_tab(p_option - WINDOW_SELECT_BASE); + _go_to_tab(p_option - WINDOW_SELECT_BASE); _update_script_names(); } } @@ -1494,14 +1494,14 @@ void ScriptEditor::_menu_option(int p_option) { case WINDOW_MOVE_UP: { if (tab_container->get_current_tab() > 0) { tab_container->move_child(help, tab_container->get_current_tab() - 1); - tab_container->set_current_tab(tab_container->get_current_tab() - 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; case WINDOW_MOVE_DOWN: { if (tab_container->get_current_tab() < tab_container->get_tab_count() - 1) { tab_container->move_child(help, tab_container->get_current_tab() + 1); - tab_container->set_current_tab(tab_container->get_current_tab() + 1); + tab_container->set_current_tab(tab_container->get_current_tab()); _update_script_names(); } } break; @@ -2125,8 +2125,8 @@ void ScriptEditor::_update_script_names() { sd.index = i; sedata.set(i, sd); } - tab_container->set_current_tab(new_prev_tab); - tab_container->set_current_tab(new_cur_tab); + _go_to_tab(new_prev_tab); + _go_to_tab(new_cur_tab); _sort_list_on_update = false; } @@ -2154,8 +2154,10 @@ void ScriptEditor::_update_script_names() { } if (tab_container->get_current_tab() == sedata_filtered[i].index) { script_list->select(index); + script_name_label->set_text(sedata_filtered[i].name); script_icon->set_texture(sedata_filtered[i].icon); + ScriptEditorBase *se = _get_current_editor(); if (se) { se->enable_editor(); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index f77e23e63e..e700412188 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -41,7 +41,6 @@ #include "editor/filesystem_dock.h" #include "editor/plugins/visual_shader_editor_plugin.h" #include "editor/project_settings_editor.h" -#include "editor/property_editor.h" #include "editor/shader_create_dialog.h" #include "scene/gui/split_container.h" #include "servers/display_server.h" diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp index 4564f60fa5..4874944d33 100644 --- a/editor/plugins/shader_file_editor_plugin.cpp +++ b/editor/plugins/shader_file_editor_plugin.cpp @@ -37,7 +37,6 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" -#include "editor/property_editor.h" #include "servers/display_server.h" #include "servers/rendering/shader_types.h" diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 2e9b89f1f3..196d87da36 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -32,6 +32,7 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" void TextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) { ERR_FAIL_COND(p_highlighter.is_null()); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index a2b09b95eb..0bd8a8a484 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -35,7 +35,9 @@ #include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/gui/check_box.h" +#include "scene/gui/separator.h" #include "scene/gui/view_panner.h" #include "scene/resources/texture.h" diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index b4eab5f811..2a61ea0baa 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "editor/editor_resource_picker.h" #include "editor/editor_scale.h" #include "editor/progress_dialog.h" +#include "scene/gui/color_picker.h" void ThemeItemImportTree::_update_items_tree() { import_items_tree->clear(); diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp index 0c7303dda4..b5c6c6d651 100644 --- a/editor/plugins/theme_editor_preview.cpp +++ b/editor/plugins/theme_editor_preview.cpp @@ -36,6 +36,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "scene/gui/button.h" +#include "scene/gui/check_button.h" #include "scene/gui/color_picker.h" #include "scene/gui/progress_bar.h" #include "scene/resources/packed_scene.h" diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 443d5975cd..cf55465417 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -35,6 +35,8 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "scene/gui/separator.h" VersionControlEditorPlugin *VersionControlEditorPlugin::singleton = nullptr; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 626071aa72..e28122d93c 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -40,10 +40,17 @@ #include "editor/editor_node.h" #include "editor/editor_properties.h" #include "editor/editor_scale.h" +#include "editor/plugins/curve_editor_plugin.h" #include "editor/plugins/shader_editor_plugin.h" #include "scene/animation/animation_player.h" +#include "scene/gui/button.h" +#include "scene/gui/code_edit.h" +#include "scene/gui/graph_edit.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" +#include "scene/gui/popup.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/tree.h" #include "scene/gui/view_panner.h" #include "scene/main/window.h" #include "scene/resources/visual_shader_nodes.h" @@ -91,17 +98,6 @@ void VisualShaderNodePlugin::_bind_methods() { /////////////////// -static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { - Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); - style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE); - return style; -} - -/////////////////// - VisualShaderGraphPlugin::VisualShaderGraphPlugin() { } @@ -364,8 +360,6 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Control *offset; - static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); - static const Color type_color[] = { Color(0.38, 0.85, 0.96), // scalar (float) Color(0.49, 0.78, 0.94), // scalar (int) @@ -765,14 +759,14 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { } else { Label *label = memnew(Label); label->set_text(name_left); - label->add_theme_style_override("normal", label_style); //more compact + label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact hb->add_child(label); if (vsnode->is_input_port_default(i, mode) && !port_left_used) { Label *hint_label = memnew(Label); hint_label->set_text(TTR("[default]")); hint_label->add_theme_color_override("font_color", editor->get_theme_color(SNAME("font_readonly_color"), SNAME("TextEdit"))); - hint_label->add_theme_style_override("normal", label_style); + hint_label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); hb->add_child(hint_label); } } @@ -813,7 +807,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { } else { Label *label = memnew(Label); label->set_text(name_right); - label->add_theme_style_override("normal", label_style); //more compact + label->add_theme_style_override("normal", editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact hb->add_child(label); } } @@ -1080,6 +1074,23 @@ VisualShaderGraphPlugin::~VisualShaderGraphPlugin() { ///////////////// +void VisualShaderEditedProperty::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualShaderEditedProperty::set_edited_property); + ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualShaderEditedProperty::get_edited_property); + + ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property"); +} + +void VisualShaderEditedProperty::set_edited_property(Variant p_variant) { + edited_property = p_variant; +} + +Variant VisualShaderEditedProperty::get_edited_property() const { + return edited_property; +} + +///////////////// + Vector2 VisualShaderEditor::selection_center; List<VisualShaderEditor::CopyItem> VisualShaderEditor::copy_items_buffer; List<VisualShader::Connection> VisualShaderEditor::copy_connections_buffer; @@ -2287,10 +2298,8 @@ void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, } } -void VisualShaderEditor::_port_edited() { +void VisualShaderEditor::_port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) { VisualShader::Type type = get_current_shader_type(); - - Variant value = property_editor->get_variant(); Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node); ERR_FAIL_COND(!vsn.is_valid()); @@ -2298,30 +2307,51 @@ void VisualShaderEditor::_port_edited() { Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(vsn.ptr()); if (custom.is_valid()) { - undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, value); + undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, p_value); undo_redo->add_undo_method(custom.ptr(), "_set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); } else { - undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); + undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, p_value); undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); } - undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, value); + undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, p_value); undo_redo->add_undo_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, vsn->get_input_port_default_value(editing_port)); undo_redo->commit_action(); - - property_editor->hide(); } void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, int p_port) { VisualShader::Type type = get_current_shader_type(); + Ref<VisualShaderNode> vs_node = visual_shader->get_node(type, p_node); + Variant value = vs_node->get_input_port_default_value(p_port); + + edited_property_holder->set_edited_property(value); + + if (property_editor) { + property_editor->disconnect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited)); + property_editor_popup->remove_child(property_editor); + } - Ref<VisualShaderNode> vsn = visual_shader->get_node(type, p_node); + // TODO: Define these properties with actual PropertyInfo and feed it to the property editor widget. + property_editor = EditorInspector::instantiate_property_editor(edited_property_holder.ptr(), value.get_type(), "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE); + if (property_editor) { + property_editor->set_object_and_property(edited_property_holder.ptr(), "edited_property"); + property_editor->update_property(); + property_editor->set_name_split_ratio(0); + property_editor_popup->add_child(property_editor); + + property_editor->connect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited)); + + Button *button = Object::cast_to<Button>(p_button); + if (button) { + property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom()); + } + property_editor_popup->reset_size(); + if (button) { + property_editor_popup->popup(); + } else { + property_editor_popup->popup_centered_ratio(); + } + } - Button *button = Object::cast_to<Button>(p_button); - ERR_FAIL_COND(!button); - Variant value = vsn->get_input_port_default_value(p_port); - property_editor->set_position(button->get_screen_position() + Vector2(0, button->get_size().height)); - property_editor->edit(nullptr, "", value.get_type(), value, 0, ""); - property_editor->popup(); editing_node = p_node; editing_port = p_port; } @@ -5636,10 +5666,11 @@ VisualShaderEditor::VisualShaderEditor() { graph_plugin.instantiate(); graph_plugin->set_editor(this); - property_editor = memnew(CustomPropertyEditor); - add_child(property_editor); + property_editor_popup = memnew(PopupPanel); + property_editor_popup->set_min_size(Size2i(180, 0) * EDSCALE); + add_child(property_editor_popup); - property_editor->connect("variant_changed", callable_mp(this, &VisualShaderEditor::_port_edited)); + edited_property_holder.instantiate(); } class VisualShaderNodePluginInputEditor : public OptionButton { diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 2feed6108a..b846c34f9e 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -32,16 +32,21 @@ #define VISUAL_SHADER_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" -#include "editor/plugins/curve_editor_plugin.h" -#include "editor/property_editor.h" -#include "scene/gui/button.h" -#include "scene/gui/code_edit.h" -#include "scene/gui/graph_edit.h" -#include "scene/gui/popup.h" -#include "scene/gui/rich_text_label.h" -#include "scene/gui/tree.h" +#include "editor/plugins/editor_resource_conversion_plugin.h" #include "scene/resources/visual_shader.h" +class Button; +class CodeEdit; +class CodeHighlighter; +class CurveEditor; +class GraphEdit; +class GraphNode; +class PopupMenu; +class PopupPanel; +class RichTextLabel; +class TextEdit; +class Tree; + class VisualShaderEditor; class VisualShaderNodePlugin : public RefCounted { @@ -137,13 +142,31 @@ public: ~VisualShaderGraphPlugin(); }; +class VisualShaderEditedProperty : public RefCounted { + GDCLASS(VisualShaderEditedProperty, RefCounted); + +private: + Variant edited_property; + +protected: + static void _bind_methods(); + +public: + void set_edited_property(Variant p_variant); + Variant get_edited_property() const; + + VisualShaderEditedProperty() {} +}; + class VisualShaderEditor : public VBoxContainer { GDCLASS(VisualShaderEditor, VBoxContainer); friend class VisualShaderGraphPlugin; - CustomPropertyEditor *property_editor = nullptr; + PopupPanel *property_editor_popup = nullptr; + EditorProperty *property_editor = nullptr; int editing_node = -1; int editing_port = -1; + Ref<VisualShaderEditedProperty> edited_property_holder; Ref<VisualShader> visual_shader; GraphEdit *graph = nullptr; @@ -358,7 +381,7 @@ class VisualShaderEditor : public VBoxContainer { void _node_changed(int p_id); void _edit_port_default_input(Object *p_button, int p_node, int p_port); - void _port_edited(); + void _port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing); int to_node = -1; int to_slot = -1; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 7d35d5a3d5..8395fa996a 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -646,14 +646,6 @@ private: protected: static void _bind_methods() { - ClassDB::bind_method("_browse_path", &ProjectDialog::_browse_path); - ClassDB::bind_method("_create_folder", &ProjectDialog::_create_folder); - ClassDB::bind_method("_text_changed", &ProjectDialog::_text_changed); - ClassDB::bind_method("_path_text_changed", &ProjectDialog::_path_text_changed); - ClassDB::bind_method("_path_selected", &ProjectDialog::_path_selected); - ClassDB::bind_method("_file_selected", &ProjectDialog::_file_selected); - ClassDB::bind_method("_install_path_selected", &ProjectDialog::_install_path_selected); - ClassDB::bind_method("_browse_install_path", &ProjectDialog::_browse_install_path); ADD_SIGNAL(MethodInfo("project_created")); ADD_SIGNAL(MethodInfo("projects_updated")); } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index be1ad1ca9c..fba8c5c522 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -34,6 +34,7 @@ #include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "servers/movie_writer/movie_writer.h" ProjectSettingsEditor *ProjectSettingsEditor::singleton = nullptr; @@ -74,8 +75,13 @@ void ProjectSettingsEditor::_setting_edited(const String &p_name) { queue_save(); } +void ProjectSettingsEditor::_update_advanced(bool p_is_advanced) { + custom_properties->set_visible(p_is_advanced); +} + void ProjectSettingsEditor::_advanced_toggled(bool p_button_pressed) { EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", p_button_pressed); + _update_advanced(p_button_pressed); general_settings_inspector->set_restrict_to_basic_settings(!p_button_pressed); } @@ -584,35 +590,35 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { advanced->connect("toggled", callable_mp(this, &ProjectSettingsEditor::_advanced_toggled)); search_bar->add_child(advanced); - HBoxContainer *header = memnew(HBoxContainer); - general_editor->add_child(header); + custom_properties = memnew(HBoxContainer); + general_editor->add_child(custom_properties); property_box = memnew(LineEdit); property_box->set_placeholder(TTR("Select a Setting or Type its Name")); property_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); property_box->connect("text_changed", callable_mp(this, &ProjectSettingsEditor::_property_box_changed)); - header->add_child(property_box); + custom_properties->add_child(property_box); feature_box = memnew(OptionButton); feature_box->set_custom_minimum_size(Size2(120, 0) * EDSCALE); feature_box->connect("item_selected", callable_mp(this, &ProjectSettingsEditor::_feature_selected)); - header->add_child(feature_box); + custom_properties->add_child(feature_box); type_box = memnew(OptionButton); type_box->set_custom_minimum_size(Size2(120, 0) * EDSCALE); - header->add_child(type_box); + custom_properties->add_child(type_box); add_button = memnew(Button); add_button->set_text(TTR("Add")); add_button->set_disabled(true); add_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_add_setting)); - header->add_child(add_button); + custom_properties->add_child(add_button); del_button = memnew(Button); del_button->set_text(TTR("Delete")); del_button->set_disabled(true); del_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_delete_setting)); - header->add_child(del_button); + custom_properties->add_child(del_button); general_settings_inspector = memnew(SectionedInspector); general_settings_inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); @@ -693,6 +699,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { advanced->set_pressed(true); } + _update_advanced(use_advanced); general_settings_inspector->set_restrict_to_basic_settings(!use_advanced); import_defaults_editor = memnew(ImportDefaultsEditor); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 455aaae11c..849c50b9ba 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -61,6 +61,7 @@ class ProjectSettingsEditor : public AcceptDialog { LineEdit *search_box = nullptr; CheckButton *advanced = nullptr; + HBoxContainer *custom_properties = nullptr; LineEdit *property_box = nullptr; OptionButton *feature_box = nullptr; OptionButton *type_box = nullptr; @@ -77,6 +78,7 @@ class ProjectSettingsEditor : public AcceptDialog { UndoRedo *undo_redo = nullptr; void _advanced_toggled(bool p_button_pressed); + void _update_advanced(bool p_is_advanced); void _property_box_changed(const String &p_text); void _update_property_box(); void _feature_selected(int p_index); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp deleted file mode 100644 index 5f4375b424..0000000000 --- a/editor/property_editor.cpp +++ /dev/null @@ -1,1898 +0,0 @@ -/*************************************************************************/ -/* property_editor.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "property_editor.h" - -#include "core/config/project_settings.h" -#include "core/input/input.h" -#include "core/io/image_loader.h" -#include "core/io/marshalls.h" -#include "core/io/resource_loader.h" -#include "core/math/expression.h" -#include "core/object/class_db.h" -#include "core/os/keyboard.h" -#include "core/string/print_string.h" -#include "core/templates/pair.h" -#include "editor/array_property_edit.h" -#include "editor/create_dialog.h" -#include "editor/dictionary_property_edit.h" -#include "editor/editor_file_dialog.h" -#include "editor/editor_file_system.h" -#include "editor/editor_help.h" -#include "editor/editor_node.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" -#include "editor/filesystem_dock.h" -#include "editor/multi_node_edit.h" -#include "editor/property_selector.h" -#include "editor/scene_tree_dock.h" -#include "scene/gui/label.h" -#include "scene/main/window.h" -#include "scene/resources/font.h" -#include "scene/resources/packed_scene.h" -#include "scene/scene_string_names.h" - -void EditorResourceConversionPlugin::_bind_methods() { - GDVIRTUAL_BIND(_converts_to); - GDVIRTUAL_BIND(_handles, "resource"); - GDVIRTUAL_BIND(_convert, "resource"); -} - -String EditorResourceConversionPlugin::converts_to() const { - String ret; - if (GDVIRTUAL_CALL(_converts_to, ret)) { - return ret; - } - - return ""; -} - -bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const { - bool ret; - if (GDVIRTUAL_CALL(_handles, p_resource, ret)) { - return ret; - } - - return false; -} - -Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) const { - Ref<Resource> ret; - if (GDVIRTUAL_CALL(_convert, p_resource, ret)) { - return ret; - } - - return Ref<Resource>(); -} - -void CustomPropertyEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_WM_CLOSE_REQUEST: { - hide(); - } break; - } -} - -void CustomPropertyEditor::_menu_option(int p_which) { - switch (type) { - case Variant::INT: { - if (hint == PROPERTY_HINT_FLAGS) { - int idx = menu->get_item_index(p_which); - uint32_t item_value = menu->get_item_metadata(idx); - uint32_t value = v; - // If the item wasn't previously checked it means it was pressed, - // otherwise it was unpressed. - if (!menu->is_item_checked(idx)) { - v = value | item_value; - } else { - v = value & ~item_value; - } - emit_signal(SNAME("variant_changed")); - } else if (hint == PROPERTY_HINT_ENUM) { - v = menu->get_item_metadata(p_which); - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::STRING: { - if (hint == PROPERTY_HINT_ENUM) { - v = hint_text.get_slice(",", p_which); - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::OBJECT: { - switch (p_which) { - case OBJ_MENU_LOAD: { - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); - - List<String> extensions; - for (int i = 0; i < type.get_slice_count(","); i++) { - ResourceLoader::get_recognized_extensions_for_type(type.get_slice(",", i), &extensions); - } - - HashSet<String> valid_extensions; - for (const String &E : extensions) { - valid_extensions.insert(E); - } - - file->clear_filters(); - for (const String &E : valid_extensions) { - file->add_filter("*." + E, E.to_upper()); - } - - file->popup_file_dialog(); - } break; - - case OBJ_MENU_EDIT: { - Ref<RefCounted> r = v; - - if (!r.is_null()) { - emit_signal(SNAME("resource_edit_request")); - hide(); - } - } break; - case OBJ_MENU_CLEAR: { - v = Variant(); - emit_signal(SNAME("variant_changed")); - hide(); - } break; - - case OBJ_MENU_MAKE_UNIQUE: { - Ref<Resource> res_orig = v; - if (res_orig.is_null()) { - return; - } - - List<PropertyInfo> property_list; - res_orig->get_property_list(&property_list); - List<Pair<String, Variant>> propvalues; - - for (const PropertyInfo &pi : property_list) { - Pair<String, Variant> p; - if (pi.usage & PROPERTY_USAGE_STORAGE) { - p.first = pi.name; - p.second = res_orig->get(pi.name); - } - - propvalues.push_back(p); - } - - String orig_type = res_orig->get_class(); - - Object *inst = ClassDB::instantiate(orig_type); - - Ref<Resource> res = Ref<Resource>(Object::cast_to<Resource>(inst)); - - ERR_FAIL_COND(res.is_null()); - - for (const Pair<String, Variant> &p : propvalues) { - res->set(p.first, p.second); - } - - v = res; - emit_signal(SNAME("variant_changed")); - hide(); - } break; - - case OBJ_MENU_COPY: { - EditorSettings::get_singleton()->set_resource_clipboard(v); - - } break; - case OBJ_MENU_PASTE: { - v = EditorSettings::get_singleton()->get_resource_clipboard(); - emit_signal(SNAME("variant_changed")); - - } break; - case OBJ_MENU_NEW_SCRIPT: { - if (Object::cast_to<Node>(owner)) { - SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), false); - } - - } break; - case OBJ_MENU_EXTEND_SCRIPT: { - if (Object::cast_to<Node>(owner)) { - SceneTreeDock::get_singleton()->open_script_dialog(Object::cast_to<Node>(owner), true); - } - - } break; - case OBJ_MENU_SHOW_IN_FILE_SYSTEM: { - Ref<Resource> r = v; - FileSystemDock *file_system_dock = FileSystemDock::get_singleton(); - file_system_dock->navigate_to_path(r->get_path()); - // Ensure that the FileSystem dock is visible. - TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); - tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock)); - } break; - default: { - if (p_which >= CONVERT_BASE_ID) { - int to_type = p_which - CONVERT_BASE_ID; - - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(Ref<Resource>(v)); - - ERR_FAIL_INDEX(to_type, conversions.size()); - - Ref<Resource> new_res = conversions[to_type]->convert(v); - - v = new_res; - emit_signal(SNAME("variant_changed")); - break; - } - ERR_FAIL_COND(inheritors_array.is_empty()); - - String intype = inheritors_array[p_which - TYPE_BASE_ID]; - - if (intype == "ViewportTexture") { - scene_tree->set_title(TTR("Pick a Viewport")); - scene_tree->popup_scenetree_dialog(); - picking_viewport = true; - return; - } - - Variant obj = ClassDB::instantiate(intype); - - if (!obj) { - if (ScriptServer::is_global_class(intype)) { - obj = EditorNode::get_editor_data().script_class_instance(intype); - } else { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - } - - ERR_BREAK(!obj); - Resource *res = Object::cast_to<Resource>(obj); - ERR_BREAK(!res); - if (owner && hint == PROPERTY_HINT_RESOURCE_TYPE && hint_text == "Script") { - //make visual script the right type - res->call("set_instance_base_type", owner->get_class()); - } - - EditorNode::get_editor_data().instantiate_object_properties(obj); - v = obj; - - emit_signal(SNAME("variant_changed")); - - } break; - } - - } break; - default: { - } - } -} - -void CustomPropertyEditor::hide_menu() { - menu->hide(); -} - -Variant CustomPropertyEditor::get_variant() const { - return v; -} - -String CustomPropertyEditor::get_name() const { - return name; -} - -bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text) { - owner = p_owner; - updating = true; - name = p_name; - v = p_variant; - field_names.clear(); - hint = p_hint; - hint_text = p_hint_text; - type_button->hide(); - if (color_picker) { - color_picker->hide(); - } - texture_preview->hide(); - inheritors_array.clear(); - text_edit->hide(); - easing_draw->hide(); - spinbox->hide(); - slider->hide(); - menu->clear(); - menu->reset_size(); - - for (int i = 0; i < MAX_VALUE_EDITORS; i++) { - if (i < MAX_VALUE_EDITORS / 4) { - value_hboxes[i]->hide(); - } - value_editor[i]->hide(); - value_label[i]->hide(); - if (i < 4) { - scroll[i]->hide(); - } - } - - for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { - action_buttons[i]->hide(); - } - - checks20gc->hide(); - for (int i = 0; i < 20; i++) { - checks20[i]->hide(); - } - - type = (p_variant.get_type() != Variant::NIL && p_variant.get_type() != Variant::RID && p_type != Variant::OBJECT) ? p_variant.get_type() : p_type; - - switch (type) { - case Variant::BOOL: { - checks20gc->show(); - - CheckBox *c = checks20[0]; - c->set_text("True"); - checks20gc->set_position(Vector2(4, 4) * EDSCALE); - c->set_pressed(v); - c->show(); - - checks20gc->set_size(checks20gc->get_minimum_size()); - set_size(checks20gc->get_position() + checks20gc->get_size() + c->get_size() + Vector2(4, 4) * EDSCALE); - - } break; - case Variant::INT: - case Variant::FLOAT: { - if (hint == PROPERTY_HINT_RANGE) { - int c = hint_text.get_slice_count(","); - float min = 0, max = 100, step = type == Variant::FLOAT ? .01 : 1; - if (c >= 1) { - if (!hint_text.get_slice(",", 0).is_empty()) { - min = hint_text.get_slice(",", 0).to_float(); - } - } - if (c >= 2) { - if (!hint_text.get_slice(",", 1).is_empty()) { - max = hint_text.get_slice(",", 1).to_float(); - } - } - - if (c >= 3) { - if (!hint_text.get_slice(",", 2).is_empty()) { - step = hint_text.get_slice(",", 2).to_float(); - } - } - - if (c >= 4 && hint_text.get_slice(",", 3) == "slider") { - slider->set_min(min); - slider->set_max(max); - slider->set_step(step); - slider->set_value(v); - slider->show(); - set_size(Size2(110, 30) * EDSCALE); - } else { - spinbox->set_min(min); - spinbox->set_max(max); - spinbox->set_step(step); - spinbox->set_value(v); - spinbox->show(); - set_size(Size2(70, 35) * EDSCALE); - } - - } else if (hint == PROPERTY_HINT_ENUM) { - Vector<String> options = hint_text.split(","); - int current_val = 0; - for (int i = 0; i < options.size(); i++) { - Vector<String> text_split = options[i].split(":"); - if (text_split.size() != 1) { - current_val = text_split[1].to_int(); - } - menu->add_item(text_split[0]); - menu->set_item_metadata(i, current_val); - current_val += 1; - } - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_2D_RENDER || - hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || - hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_3D_RENDER || - hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { - String basename; - switch (hint) { - case PROPERTY_HINT_LAYERS_2D_RENDER: - basename = "layer_names/2d_render"; - break; - case PROPERTY_HINT_LAYERS_2D_PHYSICS: - basename = "layer_names/2d_physics"; - break; - case PROPERTY_HINT_LAYERS_2D_NAVIGATION: - basename = "layer_names/2d_navigation"; - break; - case PROPERTY_HINT_LAYERS_3D_RENDER: - basename = "layer_names/3d_render"; - break; - case PROPERTY_HINT_LAYERS_3D_PHYSICS: - basename = "layer_names/3d_physics"; - break; - case PROPERTY_HINT_LAYERS_3D_NAVIGATION: - basename = "layer_names/3d_navigation"; - break; - } - - checks20gc->show(); - uint32_t flgs = v; - for (int i = 0; i < 2; i++) { - Point2 ofs(4, 4); - ofs.y += 22 * i; - for (int j = 0; j < 10; j++) { - int idx = i * 10 + j; - CheckBox *c = checks20[idx]; - c->set_text(ProjectSettings::get_singleton()->get(basename + "/layer_" + itos(idx + 1))); - c->set_pressed(flgs & (1 << (i * 10 + j))); - c->show(); - } - } - - show(); - - checks20gc->set_position(Vector2(4, 4) * EDSCALE); - checks20gc->set_size(checks20gc->get_minimum_size()); - - set_size(Vector2(4, 4) * EDSCALE + checks20gc->get_position() + checks20gc->get_size()); - - } else if (hint == PROPERTY_HINT_EXP_EASING) { - easing_draw->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5 * EDSCALE); - easing_draw->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5 * EDSCALE); - easing_draw->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 5 * EDSCALE); - easing_draw->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -30 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 3 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -3 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_END, -25 * EDSCALE); - type_button->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -7 * EDSCALE); - type_button->set_text(TTR("Preset...")); - type_button->get_popup()->clear(); - type_button->get_popup()->add_item(TTR("Linear"), EASING_LINEAR); - type_button->get_popup()->add_item(TTR("Ease In"), EASING_EASE_IN); - type_button->get_popup()->add_item(TTR("Ease Out"), EASING_EASE_OUT); - if (hint_text != "attenuation") { - type_button->get_popup()->add_item(TTR("Zero"), EASING_ZERO); - type_button->get_popup()->add_item(TTR("Easing In-Out"), EASING_IN_OUT); - type_button->get_popup()->add_item(TTR("Easing Out-In"), EASING_OUT_IN); - } - - type_button->show(); - easing_draw->show(); - set_size(Size2(200, 150) * EDSCALE); - } else if (hint == PROPERTY_HINT_FLAGS) { - Vector<String> flags = hint_text.split(","); - uint32_t value = v; - for (int i = 0; i < flags.size(); i++) { - uint32_t current_val; - Vector<String> text_split = flags[i].split(":"); - if (text_split.size() != 1) { - current_val = text_split[1].to_int(); - } else { - current_val = 1 << i; - } - menu->add_check_item(text_split[0], current_val); - menu->set_item_metadata(i, current_val); - if ((value & current_val) == current_val) { - menu->set_item_checked(menu->get_item_index(current_val), true); - } - } - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - - } else { - List<String> names; - names.push_back("value:"); - config_value_editors(1, 1, 50, names); - value_editor[0]->set_text(TS->format_number(String::num(v))); - } - - } break; - case Variant::STRING: { - if (hint == PROPERTY_HINT_LOCALE_ID) { - List<String> names; - names.push_back(TTR("Locale...")); - names.push_back(TTR("Clear")); - config_action_buttons(names); - } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { - List<String> names; - names.push_back(TTR("File...")); - names.push_back(TTR("Clear")); - config_action_buttons(names); - } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) { - List<String> names; - names.push_back(TTR("Dir...")); - names.push_back(TTR("Clear")); - config_action_buttons(names); - } else if (hint == PROPERTY_HINT_ENUM) { - Vector<String> options = hint_text.split(","); - for (int i = 0; i < options.size(); i++) { - menu->add_item(options[i], i); - } - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_MULTILINE_TEXT) { - text_edit->show(); - text_edit->set_text(v); - text_edit->deselect(); - - int button_margin = text_edit->get_theme_constant(SNAME("button_margin"), SNAME("Dialogs")); - int margin = text_edit->get_theme_constant(SNAME("margin"), SNAME("Dialogs")); - - action_buttons[0]->set_anchor(SIDE_LEFT, Control::ANCHOR_END); - action_buttons[0]->set_anchor(SIDE_TOP, Control::ANCHOR_END); - action_buttons[0]->set_anchor(SIDE_RIGHT, Control::ANCHOR_END); - action_buttons[0]->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END); - action_buttons[0]->set_begin(Point2(-70 * EDSCALE, -button_margin + 5 * EDSCALE)); - action_buttons[0]->set_end(Point2(-margin, -margin)); - action_buttons[0]->set_text(TTR("Close")); - action_buttons[0]->show(); - - } else if (hint == PROPERTY_HINT_TYPE_STRING) { - if (!create_dialog) { - create_dialog = memnew(CreateDialog); - create_dialog->connect("create", callable_mp(this, &CustomPropertyEditor::_create_dialog_callback)); - add_child(create_dialog); - } - - if (!hint_text.is_empty()) { - create_dialog->set_base_type(hint_text); - } else { - create_dialog->set_base_type("Object"); - } - - create_dialog->popup_create(false); - hide(); - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_VARIANT_TYPE) { -#define MAKE_PROPSELECT \ - if (!property_select) { \ - property_select = memnew(PropertySelector); \ - property_select->connect("selected", callable_mp(this, &CustomPropertyEditor::_create_selected_property)); \ - add_child(property_select); \ - } \ - hide(); - - MAKE_PROPSELECT; - - Variant::Type type = Variant::NIL; - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (hint_text == Variant::get_type_name(Variant::Type(i))) { - type = Variant::Type(i); - } - } - if (type != Variant::NIL) { - property_select->select_method_from_basic_type(type, v); - } - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_BASE_TYPE) { - MAKE_PROPSELECT - - property_select->select_method_from_base_type(hint_text, v); - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_INSTANCE) { - MAKE_PROPSELECT - - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (instance) { - property_select->select_method_from_instance(instance, v); - } - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_METHOD_OF_SCRIPT) { - MAKE_PROPSELECT - - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (Object::cast_to<Script>(obj)) { - property_select->select_method_from_script(Object::cast_to<Script>(obj), v); - } - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE) { - MAKE_PROPSELECT - Variant::Type type = Variant::NIL; - String tname = hint_text; - if (tname.contains(".")) { - tname = tname.get_slice(".", 0); - } - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (tname == Variant::get_type_name(Variant::Type(i))) { - type = Variant::Type(Variant::Type(i)); - } - } - - if (type != Variant::NIL) { - property_select->select_property_from_basic_type(type, v); - } - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_BASE_TYPE) { - MAKE_PROPSELECT - - property_select->select_property_from_base_type(hint_text, v); - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_INSTANCE) { - MAKE_PROPSELECT - - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (instance) { - property_select->select_property_from_instance(instance, v); - } - - updating = false; - return false; - - } else if (hint == PROPERTY_HINT_PROPERTY_OF_SCRIPT) { - MAKE_PROPSELECT - - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); - if (Object::cast_to<Script>(obj)) { - property_select->select_property_from_script(Object::cast_to<Script>(obj), v); - } - - updating = false; - return false; - - } else { - List<String> names; - names.push_back("string:"); - config_value_editors(1, 1, 50, names); - value_editor[0]->set_text(v); - } - - } break; - case Variant::VECTOR2: { - field_names.push_back("x"); - field_names.push_back("y"); - config_value_editors(2, 2, 10, field_names); - Vector2 vec = v; - value_editor[0]->set_text(String::num(vec.x)); - value_editor[1]->set_text(String::num(vec.y)); - } break; - case Variant::RECT2: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("w"); - field_names.push_back("h"); - config_value_editors(4, 4, 10, field_names); - Rect2 r = v; - value_editor[0]->set_text(String::num(r.position.x)); - value_editor[1]->set_text(String::num(r.position.y)); - value_editor[2]->set_text(String::num(r.size.x)); - value_editor[3]->set_text(String::num(r.size.y)); - } break; - case Variant::VECTOR3: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("z"); - config_value_editors(3, 3, 10, field_names); - Vector3 vec = v; - value_editor[0]->set_text(String::num(vec.x)); - value_editor[1]->set_text(String::num(vec.y)); - value_editor[2]->set_text(String::num(vec.z)); - } break; - case Variant::PLANE: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("z"); - field_names.push_back("d"); - config_value_editors(4, 4, 10, field_names); - Plane plane = v; - value_editor[0]->set_text(String::num(plane.normal.x)); - value_editor[1]->set_text(String::num(plane.normal.y)); - value_editor[2]->set_text(String::num(plane.normal.z)); - value_editor[3]->set_text(String::num(plane.d)); - - } break; - case Variant::QUATERNION: { - field_names.push_back("x"); - field_names.push_back("y"); - field_names.push_back("z"); - field_names.push_back("w"); - config_value_editors(4, 4, 10, field_names); - Quaternion q = v; - value_editor[0]->set_text(String::num(q.x)); - value_editor[1]->set_text(String::num(q.y)); - value_editor[2]->set_text(String::num(q.z)); - value_editor[3]->set_text(String::num(q.w)); - - } break; - case Variant::AABB: { - field_names.push_back("px"); - field_names.push_back("py"); - field_names.push_back("pz"); - field_names.push_back("sx"); - field_names.push_back("sy"); - field_names.push_back("sz"); - config_value_editors(6, 3, 16, field_names); - - AABB aabb = v; - value_editor[0]->set_text(String::num(aabb.position.x)); - value_editor[1]->set_text(String::num(aabb.position.y)); - value_editor[2]->set_text(String::num(aabb.position.z)); - value_editor[3]->set_text(String::num(aabb.size.x)); - value_editor[4]->set_text(String::num(aabb.size.y)); - value_editor[5]->set_text(String::num(aabb.size.z)); - - } break; - case Variant::TRANSFORM2D: { - field_names.push_back("xx"); - field_names.push_back("xy"); - field_names.push_back("yx"); - field_names.push_back("yy"); - field_names.push_back("ox"); - field_names.push_back("oy"); - config_value_editors(6, 2, 16, field_names); - - Transform2D basis = v; - for (int i = 0; i < 6; i++) { - value_editor[i]->set_text(String::num(basis.columns[i / 2][i % 2])); - } - - } break; - case Variant::BASIS: { - field_names.push_back("xx"); - field_names.push_back("xy"); - field_names.push_back("xz"); - field_names.push_back("yx"); - field_names.push_back("yy"); - field_names.push_back("yz"); - field_names.push_back("zx"); - field_names.push_back("zy"); - field_names.push_back("zz"); - config_value_editors(9, 3, 16, field_names); - - Basis basis = v; - for (int i = 0; i < 9; i++) { - value_editor[i]->set_text(String::num(basis.rows[i / 3][i % 3])); - } - - } break; - case Variant::TRANSFORM3D: { - field_names.push_back("xx"); - field_names.push_back("xy"); - field_names.push_back("xz"); - field_names.push_back("xo"); - field_names.push_back("yx"); - field_names.push_back("yy"); - field_names.push_back("yz"); - field_names.push_back("yo"); - field_names.push_back("zx"); - field_names.push_back("zy"); - field_names.push_back("zz"); - field_names.push_back("zo"); - config_value_editors(12, 4, 16, field_names); - - Transform3D tr = v; - for (int i = 0; i < 9; i++) { - value_editor[(i / 3) * 4 + i % 3]->set_text(String::num(tr.basis.rows[i / 3][i % 3])); - } - - value_editor[3]->set_text(String::num(tr.origin.x)); - value_editor[7]->set_text(String::num(tr.origin.y)); - value_editor[11]->set_text(String::num(tr.origin.z)); - - } break; - case Variant::COLOR: { - if (!color_picker) { - //late init for performance - color_picker = memnew(ColorPicker); - color_picker->set_deferred_mode(true); - value_vbox->add_child(color_picker); - color_picker->hide(); - color_picker->connect("color_changed", callable_mp(this, &CustomPropertyEditor::_color_changed)); - color_picker->connect("show", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(color_picker)); - } - - color_picker->show(); - color_picker->set_edit_alpha(hint != PROPERTY_HINT_COLOR_NO_ALPHA); - color_picker->set_pick_color(v); - color_picker->set_focus_on_line_edit(); - - } break; - - case Variant::NODE_PATH: { - List<String> names; - names.push_back(TTR("Assign")); - names.push_back(TTR("Clear")); - - if (owner && owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) { - names.push_back(TTR("Select Node")); - } - - config_action_buttons(names); - - } break; - case Variant::OBJECT: { - if (hint != PROPERTY_HINT_RESOURCE_TYPE) { - break; - } - - if (p_name == "script" && hint_text == "Script" && Object::cast_to<Node>(owner)) { - menu->add_item(TTR("New Script"), OBJ_MENU_NEW_SCRIPT); - menu->add_separator(); - } else if (!hint_text.is_empty()) { - int idx = 0; - - Vector<EditorData::CustomType> custom_resources; - - if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { - custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; - } - - for (int i = 0; i < hint_text.get_slice_count(","); i++) { - String base = hint_text.get_slice(",", i); - - HashSet<String> valid_inheritors; - valid_inheritors.insert(base); - List<StringName> inheritors; - ClassDB::get_inheriters_from_class(base.strip_edges(), &inheritors); - - for (int j = 0; j < custom_resources.size(); j++) { - inheritors.push_back(custom_resources[j].name); - } - - List<StringName>::Element *E = inheritors.front(); - while (E) { - valid_inheritors.insert(E->get()); - E = E->next(); - } - - for (const String &j : valid_inheritors) { - const String &t = j; - - bool is_custom_resource = false; - Ref<Texture2D> icon; - if (!custom_resources.is_empty()) { - for (int k = 0; k < custom_resources.size(); k++) { - if (custom_resources[k].name == t) { - is_custom_resource = true; - if (custom_resources[k].icon.is_valid()) { - icon = custom_resources[k].icon; - } - break; - } - } - } - - if (!is_custom_resource && (!ClassDB::can_instantiate(t) || ClassDB::is_virtual(t))) { - continue; - } - - inheritors_array.push_back(t); - - int id = TYPE_BASE_ID + idx; - - menu->add_item(vformat(TTR("New %s"), t), id); - - idx++; - } - } - - if (menu->get_item_count()) { - menu->add_separator(); - } - } - - menu->add_item(TTR("Load"), OBJ_MENU_LOAD); - - if (!Ref<Resource>(v).is_null()) { - menu->add_item(TTR("Edit"), OBJ_MENU_EDIT); - menu->add_item(TTR("Clear"), OBJ_MENU_CLEAR); - menu->add_item(TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); - - Ref<Resource> r = v; - if (r.is_valid() && r->get_path().is_resource_file()) { - menu->add_separator(); - menu->add_item(TTR("Show in FileSystem"), OBJ_MENU_SHOW_IN_FILE_SYSTEM); - } - } - - Ref<Resource> cb = EditorSettings::get_singleton()->get_resource_clipboard(); - bool paste_valid = false; - if (cb.is_valid()) { - if (hint_text.is_empty()) { - paste_valid = true; - } else { - for (int i = 0; i < hint_text.get_slice_count(","); i++) { - if (ClassDB::is_parent_class(cb->get_class(), hint_text.get_slice(",", i))) { - paste_valid = true; - break; - } - } - } - } - - if (!Ref<Resource>(v).is_null() || paste_valid) { - menu->add_separator(); - - if (!Ref<Resource>(v).is_null()) { - menu->add_item(TTR("Copy"), OBJ_MENU_COPY); - } - - if (paste_valid) { - menu->add_item(TTR("Paste"), OBJ_MENU_PASTE); - } - } - - if (!Ref<Resource>(v).is_null()) { - Vector<Ref<EditorResourceConversionPlugin>> conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(Ref<Resource>(v)); - if (conversions.size()) { - menu->add_separator(); - } - for (int i = 0; i < conversions.size(); i++) { - String what = conversions[i]->converts_to(); - menu->add_item(vformat(TTR("Convert to %s"), what), CONVERT_BASE_ID + i); - } - } - - menu->set_position(get_position()); - menu->popup(); - hide(); - updating = false; - return false; - } break; - case Variant::DICTIONARY: { - } break; - case Variant::PACKED_BYTE_ARRAY: { - } break; - case Variant::PACKED_INT32_ARRAY: { - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - } break; - case Variant::PACKED_INT64_ARRAY: { - } break; - case Variant::PACKED_FLOAT64_ARRAY: { - } break; - case Variant::PACKED_STRING_ARRAY: { - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - } break; - case Variant::PACKED_COLOR_ARRAY: { - } break; - default: { - } - } - - updating = false; - return true; -} - -void CustomPropertyEditor::_file_selected(String p_file) { - switch (type) { - case Variant::STRING: { - if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_DIR) { - v = ProjectSettings::get_singleton()->localize_path(p_file); - emit_signal(SNAME("variant_changed")); - hide(); - } - - if (hint == PROPERTY_HINT_GLOBAL_FILE || hint == PROPERTY_HINT_GLOBAL_DIR) { - v = p_file; - emit_signal(SNAME("variant_changed")); - hide(); - } - - } break; - case Variant::OBJECT: { - String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); - - Ref<Resource> res = ResourceLoader::load(p_file, type); - if (res.is_null()) { - error->set_text(TTR("Error loading file: Not a resource!")); - error->popup_centered(); - break; - } - v = res; - emit_signal(SNAME("variant_changed")); - hide(); - } break; - default: { - } - } -} - -void CustomPropertyEditor::_locale_selected(String p_locale) { - if (type == Variant::STRING && hint == PROPERTY_HINT_LOCALE_ID) { - v = p_locale; - emit_signal(SNAME("variant_changed")); - hide(); - } -} - -void CustomPropertyEditor::_type_create_selected(int p_idx) { - if (type == Variant::INT || type == Variant::FLOAT) { - float newval = 0; - switch (p_idx) { - case EASING_LINEAR: { - newval = 1; - } break; - case EASING_EASE_IN: { - newval = 2.0; - } break; - case EASING_EASE_OUT: { - newval = 0.5; - } break; - case EASING_ZERO: { - newval = 0; - } break; - case EASING_IN_OUT: { - newval = -0.5; - } break; - case EASING_OUT_IN: { - newval = -2.0; - } break; - } - - v = newval; - emit_signal(SNAME("variant_changed")); - easing_draw->update(); - - } else if (type == Variant::OBJECT) { - ERR_FAIL_INDEX(p_idx, inheritors_array.size()); - - String intype = inheritors_array[p_idx]; - - Variant obj = ClassDB::instantiate(intype); - - if (!obj) { - if (ScriptServer::is_global_class(intype)) { - obj = EditorNode::get_editor_data().script_class_instance(intype); - } else { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - } - - ERR_FAIL_COND(!obj); - ERR_FAIL_COND(!Object::cast_to<Resource>(obj)); - - EditorNode::get_editor_data().instantiate_object_properties(obj); - v = obj; - - emit_signal(SNAME("variant_changed")); - hide(); - } -} - -void CustomPropertyEditor::_color_changed(const Color &p_color) { - v = p_color; - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_node_path_selected(NodePath p_path) { - if (picking_viewport) { - Node *to_node = get_node(p_path); - if (!Object::cast_to<Viewport>(to_node)) { - EditorNode::get_singleton()->show_warning(TTR("Selected node is not a Viewport!")); - return; - } - - Ref<ViewportTexture> vt; - vt.instantiate(); - vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); - vt->setup_local_to_scene(); - v = vt; - emit_signal(SNAME("variant_changed")); - return; - } - - if (hint == PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && !hint_text.is_empty()) { - Node *node = get_node(hint_text); - if (node) { - Node *tonode = node->get_node(p_path); - if (tonode) { - p_path = node->get_path_to(tonode); - } - } - - } else if (owner) { - Node *node = nullptr; - - if (owner->is_class("Node")) { - node = Object::cast_to<Node>(owner); - } else if (owner->is_class("ArrayPropertyEdit")) { - node = Object::cast_to<ArrayPropertyEdit>(owner)->get_node(); - } else if (owner->is_class("DictionaryPropertyEdit")) { - node = Object::cast_to<DictionaryPropertyEdit>(owner)->get_node(); - } - if (!node) { - v = p_path; - emit_signal(SNAME("variant_changed")); - call_deferred(SNAME("hide")); //to not mess with dialogs - return; - } - - Node *tonode = node->get_node(p_path); - if (tonode) { - p_path = node->get_path_to(tonode); - } - } - - v = p_path; - emit_signal(SNAME("variant_changed")); - call_deferred(SNAME("hide")); //to not mess with dialogs -} - -void CustomPropertyEditor::_action_pressed(int p_which) { - if (updating) { - return; - } - - switch (type) { - case Variant::BOOL: { - v = checks20[0]->is_pressed(); - emit_signal(SNAME("variant_changed")); - } break; - case Variant::INT: { - if (hint == PROPERTY_HINT_LAYERS_2D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_2D_RENDER || - hint == PROPERTY_HINT_LAYERS_2D_NAVIGATION || - hint == PROPERTY_HINT_LAYERS_3D_PHYSICS || - hint == PROPERTY_HINT_LAYERS_3D_RENDER || - hint == PROPERTY_HINT_LAYERS_3D_NAVIGATION) { - uint32_t f = v; - if (checks20[p_which]->is_pressed()) { - f |= (1 << p_which); - } else { - f &= ~(1 << p_which); - } - - v = f; - emit_signal(SNAME("variant_changed")); - } - - } break; - case Variant::STRING: { - if (hint == PROPERTY_HINT_MULTILINE_TEXT) { - hide(); - } else if (hint == PROPERTY_HINT_LOCALE_ID) { - locale->popup_locale_dialog(); - } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { - if (p_which == 0) { - if (hint == PROPERTY_HINT_FILE) { - file->set_access(EditorFileDialog::ACCESS_RESOURCES); - } else { - file->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - } - - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - file->clear_filters(); - - file->clear_filters(); - - if (!hint_text.is_empty()) { - Vector<String> extensions = hint_text.split(","); - for (int i = 0; i < extensions.size(); i++) { - String filter = extensions[i]; - if (filter.begins_with(".")) { - filter = "*" + extensions[i]; - } else if (!filter.begins_with("*")) { - filter = "*." + extensions[i]; - } - - file->add_filter(filter, extensions[i].to_upper()); - } - } - file->popup_file_dialog(); - } else { - v = ""; - emit_signal(SNAME("variant_changed")); - hide(); - } - - } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) { - if (p_which == 0) { - if (hint == PROPERTY_HINT_DIR) { - file->set_access(EditorFileDialog::ACCESS_RESOURCES); - } else { - file->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - } - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); - file->clear_filters(); - file->popup_file_dialog(); - } else { - v = ""; - emit_signal(SNAME("variant_changed")); - hide(); - } - } - - } break; - case Variant::NODE_PATH: { - if (p_which == 0) { - picking_viewport = false; - scene_tree->set_title(TTR("Pick a Node")); - scene_tree->popup_scenetree_dialog(); - - } else if (p_which == 1) { - v = NodePath(); - emit_signal(SNAME("variant_changed")); - hide(); - } else if (p_which == 2) { - if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) { - Node *target_node = Object::cast_to<Node>(owner)->get_node(v); - EditorNode::get_singleton()->get_editor_selection()->clear(); - SceneTreeDock::get_singleton()->set_selected(target_node); - } - - hide(); - } - - } break; - case Variant::OBJECT: { - if (p_which == 0) { - ERR_FAIL_COND(inheritors_array.is_empty()); - - String intype = inheritors_array[0]; - - if (hint == PROPERTY_HINT_RESOURCE_TYPE) { - Variant obj = ClassDB::instantiate(intype); - - if (!obj) { - if (ScriptServer::is_global_class(intype)) { - obj = EditorNode::get_editor_data().script_class_instance(intype); - } else { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); - } - } - - ERR_BREAK(!obj); - ERR_BREAK(!Object::cast_to<Resource>(obj)); - - EditorNode::get_editor_data().instantiate_object_properties(obj); - v = obj; - - emit_signal(SNAME("variant_changed")); - hide(); - } - } else if (p_which == 1) { - file->set_access(EditorFileDialog::ACCESS_RESOURCES); - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - List<String> extensions; - String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); - - ResourceLoader::get_recognized_extensions_for_type(type, &extensions); - file->clear_filters(); - for (const String &E : extensions) { - file->add_filter("*." + E, E.to_upper()); - } - - file->popup_file_dialog(); - - } else if (p_which == 2) { - Ref<Resource> r = v; - - if (!r.is_null()) { - emit_signal(SNAME("resource_edit_request")); - hide(); - } - - } else if (p_which == 3) { - v = Variant(); - emit_signal(SNAME("variant_changed")); - hide(); - } else if (p_which == 4) { - Ref<Resource> res_orig = v; - if (res_orig.is_null()) { - return; - } - - List<PropertyInfo> property_list; - res_orig->get_property_list(&property_list); - List<Pair<String, Variant>> propvalues; - - for (const PropertyInfo &pi : property_list) { - Pair<String, Variant> p; - if (pi.usage & PROPERTY_USAGE_STORAGE) { - p.first = pi.name; - p.second = res_orig->get(pi.name); - } - - propvalues.push_back(p); - } - - Ref<Resource> res = Ref<Resource>(ClassDB::instantiate(res_orig->get_class())); - - ERR_FAIL_COND(res.is_null()); - - for (const Pair<String, Variant> &p : propvalues) { - res->set(p.first, p.second); - } - - v = res; - emit_signal(SNAME("variant_changed")); - hide(); - } - - } break; - - default: { - }; - } -} - -void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) { - Ref<InputEventMouseMotion> mm = p_ev; - - if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { - float rel = mm->get_relative().x; - if (rel == 0) { - return; - } - - bool flip = hint_text == "attenuation"; - - if (flip) { - rel = -rel; - } - - float val = v; - if (val == 0) { - return; - } - bool sg = val < 0; - val = Math::absf(val); - - val = Math::log(val) / Math::log((float)2.0); - //logspace - val += rel * 0.05; - - val = Math::pow(2.0f, val); - if (sg) { - val = -val; - } - - v = val; - easing_draw->update(); - emit_signal(SNAME("variant_changed")); - } -} - -void CustomPropertyEditor::_draw_easing() { - RID ci = easing_draw->get_canvas_item(); - - Size2 s = easing_draw->get_size(); - Rect2 r(Point2(), s); - r = r.grow(3); - easing_draw->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->draw(ci, r); - - int points = 48; - - float prev = 1.0; - float exp = v; - bool flip = hint_text == "attenuation"; - - Ref<Font> f = easing_draw->get_theme_font(SNAME("font"), SNAME("Label")); - int font_size = easing_draw->get_theme_font_size(SNAME("font_size"), SNAME("Label")); - Color color = easing_draw->get_theme_color(SNAME("font_color"), SNAME("Label")); - - for (int i = 1; i <= points; i++) { - float ifl = i / float(points); - float iflp = (i - 1) / float(points); - - float h = 1.0 - Math::ease(ifl, exp); - - if (flip) { - ifl = 1.0 - ifl; - iflp = 1.0 - iflp; - } - - RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(iflp * s.width, prev * s.height), Point2(ifl * s.width, h * s.height), color); - prev = h; - } - - f->draw_string(ci, Point2(10, 10 + f->get_ascent(font_size)), String::num(exp, 2), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color); -} - -void CustomPropertyEditor::_text_edit_changed() { - v = text_edit->get_text(); - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_create_dialog_callback() { - v = create_dialog->get_selected_type(); - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_create_selected_property(const String &p_prop) { - v = p_prop; - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_modified(String p_string) { - if (updating) { - return; - } - - Variant prev_v = v; - - updating = true; - switch (type) { - case Variant::INT: { - String text = TS->parse_number(value_editor[0]->get_text()); - Ref<Expression> expr; - expr.instantiate(); - Error err = expr->parse(text); - if (err != OK) { - v = value_editor[0]->get_text().to_int(); - return; - } else { - v = expr->execute(Array(), nullptr, false, false); - } - - if (v != prev_v) { - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::FLOAT: { - if (hint != PROPERTY_HINT_EXP_EASING) { - String text = TS->parse_number(value_editor[0]->get_text()); - v = _parse_real_expression(text); - if (v != prev_v) { - emit_signal(SNAME("variant_changed")); - } - } - - } break; - case Variant::STRING: { - v = value_editor[0]->get_text(); - emit_signal(SNAME("variant_changed")); - } break; - case Variant::VECTOR2: { - Vector2 vec; - vec.x = _parse_real_expression(value_editor[0]->get_text()); - vec.y = _parse_real_expression(value_editor[1]->get_text()); - v = vec; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::RECT2: { - Rect2 r2; - - r2.position.x = _parse_real_expression(value_editor[0]->get_text()); - r2.position.y = _parse_real_expression(value_editor[1]->get_text()); - r2.size.x = _parse_real_expression(value_editor[2]->get_text()); - r2.size.y = _parse_real_expression(value_editor[3]->get_text()); - v = r2; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - - case Variant::VECTOR3: { - Vector3 vec; - vec.x = _parse_real_expression(value_editor[0]->get_text()); - vec.y = _parse_real_expression(value_editor[1]->get_text()); - vec.z = _parse_real_expression(value_editor[2]->get_text()); - v = vec; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::PLANE: { - Plane pl; - pl.normal.x = _parse_real_expression(value_editor[0]->get_text()); - pl.normal.y = _parse_real_expression(value_editor[1]->get_text()); - pl.normal.z = _parse_real_expression(value_editor[2]->get_text()); - pl.d = _parse_real_expression(value_editor[3]->get_text()); - v = pl; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::QUATERNION: { - Quaternion q; - q.x = _parse_real_expression(value_editor[0]->get_text()); - q.y = _parse_real_expression(value_editor[1]->get_text()); - q.z = _parse_real_expression(value_editor[2]->get_text()); - q.w = _parse_real_expression(value_editor[3]->get_text()); - v = q; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::AABB: { - Vector3 pos; - Vector3 size; - - pos.x = _parse_real_expression(value_editor[0]->get_text()); - pos.y = _parse_real_expression(value_editor[1]->get_text()); - pos.z = _parse_real_expression(value_editor[2]->get_text()); - size.x = _parse_real_expression(value_editor[3]->get_text()); - size.y = _parse_real_expression(value_editor[4]->get_text()); - size.z = _parse_real_expression(value_editor[5]->get_text()); - v = AABB(pos, size); - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::TRANSFORM2D: { - Transform2D m; - for (int i = 0; i < 6; i++) { - m.columns[i / 2][i % 2] = _parse_real_expression(value_editor[i]->get_text()); - } - - v = m; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::BASIS: { - Basis m; - for (int i = 0; i < 9; i++) { - m.rows[i / 3][i % 3] = _parse_real_expression(value_editor[i]->get_text()); - } - - v = m; - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::TRANSFORM3D: { - Basis basis; - for (int i = 0; i < 9; i++) { - basis.rows[i / 3][i % 3] = _parse_real_expression(value_editor[(i / 3) * 4 + i % 3]->get_text()); - } - - Vector3 origin; - - origin.x = _parse_real_expression(value_editor[3]->get_text()); - origin.y = _parse_real_expression(value_editor[7]->get_text()); - origin.z = _parse_real_expression(value_editor[11]->get_text()); - - v = Transform3D(basis, origin); - if (v != prev_v) { - _emit_changed_whole_or_field(); - } - - } break; - case Variant::COLOR: { - } break; - - case Variant::NODE_PATH: { - v = NodePath(value_editor[0]->get_text()); - if (v != prev_v) { - emit_signal(SNAME("variant_changed")); - } - } break; - case Variant::DICTIONARY: { - } break; - case Variant::PACKED_BYTE_ARRAY: { - } break; - case Variant::PACKED_INT32_ARRAY: { - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - } break; - case Variant::PACKED_STRING_ARRAY: { - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - } break; - case Variant::PACKED_COLOR_ARRAY: { - } break; - default: { - } - } - - updating = false; -} - -real_t CustomPropertyEditor::_parse_real_expression(String text) { - Ref<Expression> expr; - expr.instantiate(); - Error err = expr->parse(text); - real_t out; - if (err != OK) { - out = value_editor[0]->get_text().to_float(); - } else { - out = expr->execute(Array(), nullptr, false, true); - } - return out; -} - -void CustomPropertyEditor::_emit_changed_whole_or_field() { - if (!Input::get_singleton()->is_key_pressed(Key::SHIFT)) { - emit_signal(SNAME("variant_changed")); - } else { - emit_signal(SNAME("variant_field_changed"), field_names[focused_value_editor]); - } -} - -void CustomPropertyEditor::_range_modified(double p_value) { - v = p_value; - emit_signal(SNAME("variant_changed")); -} - -void CustomPropertyEditor::_focus_enter() { - switch (type) { - case Variant::FLOAT: - case Variant::STRING: - case Variant::VECTOR2: - case Variant::RECT2: - case Variant::VECTOR3: - case Variant::PLANE: - case Variant::QUATERNION: - case Variant::AABB: - case Variant::TRANSFORM2D: - case Variant::BASIS: - case Variant::TRANSFORM3D: { - for (int i = 0; i < MAX_VALUE_EDITORS; ++i) { - if (value_editor[i]->has_focus()) { - focused_value_editor = i; - value_editor[i]->select_all(); - break; - } - } - } break; - default: { - } - } -} - -void CustomPropertyEditor::_focus_exit() { - _modified(String()); -} - -void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) { - Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox(SNAME("button")); - int margin_top = sb->get_margin(SIDE_TOP); - int margin_left = sb->get_margin(SIDE_LEFT); - int margin_bottom = sb->get_margin(SIDE_BOTTOM); - int margin_right = sb->get_margin(SIDE_RIGHT); - - int max_width = 0; - int height = 0; - - for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { - if (i < p_strings.size()) { - action_buttons[i]->show(); - action_buttons[i]->set_text(p_strings[i]); - - Size2 btn_m_size = action_buttons[i]->get_minimum_size(); - if (btn_m_size.width > max_width) { - max_width = btn_m_size.width; - } - - } else { - action_buttons[i]->hide(); - } - } - - for (int i = 0; i < p_strings.size(); i++) { - Size2 btn_m_size = action_buttons[i]->get_size(); - action_buttons[i]->set_position(Point2(0, height) + Point2(margin_left, margin_top)); - action_buttons[i]->set_size(Size2(max_width, btn_m_size.height)); - - height += btn_m_size.height; - } - set_size(Size2(max_width, height) + Size2(margin_left + margin_right, margin_top + margin_bottom)); -} - -void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings) { - int cell_width = 95; - int cell_height = 25; - int cell_margin = 5; - int rows = ((p_amount - 1) / p_columns) + 1; - - set_size(Size2(cell_margin + p_label_w + (cell_width + cell_margin + p_label_w) * p_columns, cell_margin + (cell_height + cell_margin) * rows) * EDSCALE); - - for (int i = 0; i < MAX_VALUE_EDITORS; i++) { - value_label[i]->get_parent()->remove_child(value_label[i]); - value_editor[i]->get_parent()->remove_child(value_editor[i]); - - int box_id = i / p_columns; - value_hboxes[box_id]->add_child(value_label[i]); - value_hboxes[box_id]->add_child(value_editor[i]); - - if (i < MAX_VALUE_EDITORS / 4) { - if (i <= p_amount / 4) { - value_hboxes[i]->show(); - } else { - value_hboxes[i]->hide(); - } - } - - if (i < p_amount) { - value_editor[i]->show(); - value_label[i]->show(); - value_label[i]->set_text(i < p_strings.size() ? p_strings[i] : String("")); - value_editor[i]->set_editable(!read_only); - } else { - value_editor[i]->hide(); - value_label[i]->hide(); - } - } -} - -void CustomPropertyEditor::_bind_methods() { - ADD_SIGNAL(MethodInfo("variant_changed")); - ADD_SIGNAL(MethodInfo("variant_field_changed", PropertyInfo(Variant::STRING, "field"))); - ADD_SIGNAL(MethodInfo("resource_edit_request")); -} - -CustomPropertyEditor::CustomPropertyEditor() { - value_vbox = memnew(VBoxContainer); - add_child(value_vbox); - - for (int i = 0; i < MAX_VALUE_EDITORS; i++) { - if (i < MAX_VALUE_EDITORS / 4) { - value_hboxes[i] = memnew(HBoxContainer); - value_vbox->add_child(value_hboxes[i]); - value_hboxes[i]->hide(); - } - int hbox_idx = i / 4; - value_label[i] = memnew(Label); - value_hboxes[hbox_idx]->add_child(value_label[i]); - value_label[i]->hide(); - value_editor[i] = memnew(LineEdit); - value_hboxes[hbox_idx]->add_child(value_editor[i]); - value_editor[i]->set_h_size_flags(Control::SIZE_EXPAND_FILL); - value_editor[i]->hide(); - value_editor[i]->connect("text_submitted", callable_mp(this, &CustomPropertyEditor::_modified)); - value_editor[i]->connect("focus_entered", callable_mp(this, &CustomPropertyEditor::_focus_enter)); - value_editor[i]->connect("focus_exited", callable_mp(this, &CustomPropertyEditor::_focus_exit)); - } - focused_value_editor = -1; - - for (int i = 0; i < 4; i++) { - scroll[i] = memnew(HScrollBar); - scroll[i]->hide(); - scroll[i]->set_min(0); - scroll[i]->set_max(1.0); - scroll[i]->set_step(0.01); - add_child(scroll[i]); - } - - checks20gc = memnew(GridContainer); - add_child(checks20gc); - checks20gc->set_columns(11); - - for (int i = 0; i < 20; i++) { - if (i == 5 || i == 15) { - Control *space = memnew(Control); - space->set_custom_minimum_size(Size2(20, 0) * EDSCALE); - checks20gc->add_child(space); - } - - checks20[i] = memnew(CheckBox); - checks20[i]->set_toggle_mode(true); - checks20[i]->set_focus_mode(Control::FOCUS_NONE); - checks20gc->add_child(checks20[i]); - checks20[i]->hide(); - checks20[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed).bind(i)); - checks20[i]->set_tooltip(vformat(TTR("Bit %d, val %d."), i, 1 << i)); - } - - text_edit = memnew(TextEdit); - value_vbox->add_child(text_edit); - text_edit->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 5); - text_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL); - text_edit->set_offset(SIDE_BOTTOM, -30); - - text_edit->hide(); - text_edit->connect("text_changed", callable_mp(this, &CustomPropertyEditor::_text_edit_changed)); - - color_picker = nullptr; - - file = memnew(EditorFileDialog); - value_vbox->add_child(file); - file->hide(); - - file->connect("file_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); - file->connect("dir_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); - - locale = memnew(EditorLocaleDialog); - value_vbox->add_child(locale); - locale->hide(); - - locale->connect("locale_selected", callable_mp(this, &CustomPropertyEditor::_locale_selected)); - - error = memnew(ConfirmationDialog); - error->set_title(TTR("Error!")); - value_vbox->add_child(error); - - scene_tree = memnew(SceneTreeDialog); - value_vbox->add_child(scene_tree); - scene_tree->connect("selected", callable_mp(this, &CustomPropertyEditor::_node_path_selected)); - scene_tree->get_scene_tree()->set_show_enabled_subscene(true); - - texture_preview = memnew(TextureRect); - value_vbox->add_child(texture_preview); - texture_preview->hide(); - - easing_draw = memnew(Control); - value_vbox->add_child(easing_draw); - easing_draw->hide(); - easing_draw->connect("draw", callable_mp(this, &CustomPropertyEditor::_draw_easing)); - easing_draw->connect("gui_input", callable_mp(this, &CustomPropertyEditor::_drag_easing)); - easing_draw->set_default_cursor_shape(Control::CURSOR_MOVE); - - type_button = memnew(MenuButton); - value_vbox->add_child(type_button); - type_button->hide(); - type_button->get_popup()->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_type_create_selected)); - - menu = memnew(PopupMenu); - // menu->set_pass_on_modal_close_click(false); - value_vbox->add_child(menu); - menu->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_menu_option)); - - evaluator = nullptr; - - spinbox = memnew(SpinBox); - value_vbox->add_child(spinbox); - spinbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 5); - spinbox->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified)); - - slider = memnew(HSlider); - value_vbox->add_child(slider); - slider->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 5); - slider->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified)); - - action_hboxes = memnew(HBoxContainer); - action_hboxes->set_alignment(BoxContainer::ALIGNMENT_CENTER); - value_vbox->add_child(action_hboxes); - for (int i = 0; i < MAX_ACTION_BUTTONS; i++) { - action_buttons[i] = memnew(Button); - action_buttons[i]->hide(); - action_hboxes->add_child(action_buttons[i]); - action_buttons[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed).bind(i)); - } - - create_dialog = nullptr; - property_select = nullptr; -} diff --git a/editor/property_editor.h b/editor/property_editor.h deleted file mode 100644 index 27d1cabc3d..0000000000 --- a/editor/property_editor.h +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************/ -/* property_editor.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PROPERTY_EDITOR_H -#define PROPERTY_EDITOR_H - -#include "editor/editor_locale_dialog.h" -#include "editor/scene_tree_editor.h" -#include "scene/gui/button.h" -#include "scene/gui/check_box.h" -#include "scene/gui/check_button.h" -#include "scene/gui/color_picker.h" -#include "scene/gui/dialogs.h" -#include "scene/gui/grid_container.h" -#include "scene/gui/label.h" -#include "scene/gui/menu_button.h" -#include "scene/gui/split_container.h" -#include "scene/gui/text_edit.h" -#include "scene/gui/texture_rect.h" -#include "scene/gui/tree.h" - -class CreateDialog; -class EditorFileDialog; -class PropertyValueEvaluator; -class PropertySelector; - -class EditorResourceConversionPlugin : public RefCounted { - GDCLASS(EditorResourceConversionPlugin, RefCounted); - -protected: - static void _bind_methods(); - - GDVIRTUAL0RC(String, _converts_to) - GDVIRTUAL1RC(bool, _handles, Ref<Resource>) - GDVIRTUAL1RC(Ref<Resource>, _convert, Ref<Resource>) - -public: - virtual String converts_to() const; - virtual bool handles(const Ref<Resource> &p_resource) const; - virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const; -}; - -class CustomPropertyEditor : public PopupPanel { - GDCLASS(CustomPropertyEditor, PopupPanel); - - enum { - MAX_VALUE_EDITORS = 12, - MAX_ACTION_BUTTONS = 5, - OBJ_MENU_LOAD = 0, - OBJ_MENU_EDIT = 1, - OBJ_MENU_CLEAR = 2, - OBJ_MENU_MAKE_UNIQUE = 3, - OBJ_MENU_COPY = 4, - OBJ_MENU_PASTE = 5, - OBJ_MENU_NEW_SCRIPT = 6, - OBJ_MENU_EXTEND_SCRIPT = 7, - OBJ_MENU_SHOW_IN_FILE_SYSTEM = 8, - TYPE_BASE_ID = 100, - CONVERT_BASE_ID = 1000 - }; - - enum { - EASING_LINEAR, - EASING_EASE_IN, - EASING_EASE_OUT, - EASING_ZERO, - EASING_IN_OUT, - EASING_OUT_IN - }; - - PopupMenu *menu = nullptr; - SceneTreeDialog *scene_tree = nullptr; - EditorFileDialog *file = nullptr; - EditorLocaleDialog *locale = nullptr; - ConfirmationDialog *error = nullptr; - String name; - Variant::Type type; - Variant v; - List<String> field_names; - int hint = 0; - String hint_text; - HBoxContainer *value_hboxes[MAX_VALUE_EDITORS / 4]; - VBoxContainer *value_vbox = nullptr; - LineEdit *value_editor[MAX_VALUE_EDITORS]; - int focused_value_editor; - Label *value_label[MAX_VALUE_EDITORS]; - HScrollBar *scroll[4]; - HBoxContainer *action_hboxes = nullptr; - Button *action_buttons[MAX_ACTION_BUTTONS]; - MenuButton *type_button = nullptr; - Vector<String> inheritors_array; - TextureRect *texture_preview = nullptr; - ColorPicker *color_picker = nullptr; - TextEdit *text_edit = nullptr; - bool read_only = false; - bool picking_viewport = false; - GridContainer *checks20gc = nullptr; - CheckBox *checks20[20]; - SpinBox *spinbox = nullptr; - HSlider *slider = nullptr; - - Control *easing_draw = nullptr; - CreateDialog *create_dialog = nullptr; - PropertySelector *property_select = nullptr; - - Object *owner = nullptr; - - bool updating = false; - - PropertyValueEvaluator *evaluator = nullptr; - - void _text_edit_changed(); - void _file_selected(String p_file); - void _locale_selected(String p_locale); - void _modified(String p_string); - - real_t _parse_real_expression(String text); - - void _range_modified(double p_value); - void _focus_enter(); - void _focus_exit(); - void _action_pressed(int p_which); - void _type_create_selected(int p_idx); - void _create_dialog_callback(); - void _create_selected_property(const String &p_prop); - - void _color_changed(const Color &p_color); - void _draw_easing(); - void _menu_option(int p_which); - - void _drag_easing(const Ref<InputEvent> &p_ev); - - void _node_path_selected(NodePath p_path); - void show_value_editors(int p_amount); - void config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings); - void config_action_buttons(const List<String> &p_strings); - - void _emit_changed_whole_or_field(); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void hide_menu(); - - Variant get_variant() const; - String get_name() const; - - void set_read_only(bool p_read_only) { read_only = p_read_only; } - - bool edit(Object *p_owner, const String &p_name, Variant::Type p_type, const Variant &p_variant, int p_hint, String p_hint_text); - - CustomPropertyEditor(); -}; - -#endif // PROPERTY_EDITOR_H diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 841c3ff3b1..1b17a740dd 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -32,8 +32,12 @@ #include "core/os/keyboard.h" #include "editor/doc_tools.h" +#include "editor/editor_help.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/tree.h" void PropertySelector::_text_changed(const String &p_newtext) { _update_search(); diff --git a/editor/property_selector.h b/editor/property_selector.h index e2bf5c02b7..9f1af576dd 100644 --- a/editor/property_selector.h +++ b/editor/property_selector.h @@ -31,9 +31,11 @@ #ifndef PROPERTY_SELECTOR_H #define PROPERTY_SELECTOR_H -#include "editor/editor_help.h" -#include "editor/property_editor.h" -#include "scene/gui/rich_text_label.h" +#include "scene/gui/dialogs.h" + +class EditorHelpBit; +class LineEdit; +class Tree; class PropertySelector : public ConfirmationDialog { GDCLASS(PropertySelector, ConfirmationDialog); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 3222fb6eec..665aca6a37 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -42,6 +42,7 @@ #include "plugins/script_editor_plugin.h" #include "scene/gui/control.h" #include "scene/gui/label.h" +#include "scene/gui/separator.h" #include "scene/gui/tab_container.h" RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_undo_redo) { diff --git a/main/main.cpp b/main/main.cpp index 42a866317e..190f25dbe6 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -285,6 +285,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print("\n"); OS::get_singleton()->print("Run options:\n"); + OS::get_singleton()->print(" -- Separator for user-provided arguments. Following arguments are not used by the engine, but can be read from `OS.get_cmdline_user_args()`.\n"); #ifdef TOOLS_ENABLED OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n"); OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n"); @@ -623,6 +624,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph /* argument parsing and main creation */ List<String> args; List<String> main_args; + List<String> user_args; + bool adding_user_args = false; List<String> platform_args = OS::get_singleton()->get_cmdline_platform_args(); // Add command line arguments. @@ -695,9 +698,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph continue; } #endif + List<String>::Element *N = I->next(); - if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help + if (adding_user_args) { + user_args.push_back(I->get()); + } else if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help show_help = true; exit_code = ERR_HELP; // Hack to force an early exit in `main()` with a success code. @@ -1200,7 +1206,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n"); goto error; } - + } else if (I->get() == "--") { + adding_user_args = true; } else { main_args.push_back(I->get()); } @@ -1377,7 +1384,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph Logger::set_flush_stdout_on_print(ProjectSettings::get_singleton()->get("application/run/flush_stdout_on_print")); - OS::get_singleton()->set_cmdline(execpath, main_args); + OS::get_singleton()->set_cmdline(execpath, main_args, user_args); // possibly be worth changing the default from vulkan to something lower spec, // for the project manager, depending on how smooth the fallback is. @@ -1670,6 +1677,7 @@ error: unregister_core_types(); OS::get_singleton()->_cmdline.clear(); + OS::get_singleton()->_user_args.clear(); if (message_queue) { memdelete(message_queue); @@ -3001,6 +3009,7 @@ void Main::cleanup(bool p_force) { OS::get_singleton()->delete_main_loop(); OS::get_singleton()->_cmdline.clear(); + OS::get_singleton()->_user_args.clear(); OS::get_singleton()->_execpath = ""; OS::get_singleton()->_local_clipboard = ""; diff --git a/methods.py b/methods.py index 571b134c8a..b719395ae0 100644 --- a/methods.py +++ b/methods.py @@ -607,8 +607,18 @@ def find_visual_c_batch_file(env): find_batch_file, ) + # Syntax changed in SCons 4.4.0. + from SCons import __version__ as scons_raw_version + + scons_ver = env._get_major_minor_revision(scons_raw_version) + version = get_default_version(env) - (host_platform, target_platform, _) = get_host_target(env) + + if scons_ver >= (4, 4, 0): + (host_platform, target_platform, _) = get_host_target(env, version) + else: + (host_platform, target_platform, _) = get_host_target(env) + return find_batch_file(env, version, host_platform, target_platform)[0] diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh index c767d3f8a0..731b3ee005 100755 --- a/misc/scripts/file_format.sh +++ b/misc/scripts/file_format.sh @@ -37,6 +37,8 @@ while IFS= read -rd '' f; do continue elif [[ "$f" == *"-so_wrap."* ]]; then continue + elif [[ "$f" == *".test.txt" ]]; then + continue fi # Ensure that files are UTF-8 formatted. recode UTF-8 "$f" 2> /dev/null diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 4372bb33ba..a23f19de85 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -623,11 +623,11 @@ void GDScriptSyntaxHighlighter::_update_cache() { annotation_color = Color(1.0, 0.7, 0.45); string_name_color = Color(1.0, 0.66, 0.72); } else { - function_definition_color = Color(0.0, 0.65, 0.73); - node_path_color = Color(0.62, 0.67, 0.39); - node_ref_color = Color(0.32, 0.55, 0.29); - annotation_color = Color(0.8, 0.5, 0.25); - string_name_color = Color(0.9, 0.56, 0.62); + function_definition_color = Color(0, 0.6, 0.6); + node_path_color = Color(0.18, 0.55, 0); + node_ref_color = Color(0.0, 0.5, 0); + annotation_color = Color(0.8, 0.37, 0); + string_name_color = Color(0.8, 0.46, 0.52); } EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color); diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 7460f8edff..c0d5856be5 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -34,6 +34,7 @@ #include "editor/doc_tools.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = nullptr; diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 14337e87da..ead4ef1987 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" GDScriptLanguageServer::GDScriptLanguageServer() { _EDITOR_DEF("network/language_server/remote_host", host); diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 959651c024..ded2a7b4d4 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -38,6 +38,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_help.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "gdscript_language_protocol.h" #include "scene/resources/packed_scene.h" diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 4ca8482ba3..7e90f198f6 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -4938,7 +4938,8 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { if (d.has("name")) { const String name = d["name"]; - if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) { + const String name_lower = name.to_lower(); + if (name_lower.begins_with("loop") || name_lower.ends_with("loop") || name_lower.begins_with("cycle") || name_lower.ends_with("cycle")) { animation->set_loop(true); } animation->set_name(_gen_unique_animation_name(state, name)); diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp index 8b1b44852f..f830c7ffe1 100644 --- a/modules/mono/editor/editor_internal_calls.cpp +++ b/modules/mono/editor/editor_internal_calls.cpp @@ -39,7 +39,9 @@ #include "core/version.h" #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_node.h" +#include "editor/editor_paths.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/plugins/script_editor_plugin.h" #include "main/main.h" diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 37bdc42c2d..b1f1decd72 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -531,9 +531,9 @@ namespace Godot /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated basis matrix.</returns> - public Basis Rotated(Vector3 axis, real_t phi) + public Basis Rotated(Vector3 axis, real_t angle) { - return new Basis(axis, phi) * this; + return new Basis(axis, angle) * this; } /// <summary> @@ -774,15 +774,15 @@ namespace Godot /// </summary> /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> - public Basis(Vector3 axis, real_t phi) + public Basis(Vector3 axis, real_t angle) { Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); - real_t cosine = Mathf.Cos(phi); + real_t cosine = Mathf.Cos(angle); Row0.x = axisSq.x + cosine * (1.0f - axisSq.x); Row1.y = axisSq.y + cosine * (1.0f - axisSq.y); Row2.z = axisSq.z + cosine * (1.0f - axisSq.z); - real_t sine = Mathf.Sin(phi); + real_t sine = Mathf.Sin(angle); real_t t = 1.0f - cosine; real_t xyzt = axis.x * axis.y * t; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs new file mode 100644 index 0000000000..d774021131 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs @@ -0,0 +1,820 @@ +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif +using System; +using System.Runtime.InteropServices; + +namespace Godot +{ + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Projection : IEquatable<Projection> + { + /// <summary> + /// Enumerated index values for the planes. + /// </summary> + public enum Planes + { + /// <summary> + /// The projection's near plane. + /// </summary> + Near, + /// <summary> + /// The projection's far plane. + /// </summary> + Far, + /// <summary> + /// The projection's left plane. + /// </summary> + Left, + /// <summary> + /// The projection's top plane. + /// </summary> + Top, + /// <summary> + /// The projection's right plane. + /// </summary> + Right, + /// <summary> + /// The projection's bottom plane. + /// </summary> + Bottom, + } + + /// <summary> + /// The projections's X column. Also accessible by using the index position <c>[0]</c>. + /// </summary> + public Vector4 x; + + /// <summary> + /// The projections's Y column. Also accessible by using the index position <c>[1]</c>. + /// </summary> + public Vector4 y; + + /// <summary> + /// The projections's Z column. Also accessible by using the index position <c>[2]</c>. + /// </summary> + public Vector4 z; + + /// <summary> + /// The projections's W column. Also accessible by using the index position <c>[3]</c>. + /// </summary> + public Vector4 w; + + /// <summary> + /// Constructs a projection from 4 vectors (matrix columns). + /// </summary> + /// <param name="x">The X column, or column index 0.</param> + /// <param name="y">The Y column, or column index 1.</param> + /// <param name="z">The Z column, or column index 2.</param> + /// <param name="w">The W column, or column index 3.</param> + public Projection(Vector4 x, Vector4 y, Vector4 z, Vector4 w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /// <summary> + /// Constructs a new <see cref="Projection"/> from an existing <see cref="Projection"/>. + /// </summary> + /// <param name="proj">The existing <see cref="Projection"/>.</param> + public Projection(Projection proj) + { + x = proj.x; + y = proj.y; + z = proj.z; + w = proj.w; + } + + /// <summary> + /// Constructs a new <see cref="Projection"/> from a <see cref="Transform3D"/>. + /// </summary> + /// <param name="transform">The <see cref="Transform3D"/>.</param> + public Projection(Transform3D transform) + { + x = new Vector4(transform.basis.Row0.x, transform.basis.Row1.x, transform.basis.Row2.x, 0); + y = new Vector4(transform.basis.Row0.y, transform.basis.Row1.y, transform.basis.Row2.y, 0); + z = new Vector4(transform.basis.Row0.z, transform.basis.Row1.z, transform.basis.Row2.z, 0); + w = new Vector4(transform.origin.x, transform.origin.y, transform.origin.z, 1); + } + + /// <summary> + /// Constructs a new <see cref="Transform3D"/> from the <see cref="Projection"/>. + /// </summary> + /// <param name="proj">The <see cref="Projection"/>.</param> + public static explicit operator Transform3D(Projection proj) + { + return new Transform3D( + new Basis( + new Vector3(proj.x.x, proj.x.y, proj.x.z), + new Vector3(proj.y.x, proj.y.y, proj.y.z), + new Vector3(proj.z.x, proj.z.y, proj.z.z) + ), + new Vector3(proj.w.x, proj.w.y, proj.w.z) + ); + } + + public static Projection CreateDepthCorrection(bool flipY) + { + return new Projection( + new Vector4(1, 0, 0, 0), + new Vector4(0, flipY ? -1 : 1, 0, 0), + new Vector4(0, 0, (real_t)0.5, 0), + new Vector4(0, 0, (real_t)0.5, 1) + ); + } + + public static Projection CreateFitAabb(AABB aabb) + { + Vector3 min = aabb.Position; + Vector3 max = aabb.Position + aabb.Size; + + return new Projection( + new Vector4(2 / (max.x - min.x), 0, 0, 0), + new Vector4(0, 2 / (max.y - min.y), 0, 0), + new Vector4(0, 0, 2 / (max.z - min.z), 0), + new Vector4(-(max.x + min.x) / (max.x - min.x), -(max.y + min.y) / (max.y - min.y), -(max.z + min.z) / (max.z - min.z), 1) + ); + } + + public static Projection CreateForHmd(int eye, real_t aspect, real_t intraocularDist, real_t displayWidth, real_t displayToLens, real_t oversample, real_t zNear, real_t zFar) + { + real_t f1 = (intraocularDist * (real_t)0.5) / displayToLens; + real_t f2 = ((displayWidth - intraocularDist) * (real_t)0.5) / displayToLens; + real_t f3 = (displayWidth / (real_t)4.0) / displayToLens; + + real_t add = ((f1 + f2) * (oversample - (real_t)1.0)) / (real_t)2.0; + f1 += add; + f2 += add; + f3 *= oversample; + + f3 /= aspect; + + switch (eye) + { + case 1: + return CreateFrustum(-f2 * zNear, f1 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar); + case 2: + return CreateFrustum(-f1 * zNear, f2 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar); + default: + return Zero; + } + } + + public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t near, real_t far) + { + if (right <= left) + { + throw new ArgumentException("right is less or equal to left."); + } + if (top <= bottom) + { + throw new ArgumentException("top is less or equal to bottom."); + } + if (far <= near) + { + throw new ArgumentException("far is less or equal to near."); + } + + real_t x = 2 * near / (right - left); + real_t y = 2 * near / (top - bottom); + + real_t a = (right + left) / (right - left); + real_t b = (top + bottom) / (top - bottom); + real_t c = -(far + near) / (far - near); + real_t d = -2 * far * near / (far - near); + + return new Projection( + new Vector4(x, 0, 0, 0), + new Vector4(0, y, 0, 0), + new Vector4(a, b, c, -1), + new Vector4(0, 0, d, 0) + ); + } + + public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t near, real_t far, bool flipFov) + { + if (!flipFov) + { + size *= aspect; + } + return CreateFrustum(-size / 2 + offset.x, +size / 2 + offset.x, -size / aspect / 2 + offset.y, +size / aspect / 2 + offset.y, near, far); + } + + public static Projection CreateLightAtlasRect(Rect2 rect) + { + return new Projection( + new Vector4(rect.Size.x, 0, 0, 0), + new Vector4(0, rect.Size.y, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(rect.Position.x, rect.Position.y, 0, 1) + ); + } + + public static Projection CreateOrthogonal(real_t left, real_t right, real_t bottom, real_t top, real_t zNear, real_t zFar) + { + Projection proj = Projection.Identity; + proj.x.x = (real_t)2.0 / (right - left); + proj.w.x = -((right + left) / (right - left)); + proj.y.y = (real_t)2.0 / (top - bottom); + proj.w.y = -((top + bottom) / (top - bottom)); + proj.z.z = (real_t)(-2.0) / (zFar - zNear); + proj.w.z = -((zFar + zNear) / (zFar - zNear)); + proj.w.w = (real_t)1.0; + return proj; + } + + public static Projection CreateOrthogonalAspect(real_t size, real_t aspect, real_t zNear, real_t zFar, bool flipFov) + { + if (!flipFov) + { + size *= aspect; + } + return CreateOrthogonal(-size / 2, +size / 2, -size / aspect / 2, +size / aspect / 2, zNear, zFar); + } + + public static Projection CreatePerspective(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov) + { + if (flipFov) + { + fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); + } + real_t radians = Mathf.Deg2Rad(fovyDegrees / (real_t)2.0); + real_t deltaZ = zFar - zNear; + real_t sine = Mathf.Sin(radians); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) + { + return Zero; + } + + real_t cotangent = Mathf.Cos(radians) / sine; + + Projection proj = Projection.Identity; + + proj.x.x = cotangent / aspect; + proj.y.y = cotangent; + proj.z.z = -(zFar + zNear) / deltaZ; + proj.z.w = -1; + proj.w.z = -2 * zNear * zFar / deltaZ; + proj.w.w = 0; + + return proj; + } + + public static Projection CreatePerspectiveHmd(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov, int eye, real_t intraocularDist, real_t convergenceDist) + { + if (flipFov) + { + fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); + } + + real_t ymax = zNear * Mathf.Tan(Mathf.Deg2Rad(fovyDegrees / (real_t)2.0)); + real_t xmax = ymax * aspect; + real_t frustumshift = (intraocularDist / (real_t)2.0) * zNear / convergenceDist; + real_t left; + real_t right; + real_t modeltranslation; + switch (eye) + { + case 1: + left = -xmax + frustumshift; + right = xmax + frustumshift; + modeltranslation = intraocularDist / (real_t)2.0; + break; + case 2: + left = -xmax - frustumshift; + right = xmax - frustumshift; + modeltranslation = -intraocularDist / (real_t)2.0; + break; + default: + left = -xmax; + right = xmax; + modeltranslation = (real_t)0.0; + break; + } + Projection proj = CreateFrustum(left, right, -ymax, ymax, zNear, zFar); + Projection cm = Projection.Identity; + cm.w.x = modeltranslation; + return proj * cm; + } + + public real_t Determinant() + { + return x.w * y.z * z.y * w.x - x.z * y.w * z.y * w.x - + x.w * y.y * z.z * w.x + x.y * y.w * z.z * w.x + + x.z * y.y * z.w * w.x - x.y * y.z * z.w * w.x - + x.w * y.z * z.x * w.y + x.z * y.w * z.x * w.y + + x.w * y.x * z.z * w.y - x.x * y.w * z.z * w.y - + x.z * y.x * z.w * w.y + x.x * y.z * z.w * w.y + + x.w * y.y * z.x * w.z - x.y * y.w * z.x * w.z - + x.w * y.x * z.y * w.z + x.x * y.w * z.y * w.z + + x.y * y.x * z.w * w.z - x.x * y.y * z.w * w.z - + x.z * y.y * z.x * w.w + x.y * y.z * z.x * w.w + + x.z * y.x * z.y * w.w - x.x * y.z * z.y * w.w - + x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w; + } + + public real_t GetAspect() + { + Vector2 vpHe = GetViewportHalfExtents(); + return vpHe.x / vpHe.y; + } + + public real_t GetFov() + { + Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized(); + if (z.x == 0 && z.y == 0) + { + return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0; + } + else + { + Plane leftPlane = new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x).Normalized(); + return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))); + } + } + + public static real_t GetFovy(real_t fovx, real_t aspect) + { + return Mathf.Rad2Deg(Mathf.Atan(aspect * Mathf.Tan(Mathf.Deg2Rad(fovx) * (real_t)0.5)) * (real_t)2.0); + } + + public real_t GetLodMultiplier() + { + if (IsOrthogonal()) + { + return GetViewportHalfExtents().x; + } + else + { + real_t zn = GetZNear(); + real_t width = GetViewportHalfExtents().x * (real_t)2.0; + return (real_t)1.0 / (zn / width); + } + } + + public int GetPixelsPerMeter(int forPixelWidth) + { + Vector3 result = Xform(new Vector3(1, 0, -1)); + + return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth); + } + + public Plane GetProjectionPlane(Planes plane) + { + Plane newPlane = plane switch + { + Planes.Near => new Plane(x.w + x.z, y.w + y.z, z.w + z.z, w.w + w.z), + Planes.Far => new Plane(x.w - x.z, y.w - y.z, z.w - z.z, w.w - w.z), + Planes.Left => new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x), + Planes.Top => new Plane(x.w - x.y, y.w - y.y, z.w - z.y, w.w - w.y), + Planes.Right => new Plane(x.w - x.x, y.w - y.x, z.w - z.x, w.w - w.x), + Planes.Bottom => new Plane(x.w + x.y, y.w + y.y, z.w + z.y, w.w + w.y), + _ => new Plane(), + }; + newPlane.Normal = -newPlane.Normal; + return newPlane.Normalized(); + } + + public Vector2 GetFarPlaneHalfExtents() + { + var res = GetProjectionPlane(Planes.Far).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top)); + return new Vector2(res.Value.x, res.Value.y); + } + + public Vector2 GetViewportHalfExtents() + { + var res = GetProjectionPlane(Planes.Near).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top)); + return new Vector2(res.Value.x, res.Value.y); + } + + public real_t GetZFar() + { + return GetProjectionPlane(Planes.Far).D; + } + + public real_t GetZNear() + { + return -GetProjectionPlane(Planes.Near).D; + } + + public Projection FlippedY() + { + Projection proj = this; + proj.y = -proj.y; + return proj; + } + + public Projection PerspectiveZNearAdjusted(real_t newZNear) + { + Projection proj = this; + real_t zFar = GetZFar(); + real_t zNear = newZNear; + real_t deltaZ = zFar - zNear; + proj.z.z = -(zFar + zNear) / deltaZ; + proj.w.z = -2 * zNear * zFar / deltaZ; + return proj; + } + + public Projection JitterOffseted(Vector2 offset) + { + Projection proj = this; + proj.w.x += offset.x; + proj.w.y += offset.y; + return proj; + } + + public Projection Inverse() + { + Projection proj = this; + int i, j, k; + int[] pvt_i = new int[4]; + int[] pvt_j = new int[4]; /* Locations of pivot matrix */ + real_t pvt_val; /* Value of current pivot element */ + real_t hold; /* Temporary storage */ + real_t determinant = 1.0f; + for (k = 0; k < 4; k++) + { + /* Locate k'th pivot element */ + pvt_val = proj[k][k]; /* Initialize for search */ + pvt_i[k] = k; + pvt_j[k] = k; + for (i = k; i < 4; i++) + { + for (j = k; j < 4; j++) + { + if (Mathf.Abs(proj[i][j]) > Mathf.Abs(pvt_val)) + { + pvt_i[k] = i; + pvt_j[k] = j; + pvt_val = proj[i][j]; + } + } + } + + /* Product of pivots, gives determinant when finished */ + determinant *= pvt_val; + if (Mathf.IsZeroApprox(determinant)) + { + return Zero; + } + + /* "Interchange" rows (with sign change stuff) */ + i = pvt_i[k]; + if (i != k) + { /* If rows are different */ + for (j = 0; j < 4; j++) + { + hold = -proj[k][j]; + proj[k, j] = proj[i][j]; + proj[i, j] = hold; + } + } + + /* "Interchange" columns */ + j = pvt_j[k]; + if (j != k) + { /* If columns are different */ + for (i = 0; i < 4; i++) + { + hold = -proj[i][k]; + proj[i, k] = proj[i][j]; + proj[i, j] = hold; + } + } + + /* Divide column by minus pivot value */ + for (i = 0; i < 4; i++) + { + if (i != k) + { + proj[i, k] /= (-pvt_val); + } + } + + /* Reduce the matrix */ + for (i = 0; i < 4; i++) + { + hold = proj[i][k]; + for (j = 0; j < 4; j++) + { + if (i != k && j != k) + { + proj[i, j] += hold * proj[k][j]; + } + } + } + + /* Divide row by pivot */ + for (j = 0; j < 4; j++) + { + if (j != k) + { + proj[k, j] /= pvt_val; + } + } + + /* Replace pivot by reciprocal (at last we can touch it). */ + proj[k, k] = (real_t)1.0 / pvt_val; + } + + /* That was most of the work, one final pass of row/column interchange */ + /* to finish */ + for (k = 4 - 2; k >= 0; k--) + { /* Don't need to work with 1 by 1 corner*/ + i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */ + if (i != k) + { /* If rows are different */ + for (j = 0; j < 4; j++) + { + hold = proj[k][j]; + proj[k, j] = -proj[i][j]; + proj[i, j] = hold; + } + } + + j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */ + if (j != k) + { /* If columns are different */ + for (i = 0; i < 4; i++) + { + hold = proj[i][k]; + proj[i, k] = -proj[i][j]; + proj[i, j] = hold; + } + } + } + return proj; + } + + public bool IsOrthogonal() + { + return w.w == (real_t)1.0; + } + + /// <summary> + /// Composes these two projections by multiplying them + /// together. This has the effect of applying the right + /// and then the left projection. + /// </summary> + /// <param name="left">The parent transform.</param> + /// <param name="right">The child transform.</param> + /// <returns>The composed projection.</returns> + public static Projection operator *(Projection left, Projection right) + { + return new Projection( + new Vector4( + left.x.x * right.x.x + left.y.x * right.x.y + left.z.x * right.x.z + left.w.x * right.x.w, + left.x.y * right.x.x + left.y.y * right.x.y + left.z.y * right.x.z + left.w.y * right.x.w, + left.x.z * right.x.x + left.y.z * right.x.y + left.z.z * right.x.z + left.w.z * right.x.w, + left.x.w * right.x.x + left.y.w * right.x.y + left.z.w * right.x.z + left.w.w * right.x.w + ), new Vector4( + left.x.x * right.y.x + left.y.x * right.y.y + left.z.x * right.y.z + left.w.x * right.y.w, + left.x.y * right.y.x + left.y.y * right.y.y + left.z.y * right.y.z + left.w.y * right.y.w, + left.x.z * right.y.x + left.y.z * right.y.y + left.z.z * right.y.z + left.w.z * right.y.w, + left.x.w * right.y.x + left.y.w * right.y.y + left.z.w * right.y.z + left.w.w * right.y.w + ), new Vector4( + left.x.x * right.z.x + left.y.x * right.z.y + left.z.x * right.z.z + left.w.x * right.z.w, + left.x.y * right.z.x + left.y.y * right.z.y + left.z.y * right.z.z + left.w.y * right.z.w, + left.x.z * right.z.x + left.y.z * right.z.y + left.z.z * right.z.z + left.w.z * right.z.w, + left.x.w * right.z.x + left.y.w * right.z.y + left.z.w * right.z.z + left.w.w * right.z.w + ), new Vector4( + left.x.x * right.w.x + left.y.x * right.w.y + left.z.x * right.w.z + left.w.x * right.w.w, + left.x.y * right.w.x + left.y.y * right.w.y + left.z.y * right.w.z + left.w.y * right.w.w, + left.x.z * right.w.x + left.y.z * right.w.y + left.z.z * right.w.z + left.w.z * right.w.w, + left.x.w * right.w.x + left.y.w * right.w.y + left.z.w * right.w.z + left.w.w * right.w.w + ) + ); + } + + /// <summary> + /// Returns a vector transformed (multiplied) by this projection. + /// </summary> + /// <param name="proj">The projection to apply.</param> + /// <param name="v">A vector to transform.</param> + /// <returns>The transformed vector.</returns> + public static Vector4 operator *(Projection proj, Vector4 v) + { + return new Vector4( + proj.x.x * v.x + proj.y.x * v.y + proj.z.x * v.z + proj.w.x * v.w, + proj.x.y * v.x + proj.y.y * v.y + proj.z.y * v.z + proj.w.y * v.w, + proj.x.z * v.x + proj.y.z * v.y + proj.z.z * v.z + proj.w.z * v.w, + proj.x.w * v.x + proj.y.w * v.y + proj.z.w * v.z + proj.w.w * v.w + ); + } + + /// <summary> + /// Returns <see langword="true"/> if the projections are exactly equal. + /// </summary> + /// <param name="left">The left projection.</param> + /// <param name="right">The right projection.</param> + /// <returns>Whether or not the projections are exactly equal.</returns> + public static bool operator ==(Projection left, Projection right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the projections are not exactly equal. + /// </summary> + /// <param name="left">The left projection.</param> + /// <param name="right">The right projection.</param> + /// <returns>Whether or not the projections are not exactly equal.</returns> + public static bool operator !=(Projection left, Projection right) + { + return !left.Equals(right); + } + + /// <summary> + /// Access whole columns in the form of <see cref="Vector4"/>. + /// </summary> + /// <param name="column">Which column vector.</param> + public Vector4 this[int column] + { + get + { + switch (column) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (column) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + case 2: + z = value; + return; + case 3: + w = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Access single values. + /// </summary> + /// <param name="column">Which column vector.</param> + /// <param name="row">Which row of the column.</param> + public real_t this[int column, int row] + { + get + { + switch (column) + { + case 0: + return x[row]; + case 1: + return y[row]; + case 2: + return z[row]; + case 3: + return w[row]; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (column) + { + case 0: + x[row] = value; + return; + case 1: + y[row] = value; + return; + case 2: + z[row] = value; + return; + case 3: + w[row] = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Returns a vector transformed (multiplied) by this projection. + /// </summary> + /// <param name="v">A vector to transform.</param> + /// <returns>The transformed vector.</returns> + private Vector3 Xform(Vector3 v) + { + Vector3 ret = new Vector3( + x.x * v.x + y.x * v.y + z.x * v.z + w.x, + x.y * v.x + y.y * v.y + z.y * v.z + w.y, + x.z * v.x + y.z * v.y + z.z * v.z + w.z + ); + return ret / (x.w * v.x + y.w * v.y + z.w * v.z + w.w); + } + + // Constants + private static readonly Projection _zero = new Projection( + new Vector4(0, 0, 0, 0), + new Vector4(0, 0, 0, 0), + new Vector4(0, 0, 0, 0), + new Vector4(0, 0, 0, 0) + ); + private static readonly Projection _identity = new Projection( + new Vector4(1, 0, 0, 0), + new Vector4(0, 1, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(0, 0, 0, 1) + ); + + /// <summary> + /// Zero projection, a projection with all components set to <c>0</c>. + /// </summary> + /// <value>Equivalent to <c>new Projection(Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero)</c>.</value> + public static Projection Zero { get { return _zero; } } + + /// <summary> + /// The identity projection, with no distortion applied. + /// This is used as a replacement for <c>Projection()</c> in GDScript. + /// Do not use <c>new Projection()</c> with no arguments in C#, because it sets all values to zero. + /// </summary> + /// <value>Equivalent to <c>new Projection(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1))</c>.</value> + public static Projection Identity { get { return _identity; } } + + /// <summary> + /// Serves as the hash function for <see cref="Projection"/>. + /// </summary> + /// <returns>A hash code for this projection.</returns> + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + } + + /// <summary> + /// Converts this <see cref="Projection"/> to a string. + /// </summary> + /// <returns>A string representation of this projection.</returns> + public override string ToString() + { + return $"{x.x}, {x.y}, {x.z}, {x.w}\n{y.x}, {y.y}, {y.z}, {y.w}\n{z.x}, {z.y}, {z.z}, {z.w}\n{w.x}, {w.y}, {w.z}, {w.w}\n"; + } + + /// <summary> + /// Converts this <see cref="Projection"/> to a string with the given <paramref name="format"/>. + /// </summary> + /// <returns>A string representation of this projection.</returns> + public string ToString(string format) + { + return $"{x.x.ToString(format)}, {x.y.ToString(format)}, {x.z.ToString(format)}, {x.w.ToString(format)}\n" + + $"{y.x.ToString(format)}, {y.y.ToString(format)}, {y.z.ToString(format)}, {y.w.ToString(format)}\n" + + $"{z.x.ToString(format)}, {z.y.ToString(format)}, {z.z.ToString(format)}, {z.w.ToString(format)}\n" + + $"{w.x.ToString(format)}, {w.y.ToString(format)}, {w.z.ToString(format)}, {w.w.ToString(format)}\n"; + } + + /// <summary> + /// Returns <see langword="true"/> if the projection is exactly equal + /// to the given object (<see paramref="obj"/>). + /// </summary> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> + public override bool Equals(object obj) + { + if (obj is Projection) + { + return Equals((Projection)obj); + } + return false; + } + + /// <summary> + /// Returns <see langword="true"/> if the projections are exactly equal. + /// </summary> + /// <param name="other">The other projection.</param> + /// <returns>Whether or not the projections are exactly equal.</returns> + public bool Equals(Projection other) + { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index e01db7b88c..b8413f1e16 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -301,9 +301,9 @@ namespace Godot /// </summary> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> - public Transform2D Rotated(real_t phi) + public Transform2D Rotated(real_t angle) { - return this * new Transform2D(phi, new Vector2()); + return this * new Transform2D(angle, new Vector2()); } /// <summary> @@ -320,14 +320,6 @@ namespace Godot return copy; } - private void ScaleBasis(Vector2 scale) - { - x.x *= scale.x; - x.y *= scale.y; - y.x *= scale.x; - y.y *= scale.y; - } - private real_t Tdotx(Vector2 with) { return (this[0, 0] * with[0]) + (this[1, 0] * with[1]); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 7f03a8930d..97b4a87713 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -192,9 +192,9 @@ namespace Godot /// <param name="axis">The axis to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate, in radians.</param> /// <returns>The rotated transformation matrix.</returns> - public Transform3D Rotated(Vector3 axis, real_t phi) + public Transform3D Rotated(Vector3 axis, real_t angle) { - return new Transform3D(new Basis(axis, phi), new Vector3()) * this; + return new Transform3D(new Basis(axis, angle), new Vector3()) * this; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 7bdbe1c28b..9c80dd0217 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -495,10 +495,10 @@ namespace Godot /// </summary> /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> - public Vector2 Rotated(real_t phi) + public Vector2 Rotated(real_t angle) { - real_t sine = Mathf.Sin(phi); - real_t cosi = Mathf.Cos(phi); + real_t sine = Mathf.Sin(angle); + real_t cosi = Mathf.Cos(angle); return new Vector2( x * cosi - y * sine, x * sine + y * cosi); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 480165d44a..ec2e724b10 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -515,7 +515,7 @@ namespace Godot /// <param name="axis">The vector to rotate around. Must be normalized.</param> /// <param name="angle">The angle to rotate by, in radians.</param> /// <returns>The rotated vector.</returns> - public Vector3 Rotated(Vector3 axis, real_t phi) + public Vector3 Rotated(Vector3 axis, real_t angle) { #if DEBUG if (!axis.IsNormalized()) @@ -523,7 +523,7 @@ namespace Godot throw new ArgumentException("Argument is not normalized", nameof(axis)); } #endif - return new Basis(axis, phi).Xform(this); + return new Basis(axis, angle).Xform(this); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs new file mode 100644 index 0000000000..72fe9cb16f --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs @@ -0,0 +1,730 @@ +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif +using System; +using System.Runtime.InteropServices; + +namespace Godot +{ + /// <summary> + /// 4-element structure that can be used to represent positions in 4D space or any other pair of numeric values. + /// </summary> + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Vector4 : IEquatable<Vector4> + { + /// <summary> + /// Enumerated index values for the axes. + /// Returned by <see cref="MaxAxisIndex"/> and <see cref="MinAxisIndex"/>. + /// </summary> + public enum Axis + { + /// <summary> + /// The vector's X axis. + /// </summary> + X = 0, + /// <summary> + /// The vector's Y axis. + /// </summary> + Y, + /// <summary> + /// The vector's Z axis. + /// </summary> + Z, + /// <summary> + /// The vector's W axis. + /// </summary> + W + } + + /// <summary> + /// The vector's X component. Also accessible by using the index position <c>[0]</c>. + /// </summary> + public real_t x; + + /// <summary> + /// The vector's Y component. Also accessible by using the index position <c>[1]</c>. + /// </summary> + public real_t y; + + /// <summary> + /// The vector's Z component. Also accessible by using the index position <c>[2]</c>. + /// </summary> + public real_t z; + + /// <summary> + /// The vector's W component. Also accessible by using the index position <c>[3]</c>. + /// </summary> + public real_t w; + + /// <summary> + /// Access vector components using their index. + /// </summary> + /// <exception cref="IndexOutOfRangeException"> + /// Thrown when the given the <paramref name="index"/> is not 0, 1, 2 or 3. + /// </exception> + /// <value> + /// <c>[0]</c> is equivalent to <see cref="x"/>, + /// <c>[1]</c> is equivalent to <see cref="y"/>, + /// <c>[2]</c> is equivalent to <see cref="z"/>. + /// <c>[3]</c> is equivalent to <see cref="w"/>. + /// </value> + public real_t this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (index) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + case 2: + z = value; + return; + case 3: + w = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w) + { + x = this.x; + y = this.y; + z = this.z; + w = this.w; + } + + internal void Normalize() + { + real_t lengthsq = LengthSquared(); + + if (lengthsq == 0) + { + x = y = z = w = 0f; + } + else + { + real_t length = Mathf.Sqrt(lengthsq); + x /= length; + y /= length; + z /= length; + w /= length; + } + } + + + /// <summary> + /// Returns a new vector with all components in absolute values (i.e. positive). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Abs(real_t)"/> called on each component.</returns> + public Vector4 Abs() + { + return new Vector4(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w)); + } + + /// <summary> + /// Returns a new vector with all components rounded up (towards positive infinity). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Ceil"/> called on each component.</returns> + public Vector4 Ceil() + { + return new Vector4(Mathf.Ceil(x), Mathf.Ceil(y), Mathf.Ceil(z), Mathf.Ceil(w)); + } + + /// <summary> + /// Returns a new vector with all components clamped between the + /// components of <paramref name="min"/> and <paramref name="max"/> using + /// <see cref="Mathf.Clamp(real_t, real_t, real_t)"/>. + /// </summary> + /// <param name="min">The vector with minimum allowed values.</param> + /// <param name="max">The vector with maximum allowed values.</param> + /// <returns>The vector with all components clamped.</returns> + public Vector4 Clamp(Vector4 min, Vector4 max) + { + return new Vector4 + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y), + Mathf.Clamp(z, min.z, max.z), + Mathf.Clamp(w, min.w, max.w) + ); + } + + + /// <summary> + /// Returns a new vector with all components rounded down (towards negative infinity). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Floor"/> called on each component.</returns> + public Vector4 Floor() + { + return new Vector4(Mathf.Floor(x), Mathf.Floor(y), Mathf.Floor(z), Mathf.Floor(w)); + } + + + /// <summary> + /// Returns the dot product of this vector and <paramref name="with"/>. + /// </summary> + /// <param name="with">The other vector to use.</param> + /// <returns>The dot product of the two vectors.</returns> + public real_t Dot(Vector4 with) + { + return (x * with.x) + (y * with.y) + (z * with.z) + (w + with.w); + } + + /// <summary> + /// Returns the inverse of this vector. This is the same as <c>new Vector4(1 / v.x, 1 / v.y, 1 / v.z, 1 / v.w)</c>. + /// </summary> + /// <returns>The inverse of this vector.</returns> + public Vector4 Inverse() + { + return new Vector4(1 / x, 1 / y, 1 / z, 1 / w); + } + + /// <summary> + /// Returns <see langword="true"/> if the vector is normalized, and <see langword="false"/> otherwise. + /// </summary> + /// <returns>A <see langword="bool"/> indicating whether or not the vector is normalized.</returns> + public bool IsNormalized() + { + return Mathf.Abs(LengthSquared() - 1.0f) < Mathf.Epsilon; + } + + /// <summary> + /// Returns the length (magnitude) of this vector. + /// </summary> + /// <seealso cref="LengthSquared"/> + /// <returns>The length of this vector.</returns> + public real_t Length() + { + real_t x2 = x * x; + real_t y2 = y * y; + real_t z2 = z * z; + real_t w2 = w * w; + + return Mathf.Sqrt(x2 + y2 + z2 + w2); + } + + /// <summary> + /// Returns the squared length (squared magnitude) of this vector. + /// This method runs faster than <see cref="Length"/>, so prefer it if + /// you need to compare vectors or need the squared length for some formula. + /// </summary> + /// <returns>The squared length of this vector.</returns> + public real_t LengthSquared() + { + real_t x2 = x * x; + real_t y2 = y * y; + real_t z2 = z * z; + real_t w2 = w * w; + + return x2 + y2 + z2 + w2; + } + + /// <summary> + /// Returns the result of the linear interpolation between + /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>. + /// </summary> + /// <param name="to">The destination vector for interpolation.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The resulting vector of the interpolation.</returns> + public Vector4 Lerp(Vector4 to, real_t weight) + { + return new Vector4 + ( + Mathf.Lerp(x, to.x, weight), + Mathf.Lerp(y, to.y, weight), + Mathf.Lerp(z, to.z, weight), + Mathf.Lerp(w, to.w, weight) + ); + } + + /// <summary> + /// Returns the axis of the vector's highest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.X"/>. + /// </summary> + /// <returns>The index of the highest axis.</returns> + public Axis MaxAxisIndex() + { + int max_index = 0; + real_t max_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] > max_value) + { + max_index = i; + max_value = this[i]; + } + } + return (Axis)max_index; + } + + /// <summary> + /// Returns the axis of the vector's lowest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.W"/>. + /// </summary> + /// <returns>The index of the lowest axis.</returns> + public Axis MinAxisIndex() + { + int min_index = 0; + real_t min_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] <= min_value) + { + min_index = i; + min_value = this[i]; + } + } + return (Axis)min_index; + } + + /// <summary> + /// Returns the vector scaled to unit length. Equivalent to <c>v / v.Length()</c>. + /// </summary> + /// <returns>A normalized version of the vector.</returns> + public Vector4 Normalized() + { + Vector4 v = this; + v.Normalize(); + return v; + } + + /// <summary> + /// Returns this vector with all components rounded to the nearest integer, + /// with halfway cases rounded towards the nearest multiple of two. + /// </summary> + /// <returns>The rounded vector.</returns> + public Vector4 Round() + { + return new Vector4(Mathf.Round(x), Mathf.Round(y), Mathf.Round(z), Mathf.Round(w)); + } + + /// <summary> + /// Returns a vector with each component set to one or negative one, depending + /// on the signs of this vector's components, or zero if the component is zero, + /// by calling <see cref="Mathf.Sign(real_t)"/> on each component. + /// </summary> + /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> + public Vector4 Sign() + { + Vector4 v; + v.x = Mathf.Sign(x); + v.y = Mathf.Sign(y); + v.z = Mathf.Sign(z); + v.w = Mathf.Sign(w); + return v; + } + + // Constants + private static readonly Vector4 _zero = new Vector4(0, 0, 0, 0); + private static readonly Vector4 _one = new Vector4(1, 1, 1, 1); + private static readonly Vector4 _inf = new Vector4(Mathf.Inf, Mathf.Inf, Mathf.Inf, Mathf.Inf); + + /// <summary> + /// Zero vector, a vector with all components set to <c>0</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4(0, 0, 0, 0)</c>.</value> + public static Vector4 Zero { get { return _zero; } } + /// <summary> + /// One vector, a vector with all components set to <c>1</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4(1, 1, 1, 1)</c>.</value> + public static Vector4 One { get { return _one; } } + /// <summary> + /// Infinity vector, a vector with all components set to <see cref="Mathf.Inf"/>. + /// </summary> + /// <value>Equivalent to <c>new Vector4(Mathf.Inf, Mathf.Inf, Mathf.Inf, Mathf.Inf)</c>.</value> + public static Vector4 Inf { get { return _inf; } } + + /// <summary> + /// Constructs a new <see cref="Vector4"/> with the given components. + /// </summary> + /// <param name="x">The vector's X component.</param> + /// <param name="y">The vector's Y component.</param> + /// <param name="z">The vector's Z component.</param> + /// <param name="w">The vector's W component.</param> + public Vector4(real_t x, real_t y, real_t z, real_t w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /// <summary> + /// Constructs a new <see cref="Vector4"/> from an existing <see cref="Vector4"/>. + /// </summary> + /// <param name="v">The existing <see cref="Vector4"/>.</param> + public Vector4(Vector4 v) + { + x = v.x; + y = v.y; + z = v.z; + w = v.w; + } + + /// <summary> + /// Adds each component of the <see cref="Vector4"/> + /// with the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> + public static Vector4 operator +(Vector4 left, Vector4 right) + { + left.x += right.x; + left.y += right.y; + left.z += right.z; + left.w += right.w; + return left; + } + + /// <summary> + /// Subtracts each component of the <see cref="Vector4"/> + /// by the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> + public static Vector4 operator -(Vector4 left, Vector4 right) + { + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + left.w -= right.w; + return left; + } + + /// <summary> + /// Returns the negative value of the <see cref="Vector4"/>. + /// This is the same as writing <c>new Vector4(-v.x, -v.y, -v.z, -v.w)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// With floats, the number zero can be either positive or negative. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> + public static Vector4 operator -(Vector4 vec) + { + vec.x = -vec.x; + vec.y = -vec.y; + vec.z = -vec.z; + vec.w = -vec.w; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4 operator *(Vector4 vec, real_t scale) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4 operator *(real_t scale, Vector4 vec) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4"/> + /// by the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4 operator *(Vector4 left, Vector4 right) + { + left.x *= right.x; + left.y *= right.y; + left.z *= right.z; + left.w *= right.w; + return left; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> + public static Vector4 operator /(Vector4 vec, real_t divisor) + { + vec.x /= divisor; + vec.y /= divisor; + vec.z /= divisor; + vec.w /= divisor; + return vec; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4"/> + /// by the components of the given <see cref="Vector4"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> + public static Vector4 operator /(Vector4 vec, Vector4 divisorv) + { + vec.x /= divisorv.x; + vec.y /= divisorv.y; + vec.z /= divisorv.z; + vec.w /= divisorv.w; + return vec; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> + public static bool operator ==(Vector4 left, Vector4 right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> + public static bool operator !=(Vector4 left, Vector4 right) + { + return !left.Equals(right); + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> + public static bool operator <(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w < right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> + public static bool operator >(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w > right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> + public static bool operator <=(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w <= right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> + public static bool operator >=(Vector4 left, Vector4 right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w >= right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Returns <see langword="true"/> if the vector is exactly equal + /// to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> + public override bool Equals(object obj) + { + if (obj is Vector4) + { + return Equals((Vector4)obj); + } + + return false; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="other">The other vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> + public bool Equals(Vector4 other) + { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + + /// <summary> + /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are approximately equal, + /// by running <see cref="Mathf.IsEqualApprox(real_t, real_t)"/> on each component. + /// </summary> + /// <param name="other">The other vector to compare.</param> + /// <returns>Whether or not the vectors are approximately equal.</returns> + public bool IsEqualApprox(Vector4 other) + { + return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w); + } + + /// <summary> + /// Serves as the hash function for <see cref="Vector4"/>. + /// </summary> + /// <returns>A hash code for this vector.</returns> + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + } + + /// <summary> + /// Converts this <see cref="Vector4"/> to a string. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public override string ToString() + { + return $"({x}, {y}, {z}, {w})"; + } + + /// <summary> + /// Converts this <see cref="Vector4"/> to a string with the given <paramref name="format"/>. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public string ToString(string format) + { + return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}, {w.ToString(format)})"; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs new file mode 100644 index 0000000000..365dcef486 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs @@ -0,0 +1,702 @@ +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif +using System; +using System.Runtime.InteropServices; + +namespace Godot +{ + /// <summary> + /// 4-element structure that can be used to represent 4D grid coordinates or sets of integers. + /// </summary> + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Vector4i : IEquatable<Vector4i> + { + /// <summary> + /// Enumerated index values for the axes. + /// Returned by <see cref="MaxAxisIndex"/> and <see cref="MinAxisIndex"/>. + /// </summary> + public enum Axis + { + /// <summary> + /// The vector's X axis. + /// </summary> + X = 0, + /// <summary> + /// The vector's Y axis. + /// </summary> + Y, + /// <summary> + /// The vector's Z axis. + /// </summary> + Z, + /// <summary> + /// The vector's W axis. + /// </summary> + W + } + + /// <summary> + /// The vector's X component. Also accessible by using the index position <c>[0]</c>. + /// </summary> + public int x; + + /// <summary> + /// The vector's Y component. Also accessible by using the index position <c>[1]</c>. + /// </summary> + public int y; + + /// <summary> + /// The vector's Z component. Also accessible by using the index position <c>[2]</c>. + /// </summary> + public int z; + + /// <summary> + /// The vector's W component. Also accessible by using the index position <c>[3]</c>. + /// </summary> + public int w; + + /// <summary> + /// Access vector components using their <paramref name="index"/>. + /// </summary> + /// <exception cref="IndexOutOfRangeException"> + /// Thrown when the given the <paramref name="index"/> is not 0, 1, 2 or 3. + /// </exception> + /// <value> + /// <c>[0]</c> is equivalent to <see cref="x"/>, + /// <c>[1]</c> is equivalent to <see cref="y"/>, + /// <c>[2]</c> is equivalent to <see cref="z"/>. + /// <c>[3]</c> is equivalent to <see cref="w"/>. + /// </value> + public int this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (index) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + case 2: + z = value; + return; + case 3: + w = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y, out int z, out int w) + { + x = this.x; + y = this.y; + z = this.z; + w = this.w; + } + + /// <summary> + /// Returns a new vector with all components in absolute values (i.e. positive). + /// </summary> + /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> + public Vector4i Abs() + { + return new Vector4i(Mathf.Abs(x), Mathf.Abs(y), Mathf.Abs(z), Mathf.Abs(w)); + } + + /// <summary> + /// Returns a new vector with all components clamped between the + /// components of <paramref name="min"/> and <paramref name="max"/> using + /// <see cref="Mathf.Clamp(int, int, int)"/>. + /// </summary> + /// <param name="min">The vector with minimum allowed values.</param> + /// <param name="max">The vector with maximum allowed values.</param> + /// <returns>The vector with all components clamped.</returns> + public Vector4i Clamp(Vector4i min, Vector4i max) + { + return new Vector4i + ( + Mathf.Clamp(x, min.x, max.x), + Mathf.Clamp(y, min.y, max.y), + Mathf.Clamp(z, min.z, max.z), + Mathf.Clamp(w, min.w, max.w) + ); + } + + /// <summary> + /// Returns the length (magnitude) of this vector. + /// </summary> + /// <seealso cref="LengthSquared"/> + /// <returns>The length of this vector.</returns> + public real_t Length() + { + int x2 = x * x; + int y2 = y * y; + int z2 = z * z; + int w2 = w * w; + + return Mathf.Sqrt(x2 + y2 + z2 + w2); + } + + /// <summary> + /// Returns the squared length (squared magnitude) of this vector. + /// This method runs faster than <see cref="Length"/>, so prefer it if + /// you need to compare vectors or need the squared length for some formula. + /// </summary> + /// <returns>The squared length of this vector.</returns> + public int LengthSquared() + { + int x2 = x * x; + int y2 = y * y; + int z2 = z * z; + int w2 = w * w; + + return x2 + y2 + z2 + w2; + } + + /// <summary> + /// Returns the axis of the vector's highest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.X"/>. + /// </summary> + /// <returns>The index of the highest axis.</returns> + public Axis MaxAxisIndex() + { + int max_index = 0; + int max_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] > max_value) + { + max_index = i; + max_value = this[i]; + } + } + return (Axis)max_index; + } + + /// <summary> + /// Returns the axis of the vector's lowest value. See <see cref="Axis"/>. + /// If all components are equal, this method returns <see cref="Axis.W"/>. + /// </summary> + /// <returns>The index of the lowest axis.</returns> + public Axis MinAxisIndex() + { + int min_index = 0; + int min_value = x; + for (int i = 1; i < 4; i++) + { + if (this[i] <= min_value) + { + min_index = i; + min_value = this[i]; + } + } + return (Axis)min_index; + } + + /// <summary> + /// Returns a vector with each component set to one or negative one, depending + /// on the signs of this vector's components, or zero if the component is zero, + /// by calling <see cref="Mathf.Sign(int)"/> on each component. + /// </summary> + /// <returns>A vector with all components as either <c>1</c>, <c>-1</c>, or <c>0</c>.</returns> + public Vector4i Sign() + { + return new Vector4i(Mathf.Sign(x), Mathf.Sign(y), Mathf.Sign(z), Mathf.Sign(w)); + } + + // Constants + private static readonly Vector4i _zero = new Vector4i(0, 0, 0, 0); + private static readonly Vector4i _one = new Vector4i(1, 1, 1, 1); + + /// <summary> + /// Zero vector, a vector with all components set to <c>0</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4i(0, 0, 0, 0)</c>.</value> + public static Vector4i Zero { get { return _zero; } } + /// <summary> + /// One vector, a vector with all components set to <c>1</c>. + /// </summary> + /// <value>Equivalent to <c>new Vector4i(1, 1, 1, 1)</c>.</value> + public static Vector4i One { get { return _one; } } + + /// <summary> + /// Constructs a new <see cref="Vector4i"/> with the given components. + /// </summary> + /// <param name="x">The vector's X component.</param> + /// <param name="y">The vector's Y component.</param> + /// <param name="z">The vector's Z component.</param> + /// <param name="w">The vector's W component.</param> + public Vector4i(int x, int y, int z, int w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /// <summary> + /// Constructs a new <see cref="Vector4i"/> from an existing <see cref="Vector4i"/>. + /// </summary> + /// <param name="vi">The existing <see cref="Vector4i"/>.</param> + public Vector4i(Vector4i vi) + { + this.x = vi.x; + this.y = vi.y; + this.z = vi.z; + this.w = vi.w; + } + + /// <summary> + /// Constructs a new <see cref="Vector4i"/> from an existing <see cref="Vector4"/> + /// by rounding the components via <see cref="Mathf.RoundToInt(real_t)"/>. + /// </summary> + /// <param name="v">The <see cref="Vector4"/> to convert.</param> + public Vector4i(Vector4 v) + { + this.x = Mathf.RoundToInt(v.x); + this.y = Mathf.RoundToInt(v.y); + this.z = Mathf.RoundToInt(v.z); + this.w = Mathf.RoundToInt(v.w); + } + + /// <summary> + /// Adds each component of the <see cref="Vector4i"/> + /// with the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> + public static Vector4i operator +(Vector4i left, Vector4i right) + { + left.x += right.x; + left.y += right.y; + left.z += right.z; + left.w += right.w; + return left; + } + + /// <summary> + /// Subtracts each component of the <see cref="Vector4i"/> + /// by the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> + public static Vector4i operator -(Vector4i left, Vector4i right) + { + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + left.w -= right.w; + return left; + } + + /// <summary> + /// Returns the negative value of the <see cref="Vector4i"/>. + /// This is the same as writing <c>new Vector4i(-v.x, -v.y, -v.z, -v.w)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> + public static Vector4i operator -(Vector4i vec) + { + vec.x = -vec.x; + vec.y = -vec.y; + vec.z = -vec.z; + vec.w = -vec.w; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4i operator *(Vector4i vec, int scale) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4i operator *(int scale, Vector4i vec) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + vec.w *= scale; + return vec; + } + + /// <summary> + /// Multiplies each component of the <see cref="Vector4i"/> + /// by the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> + public static Vector4i operator *(Vector4i left, Vector4i right) + { + left.x *= right.x; + left.y *= right.y; + left.z *= right.z; + left.w *= right.w; + return left; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> + public static Vector4i operator /(Vector4i vec, int divisor) + { + vec.x /= divisor; + vec.y /= divisor; + vec.z /= divisor; + vec.w /= divisor; + return vec; + } + + /// <summary> + /// Divides each component of the <see cref="Vector4i"/> + /// by the components of the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> + public static Vector4i operator /(Vector4i vec, Vector4i divisorv) + { + vec.x /= divisorv.x; + vec.y /= divisorv.y; + vec.z /= divisorv.z; + vec.w /= divisorv.w; + return vec; + } + + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector4i"/> + /// with the components of the given <see langword="int"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vecto43i(10, -20, 30, -40) % 7); // Prints "(3, -6, 2, -5)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The remainder vector.</returns> + public static Vector4i operator %(Vector4i vec, int divisor) + { + vec.x %= divisor; + vec.y %= divisor; + vec.z %= divisor; + vec.w %= divisor; + return vec; + } + + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector4i"/> + /// with the components of the given <see cref="Vector4i"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector4i(10, -20, 30, -40) % new Vector4i(6, 7, 8, 9)); // Prints "(4, -6, 6, -4)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The remainder vector.</returns> + public static Vector4i operator %(Vector4i vec, Vector4i divisorv) + { + vec.x %= divisorv.x; + vec.y %= divisorv.y; + vec.z %= divisorv.z; + vec.w %= divisorv.w; + return vec; + } + + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector4i"/> + /// and the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to AND with.</param> + /// <param name="and">The integer to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> + public static Vector4i operator &(Vector4i vec, int and) + { + vec.x &= and; + vec.y &= and; + vec.z &= and; + vec.w &= and; + return vec; + } + + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector4i"/> + /// and the given <see cref="Vector4i"/>. + /// </summary> + /// <param name="vec">The left vector to AND with.</param> + /// <param name="andv">The right vector to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> + public static Vector4i operator &(Vector4i vec, Vector4i andv) + { + vec.x &= andv.x; + vec.y &= andv.y; + vec.z &= andv.z; + vec.w &= andv.w; + return vec; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are equal.</returns> + public static bool operator ==(Vector4i left, Vector4i right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> + public static bool operator !=(Vector4i left, Vector4i right) + { + return !left.Equals(right); + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> + public static bool operator <(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w < right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> + public static bool operator >(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w > right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> + public static bool operator <=(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w <= right.w; + } + return left.z < right.z; + } + return left.y < right.y; + } + return left.x < right.x; + } + + /// <summary> + /// Compares two <see cref="Vector4i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y, Z and finally W values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> + public static bool operator >=(Vector4i left, Vector4i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + { + if (left.z == right.z) + { + return left.w >= right.w; + } + return left.z > right.z; + } + return left.y > right.y; + } + return left.x > right.x; + } + + /// <summary> + /// Converts this <see cref="Vector4i"/> to a <see cref="Vector4"/>. + /// </summary> + /// <param name="value">The vector to convert.</param> + public static implicit operator Vector4(Vector4i value) + { + return new Vector4(value.x, value.y, value.z, value.w); + } + + /// <summary> + /// Converts a <see cref="Vector4"/> to a <see cref="Vector4i"/>. + /// </summary> + /// <param name="value">The vector to convert.</param> + public static explicit operator Vector4i(Vector4 value) + { + return new Vector4i(value); + } + + /// <summary> + /// Returns <see langword="true"/> if the vector is equal + /// to the given object (<see paramref="obj"/>). + /// </summary> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> + public override bool Equals(object obj) + { + if (obj is Vector4i) + { + return Equals((Vector4i)obj); + } + + return false; + } + + /// <summary> + /// Returns <see langword="true"/> if the vectors are equal. + /// </summary> + /// <param name="other">The other vector.</param> + /// <returns>Whether or not the vectors are equal.</returns> + public bool Equals(Vector4i other) + { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + + /// <summary> + /// Serves as the hash function for <see cref="Vector4i"/>. + /// </summary> + /// <returns>A hash code for this vector.</returns> + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + } + + /// <summary> + /// Converts this <see cref="Vector4i"/> to a string. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public override string ToString() + { + return $"({x}, {y}, {z}, {w})"; + } + + /// <summary> + /// Converts this <see cref="Vector4i"/> to a string with the given <paramref name="format"/>. + /// </summary> + /// <returns>A string representation of this vector.</returns> + public string ToString(string format) + { + return $"({x.ToString(format)}, {y.ToString(format)}, {z.ToString(format)}), {w.ToString(format)})"; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index e59f45bbf6..4f55ce47e8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -50,6 +50,7 @@ <Compile Include="Core\NodePath.cs" /> <Compile Include="Core\Object.base.cs" /> <Compile Include="Core\Plane.cs" /> + <Compile Include="Core\Projection.cs" /> <Compile Include="Core\Quaternion.cs" /> <Compile Include="Core\Rect2.cs" /> <Compile Include="Core\Rect2i.cs" /> @@ -65,6 +66,8 @@ <Compile Include="Core\Vector2i.cs" /> <Compile Include="Core\Vector3.cs" /> <Compile Include="Core\Vector3i.cs" /> + <Compile Include="Core\Vector4.cs" /> + <Compile Include="Core\Vector4i.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <!-- diff --git a/modules/mono/glue/callable_glue.cpp b/modules/mono/glue/callable_glue.cpp index e59b34313c..521dc3dff7 100644 --- a/modules/mono/glue/callable_glue.cpp +++ b/modules/mono/glue/callable_glue.cpp @@ -49,7 +49,7 @@ MonoObject *godot_icall_Callable_Call(GDMonoMarshal::M_Callable *p_callable, Mon Variant result; Callable::CallError error; - callable.call(args.ptr(), argc, result, error); + callable.callp(args.ptr(), argc, result, error); return GDMonoMarshal::variant_to_mono_object(result); } @@ -68,7 +68,7 @@ void godot_icall_Callable_CallDeferred(GDMonoMarshal::M_Callable *p_callable, Mo args.set(i, &arg_store.get(i)); } - callable.call_deferred(args.ptr(), argc); + callable.call_deferredp(args.ptr(), argc); } void godot_register_callable_icalls() { diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 3b6fd25d71..51f11ab18a 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -262,7 +262,7 @@ enum { offsetof(Vector4, z) == (sizeof(real_t) * 2) && offsetof(Vector4, w) == (sizeof(real_t) * 3)), - MATCHES_Vector4i = (MATCHES_int && (sizeof(Vector4i) == (sizeof(int32_t) * 4i)) && + MATCHES_Vector4i = (MATCHES_int && (sizeof(Vector4i) == (sizeof(int32_t) * 4)) && offsetof(Vector4i, x) == (sizeof(int32_t) * 0) && offsetof(Vector4i, y) == (sizeof(int32_t) * 1) && offsetof(Vector4i, z) == (sizeof(int32_t) * 2) && diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 618e1b58e0..437c4ca54a 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -44,7 +44,7 @@ Error gd_mono_connect_signal_awaiter(Object *p_source, const StringName &p_signa SignalAwaiterCallable *awaiter_callable = memnew(SignalAwaiterCallable(p_target, p_awaiter, p_signal)); Callable callable = Callable(awaiter_callable); - return p_source->connect(p_signal, callable, Vector<Variant>(), Object::CONNECT_ONESHOT); + return p_source->connect(p_signal, callable, Object::CONNECT_ONESHOT); } bool SignalAwaiterCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) { diff --git a/modules/msdfgen/SCsub b/modules/msdfgen/SCsub index 227369f4bd..0c269bc7f4 100644 --- a/modules/msdfgen/SCsub +++ b/modules/msdfgen/SCsub @@ -36,7 +36,7 @@ if env["builtin_msdfgen"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_msdfgen.Append(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"]) + env_msdfgen.Prepend(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"]) lib = env_msdfgen.add_library("msdfgen_builtin", thirdparty_sources) thirdparty_obj += lib diff --git a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml index 44ab34f52c..881796ed26 100644 --- a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml +++ b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml @@ -1,65 +1,83 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> + Automatically replicates spawnable nodes from the authority to other multiplayer peers. </brief_description> <description> - This node uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way. + Spawnable scenes can be configured in the editor or through code (see [method add_spawnable_scene]). + Also supports custom node spawns through [method spawn], calling [method _spawn_custom] on all peers. + + Internally, [MultiplayerSpawner] uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way. </description> <tutorials> </tutorials> <methods> <method name="_spawn_custom" qualifiers="virtual"> - <return type="Object" /> + <return type="Node" /> <argument index="0" name="data" type="Variant" /> <description> + Method called on all peers when a custom spawn was requested by the authority using [method spawn]. Should return a [Node] that is not in the scene tree. + + [b]Note:[/b] Spawned nodes should [b]not[/b] be added to the scene with `add_child`. This is done automatically. </description> </method> <method name="add_spawnable_scene"> <return type="void" /> <argument index="0" name="path" type="String" /> <description> + Adds a scene path to spawnable scenes, making it automatically replicated from the multiplayer authority to other peers when added as children of the node pointed by [member spawn_path]. </description> </method> <method name="clear_spawnable_scenes"> <return type="void" /> <description> + Clears all spawnable scenes. Does not despawn existing instances on remote peers. </description> </method> <method name="get_spawnable_scene" qualifiers="const"> <return type="String" /> - <argument index="0" name="path" type="int" /> + <argument index="0" name="index" type="int" /> <description> + Returns the spawnable scene path by index. </description> </method> <method name="get_spawnable_scene_count" qualifiers="const"> <return type="int" /> <description> + Returns the count of spawnable scene paths. </description> </method> <method name="spawn"> <return type="Node" /> <argument index="0" name="data" type="Variant" default="null" /> <description> + Requests a custom spawn, with [code]data[/code] passed to [method _spawn_custom] on all peers. Returns the locally spawned node instance already inside the scene tree, and added as a child of the node pointed by [member spawn_path]. + + [b]Note:[/b] Spawnable scenes are spawned automatically. [method spawn] is only needed for custom spawns. </description> </method> </methods> <members> <member name="spawn_limit" type="int" setter="set_spawn_limit" getter="get_spawn_limit" default="0"> + Maximum nodes that is allowed to be spawned by this spawner. Includes both spawnable scenes and custom spawns. + + When set to [code]0[/code] (the default), there is no limit. </member> <member name="spawn_path" type="NodePath" setter="set_spawn_path" getter="get_spawn_path" default="NodePath("")"> + Path to the spawn root. Spawnable scenes that are added as direct children are replicated to other peers. </member> </members> <signals> <signal name="despawned"> - <argument index="0" name="scene_id" type="int" /> - <argument index="1" name="node" type="Node" /> + <argument index="0" name="node" type="Node" /> <description> + Emitted when a spawnable scene or custom spawn was despawned by the multiplayer authority. Only called on puppets. </description> </signal> <signal name="spawned"> - <argument index="0" name="scene_id" type="int" /> - <argument index="1" name="node" type="Node" /> + <argument index="0" name="node" type="Node" /> <description> + Emitted when a spawnable scene or custom spawn was spawned by the multiplayer authority. Only called on puppets. </description> </signal> </signals> diff --git a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml index ebd1b50201..a2ea64061c 100644 --- a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml +++ b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml @@ -1,9 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> + Synchronizes properties from the multiplayer authority to the remote peers. </brief_description> <description> - The [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way. + By default, [MultiplayerSynchronizer] synchronizes configured properties to all peers. + Visiblity can be handled directly with [method set_visibility_for] or as-needed with [method add_visibility_filter] and [method update_visibility]. + + [MultiplayerSpawner]s will handle nodes according to visibility of synchronizers as long as the node at [member root_path] was spawned by one. + + Internally, [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way. </description> <tutorials> </tutorials> @@ -12,18 +18,23 @@ <return type="void" /> <argument index="0" name="filter" type="Callable" /> <description> + Adds a peer visibility filter for this synchronizer. + + [code]filter[/code] should take a peer id [int] and return a [bool]. </description> </method> <method name="get_visibility_for" qualifiers="const"> <return type="bool" /> <argument index="0" name="peer" type="int" /> <description> + Queries the current visibility for peer [code]peer[/code]. </description> </method> <method name="remove_visibility_filter"> <return type="void" /> <argument index="0" name="filter" type="Callable" /> <description> + Removes a peer visiblity filter from this synchronizer. </description> </method> <method name="set_visibility_for"> @@ -31,40 +42,52 @@ <argument index="0" name="peer" type="int" /> <argument index="1" name="visible" type="bool" /> <description> + Sets the visibility of [code]peer[/code] to [code]visible[/code]. If [code]peer[/code] is [code]0[/code], the value of [member public_visibility] will be updated instead. </description> </method> <method name="update_visibility"> <return type="void" /> <argument index="0" name="for_peer" type="int" default="0" /> <description> + Updates the visibility of [code]peer[/code] according to visibility filters. If [code]peer[/code] is [code]0[/code] (the default), all peers' visibilties are updated. </description> </method> </methods> <members> <member name="public_visibility" type="bool" setter="set_visibility_public" getter="is_visibility_public" default="true"> + Whether synchronization should be visible to all peers by default. See [method set_visibility_for] and [method add_visibility_filter] for ways of configuring fine-grained visibility options. </member> <member name="replication_config" type="SceneReplicationConfig" setter="set_replication_config" getter="get_replication_config"> + Resource containing which properties to synchronize. </member> <member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0"> + Time interval between synchronizes. When set to [code]0.0[/code] (the default), synchronizes happen every network process frame. </member> <member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath("..")"> + Node path that replicated properties are relative to. + If [member root_path] was spawned by a [MultiplayerSpawner], the node will be also be spawned and despawned based on this synchronizer visibility options. </member> <member name="visibility_update_mode" type="int" setter="set_visibility_update_mode" getter="get_visibility_update_mode" enum="MultiplayerSynchronizer.VisibilityUpdateMode" default="0"> + Specifies when visibility filters are updated (see [enum VisibilityUpdateMode] for options). </member> </members> <signals> <signal name="visibility_changed"> <argument index="0" name="for_peer" type="int" /> <description> + Emitted when visibility of [code]for_peer[/code] is updated. See [method update_visibility]. </description> </signal> </signals> <constants> <constant name="VISIBILITY_PROCESS_IDLE" value="0" enum="VisibilityUpdateMode"> + Visibility filters are updated every idle process frame. </constant> <constant name="VISIBILITY_PROCESS_PHYSICS" value="1" enum="VisibilityUpdateMode"> + Visibility filters are updated every physics process frame. </constant> <constant name="VISIBILITY_PROCESS_NONE" value="2" enum="VisibilityUpdateMode"> + Visibility filters are not updated automatically, and must be updated manually by calling [method update_visibility]. </constant> </constants> </class> diff --git a/modules/multiplayer/doc_classes/SceneReplicationConfig.xml b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml index 1d6dec2f92..fc91592c7a 100644 --- a/modules/multiplayer/doc_classes/SceneReplicationConfig.xml +++ b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> + Configuration for properties to synchronize with a [MultiplayerSynchronizer]. </brief_description> <description> </description> @@ -12,35 +13,41 @@ <argument index="0" name="path" type="NodePath" /> <argument index="1" name="index" type="int" default="-1" /> <description> + Adds the property identified by the given [code]path[/code] to the list of the properties being synchronized, optionally passing an [code]index[/code]. </description> </method> <method name="get_properties" qualifiers="const"> <return type="NodePath[]" /> <description> + Returns a list of synchronized property [NodePath]s. </description> </method> <method name="has_property" qualifiers="const"> <return type="bool" /> <argument index="0" name="path" type="NodePath" /> <description> + Returns whether the given [code]path[/code] is configured for synchronization. </description> </method> <method name="property_get_index" qualifiers="const"> <return type="int" /> <argument index="0" name="path" type="NodePath" /> <description> + Finds the index of the given [code]path[/code]. </description> </method> <method name="property_get_spawn"> <return type="bool" /> <argument index="0" name="path" type="NodePath" /> <description> + Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn. </description> </method> <method name="property_get_sync"> <return type="bool" /> <argument index="0" name="path" type="NodePath" /> <description> + Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on process. </description> </method> <method name="property_set_spawn"> @@ -48,6 +55,7 @@ <argument index="0" name="path" type="NodePath" /> <argument index="1" name="enabled" type="bool" /> <description> + Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn. </description> </method> <method name="property_set_sync"> @@ -55,12 +63,14 @@ <argument index="0" name="path" type="NodePath" /> <argument index="1" name="enabled" type="bool" /> <description> + Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on process. </description> </method> <method name="remove_property"> <return type="void" /> <argument index="0" name="path" type="NodePath" /> <description> + Removes the property identified by the given [code]path[/code] from the configuration. </description> </method> </methods> diff --git a/modules/multiplayer/editor/replication_editor_plugin.cpp b/modules/multiplayer/editor/replication_editor_plugin.cpp index c6484264d0..1f79b8c3e3 100644 --- a/modules/multiplayer/editor/replication_editor_plugin.cpp +++ b/modules/multiplayer/editor/replication_editor_plugin.cpp @@ -32,9 +32,12 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "editor/inspector_dock.h" +#include "editor/scene_tree_editor.h" #include "modules/multiplayer/multiplayer_synchronizer.h" #include "scene/gui/dialogs.h" +#include "scene/gui/separator.h" #include "scene/gui/tree.h" void ReplicationEditor::_pick_node_filter_text_changed(const String &p_newtext) { diff --git a/modules/multiplayer/editor/replication_editor_plugin.h b/modules/multiplayer/editor/replication_editor_plugin.h index 57fa4c82fa..5cc2bbe937 100644 --- a/modules/multiplayer/editor/replication_editor_plugin.h +++ b/modules/multiplayer/editor/replication_editor_plugin.h @@ -34,14 +34,15 @@ #include "editor/editor_plugin.h" #include "editor/editor_spin_slider.h" -#include "editor/property_editor.h" #include "editor/property_selector.h" #include "../scene_replication_config.h" class ConfirmationDialog; class MultiplayerSynchronizer; +class SceneTreeDialog; class Tree; +class TreeItem; class ReplicationEditor : public VBoxContainer { GDCLASS(ReplicationEditor, VBoxContainer); diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp index f5edffbb0c..e8f3aecc69 100644 --- a/modules/multiplayer/multiplayer_spawner.cpp +++ b/modules/multiplayer/multiplayer_spawner.cpp @@ -126,7 +126,7 @@ void MultiplayerSpawner::_set_spawnable_scenes(const Vector<String> &p_scenes) { void MultiplayerSpawner::_bind_methods() { ClassDB::bind_method(D_METHOD("add_spawnable_scene", "path"), &MultiplayerSpawner::add_spawnable_scene); ClassDB::bind_method(D_METHOD("get_spawnable_scene_count"), &MultiplayerSpawner::get_spawnable_scene_count); - ClassDB::bind_method(D_METHOD("get_spawnable_scene", "path"), &MultiplayerSpawner::get_spawnable_scene); + ClassDB::bind_method(D_METHOD("get_spawnable_scene", "index"), &MultiplayerSpawner::get_spawnable_scene); ClassDB::bind_method(D_METHOD("clear_spawnable_scenes"), &MultiplayerSpawner::clear_spawnable_scenes); ClassDB::bind_method(D_METHOD("_get_spawnable_scenes"), &MultiplayerSpawner::_get_spawnable_scenes); @@ -146,8 +146,8 @@ void MultiplayerSpawner::_bind_methods() { GDVIRTUAL_BIND(_spawn_custom, "data"); - ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); } void MultiplayerSpawner::_update_spawn_node() { @@ -277,12 +277,11 @@ Node *MultiplayerSpawner::instantiate_scene(int p_id) { Node *MultiplayerSpawner::instantiate_custom(const Variant &p_data) { ERR_FAIL_COND_V_MSG(spawn_limit && spawn_limit <= tracked_nodes.size(), nullptr, "Spawn limit reached!"); - Object *obj = nullptr; Node *node = nullptr; - if (GDVIRTUAL_CALL(_spawn_custom, p_data, obj)) { - node = Object::cast_to<Node>(obj); + if (GDVIRTUAL_CALL(_spawn_custom, p_data, node)) { + return node; } - return node; + ERR_FAIL_V_MSG(nullptr, "Method '_spawn_custom' is not implemented on this peer."); } Node *MultiplayerSpawner::spawn(const Variant &p_data) { diff --git a/modules/multiplayer/multiplayer_spawner.h b/modules/multiplayer/multiplayer_spawner.h index 80bb878a74..fc3befc2d4 100644 --- a/modules/multiplayer/multiplayer_spawner.h +++ b/modules/multiplayer/multiplayer_spawner.h @@ -91,7 +91,9 @@ protected: void _get_property_list(List<PropertyInfo> *p_list) const; #endif public: - Node *get_spawn_node() const { return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; } + Node *get_spawn_node() const { + return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; + } void add_spawnable_scene(const String &p_path); int get_spawnable_scene_count() const; @@ -110,7 +112,7 @@ public: Node *instantiate_custom(const Variant &p_data); Node *instantiate_scene(int p_idx); - GDVIRTUAL1R(Object *, _spawn_custom, const Variant &); + GDVIRTUAL1R(Node *, _spawn_custom, const Variant &); MultiplayerSpawner() {} }; diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp index c89270fbe8..6e3dbfab47 100644 --- a/modules/multiplayer/scene_replication_interface.cpp +++ b/modules/multiplayer/scene_replication_interface.cpp @@ -396,6 +396,8 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b pending_buffer_size = state_len; } parent->add_child(node); + spawner->emit_signal(SNAME("spawned"), node); + pending_spawn = ObjectID(); pending_buffer = nullptr; pending_buffer_size = 0; @@ -411,10 +413,17 @@ Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p Error err = rep_state->peer_del_remote(p_from, net_id, &node); ERR_FAIL_COND_V(err != OK, err); ERR_FAIL_COND_V(!node, ERR_BUG); + + MultiplayerSpawner *spawner = rep_state->get_spawner(node->get_instance_id()); + ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST); + ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED); + if (node->get_parent() != nullptr) { node->get_parent()->remove_child(node); } node->queue_delete(); + spawner->emit_signal(SNAME("despawned"), node); + return OK; } diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 2d764a4006..d212fe62b4 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -117,11 +117,11 @@ if env["builtin_harfbuzz"]: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_harfbuzz.Append(CPPPATH=["#thirdparty/harfbuzz/src"]) + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"]) env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"]) if env["builtin_icu"]: - env_harfbuzz.Append(CPPPATH=["#thirdparty/icu4c/common/"]) + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/"]) env_harfbuzz.Append(CCFLAGS=["-DU_HAVE_LIB_SUFFIX=1", "-DU_LIB_SUFFIX_C_NAME=_godot", "-DHAVE_ICU_BUILTIN"]) if freetype_enabled: @@ -132,9 +132,9 @@ if env["builtin_harfbuzz"]: ] ) if env["builtin_freetype"]: - env_harfbuzz.Append(CPPPATH=["#thirdparty/freetype/include"]) + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/freetype/include"]) if env["builtin_graphite"]: - env_harfbuzz.Append(CPPPATH=["#thirdparty/graphite/include"]) + env_harfbuzz.Prepend(CPPPATH=["#thirdparty/graphite/include"]) env_harfbuzz.Append(CCFLAGS=["-DGRAPHITE2_STATIC"]) if env["platform"] == "android" or env["platform"] == "linuxbsd": @@ -146,7 +146,7 @@ if env["builtin_harfbuzz"]: else: env_harfbuzz.Append(CCFLAGS=["-DHB_NO_MT"]) - env_text_server_adv.Append(CPPPATH=["#thirdparty/harfbuzz/src"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"]) lib = env_harfbuzz.add_library("harfbuzz_builtin", thirdparty_sources) thirdparty_obj += lib @@ -209,7 +209,7 @@ if env["builtin_graphite"] and freetype_enabled: thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_graphite.Append(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"]) + env_graphite.Prepend(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"]) env_graphite.Append( CCFLAGS=[ "-DGRAPHITE2_STATIC", @@ -447,11 +447,11 @@ if env["builtin_icu"]: if env_icu["tools"]: env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name) env_icu.Command("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name, make_icu_data) - env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/"]) else: thirdparty_sources += ["icu_data/icudata_stub.cpp"] - env_icu.Append(CPPPATH=["#thirdparty/icu4c/common/"]) + env_icu.Prepend(CPPPATH=["#thirdparty/icu4c/common/"]) env_icu.Append( CXXFLAGS=[ "-DU_STATIC_IMPLEMENTATION", @@ -480,7 +480,7 @@ if env["builtin_icu"]: if env_text_server_adv["tools"]: env_text_server_adv.Append(CXXFLAGS=["-DICU_STATIC_DATA"]) - env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/common/"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/common/"]) lib = env_icu.add_library("icu_builtin", thirdparty_sources) thirdparty_obj += lib @@ -504,13 +504,13 @@ if env["builtin_icu"]: module_obj = [] if env["builtin_msdfgen"] and msdfgen_enabled: - env_text_server_adv.Append(CPPPATH=["#thirdparty/msdfgen"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/msdfgen"]) if env["builtin_freetype"] and freetype_enabled: - env_text_server_adv.Append(CPPPATH=["#thirdparty/freetype/include"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/freetype/include"]) if env["builtin_graphite"] and freetype_enabled: - env_text_server_adv.Append(CPPPATH=["#thirdparty/graphite/include"]) + env_text_server_adv.Prepend(CPPPATH=["#thirdparty/graphite/include"]) env_text_server_adv.add_source_files(module_obj, "*.cpp") env.modules_sources += module_obj diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index fa234081f0..64788bfeff 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -1359,7 +1359,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f fd->underline_position = (-FT_MulFix(fd->face->underline_position, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale; fd->underline_thickness = (FT_MulFix(fd->face->underline_thickness, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale; +#if HB_VERSION_ATLEAST(3, 3, 0) hb_font_set_synthetic_slant(fd->hb_handle, p_font_data->transform[0][1]); +#else +#ifndef _MSC_VER +#warning Building with HarfBuzz < 3.3.0, synthetic slant offset correction disabled. +#endif +#endif if (!p_font_data->face_init) { // Get style flags and name. @@ -1626,6 +1632,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f for (unsigned int i = 0; i < count; i++) { Dictionary ftr; +#if HB_VERSION_ATLEAST(2, 1, 0) hb_ot_name_id_t lbl_id; if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GSUB, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) { PackedInt32Array lbl; @@ -1635,6 +1642,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw()); ftr["label"] = String((const char32_t *)lbl.ptr()); } +#else +#ifndef _MSC_VER +#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled. +#endif +#endif ftr["type"] = _get_tag_type(feature_tags[i]); ftr["hidden"] = _get_tag_hidden(feature_tags[i]); @@ -1649,6 +1661,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f for (unsigned int i = 0; i < count; i++) { Dictionary ftr; +#if HB_VERSION_ATLEAST(2, 1, 0) hb_ot_name_id_t lbl_id; if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GPOS, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) { PackedInt32Array lbl; @@ -1658,6 +1671,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw()); ftr["label"] = String((const char32_t *)lbl.ptr()); } +#else +#ifndef _MSC_VER +#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled. +#endif +#endif ftr["type"] = _get_tag_type(feature_tags[i]); ftr["hidden"] = _get_tag_hidden(feature_tags[i]); diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub index 121f38fcd5..ca9322e450 100644 --- a/modules/text_server_fb/SCsub +++ b/modules/text_server_fb/SCsub @@ -9,9 +9,9 @@ msdfgen_enabled = env.module_check_dependencies("text_server_fb", ["msdfgen"], T env_text_server_fb = env_modules.Clone() if env["builtin_msdfgen"] and msdfgen_enabled: - env_text_server_fb.Append(CPPPATH=["#thirdparty/msdfgen"]) + env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"]) if env["builtin_freetype"] and freetype_enabled: - env_text_server_fb.Append(CPPPATH=["#thirdparty/freetype/include"]) + env_text_server_fb.Prepend(CPPPATH=["#thirdparty/freetype/include"]) env_text_server_fb.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index 1e9755f45f..7f8e9d8254 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -42,10 +42,32 @@ #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "scene/gui/check_button.h" +#include "scene/gui/graph_edit.h" +#include "scene/gui/separator.h" #include "scene/gui/view_panner.h" #include "scene/main/window.h" #ifdef TOOLS_ENABLED + +void VisualScriptEditedProperty::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualScriptEditedProperty::set_edited_property); + ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualScriptEditedProperty::get_edited_property); + + ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property"); +} + +void VisualScriptEditedProperty::set_edited_property(Variant p_variant) { + edited_property = p_variant; +} + +Variant VisualScriptEditedProperty::get_edited_property() const { + return edited_property; +} + +///////////////// + class VisualScriptEditorSignalEdit : public Object { GDCLASS(VisualScriptEditorSignalEdit, Object); @@ -3898,14 +3920,14 @@ int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const V return new_id; } -void VisualScriptEditor::_default_value_changed() { +void VisualScriptEditor::_default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) { Ref<VisualScriptNode> vsn = script->get_node(editing_id); if (vsn.is_null()) { return; } undo_redo->create_action(TTR("Change Input Value")); - undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, default_value_edit->get_variant()); + undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, p_value); undo_redo->add_undo_method(vsn.ptr(), "set_default_input_value", editing_input, vsn->get_default_input_value(editing_input)); undo_redo->add_do_method(this, "_update_graph", editing_id); @@ -3928,9 +3950,6 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i Variant::construct(pinfo.type, existing, &existingp, 1, ce); } - default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_screen_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y) * graph->get_zoom()); - default_value_edit->reset_size(); - if (pinfo.type == Variant::NODE_PATH) { Node *edited_scene = get_tree()->get_edited_scene_root(); if (edited_scene) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open). @@ -3948,11 +3967,33 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i } } - if (default_value_edit->edit(nullptr, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) { - if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT) { - default_value_edit->popup_centered_ratio(); + edited_default_property_holder->set_edited_property(existing); + + if (default_property_editor) { + default_property_editor->disconnect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed)); + default_property_editor_popup->remove_child(default_property_editor); + } + + default_property_editor = EditorInspector::instantiate_property_editor(edited_default_property_holder.ptr(), pinfo.type, "edited_property", pinfo.hint, pinfo.hint_string, PROPERTY_USAGE_NONE); + if (default_property_editor) { + default_property_editor->set_object_and_property(edited_default_property_holder.ptr(), "edited_property"); + default_property_editor->update_property(); + default_property_editor->set_name_split_ratio(0); + default_property_editor_popup->add_child(default_property_editor); + + default_property_editor->connect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed)); + + Button *button = Object::cast_to<Button>(p_button); + if (button) { + default_property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom()); + } + + default_property_editor_popup->reset_size(); + + if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT || !button) { + default_property_editor_popup->popup_centered_ratio(); } else { - default_value_edit->popup(); + default_property_editor_popup->popup(); } } @@ -4795,9 +4836,11 @@ VisualScriptEditor::VisualScriptEditor() { set_process_input(true); - default_value_edit = memnew(CustomPropertyEditor); - add_child(default_value_edit); - default_value_edit->connect("variant_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed)); + default_property_editor_popup = memnew(PopupPanel); + default_property_editor_popup->set_min_size(Size2i(180, 0) * EDSCALE); + add_child(default_property_editor_popup); + + edited_default_property_holder.instantiate(); new_connect_node_select = memnew(VisualScriptPropertySelector); add_child(new_connect_node_select); diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index a6df7bba73..6b337e52f6 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -34,15 +34,31 @@ #include "../visual_script.h" #include "editor/create_dialog.h" #include "editor/plugins/script_editor_plugin.h" -#include "editor/property_editor.h" -#include "scene/gui/graph_edit.h" #include "visual_script_property_selector.h" +class GraphEdit; + class VisualScriptEditorSignalEdit; class VisualScriptEditorVariableEdit; #ifdef TOOLS_ENABLED +class VisualScriptEditedProperty : public RefCounted { + GDCLASS(VisualScriptEditedProperty, RefCounted); + +private: + Variant edited_property; + +protected: + static void _bind_methods(); + +public: + void set_edited_property(Variant p_variant); + Variant get_edited_property() const; + + VisualScriptEditedProperty() {} +}; + // TODO: Maybe this class should be refactored. // See https://github.com/godotengine/godot/issues/51913 class VisualScriptEditor : public ScriptEditorBase { @@ -115,7 +131,9 @@ class VisualScriptEditor : public ScriptEditorBase { AcceptDialog *edit_variable_dialog = nullptr; EditorInspector *edit_variable_edit = nullptr; - CustomPropertyEditor *default_value_edit = nullptr; + PopupPanel *default_property_editor_popup = nullptr; + EditorProperty *default_property_editor = nullptr; + Ref<VisualScriptEditedProperty> edited_default_property_holder; UndoRedo *undo_redo = nullptr; @@ -276,7 +294,7 @@ class VisualScriptEditor : public ScriptEditorBase { int data_disconnect_node = 0; int data_disconnect_port = 0; - void _default_value_changed(); + void _default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing); void _default_value_edited(Node *p_button, int p_id, int p_input_port); void _menu_option(int p_what); diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index f98ce5bb26..712c89368b 100644 --- a/modules/visual_script/editor/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -39,6 +39,7 @@ #include "editor/doc_tools.h" #include "editor/editor_feature_profile.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "scene/main/node.h" #include "scene/main/window.h" diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index 41f8eea735..4de626467e 100644 --- a/modules/visual_script/editor/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h @@ -33,8 +33,8 @@ #include "../visual_script.h" #include "editor/editor_help.h" -#include "editor/property_editor.h" #include "scene/gui/rich_text_label.h" +#include "scene/gui/tree.h" class VisualScriptPropertySelector : public ConfirmationDialog { GDCLASS(VisualScriptPropertySelector, ConfirmationDialog); diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp index 733d92f741..6b21c18d59 100644 --- a/platform/android/file_access_filesystem_jandroid.cpp +++ b/platform/android/file_access_filesystem_jandroid.cpp @@ -29,9 +29,11 @@ /*************************************************************************/ #include "file_access_filesystem_jandroid.h" + #include "core/os/os.h" #include "core/templates/local_vector.h" #include "thread_jandroid.h" + #include <unistd.h> jobject FileAccessFilesystemJAndroid::file_access_handler = nullptr; @@ -198,7 +200,7 @@ String FileAccessFilesystemJAndroid::get_line() const { if (elem == '\n' || elem == '\0') { // Found the end of the line const_cast<FileAccessFilesystemJAndroid *>(this)->seek(start_position + line_buffer_position + 1); - if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position)) { + if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { return String(); } return result; @@ -206,7 +208,7 @@ String FileAccessFilesystemJAndroid::get_line() const { } } - if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position)) { + if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { return String(); } return result; diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index 85e8621aa0..9ca2948542 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -30,6 +30,7 @@ #include "export_plugin.h" +#include "core/string/translation.h" #include "editor/editor_node.h" void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 825c1b6638..ea236f62f7 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -30,6 +30,7 @@ #include "export.h" +#include "editor/editor_settings.h" #include "export_plugin.h" void register_javascript_exporter() { diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp index a9912edef7..b99f88d067 100644 --- a/platform/javascript/export/export_plugin.cpp +++ b/platform/javascript/export/export_plugin.cpp @@ -31,6 +31,7 @@ #include "export_plugin.h" #include "core/config/project_settings.h" +#include "editor/editor_settings.h" Error EditorExportPlatformJavaScript::_extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa) { Ref<FileAccess> io_fa; diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp index 2ec2bb92d3..bcc2636c07 100644 --- a/platform/macos/export/export_plugin.cpp +++ b/platform/macos/export/export_plugin.cpp @@ -32,6 +32,7 @@ #include "codesign.h" +#include "core/string/translation.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index efba006985..31105824a5 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -30,6 +30,7 @@ #include "export.h" +#include "editor/editor_settings.h" #include "export_plugin.h" void register_uwp_exporter() { diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp index a99776497b..070c46242f 100644 --- a/platform/uwp/export/export_plugin.cpp +++ b/platform/uwp/export/export_plugin.cpp @@ -30,6 +30,7 @@ #include "export_plugin.h" +#include "editor/editor_settings.h" #include "platform/uwp/logo.gen.h" String EditorExportPlatformUWP::get_name() const { diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis index 899956d65a..cdd1c14978 100644 --- a/platform/windows/godot.natvis +++ b/platform/windows/godot.natvis @@ -40,7 +40,7 @@ <DisplayString Condition="type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString> <DisplayString Condition="type == Variant::AABB">{_data._aabb}</DisplayString> <DisplayString Condition="type == Variant::BASIS">{_data._basis}</DisplayString> - <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform}</DisplayString> + <DisplayString Condition="type == Variant::TRANSFORM3D">{_data._transform3d}</DisplayString> <DisplayString Condition="type == Variant::PROJECTION">{_data._projection}</DisplayString> <DisplayString Condition="type == Variant::STRING">{*(String *)_data._mem}</DisplayString> <DisplayString Condition="type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString> @@ -74,7 +74,7 @@ <Item Name="[value]" Condition="type == Variant::TRANSFORM2D">_data._transform2d</Item> <Item Name="[value]" Condition="type == Variant::AABB">_data._aabb</Item> <Item Name="[value]" Condition="type == Variant::BASIS">_data._basis</Item> - <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform</Item> + <Item Name="[value]" Condition="type == Variant::TRANSFORM3D">_data._transform3d</Item> <Item Name="[value]" Condition="type == Variant::STRING">*(String *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::RECT2">*(Rect2 *)_data._mem</Item> diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 0871bf536b..9a5d4f5480 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -403,6 +403,9 @@ void CollisionObject3D::_on_transform_changed() { debug_shape_old_transform = get_global_transform(); for (KeyValue<uint32_t, ShapeData> &E : shapes) { ShapeData &shapedata = E.value; + if (shapedata.disabled) { + continue; // If disabled then there are no debug shapes to update. + } const ShapeData::ShapeBase *shapes = shapedata.shapes.ptr(); for (int i = 0; i < shapedata.shapes.size(); i++) { RS::get_singleton()->instance_set_transform(shapes[i].debug_shape, debug_shape_old_transform * shapedata.xform); diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index bc435c5451..712a37e745 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -126,7 +126,7 @@ void Label3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority"); ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_outline_render_priority", "get_outline_render_priority"); diff --git a/scene/3d/shape_cast_3d.cpp b/scene/3d/shape_cast_3d.cpp index ac804280fe..d324e09df5 100644 --- a/scene/3d/shape_cast_3d.cpp +++ b/scene/3d/shape_cast_3d.cpp @@ -154,7 +154,7 @@ void ShapeCast3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position", PROPERTY_HINT_NONE, "suffix:m"), "set_target_position", "get_target_position"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01,suffix:m"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_results"), "set_max_results", "get_max_results"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "_get_collision_result"); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index cb6354f7a8..ef2b9e1ce5 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -377,7 +377,7 @@ SpriteBase3D::SpriteBase3D() { RS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1)); RS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0)); RS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1)); - RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.98); + RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.5); mesh = RenderingServer::get_singleton()->mesh_create(); diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h index e1a38dd7a0..6d173dea87 100644 --- a/scene/3d/voxel_gi.h +++ b/scene/3d/voxel_gi.h @@ -49,9 +49,9 @@ class VoxelGIData : public Resource { float energy = 1.0; float bias = 1.5; float normal_bias = 0.0; - float propagation = 0.7; + float propagation = 0.5; bool interior = false; - bool use_two_bounces = false; + bool use_two_bounces = true; protected: static void _bind_methods(); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 3a45d9f26c..793967d9ad 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -830,20 +830,12 @@ void AnimationNodeStateMachine::rename_node(const StringName &p_name, const Stri anodesm->state_machine_name = p_new_name; } - for (int i = 0; i < transitions.size(); i++) { - if (transitions[i].local_from == p_name) { - _rename_transition(transitions[i].from, String(transitions[i].from).replace_first(p_name, p_new_name)); - } - - if (transitions[i].local_to == p_name) { - _rename_transition(transitions[i].to, String(transitions[i].to).replace_first(p_name, p_new_name)); - } - } + _rename_transitions(p_name, p_new_name); emit_signal("tree_changed"); } -void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, const StringName &p_new_name) { +void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, const StringName &p_new_name) { if (updating_transitions) { return; } @@ -854,12 +846,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con Vector<String> path = String(transitions[i].to).split("/"); if (path.size() > 1) { if (path[0] == "..") { - prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); + prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); } else { - ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transition("../" + p_name, "../" + p_new_name); + ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_to].node)->_rename_transitions("../" + p_name, "../" + p_new_name); } } + if (transitions[i].local_from == p_name) { + transitions.write[i].local_from = p_new_name; + } + transitions.write[i].from = p_new_name; } @@ -867,12 +863,16 @@ void AnimationNodeStateMachine::_rename_transition(const StringName &p_name, con Vector<String> path = String(transitions[i].from).split("/"); if (path.size() > 1) { if (path[0] == "..") { - prev_state_machine->_rename_transition(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); + prev_state_machine->_rename_transitions(String(state_machine_name) + "/" + p_name, String(state_machine_name) + "/" + p_new_name); } else { - ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transition("../" + p_name, "../" + p_new_name); + ((Ref<AnimationNodeStateMachine>)states[transitions[i].local_from].node)->_rename_transitions("../" + p_name, "../" + p_new_name); } } + if (transitions[i].local_to == p_name) { + transitions.write[i].local_to = p_new_name; + } + transitions.write[i].to = p_new_name; } diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index d4e58ca3d3..ead914db7a 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -185,7 +185,7 @@ private: void _tree_changed(); void _remove_transition(const Ref<AnimationNodeStateMachineTransition> p_transition); - void _rename_transition(const StringName &p_name, const StringName &p_new_name); + void _rename_transitions(const StringName &p_name, const StringName &p_new_name); bool _can_connect(const StringName &p_name, Vector<AnimationNodeStateMachine *> p_parents = Vector<AnimationNodeStateMachine *>()); StringName _get_shortest_path(const StringName &p_path) const; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index e2ead6415a..788feacdd9 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -264,15 +264,7 @@ void ColorPicker::_update_controls() { void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) { color = p_color; if (color != last_color) { - if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { - h = color.get_ok_hsl_h(); - s = color.get_ok_hsl_s(); - v = color.get_ok_hsl_l(); - } else { - h = color.get_h(); - s = color.get_s(); - v = color.get_v(); - } + _copy_color_to_hsv(); last_color = color; } @@ -386,6 +378,26 @@ Vector<float> ColorPicker::get_active_slider_values() { return values; } +void ColorPicker::_copy_color_to_hsv() { + if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { + h = color.get_ok_hsl_h(); + s = color.get_ok_hsl_s(); + v = color.get_ok_hsl_l(); + } else { + h = color.get_h(); + s = color.get_s(); + v = color.get_v(); + } +} + +void ColorPicker::_copy_hsv_to_color() { + if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) { + color.set_ok_hsl(h, s, v, color.a); + } else { + color.set_hsv(h, s, v, color.a); + } +} + ColorPicker::PickerShapeType ColorPicker::_get_actual_shape() const { return modes[current_mode]->get_shape_override() != SHAPE_MAX ? modes[current_mode]->get_shape_override() : current_shape; } @@ -499,6 +511,8 @@ void ColorPicker::set_picker_shape(PickerShapeType p_shape) { ERR_FAIL_INDEX(p_shape, SHAPE_MAX); current_shape = p_shape; + _copy_color_to_hsv(); + _update_controls(); _update_color(); } @@ -640,8 +654,7 @@ void ColorPicker::_sample_input(const Ref<InputEvent> &p_event) { const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95)); if (rect_old.has_point(mb->get_position())) { // Revert to the old color when left-clicking the old color sample. - color = old_color; - _update_color(); + set_pick_color(old_color); emit_signal(SNAME("color_changed"), color); } } @@ -887,17 +900,14 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { v = 1.0 - (y - c->get_position().y - corner_y) / real_size.y; } } + changing_color = true; - if (current_picker == SHAPE_OKHSL_CIRCLE) { - color.set_ok_hsl(h, s, v, color.a); - } else { - color.set_hsv(h, s, v, color.a); - } + _copy_hsv_to_color(); last_color = color; - set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } @@ -940,14 +950,12 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { v = 1.0 - (y - corner_y) / real_size.y; } } - if (current_picker != SHAPE_OKHSL_CIRCLE) { - color.set_hsv(h, s, v, color.a); - } else { - color.set_ok_hsl(h, s, v, color.a); - } + + _copy_hsv_to_color(); last_color = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } @@ -970,14 +978,12 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { } else { changing_color = false; } - if (actual_shape != SHAPE_OKHSL_CIRCLE) { - color.set_hsv(h, s, v, color.a); - } else { - color.set_ok_hsl(h, s, v, color.a); - } + + _copy_hsv_to_color(); last_color = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } else if (!bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { @@ -998,15 +1004,11 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { h = y / w_edit->get_size().height; } - if (actual_shape == SHAPE_OKHSL_CIRCLE) { - color.set_ok_hsl(h, s, v, color.a); - } else { - color.set_hsv(h, s, v, color.a); - } - + _copy_hsv_to_color(); last_color = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } @@ -1019,7 +1021,6 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_c if (bev.is_valid()) { if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { set_pick_color(p_color); - _update_color(); emit_signal(SNAME("color_changed"), p_color); } else if (bev->is_pressed() && bev->get_button_index() == MouseButton::RIGHT && presets_enabled) { erase_preset(p_color); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 8e65ee1861..05b760b109 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -156,6 +156,9 @@ private: float v = 0.0; Color last_color; + void _copy_color_to_hsv(); + void _copy_hsv_to_color(); + PickerShapeType _get_actual_shape() const; void create_slider(GridContainer *gc, int idx); void _reset_theme(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index f51031765c..42f434f0ac 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -710,6 +710,9 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { int type = gn->get_connection_output_type(j); if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_output_hotzone(gn, j, mpos, port_size)) { + if (!is_node_hover_valid(gn->get_name(), j, connecting_from, connecting_index)) { + continue; + } connecting_target = true; connecting_to = pos; connecting_target_to = gn->get_name(); @@ -725,6 +728,9 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { int type = gn->get_connection_input_type(j); if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_input_hotzone(gn, j, mpos, port_size)) { + if (!is_node_hover_valid(connecting_from, connecting_index, gn->get_name(), j)) { + continue; + } connecting_target = true; connecting_to = pos; connecting_target_to = gn->get_name(); @@ -1453,6 +1459,14 @@ void GraphEdit::force_connection_drag_end() { emit_signal(SNAME("connection_drag_ended")); } +bool GraphEdit::is_node_hover_valid(const StringName &p_from, const int p_from_port, const StringName &p_to, const int p_to_port) { + bool valid; + if (GDVIRTUAL_CALL(_is_node_hover_valid, p_from, p_from_port, p_to, p_to_port, valid)) { + return valid; + } + return true; +} + void GraphEdit::set_panning_scheme(PanningScheme p_scheme) { panning_scheme = p_scheme; panner->set_control_scheme((ViewPanner::ControlScheme)p_scheme); @@ -2315,6 +2329,7 @@ void GraphEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_selected", "node"), &GraphEdit::set_selected); GDVIRTUAL_BIND(_get_connection_line, "from", "to") + GDVIRTUAL_BIND(_is_node_hover_valid, "from", "from_slot", "to", "to_slot"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "right_disconnects"), "set_right_disconnects", "is_right_disconnects_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scroll_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_scroll_ofs", "get_scroll_ofs"); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index beb17ec4cf..cf35aeb8b2 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -280,6 +280,7 @@ protected: GDVIRTUAL2RC(Vector<Vector2>, _get_connection_line, Vector2, Vector2) GDVIRTUAL3R(bool, _is_in_input_hotzone, Object *, int, Vector2) GDVIRTUAL3R(bool, _is_in_output_hotzone, Object *, int, Vector2) + GDVIRTUAL4R(bool, _is_node_hover_valid, StringName, int, StringName, int); public: Error connect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); @@ -287,6 +288,7 @@ public: void disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); void clear_connections(); void force_connection_drag_end(); + virtual bool is_node_hover_valid(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); void set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 19545167c8..69b30b72b0 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1563,33 +1563,35 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const { return -1; } -void Animation::track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition) { - ERR_FAIL_INDEX(p_track, tracks.size()); +int Animation::track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition) { + ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; + int ret = -1; + switch (t->type) { case TYPE_POSITION_3D: { - ERR_FAIL_COND((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I)); - int idx = position_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I), -1); + ret = position_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_ROTATION_3D: { - ERR_FAIL_COND((p_key.get_type() != Variant::QUATERNION) && (p_key.get_type() != Variant::BASIS)); - int idx = rotation_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::QUATERNION) && (p_key.get_type() != Variant::BASIS), -1); + ret = rotation_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_SCALE_3D: { - ERR_FAIL_COND((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I)); - int idx = scale_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I), -1); + ret = scale_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_BLEND_SHAPE: { - ERR_FAIL_COND((p_key.get_type() != Variant::FLOAT) && (p_key.get_type() != Variant::INT)); - int idx = blend_shape_track_insert_key(p_track, p_time, p_key); - track_set_key_transition(p_track, idx, p_transition); + ERR_FAIL_COND_V((p_key.get_type() != Variant::FLOAT) && (p_key.get_type() != Variant::INT), -1); + ret = blend_shape_track_insert_key(p_track, p_time, p_key); + track_set_key_transition(p_track, ret, p_transition); } break; case TYPE_VALUE: { @@ -1599,17 +1601,17 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.time = p_time; k.transition = p_transition; k.value = p_key; - _insert(p_time, vt->values, k); + ret = _insert(p_time, vt->values, k); } break; case TYPE_METHOD: { MethodTrack *mt = static_cast<MethodTrack *>(t); - ERR_FAIL_COND(p_key.get_type() != Variant::DICTIONARY); + ERR_FAIL_COND_V(p_key.get_type() != Variant::DICTIONARY, -1); Dictionary d = p_key; - ERR_FAIL_COND(!d.has("method") || (d["method"].get_type() != Variant::STRING_NAME && d["method"].get_type() != Variant::STRING)); - ERR_FAIL_COND(!d.has("args") || !d["args"].is_array()); + ERR_FAIL_COND_V(!d.has("method") || (d["method"].get_type() != Variant::STRING_NAME && d["method"].get_type() != Variant::STRING), -1); + ERR_FAIL_COND_V(!d.has("args") || !d["args"].is_array(), -1); MethodKey k; @@ -1618,14 +1620,14 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.method = d["method"]; k.params = d["args"]; - _insert(p_time, mt->methods, k); + ret = _insert(p_time, mt->methods, k); } break; case TYPE_BEZIER: { BezierTrack *bt = static_cast<BezierTrack *>(t); Array arr = p_key; - ERR_FAIL_COND(arr.size() != 6); + ERR_FAIL_COND_V(arr.size() != 6, -1); TKey<BezierKey> k; k.time = p_time; @@ -1635,23 +1637,23 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.value.out_handle.x = arr[3]; k.value.out_handle.y = arr[4]; k.value.handle_mode = static_cast<HandleMode>((int)arr[5]); - _insert(p_time, bt->values, k); + ret = _insert(p_time, bt->values, k); } break; case TYPE_AUDIO: { AudioTrack *at = static_cast<AudioTrack *>(t); Dictionary k = p_key; - ERR_FAIL_COND(!k.has("start_offset")); - ERR_FAIL_COND(!k.has("end_offset")); - ERR_FAIL_COND(!k.has("stream")); + ERR_FAIL_COND_V(!k.has("start_offset"), -1); + ERR_FAIL_COND_V(!k.has("end_offset"), -1); + ERR_FAIL_COND_V(!k.has("stream"), -1); TKey<AudioKey> ak; ak.time = p_time; ak.value.start_offset = k["start_offset"]; ak.value.end_offset = k["end_offset"]; ak.value.stream = k["stream"]; - _insert(p_time, at->values, ak); + ret = _insert(p_time, at->values, ak); } break; case TYPE_ANIMATION: { @@ -1661,12 +1663,14 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke ak.time = p_time; ak.value = p_key; - _insert(p_time, at->values, ak); + ret = _insert(p_time, at->values, ak); } break; } emit_changed(); + + return ret; } int Animation::track_get_key_count(int p_track) const { diff --git a/scene/resources/animation.h b/scene/resources/animation.h index abbcaa92bc..bf9f786a0d 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -392,7 +392,7 @@ public: void track_set_enabled(int p_track, bool p_enabled); bool track_is_enabled(int p_track) const; - void track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1); + int track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1); void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition); void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value); void track_set_key_time(int p_track, int p_key_idx, double p_time); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index a8d4903dad..95b0f9e6c0 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1249,8 +1249,8 @@ void Environment::_bind_methods() { ADD_GROUP("SSR", "ssr_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssr_enabled"), "set_ssr_enabled", "is_ssr_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ssr_max_steps", PROPERTY_HINT_RANGE, "1,512,1"), "set_ssr_max_steps", "get_ssr_max_steps"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_in", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_in", "get_ssr_fade_in"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_out", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_out", "get_ssr_fade_out"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_in", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssr_fade_in", "get_ssr_fade_in"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_fade_out", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssr_fade_out", "get_ssr_fade_out"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssr_depth_tolerance", PROPERTY_HINT_RANGE, "0.01,128,0.1"), "set_ssr_depth_tolerance", "get_ssr_depth_tolerance"); // SSAO @@ -1277,7 +1277,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssao_enabled"), "set_ssao_enabled", "is_ssao_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_radius", PROPERTY_HINT_RANGE, "0.01,16,0.01,or_greater"), "set_ssao_radius", "get_ssao_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_intensity", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_ssao_intensity", "get_ssao_intensity"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_power", PROPERTY_HINT_EXP_EASING), "set_ssao_power", "get_ssao_power"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_power", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_ssao_power", "get_ssao_power"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_detail", PROPERTY_HINT_RANGE, "0,5,0.01"), "set_ssao_detail", "get_ssao_detail"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_horizon", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssao_horizon", "get_ssao_horizon"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_sharpness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ssao_sharpness", "get_ssao_sharpness"); @@ -1462,7 +1462,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_gi_inject", PROPERTY_HINT_RANGE, "0.0,16,0.01,exp"), "set_volumetric_fog_gi_inject", "get_volumetric_fog_gi_inject"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_anisotropy", PROPERTY_HINT_RANGE, "-0.9,0.9,0.01"), "set_volumetric_fog_anisotropy", "get_volumetric_fog_anisotropy"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_ambient_inject", PROPERTY_HINT_RANGE, "0.0,16,0.01,exp"), "set_volumetric_fog_ambient_inject", "get_volumetric_fog_ambient_inject"); ADD_SUBGROUP("Temporal Reprojection", "volumetric_fog_temporal_reprojection_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_temporal_reprojection_enabled"), "set_volumetric_fog_temporal_reprojection_enabled", "is_volumetric_fog_temporal_reprojection_enabled"); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index b71fe8904a..385d815230 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -175,10 +175,10 @@ private: // Fog bool fog_enabled = false; - Color fog_light_color = Color(0.5, 0.6, 0.7); + Color fog_light_color = Color(0.518, 0.553, 0.608); float fog_light_energy = 1.0; float fog_sun_scatter = 0.0; - float fog_density = 0.001; + float fog_density = 0.01; float fog_height = 0.0; float fog_height_density = 0.0; //can be negative to invert effect float fog_aerial_perspective = 0.0; @@ -194,8 +194,8 @@ private: float volumetric_fog_anisotropy = 0.2; float volumetric_fog_length = 64.0; float volumetric_fog_detail_spread = 2.0; - float volumetric_fog_gi_inject = 0.0; - float volumetric_fog_ambient_inject = false; + float volumetric_fog_gi_inject = 1.0; + float volumetric_fog_ambient_inject = 0.0; bool volumetric_fog_temporal_reproject = true; float volumetric_fog_temporal_reproject_amount = 0.9; void _update_volumetric_fog(); diff --git a/scene/resources/label_settings.h b/scene/resources/label_settings.h index d2644a7484..062d499d50 100644 --- a/scene/resources/label_settings.h +++ b/scene/resources/label_settings.h @@ -39,17 +39,17 @@ class LabelSettings : public Resource { GDCLASS(LabelSettings, Resource); - real_t line_spacing = 0; + real_t line_spacing = 3; Ref<Font> font; int font_size = Font::DEFAULT_FONT_SIZE; - Color font_color = Color(0.875, 0.875, 0.875); + Color font_color = Color(1, 1, 1); int outline_size = 0; Color outline_color = Color(1, 1, 1); - int shadow_size = 0; - Color shadow_color = Color(1, 1, 1); + int shadow_size = 1; + Color shadow_color = Color(0, 0, 0, 0); Vector2 shadow_offset = Vector2(1, 1); void _font_changed(); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index f07232a3ad..1d7e6f6470 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -1793,12 +1793,21 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) { } flags[p_flag] = p_enabled; - if (p_flag == FLAG_USE_SHADOW_TO_OPACITY || p_flag == FLAG_USE_TEXTURE_REPEAT || p_flag == FLAG_SUBSURFACE_MODE_SKIN || p_flag == FLAG_USE_POINT_SIZE) { + + if ( + p_flag == FLAG_USE_SHADOW_TO_OPACITY || + p_flag == FLAG_USE_TEXTURE_REPEAT || + p_flag == FLAG_SUBSURFACE_MODE_SKIN || + p_flag == FLAG_USE_POINT_SIZE || + p_flag == FLAG_UV1_USE_TRIPLANAR || + p_flag == FLAG_UV2_USE_TRIPLANAR) { notify_property_list_changed(); } + if (p_flag == FLAG_PARTICLE_TRAILS_MODE) { update_configuration_warning(); } + _queue_shader_change(); } @@ -1924,6 +1933,14 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { property.usage = PROPERTY_USAGE_NO_EDITOR; } + if ((property.name == "uv1_triplanar_sharpness" || property.name == "uv1_world_triplanar") && !flags[FLAG_UV1_USE_TRIPLANAR]) { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } + + if ((property.name == "uv2_triplanar_sharpness" || property.name == "uv2_world_triplanar") && !flags[FLAG_UV2_USE_TRIPLANAR]) { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } + // you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash const bool can_select_aa = (transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH); // alpha anti aliasiasing is only enabled when you can select aa @@ -2637,7 +2654,7 @@ void BaseMaterial3D::_bind_methods() { ADD_GROUP("Transparency", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth Pre-Pass"), "set_transparency", "get_transparency"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale"); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge"); @@ -2684,7 +2701,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_EMISSION); - ADD_GROUP("NormalMap", "normal_"); + ADD_GROUP("Normal Map", "normal_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_NORMAL); @@ -2724,7 +2741,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "heightmap_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_HEIGHTMAP); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "heightmap_flip_texture"), "set_flag", "get_flag", FLAG_INVERT_HEIGHTMAP); - ADD_GROUP("Subsurf Scatter", "subsurf_scatter_"); + ADD_GROUP("Subsurface Scattering", "subsurf_scatter_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURFACE_SCATTERING); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_skin_mode"), "set_flag", "get_flag", FLAG_SUBSURFACE_MODE_SKIN); @@ -2969,7 +2986,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) : set_transparency(TRANSPARENCY_DISABLED); set_alpha_antialiasing(ALPHA_ANTIALIASING_OFF); - set_alpha_scissor_threshold(0.05); + set_alpha_scissor_threshold(0.5); set_alpha_hash_scale(1.0); set_alpha_antialiasing_edge(0.3); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 7a49b9b515..4b2fdbed5b 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -98,6 +98,17 @@ void ParticlesMaterial::init_shaders() { shader_names->emission_ring_radius = "emission_ring_radius"; shader_names->emission_ring_inner_radius = "emission_ring_inner_radius"; + shader_names->turbulence_active = "turbulence_active"; + shader_names->turbulence_noise_strength = "turbulence_noise_strength"; + shader_names->turbulence_noise_scale = "turbulence_noise_scale"; + shader_names->turbulence_noise_speed = "turbulence_noise_speed"; + shader_names->turbulence_noise_speed_random = "turbulence_noise_speed_random"; + shader_names->turbulence_influence_over_life = "turbulence_influence_over_life"; + shader_names->turbulence_influence_min = "turbulence_influence_min"; + shader_names->turbulence_influence_max = "turbulence_influence_max"; + shader_names->turbulence_initial_displacement_min = "turbulence_initial_displacement_min"; + shader_names->turbulence_initial_displacement_max = "turbulence_initial_displacement_max"; + shader_names->gravity = "gravity"; shader_names->lifetime_randomness = "lifetime_randomness"; @@ -141,7 +152,6 @@ void ParticlesMaterial::_update_shader() { shader_map[mk].users++; return; } - //must create a shader! // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). @@ -282,6 +292,77 @@ void ParticlesMaterial::_update_shader() { code += "uniform float collision_bounce;\n"; } + if (turbulence_active) { + code += "uniform float turbulence_noise_strength;\n"; + code += "uniform float turbulence_noise_scale;\n"; + code += "uniform float turbulence_influence_min;\n"; + code += "uniform float turbulence_influence_max;\n"; + code += "uniform float turbulence_initial_displacement_min;\n"; + code += "uniform float turbulence_initial_displacement_max;\n"; + code += "uniform float turbulence_noise_speed_random;\n"; + code += "uniform vec3 turbulence_noise_speed = vec3(1.0, 1.0, 1.0);\n"; + if (tex_parameters[PARAM_TURB_INFLUENCE_OVER_LIFE].is_valid()) { + code += "uniform sampler2D turbulence_influence_over_life;\n"; + } + if (turbulence_color_ramp.is_valid()) { + code += "uniform sampler2D turbulence_color_ramp;\n"; + } + code += "\n"; + + //functions for 3D noise / turbulence + code += "\n\n"; + code += "// 3D Noise with friendly permission by Inigo Quilez\n"; + code += "vec3 hash_noise( vec3 p ) {\n"; + code += " p *= mat3(vec3(127.1, 311.7, -53.7), vec3(269.5, 183.3, 77.1), vec3(-301.7, 27.3, 215.3));\n"; + code += " return 2.0 * fract(fract(p)*4375.55) -1.;\n"; + code += "}\n"; + code += "\n"; + code += "float noise( vec3 p) {\n"; + code += " vec3 i = floor(p);;\n"; + code += " vec3 f = fract(p);\n "; + code += " vec3 u = f * f * (3.0 - 2.0 * f);\n"; + code += "\n"; + code += " return 2.0*mix( mix( mix( dot( hash_noise( i + vec3(0.0,0.0,0.0) ), f - vec3(0.0,0.0,0.0) ), dot( hash_noise( i + vec3(1.0,0.0,0.0) ), f - vec3(1.0,0.0,0.0) ), u.x),\n"; + code += " mix( dot( hash_noise( i + vec3(0.0,1.0,0.0) ), f - vec3(0.0,1.0,0.0) ), dot( hash_noise( i + vec3(1.0,1.0,0.0) ), f - vec3(1.0,1.0,0.0) ), u.x), u.y),\n"; + code += " mix( mix( dot( hash_noise( i + vec3(0.0,0.0,1.0) ), f - vec3(0.0,0.0,1.0) ), dot( hash_noise( i + vec3(1.0,0.0,1.0) ), f - vec3(1.0,0.0,1.0) ), u.x),\n"; + code += " mix( dot( hash_noise( i + vec3(0.0,1.0,1.0) ), f - vec3(0.0,1.0,1.0) ), dot( hash_noise( i + vec3(1.0,1.0,1.0) ), f - vec3(1.0,1.0,1.0) ), u.x), u.y), u.z);\n"; + code += "}\n\n"; + code += "// Curl 3D and noise_3d function with friendly permission by Isaac Cohen\n"; + code += "vec3 noise_3d(vec3 p) {\n"; + code += " float s = noise(p);\n"; + code += " float s1 = noise(vec3(p.y - 19.1, p.z + 33.4, p.x + 47.2));\n"; + code += " float s2 = noise(vec3(p.z + 74.2, p.x - 124.5, p.y + 99.4));\n"; + code += " vec3 c = vec3(s, s1, s2);\n"; + code += " return c;\n"; + code += "}\n\n"; + code += "vec3 curl_3d(vec3 p, float c) {\n"; + code += " float epsilon = 0.001 + c;\n"; + code += " vec3 dx = vec3(epsilon, 0.0, 0.0);\n"; + code += " vec3 dy = vec3(0.0, epsilon, 0.0);\n"; + code += " vec3 dz = vec3(0.0, 0.0, epsilon);\n"; + code += " vec3 x0 = noise_3d(p - dx).xyz;\n"; + code += " vec3 x1 = noise_3d(p + dx).xyz;\n"; + code += " vec3 y0 = noise_3d(p - dy).xyz;\n"; + code += " vec3 y1 = noise_3d(p + dy).xyz;\n"; + code += " vec3 z0 = noise_3d(p - dz).xyz;\n"; + code += " vec3 z1 = noise_3d(p + dz).xyz;\n"; + code += " float x = y1.z - y0.z - z1.y + z0.y;\n"; + code += " float y = z1.x - z0.x - x1.z + x0.z;\n"; + code += " float z = x1.y - x0.y - y1.x + y0.x;\n"; + code += " float divisor = 1.0 / (2.0 * epsilon);\n"; + code += " return vec3(normalize(vec3(x, y, z) * divisor));\n"; + code += "}\n"; + code += "vec3 get_noise_direction(vec3 pos, vec3 emission_pos, vec3 time_noise) {\n"; + code += " float adj_contrast = max((turbulence_noise_strength - 1.0), 0.0) * 70.0;\n"; + code += " vec3 noise_time = (vec3(TIME) * turbulence_noise_speed) + time_noise;\n"; + code += " vec3 noise_pos = (pos * turbulence_noise_scale) - emission_pos;\n"; + code += " vec3 diff = pos - emission_pos;\n"; + code += " vec3 noise_direction = curl_3d(noise_pos + noise_time - diff, adj_contrast);\n"; + code += " noise_direction = mix(0.9 * noise_direction, noise_direction, turbulence_noise_strength - 9.0);\n"; + code += " return noise_direction;\n"; + code += "}\n"; + } + //need a random function code += "\n\n"; code += "float rand_from_seed(inout uint seed) {\n"; @@ -463,8 +544,18 @@ void ParticlesMaterial::_update_shader() { break; } } - code += " if (RESTART_VELOCITY) VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; + // Apply noise/turbulence: initial displacement. + if (turbulence_active) { + if (get_turbulence_noise_speed_random() >= 0.0) { + code += " vec3 time_noise = noise_3d( vec3(TIME) * turbulence_noise_speed_random ) * -turbulence_noise_speed;\n"; + } else { + code += " const vec3 time_noise = vec3(0.0);\n"; + } + code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n"; + code += " float turb_init_displacement = mix(turbulence_initial_displacement_min, turbulence_initial_displacement_max, rand_from_seed(alt_seed));"; + code += " TRANSFORM[3].xyz += noise_direction * turb_init_displacement;\n"; + } code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { code += " VELOCITY.z = 0.0;\n"; @@ -483,7 +574,6 @@ void ParticlesMaterial::_update_shader() { if (color_initial_ramp.is_valid()) { code += " float color_initial_rand = rand_from_seed(alt_seed);\n"; } - code += " float pi = 3.14159;\n"; code += " float degree_to_rad = pi / 180.0;\n"; code += "\n"; @@ -570,7 +660,7 @@ void ParticlesMaterial::_update_shader() { code += " vec3 diff = pos - org;\n"; code += " force += length(diff) > 0.0 ? normalize(diff) * tex_radial_accel * mix(radial_accel_min, radial_accel_max, rand_from_seed(alt_seed)) : vec3(0.0);\n"; code += " // apply tangential acceleration;\n"; - code += " float tangent_accel_val = tex_tangent_accel * mix(tangent_accel_min, tangent_accel_max, rand_from_seed(alt_seed))\n;"; + code += " float tangent_accel_val = tex_tangent_accel * mix(tangent_accel_min, tangent_accel_max, rand_from_seed(alt_seed));\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0, 1.0)), 0.0) * tangent_accel_val : vec3(0.0);\n"; @@ -584,6 +674,41 @@ void ParticlesMaterial::_update_shader() { code += " // apply attractor forces\n"; code += " VELOCITY += force * DELTA;\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + code += " VELOCITY = normalize(VELOCITY) * tex_linear_velocity;\n"; + } + + // Apply noise/turbulence. + if (turbulence_active) { + code += " // apply turbulence\n"; + if (tex_parameters[PARAM_TURB_INFLUENCE_OVER_LIFE].is_valid()) { + code += " float turbulence_influence = textureLod(turbulence_influence_over_life, vec2(tv, 0.0), 0.0).r;\n"; + } else { + code += " const float turbulence_influence = 1.0;\n"; + } + code += " \n"; + if (get_turbulence_noise_speed_random() >= 0.0) { + code += " vec3 time_noise = noise_3d( vec3(TIME) * turbulence_noise_speed_random ) * -turbulence_noise_speed;\n"; + } else { + code += " const vec3 time_noise = vec3(0.0);\n"; + } + code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n"; + // If collision happened, turbulence is no longer applied. + String extra_tab = ""; + if (collision_enabled) { + code += " if (!COLLIDED) {\n"; + extra_tab = " "; + } + code += extra_tab + " \n"; + code += extra_tab + " float vel_mag = length(VELOCITY);\n"; + code += extra_tab + " float vel_infl = clamp(mix(turbulence_influence_min, turbulence_influence_max, rand_from_seed(alt_seed)) * turbulence_influence, 0.0, 1.0);\n"; + code += extra_tab + " VELOCITY = mix(VELOCITY, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; + if (collision_enabled) { + code += " }"; + } + } + code += " \n"; code += " // orbit velocity\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { code += " float orbit_amount = tex_orbit_velocity * mix(orbit_velocity_min, orbit_velocity_max, rand_from_seed(alt_seed));\n"; @@ -595,9 +720,6 @@ void ParticlesMaterial::_update_shader() { code += " }\n"; } - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - code += " VELOCITY = normalize(VELOCITY) * tex_linear_velocity;\n"; - } code += " float dmp = mix(damping_min, damping_max, rand_from_seed(alt_seed));\n"; code += " if (dmp * tex_damping > 0.0) {\n"; code += " float v = length(VELOCITY);\n"; @@ -701,24 +823,34 @@ void ParticlesMaterial::_update_shader() { code += " TRANSFORM[3] = origin;\n"; } } - //scale by scale - code += " float base_scale = mix(scale_min, scale_max, scale_rand);\n"; - code += " base_scale = sign(base_scale) * max(abs(base_scale), 0.001);\n"; - code += " TRANSFORM[0].xyz *= base_scale * sign(tex_scale.r) * max(abs(tex_scale.r), 0.001);\n"; - code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n"; - code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n"; if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { - code += " VELOCITY.z = 0.0;\n"; code += " TRANSFORM[3].z = 0.0;\n"; } + if (collision_enabled) { code += " if (COLLIDED) {\n"; - code += " TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;\n"; - code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n"; - code += " VELOCITY = mix(VELOCITY,vec3(0.0),collision_friction * DELTA * 100.0);\n"; + code += " if (length(VELOCITY) > 3.0) {\n"; + code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n"; + code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n"; + code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n"; + code += " } else {\n"; + code += " VELOCITY = vec3(0.0);\n"; + // If turbulence is enabled, set the noise direction to up so the turbulence color is "neutral" + if (turbulence_active) { + code += " noise_direction = vec3(1.0, 0.0, 0.0);\n"; + } + code += " }\n"; code += " }\n"; } + + // scale by scale + code += " float base_scale = mix(scale_min, scale_max, scale_rand);\n"; + code += " base_scale = sign(base_scale) * max(abs(base_scale), 0.001);\n"; + code += " TRANSFORM[0].xyz *= base_scale * sign(tex_scale.r) * max(abs(tex_scale.r), 0.001);\n"; + code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n"; + code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n"; + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { code += " int emit_count = 0;\n"; switch (sub_emitter_mode) { @@ -856,6 +988,15 @@ void ParticlesMaterial::set_param_min(Parameter p_param, float p_value) { case PARAM_ANIM_OFFSET: { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_min, p_value); } break; + case PARAM_TURB_VEL_INFLUENCE: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_min, p_value); + } break; + case PARAM_TURB_INIT_DISPLACEMENT: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_initial_displacement_min, p_value); + } break; + case PARAM_TURB_INFLUENCE_OVER_LIFE: { + // Can't happen, but silences warning + } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -912,6 +1053,15 @@ void ParticlesMaterial::set_param_max(Parameter p_param, float p_value) { case PARAM_ANIM_OFFSET: { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_max, p_value); } break; + case PARAM_TURB_VEL_INFLUENCE: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_max, p_value); + } break; + case PARAM_TURB_INIT_DISPLACEMENT: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_initial_displacement_max, p_value); + } break; + case PARAM_TURB_INFLUENCE_OVER_LIFE: { + // Can't happen, but silences warning + } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -986,6 +1136,16 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D case PARAM_ANIM_OFFSET: { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, tex_rid); } break; + case PARAM_TURB_INFLUENCE_OVER_LIFE: { + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_influence_over_life, tex_rid); + _adjust_curve_range(p_texture, 0, 1); + } break; + case PARAM_TURB_VEL_INFLUENCE: { + // Can't happen, but silences warning + } break; + case PARAM_TURB_INIT_DISPLACEMENT: { + // Can't happen, but silences warning + } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -1151,6 +1311,54 @@ real_t ParticlesMaterial::get_emission_ring_inner_radius() const { return emission_ring_inner_radius; } +void ParticlesMaterial::set_turbulence_active(const bool p_turbulence_active) { + turbulence_active = p_turbulence_active; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_active, turbulence_active); + _queue_shader_change(); + notify_property_list_changed(); +} + +bool ParticlesMaterial::get_turbulence_active() const { + return turbulence_active; +} + +void ParticlesMaterial::set_turbulence_noise_strength(float p_turbulence_noise_strength) { + turbulence_noise_strength = p_turbulence_noise_strength; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_strength, p_turbulence_noise_strength); +} + +float ParticlesMaterial::get_turbulence_noise_strength() const { + return turbulence_noise_strength; +} + +void ParticlesMaterial::set_turbulence_noise_scale(float p_turbulence_noise_scale) { + turbulence_noise_scale = p_turbulence_noise_scale; + float shader_turbulence_noise_scale = (pow(p_turbulence_noise_scale, 0.25) * 5.6234 / 10.0) * 4.0 - 3.0; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_scale, shader_turbulence_noise_scale); +} + +float ParticlesMaterial::get_turbulence_noise_scale() const { + return turbulence_noise_scale; +} + +void ParticlesMaterial::set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random) { + turbulence_noise_speed_random = p_turbulence_noise_speed_random; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed_random, p_turbulence_noise_speed_random); +} + +float ParticlesMaterial::get_turbulence_noise_speed_random() const { + return turbulence_noise_speed_random; +} + +void ParticlesMaterial::set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed) { + turbulence_noise_speed = p_turbulence_noise_speed; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed, turbulence_noise_speed); +} + +Vector3 ParticlesMaterial::get_turbulence_noise_speed() const { + return turbulence_noise_speed; +} + void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { gravity = p_gravity; Vector3 gset = gravity; @@ -1214,6 +1422,20 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const { if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) { property.usage = PROPERTY_USAGE_NONE; } + + if (!turbulence_active) { + if (property.name == "turbulence_noise_strength" || + property.name == "turbulence_noise_scale" || + property.name == "turbulence_noise_speed" || + property.name == "turbulence_noise_speed_random" || + property.name == "turbulence_influence_over_life" || + property.name == "turbulence_influence_min" || + property.name == "turbulence_influence_max" || + property.name == "turbulence_initial_displacement_min" || + property.name == "turbulence_initial_displacement_max") { + property.usage = PROPERTY_USAGE_NONE; + } + } } void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { @@ -1365,6 +1587,21 @@ void ParticlesMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticlesMaterial::set_emission_ring_inner_radius); ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticlesMaterial::get_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("get_turbulence_active"), &ParticlesMaterial::get_turbulence_active); + ClassDB::bind_method(D_METHOD("set_turbulence_active", "turbulence_active"), &ParticlesMaterial::set_turbulence_active); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_strength"), &ParticlesMaterial::get_turbulence_noise_strength); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_strength", "turbulence_noise_strength"), &ParticlesMaterial::set_turbulence_noise_strength); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_scale"), &ParticlesMaterial::get_turbulence_noise_scale); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_scale", "turbulence_noise_scale"), &ParticlesMaterial::set_turbulence_noise_scale); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed_random"), &ParticlesMaterial::get_turbulence_noise_speed_random); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed_random", "turbulence_noise_speed_random"), &ParticlesMaterial::set_turbulence_noise_speed_random); + + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed"), &ParticlesMaterial::get_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed", "turbulence_noise_speed"), &ParticlesMaterial::set_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); @@ -1467,6 +1704,19 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_min", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_min", "get_param_min", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_max", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param_max", "get_param_max", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); + + ADD_GROUP("Turbulence", "turbulence_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "turbulence_active"), "set_turbulence_active", "get_turbulence_active"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_strength", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_turbulence_noise_strength", "get_turbulence_noise_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_scale", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_turbulence_noise_scale", "get_turbulence_noise_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "turbulence_noise_speed"), "set_turbulence_noise_speed", "get_turbulence_noise_speed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbulence_noise_speed_random", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_turbulence_noise_speed_random", "get_turbulence_noise_speed_random"); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_influence_min", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_min", "get_param_min", PARAM_TURB_VEL_INFLUENCE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_influence_max", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_max", "get_param_max", PARAM_TURB_VEL_INFLUENCE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_initial_displacement_min", PROPERTY_HINT_RANGE, "-100,100,0.1"), "set_param_min", "get_param_min", PARAM_TURB_INIT_DISPLACEMENT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "turbulence_initial_displacement_max", PROPERTY_HINT_RANGE, "-100,100,0.1"), "set_param_max", "get_param_max", PARAM_TURB_INIT_DISPLACEMENT); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "turbulence_influence_over_life", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TURB_INFLUENCE_OVER_LIFE); + ADD_GROUP("Animation", "anim_"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_min", PROPERTY_HINT_RANGE, "0,16,0.01,or_lesser,or_greater"), "set_param_min", "get_param_min", PARAM_ANIM_SPEED); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_max", PROPERTY_HINT_RANGE, "0,16,0.01,or_lesser,or_greater"), "set_param_max", "get_param_max", PARAM_ANIM_SPEED); @@ -1517,6 +1767,10 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); + BIND_ENUM_CONSTANT(PARAM_TURB_VEL_INFLUENCE); + BIND_ENUM_CONSTANT(PARAM_TURB_INIT_DISPLACEMENT); + BIND_ENUM_CONSTANT(PARAM_TURB_INFLUENCE_OVER_LIFE); + BIND_ENUM_CONSTANT(SUB_EMITTER_DISABLED); BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT); BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END); @@ -1560,6 +1814,17 @@ ParticlesMaterial::ParticlesMaterial() : set_emission_ring_height(1); set_emission_ring_radius(1); set_emission_ring_inner_radius(0); + + set_turbulence_active(false); + set_turbulence_noise_speed(Vector3(0.5, 0.5, 0.5)); + set_turbulence_noise_strength(1); + set_turbulence_noise_scale(9); + set_turbulence_noise_speed_random(0); + set_param_min(PARAM_TURB_VEL_INFLUENCE, 0.1); + set_param_max(PARAM_TURB_VEL_INFLUENCE, 0.1); + set_param_min(PARAM_TURB_INIT_DISPLACEMENT, 0.0); + set_param_max(PARAM_TURB_INIT_DISPLACEMENT, 0.0); + set_gravity(Vector3(0, -9.8, 0)); set_lifetime_randomness(0); diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index af45593f38..18ab60a431 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -58,6 +58,9 @@ public: PARAM_HUE_VARIATION, PARAM_ANIM_SPEED, PARAM_ANIM_OFFSET, + PARAM_TURB_INFLUENCE_OVER_LIFE, + PARAM_TURB_VEL_INFLUENCE, + PARAM_TURB_INIT_DISPLACEMENT, PARAM_MAX }; @@ -105,9 +108,10 @@ private: uint32_t attractor_enabled : 1; uint32_t collision_enabled : 1; uint32_t collision_scale : 1; + uint32_t turbulence_active : 1; }; - uint32_t key = 0; + uint64_t key = 0; static uint32_t hash(const MaterialKey &p_key) { return hash_murmur3_one_32(p_key.key); @@ -152,6 +156,7 @@ private: mk.collision_enabled = collision_enabled; mk.attractor_enabled = attractor_interaction_enabled; mk.collision_scale = collision_scale; + mk.turbulence_active = turbulence_active; return mk; } @@ -216,6 +221,17 @@ private: StringName emission_ring_radius; StringName emission_ring_inner_radius; + StringName turbulence_active; + StringName turbulence_noise_strength; + StringName turbulence_noise_scale; + StringName turbulence_noise_speed; + StringName turbulence_noise_speed_random; + StringName turbulence_influence_over_life; + StringName turbulence_influence_min; + StringName turbulence_influence_max; + StringName turbulence_initial_displacement_min; + StringName turbulence_initial_displacement_max; + StringName gravity; StringName lifetime_randomness; @@ -243,6 +259,7 @@ private: float params_min[PARAM_MAX]; float params_max[PARAM_MAX]; + float params[PARAM_MAX]; Ref<Texture2D> tex_parameters[PARAM_MAX]; Color color; @@ -265,6 +282,13 @@ private: bool anim_loop = false; + bool turbulence_active; + Vector3 turbulence_noise_speed; + Ref<Texture2D> turbulence_color_ramp; + float turbulence_noise_strength = 0.0f; + float turbulence_noise_scale = 0.0f; + float turbulence_noise_speed_random = 0.0f; + Vector3 gravity; double lifetime_randomness = 0.0; @@ -340,6 +364,18 @@ public: real_t get_emission_ring_inner_radius() const; int get_emission_point_count() const; + void set_turbulence_active(bool p_turbulence_active); + void set_turbulence_noise_strength(float p_turbulence_noise_strength); + void set_turbulence_noise_scale(float p_turbulence_noise_scale); + void set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random); + void set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed); + + bool get_turbulence_active() const; + float get_turbulence_noise_strength() const; + float get_turbulence_noise_scale() const; + float get_turbulence_noise_speed_random() const; + Vector3 get_turbulence_noise_speed() const; + void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index b8667f07fe..5cc2073ca5 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -5581,12 +5581,16 @@ String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_ty case VisualShaderNodeTextureUniform::TYPE_DATA: if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) { type_code = "hint_default_black"; + } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) { + type_code = "hint_default_transparent"; } break; case VisualShaderNodeTextureUniform::TYPE_COLOR: type_code = "source_color"; if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) { type_code += ", hint_default_black"; + } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) { + type_code += ", hint_default_transparent"; } break; case VisualShaderNodeTextureUniform::TYPE_NORMAL_MAP: @@ -5812,7 +5816,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("get_texture_repeat"), &VisualShaderNodeTextureUniform::get_texture_repeat); 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"), "set_color_default", "get_color_default"); + 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"); @@ -5824,6 +5828,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() { BIND_ENUM_CONSTANT(COLOR_DEFAULT_WHITE); BIND_ENUM_CONSTANT(COLOR_DEFAULT_BLACK); + BIND_ENUM_CONSTANT(COLOR_DEFAULT_TRANSPARENT); BIND_ENUM_CONSTANT(COLOR_DEFAULT_MAX); BIND_ENUM_CONSTANT(FILTER_DEFAULT); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 1eb7b7240f..f770156d14 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -2131,6 +2131,7 @@ public: enum ColorDefault { COLOR_DEFAULT_WHITE, COLOR_DEFAULT_BLACK, + COLOR_DEFAULT_TRANSPARENT, COLOR_DEFAULT_MAX, }; diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 1a22597243..f24c0117d1 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -209,7 +209,7 @@ public: virtual ~NavigationServer3D(); #ifdef DEBUG_ENABLED - bool debug_enabled = true; + bool debug_enabled = false; bool debug_dirty = true; void _emit_navigation_debug_changed_signal(); diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index 8dfcd978ac..aab5145982 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -37,17 +37,44 @@ namespace RendererDummy { class MeshStorage : public RendererMeshStorage { +private: + struct DummyMesh : public RID { + Vector<RS::SurfaceData> surfaces; + int blend_shape_count; + RS::BlendShapeMode blend_shape_mode; + PackedFloat32Array blend_shape_values; + }; + + mutable RID_Owner<DummyMesh> mesh_owner; + public: /* MESH API */ - virtual RID mesh_allocate() override { return RID(); } - virtual void mesh_initialize(RID p_rid) override {} + virtual RID mesh_allocate() override { + return mesh_owner.allocate_rid(); + } + + virtual void mesh_initialize(RID p_rid) override { + mesh_owner.initialize_rid(p_rid, DummyMesh()); + } virtual void mesh_free(RID p_rid) override {} virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {} virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; } - virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {} + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override { + DummyMesh *m = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND(!m); + m->surfaces.push_back(RS::SurfaceData()); + RS::SurfaceData *s = &m->surfaces.write[m->surfaces.size() - 1]; + s->format = p_surface.format; + s->primitive = p_surface.primitive; + s->vertex_data = p_surface.vertex_data; + s->attribute_data = p_surface.attribute_data; + s->vertex_count = p_surface.vertex_count; + s->index_data = p_surface.index_data; + s->index_count = p_surface.index_count; + } virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; } @@ -61,8 +88,19 @@ public: virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {} virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); } - virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); } - virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; } + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { + DummyMesh *m = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!m, RS::SurfaceData()); + RS::SurfaceData s = m->surfaces[p_surface]; + return s; + } + + virtual int mesh_get_surface_count(RID p_mesh) const override { + DummyMesh *m = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!m, 0); + print_line(m->surfaces.size()); + return m->surfaces.size(); + } virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {} virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); } diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp index fa0b99fef9..68cfd43d90 100644 --- a/servers/rendering/renderer_rd/effects/vrs.cpp +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -146,10 +146,11 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) { RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target); if (vrs_texture.is_valid()) { - Texture *texture = texture_storage->get_texture(vrs_texture); - if (texture) { + RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture); + int layers = texture_storage->texture_get_layers(vrs_texture); + if (rd_texture.is_valid()) { // Copy into our density buffer - copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1); + copy_vrs(rd_texture, p_vrs_fb, layers > 1); } } } else if (vrs_mode == RS::VIEWPORT_VRS_XR) { @@ -157,10 +158,12 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { if (interface.is_valid()) { RID vrs_texture = interface->get_vrs_texture(); if (vrs_texture.is_valid()) { - Texture *texture = texture_storage->get_texture(vrs_texture); - if (texture) { + RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture); + int layers = texture_storage->texture_get_layers(vrs_texture); + + if (rd_texture.is_valid()) { // Copy into our density buffer - copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1); + copy_vrs(rd_texture, p_vrs_fb, layers > 1); } } } diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index fba04c0db4..a61d1c4d02 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -145,23 +145,23 @@ Fog::FogMaterialData::~FogMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::ShaderData *Fog::_create_fog_shader_func() { +RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() { FogShaderData *shader_data = memnew(FogShaderData); return shader_data; } -RendererRD::ShaderData *Fog::_create_fog_shader_funcs() { +RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() { return Fog::get_singleton()->_create_fog_shader_func(); }; -RendererRD::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererRD::MaterialData *Fog::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); }; @@ -190,8 +190,8 @@ void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_lay volumetric_fog_modes.push_back(""); volumetric_fog.shader.initialize(volumetric_fog_modes); - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs); volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); } @@ -246,7 +246,7 @@ ALBEDO = vec3(1.0); material_storage->material_initialize(volumetric_fog.default_material); material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); - FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG)); + FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -701,7 +701,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P FogMaterialData *material = nullptr; if (fog_material.is_valid()) { - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -709,7 +709,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (!material) { fog_material = volumetric_fog.default_material; - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); } ERR_FAIL_COND(!material); @@ -805,7 +805,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; if (p_settings.shadow_atlas_depth.is_null()) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); } else { u.append_id(p_settings.shadow_atlas_depth); } @@ -821,7 +821,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (p_settings.directional_shadow_depth.is_valid()) { u.append_id(p_settings.directional_shadow_depth); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -986,7 +986,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 19; - RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RID sky_texture = RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env).is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env)) : RID(); u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); uniforms.push_back(u); diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index e777a1d383..7002d6c872 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -180,7 +180,7 @@ private: Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform); - struct FogShaderData : public RendererRD::ShaderData { + struct FogShaderData : public RendererRD::MaterialStorage::ShaderData { bool valid = false; RID version; @@ -212,7 +212,7 @@ private: virtual ~FogShaderData(); }; - struct FogMaterialData : public RendererRD::MaterialData { + struct FogMaterialData : public RendererRD::MaterialStorage::MaterialData { FogShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -223,11 +223,11 @@ private: virtual ~FogMaterialData(); }; - RendererRD::ShaderData *_create_fog_shader_func(); - static RendererRD::ShaderData *_create_fog_shader_funcs(); + RendererRD::MaterialStorage::ShaderData *_create_fog_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_fog_shader_funcs(); - RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); - static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader); + RendererRD::MaterialStorage::MaterialData *_create_fog_material_func(FogShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader); public: static Fog *get_singleton() { return singleton; } diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 7b4f61bd17..feafcc42c9 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -734,7 +734,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -978,7 +978,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -991,7 +991,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1004,7 +1004,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1017,7 +1017,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1498,7 +1498,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1511,7 +1511,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1524,7 +1524,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1537,7 +1537,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1591,34 +1591,24 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection push_constant.max_cascades = cascades.size(); push_constant.screen_size[0] = p_width; push_constant.screen_size[1] = p_height; - push_constant.probe_axis_size = probe_axis_count; - push_constant.use_occlusion = uses_occlusion; push_constant.y_mult = y_mult; push_constant.z_near = -p_projections[v].get_z_near(); - push_constant.cam_transform[0] = p_transform.basis.rows[0][0]; - push_constant.cam_transform[1] = p_transform.basis.rows[1][0]; - push_constant.cam_transform[2] = p_transform.basis.rows[2][0]; - push_constant.cam_transform[3] = 0; - push_constant.cam_transform[4] = p_transform.basis.rows[0][1]; - push_constant.cam_transform[5] = p_transform.basis.rows[1][1]; - push_constant.cam_transform[6] = p_transform.basis.rows[2][1]; - push_constant.cam_transform[7] = 0; - push_constant.cam_transform[8] = p_transform.basis.rows[0][2]; - push_constant.cam_transform[9] = p_transform.basis.rows[1][2]; - push_constant.cam_transform[10] = p_transform.basis.rows[2][2]; - push_constant.cam_transform[11] = 0; - push_constant.cam_transform[12] = p_transform.origin.x; - push_constant.cam_transform[13] = p_transform.origin.y; - push_constant.cam_transform[14] = p_transform.origin.z; - push_constant.cam_transform[15] = 1; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + push_constant.cam_basis[i][j] = p_transform.basis.rows[j][i]; + } + } + push_constant.cam_origin[0] = p_transform.origin[0]; + push_constant.cam_origin[1] = p_transform.origin[1]; + push_constant.cam_origin[2] = p_transform.origin[2]; // need to properly unproject for asymmetric projection matrices in stereo.. Projection inv_projection = p_projections[v].inverse(); for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - push_constant.inv_projection[i * 4 + j] = inv_projection.matrix[i][j]; + for (int j = 0; j < 3; j++) { + push_constant.inv_projection[j][i] = inv_projection.matrix[i][j]; } } @@ -3353,9 +3343,9 @@ void GI::init(SkyRD *p_sky) { u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; if (p_sky->sky_use_cubemap_array) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); } uniforms.push_back(u); } @@ -3550,7 +3540,7 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra } if (texture == RID()) { - texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } if (texture != rb->rbgi.voxel_gi_textures[i]) { @@ -3761,7 +3751,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3774,7 +3764,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3787,7 +3777,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3800,7 +3790,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3812,7 +3802,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, if (rb->sdfgi) { u.append_id(rb->sdfgi->occlusion_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -3854,7 +3844,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, if (rb->sdfgi) { u.append_id(rb->sdfgi->lightprobe_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } @@ -3876,7 +3866,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(buffer); uniforms.push_back(u); } @@ -3914,7 +3904,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 19; - RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_VRS); + RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS); u.append_id(buffer); uniforms.push_back(u); } diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index c9e1a14e2e..304df1605b 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -78,9 +78,9 @@ public: float energy = 1.0; float bias = 1.4; float normal_bias = 0.0; - float propagation = 0.7; + float propagation = 0.5; bool interior = false; - bool use_two_bounces = false; + bool use_two_bounces = true; uint32_t version = 1; uint32_t data_version = 1; @@ -232,16 +232,13 @@ private: uint32_t max_cascades; int32_t screen_size[2]; - uint32_t use_occlusion; float y_mult; - uint32_t probe_axis_size; float z_near; - float reserved1; - float reserved2; - float cam_transform[16]; - float inv_projection[16]; + float inv_projection[3][4]; + float cam_basis[3][3]; + float cam_origin[3]; }; SdfgiDebugShaderRD debug; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 228d2673f2..147658bea9 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -655,7 +655,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { u.append_id(radiance); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } @@ -671,9 +671,9 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -690,9 +690,9 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -789,24 +789,24 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con //////////////////////////////////////////////////////////////////////////////// // SkyRD -RendererRD::ShaderData *SkyRD::_create_sky_shader_func() { +RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() { SkyShaderData *shader_data = memnew(SkyShaderData); return shader_data; } -RendererRD::ShaderData *SkyRD::_create_sky_shader_funcs() { +RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); }; -RendererRD::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererRD::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); }; @@ -855,8 +855,8 @@ void SkyRD::init() { } // register our shader funds - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -937,7 +937,7 @@ void sky() { material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO)); @@ -999,7 +999,7 @@ void sky() { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); u.append_id(vfog); uniforms.push_back(u); } @@ -1033,21 +1033,21 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } @@ -1080,7 +1080,7 @@ SkyRD::~SkyRD() { // cleanup anything created in init... RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); sky_shader.shader.version_free(md->shader_data->version); RD::get_singleton()->free(sky_scene_state.directional_light_buffer); RD::get_singleton()->free(sky_scene_state.uniform_buffer); @@ -1122,7 +1122,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1130,7 +1130,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1330,7 +1330,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D SkyMaterialData *material = nullptr; if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1338,7 +1338,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1506,7 +1506,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1514,13 +1514,13 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1610,7 +1610,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1618,7 +1618,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1698,7 +1698,7 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1706,13 +1706,13 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index 5402705918..c5a2e2c298 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -107,7 +107,7 @@ private: // 128 is the max size of a push constant. We can replace "pad" but we can't add any more. }; - struct SkyShaderData : public RendererRD::ShaderData { + struct SkyShaderData : public RendererRD::MaterialStorage::ShaderData { bool valid = false; RID version; @@ -231,7 +231,7 @@ public: RID default_shader_rd; } sky_shader; - struct SkyMaterialData : public RendererRD::MaterialData { + struct SkyMaterialData : public RendererRD::MaterialStorage::MaterialData { SkyShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -285,11 +285,11 @@ public: mutable RID_Owner<Sky, true> sky_owner; int roughness_layers; - RendererRD::ShaderData *_create_sky_shader_func(); - static RendererRD::ShaderData *_create_sky_shader_funcs(); + RendererRD::MaterialStorage::ShaderData *_create_sky_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_sky_shader_funcs(); - RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); - static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader); + RendererRD::MaterialStorage::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader); SkyRD(); void init(); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 6f200220f0..827cce6047 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -2433,7 +2433,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -2450,7 +2450,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -2464,7 +2464,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); } u.append_id(texture); uniforms.push_back(u); @@ -2476,7 +2476,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH)); } uniforms.push_back(u); } @@ -2485,7 +2485,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); @@ -2503,7 +2503,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) { RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]); @@ -2533,7 +2533,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -2542,7 +2542,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2552,7 +2552,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL); + RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); u.append_id(texture); uniforms.push_back(u); } @@ -2562,7 +2562,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID(); - RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2572,7 +2572,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID(); - RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2582,7 +2582,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 14; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID(); - RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2594,7 +2594,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers); } else { - t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } u.append_id(t); uniforms.push_back(u); @@ -2606,7 +2606,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -2625,10 +2625,10 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers); if (vfog.is_null()) { - vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } } else { - vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(vfog); uniforms.push_back(u); @@ -2638,7 +2638,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 19; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID(); - RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2662,12 +2662,16 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]); + RID instance_buffer = scene_state.instance_buffer[RENDER_LIST_SECONDARY]; + if (instance_buffer == RID()) { + instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used + } + u.append_id(instance_buffer); uniforms.push_back(u); } { // No radiance texture. - RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RD::Uniform u; u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2677,7 +2681,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No reflection atlas. - RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -2690,7 +2694,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -2700,7 +2704,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -2711,7 +2715,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { u.append_id(default_tex); } @@ -2725,7 +2729,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { u.append_id(default_tex); } @@ -2860,7 +2864,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet void *surface_shadow = nullptr; if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); @@ -2921,7 +2925,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain( while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } @@ -2941,7 +2945,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw SceneShaderForwardClustered::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2952,7 +2956,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2963,7 +2967,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); 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 c84a4469ae..0faf2e2463 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 @@ -488,7 +488,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() { } } -RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() { +RendererRD::MaterialStorage::ShaderData *SceneShaderForwardClustered::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -512,7 +512,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -610,8 +610,8 @@ void SceneShaderForwardClustered::init(const String p_defines) { valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS); - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler @@ -817,7 +817,7 @@ void fragment() { material_storage->material_initialize(default_material); material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); @@ -845,7 +845,7 @@ void fragment() { material_storage->material_initialize(overdraw_material); material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index fb001d6933..d4fc70cada 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -93,7 +93,7 @@ public: SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3, }; - struct ShaderData : public RendererRD::ShaderData { + struct ShaderData : public RendererRD::MaterialStorage::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -198,12 +198,12 @@ public: SelfList<ShaderData>::List shader_list; - RendererRD::ShaderData *_create_shader_func(); - static RendererRD::ShaderData *_create_shader_funcs() { + RendererRD::MaterialStorage::ShaderData *_create_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererRD::MaterialData { + struct MaterialData : public RendererRD::MaterialStorage::MaterialData { ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; @@ -216,8 +216,8 @@ public: virtual ~MaterialData(); }; - RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index a179688487..15f810fb3b 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -337,7 +337,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_radiance_texture.is_valid()) { radiance_texture = p_radiance_texture; } else { - radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; u.binding = 2; @@ -354,7 +354,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (ref_texture.is_valid()) { u.append_id(ref_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } @@ -368,7 +368,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { - texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); } u.append_id(texture); uniforms.push_back(u); @@ -380,7 +380,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH)); } uniforms.push_back(u); } @@ -391,7 +391,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); @@ -412,7 +412,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.resize(MAX_VOXEL_GI_INSTANCESS); - RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { if (i < (int)p_voxel_gi_instances.size()) { RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]); @@ -443,7 +443,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH); + RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); uniforms.push_back(u); } @@ -452,7 +452,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); - RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } @@ -2227,7 +2227,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI void *surface_shadow = nullptr; if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; - material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh); @@ -2286,7 +2286,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(Geo while (material->next_pass.is_valid()) { RID next_pass = material->next_pass; - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { break; } @@ -2306,7 +2306,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward SceneShaderForwardMobile::MaterialData *material = nullptr; if (m_src.is_valid()) { - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2317,7 +2317,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); } } else { - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); m_src = scene_shader.default_material; } @@ -2328,7 +2328,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward if (ginstance->data->material_overlay.is_valid()) { m_src = ginstance->data->material_overlay; - material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D)); + material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D)); if (material && material->shader_data->valid) { if (ginstance->data->dirty_dependencies) { material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); 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 c6eac298e7..0593178829 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 @@ -445,7 +445,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() { } } -RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() { +RendererRD::MaterialStorage::ShaderData *SceneShaderForwardMobile::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); singleton->shader_list.add(&shader_data->shader_list_element); return shader_data; @@ -469,7 +469,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -512,8 +512,8 @@ void SceneShaderForwardMobile::init(const String p_defines) { } } - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler @@ -716,7 +716,7 @@ void fragment() { material_storage->material_initialize(default_material); material_storage->material_set_shader(default_material, default_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); default_material_shader_ptr = md->shader_data; @@ -743,7 +743,7 @@ void fragment() { material_storage->material_initialize(overdraw_material); material_storage->material_set_shader(overdraw_material, overdraw_material_shader); - MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D)); + MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); overdraw_material_shader_ptr = md->shader_data; overdraw_material_uniform_set = md->uniform_set; } 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 0dbed0b07a..1bb8a08ccf 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 @@ -55,7 +55,7 @@ public: SHADER_VERSION_MAX }; - struct ShaderData : public RendererRD::ShaderData { + struct ShaderData : public RendererRD::MaterialStorage::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -157,12 +157,12 @@ public: virtual ~ShaderData(); }; - RendererRD::ShaderData *_create_shader_func(); - static RendererRD::ShaderData *_create_shader_funcs() { + RendererRD::MaterialStorage::ShaderData *_create_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func(); } - struct MaterialData : public RendererRD::MaterialData { + struct MaterialData : public RendererRD::MaterialStorage::MaterialData { ShaderData *shader_data = nullptr; RID uniform_set; uint64_t last_pass = 0; @@ -177,8 +177,8 @@ public: SelfList<ShaderData>::List shader_list; - RendererRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 0b59ca6931..27399298b3 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -192,7 +192,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[1] = vd; - buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR); + buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_COLOR); } //uvs @@ -220,7 +220,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[2] = vd; - buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV); + buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_TEX_UV); } //bones @@ -253,7 +253,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[3] = vd; - buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES); + buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_BONES); } //weights @@ -286,7 +286,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve vd.stride = 0; descriptions.write[4] = vd; - buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS); + buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_WEIGHTS); } //check that everything is as it should be @@ -988,7 +988,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo } else { screen = texture_storage->render_target_get_rd_backbuffer(p_to_render_target); if (screen.is_null()) { //unallocated backbuffer - screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } } u.append_id(screen); @@ -1115,7 +1115,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co if (material != prev_material) { CanvasMaterialData *material_data = nullptr; if (material.is_valid()) { - material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); + material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D)); } if (material_data) { @@ -1383,7 +1383,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material; if (material.is_valid()) { - CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D)); + CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D)); if (md && md->shader_data->valid) { if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { if (!material_screen_texture_found) { @@ -2261,7 +2261,7 @@ RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() { } } -RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { +RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_func() { CanvasShaderData *shader_data = memnew(CanvasShaderData); return shader_data; } @@ -2276,7 +2276,7 @@ RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) { CanvasMaterialData *material_data = memnew(CanvasMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -2629,8 +2629,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size"); //create functions for shader and material - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_material_funcs); state.time = 0; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 1c0567b677..f96d4686ff 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -149,7 +149,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { ShaderCompiler compiler; } shader; - struct CanvasShaderData : public RendererRD::ShaderData { + struct CanvasShaderData : public RendererRD::MaterialStorage::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -193,12 +193,12 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual ~CanvasShaderData(); }; - RendererRD::ShaderData *_create_shader_func(); - static RendererRD::ShaderData *_create_shader_funcs() { + RendererRD::MaterialStorage::ShaderData *_create_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() { return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func(); } - struct CanvasMaterialData : public RendererRD::MaterialData { + struct CanvasMaterialData : public RendererRD::MaterialStorage::MaterialData { CanvasShaderData *shader_data = nullptr; RID uniform_set; @@ -208,8 +208,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual ~CanvasMaterialData(); }; - RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader); - static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) { + RendererRD::MaterialStorage::MaterialData *_create_material_func(CanvasShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader)); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index cf231fa4ef..c6f38012a6 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2007,7 +2007,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.exposure_texture = rb->luminance.current; tonemap.auto_exposure_grey = environment_get_auto_exp_scale(p_render_data->environment); } else { - tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) { @@ -2026,12 +2026,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_map = texture_storage->texture_get_rd_texture(environment_get_glow_map(p_render_data->environment)); } else { tonemap.glow_map_strength = 0.0f; - tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } } else { - tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { @@ -2053,7 +2053,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && p_render_data->environment.is_valid()) { tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment); @@ -2123,14 +2123,14 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr } tonemap.use_glow = false; - tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); - tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_auto_exposure = false; - tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; - tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); if (can_use_effects && p_render_data->environment.is_valid()) { tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment); @@ -2174,7 +2174,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); if (shadow_atlas_texture.is_null()) { - shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); } Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl index af5f7d0a58..9640d30e78 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl @@ -37,16 +37,14 @@ layout(push_constant, std430) uniform Params { uint max_cascades; ivec2 screen_size; - bool use_occlusion; float y_mult; - int probe_axis_size; float z_near; - float reserved1; - float reserved2; - mat4 cam_transform; - mat4 inv_projection; + mat3x4 inv_projection; + // We pack these more tightly than mat3 and vec3, which will require some reconstruction trickery. + float cam_basis[3][3]; + float cam_origin[3]; } params; @@ -82,13 +80,21 @@ void main() { vec3 ray_pos; vec3 ray_dir; { - ray_pos = params.cam_transform[3].xyz; + ray_pos = vec3(params.cam_origin[0], params.cam_origin[1], params.cam_origin[2]); ray_dir.xy = ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0); ray_dir.z = params.z_near; - ray_dir = (params.inv_projection * vec4(ray_dir, 1.0)).xyz; - ray_dir = normalize(mat3(params.cam_transform) * ray_dir); + ray_dir = (vec4(ray_dir, 1.0) * mat4(params.inv_projection)).xyz; + + mat3 cam_basis; + { + vec3 c0 = vec3(params.cam_basis[0][0], params.cam_basis[0][1], params.cam_basis[0][2]); + vec3 c1 = vec3(params.cam_basis[1][0], params.cam_basis[1][1], params.cam_basis[1][2]); + vec3 c2 = vec3(params.cam_basis[2][0], params.cam_basis[2][1], params.cam_basis[2][2]); + cam_basis = mat3(c0, c1, c2); + } + ray_dir = normalize(cam_basis * ray_dir); } ray_pos.y *= params.y_mult; diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index 4369bddc83..fb5759bc17 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -458,11 +458,11 @@ void main() { } break; case ATTRACTOR_TYPE_VECTOR_FIELD: { - vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents) * 2.0 - 1.0; + vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents + 1.0) * 0.5; if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) { continue; } - vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz; + vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * 2.0 - 1.0; dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction amount = length(s); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 5947fc5351..22058b3a06 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -947,9 +947,9 @@ void fragment_shader(in SceneData scene_data) { if (decals.data[decal_index].emission_rect != vec4(0.0)) { //emission is additive, so its independent from albedo if (sc_decal_use_mipmaps) { - emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade; } else { - emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade; + emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade; } } } @@ -1381,7 +1381,7 @@ void fragment_shader(in SceneData scene_data) { float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); #endif } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index c92b29b14a..e27c81eaea 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -199,7 +199,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif // LIGHT_ANISOTROPY_USED // F float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + // Calculate Fresnel using specular occlusion term from Filament: + // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion + float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), 0.0, 1.0); + vec3 F = f0 + (f90 - f0) * cLdotH5; vec3 specular_brdf_NL = cNdotL * D * F * G; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index e65f676785..d3831b4618 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -56,7 +56,7 @@ LightStorage::LightStorage() { } for (int i = 0; i < lightmap_textures.size(); i++) { - lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } } @@ -366,6 +366,13 @@ AABB LightStorage::light_get_aabb(RID p_light) const { ERR_FAIL_V(AABB()); } +Dependency *LightStorage::light_get_dependency(RID p_light) const { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_NULL_V(light, nullptr); + + return &light->dependency; +} + /* REFLECTION PROBE */ RID LightStorage::reflection_probe_allocate() { @@ -601,6 +608,13 @@ float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const return reflection_probe->ambient_color_energy; } +Dependency *LightStorage::reflection_probe_get_dependency(RID p_probe) const { + ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); + ERR_FAIL_NULL_V(reflection_probe, nullptr); + + return &reflection_probe->dependency; +} + /* LIGHTMAP API */ RID LightStorage::lightmap_allocate() { @@ -628,17 +642,17 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use //erase lightmap users if (lm->light_texture.is_valid()) { - RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); + RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture); if (t) { t->lightmap_users.erase(p_lightmap); } } - RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); + RendererRD::TextureStorage::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light); lm->light_texture = p_light; lm->uses_spherical_harmonics = p_uses_spherical_haromics; - RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); if (!t) { if (using_lightmap_array) { if (lm->array_index >= 0) { @@ -725,6 +739,13 @@ void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) { lightmap_probe_capture_update_speed = p_speed; } +Dependency *LightStorage::lightmap_get_dependency(RID p_lightmap) const { + Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); + ERR_FAIL_NULL_V(lm, nullptr); + + return &lm->dependency; +} + void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) { Lightmap *lm = lightmap_owner.get_or_null(p_lightmap); ERR_FAIL_COND(!lm); diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 2fb8f92fff..3e3246e8e9 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -39,87 +39,81 @@ namespace RendererRD { -/* LIGHT */ - -struct Light { - RS::LightType type; - float param[RS::LIGHT_PARAM_MAX]; - Color color = Color(1, 1, 1, 1); - RID projector; - bool shadow = false; - bool negative = false; - bool reverse_cull = false; - RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; - uint32_t max_sdfgi_cascade = 2; - uint32_t cull_mask = 0xFFFFFFFF; - bool distance_fade = false; - real_t distance_fade_begin = 40.0; - real_t distance_fade_shadow = 50.0; - real_t distance_fade_length = 10.0; - RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; - RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; - bool directional_blend_splits = false; - RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; - uint64_t version = 0; - - Dependency dependency; -}; - -/* REFLECTION PROBE */ - -struct ReflectionProbe { - RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; - int resolution = 256; - float intensity = 1.0; - RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT; - Color ambient_color; - float ambient_color_energy = 1.0; - float max_distance = 0; - Vector3 extents = Vector3(1, 1, 1); - Vector3 origin_offset; - bool interior = false; - bool box_projection = false; - bool enable_shadows = false; - uint32_t cull_mask = (1 << 20) - 1; - float mesh_lod_threshold = 0.01; - - Dependency dependency; -}; - -/* LIGHTMAP */ - -struct Lightmap { - RID light_texture; - bool uses_spherical_harmonics = false; - bool interior = false; - AABB bounds = AABB(Vector3(), Vector3(1, 1, 1)); - int32_t array_index = -1; //unassigned - PackedVector3Array points; - PackedColorArray point_sh; - PackedInt32Array tetrahedra; - PackedInt32Array bsp_tree; - - struct BSP { - static const int32_t EMPTY_LEAF = INT32_MIN; - float plane[4]; - int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; - }; - - Dependency dependency; -}; - class LightStorage : public RendererLightStorage { private: static LightStorage *singleton; /* LIGHT */ + struct Light { + RS::LightType type; + float param[RS::LIGHT_PARAM_MAX]; + Color color = Color(1, 1, 1, 1); + RID projector; + bool shadow = false; + bool negative = false; + bool reverse_cull = false; + RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; + uint32_t max_sdfgi_cascade = 2; + uint32_t cull_mask = 0xFFFFFFFF; + bool distance_fade = false; + real_t distance_fade_begin = 40.0; + real_t distance_fade_shadow = 50.0; + real_t distance_fade_length = 10.0; + RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; + RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + bool directional_blend_splits = false; + RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; + uint64_t version = 0; + + Dependency dependency; + }; + mutable RID_Owner<Light, true> light_owner; /* REFLECTION PROBE */ + + struct ReflectionProbe { + RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; + int resolution = 256; + float intensity = 1.0; + RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT; + Color ambient_color; + float ambient_color_energy = 1.0; + float max_distance = 0; + Vector3 extents = Vector3(1, 1, 1); + Vector3 origin_offset; + bool interior = false; + bool box_projection = false; + bool enable_shadows = false; + uint32_t cull_mask = (1 << 20) - 1; + float mesh_lod_threshold = 0.01; + + Dependency dependency; + }; mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner; /* LIGHTMAP */ + struct Lightmap { + RID light_texture; + bool uses_spherical_harmonics = false; + bool interior = false; + AABB bounds = AABB(Vector3(), Vector3(1, 1, 1)); + int32_t array_index = -1; //unassigned + PackedVector3Array points; + PackedColorArray point_sh; + PackedInt32Array tetrahedra; + PackedInt32Array bsp_tree; + + struct BSP { + static const int32_t EMPTY_LEAF = INT32_MIN; + float plane[4]; + int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; + }; + + Dependency dependency; + }; + bool using_lightmap_array; Vector<RID> lightmap_textures; uint64_t lightmap_array_version = 0; @@ -135,7 +129,6 @@ public: /* LIGHT */ - Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); }; bool owns_light(RID p_rid) { return light_owner.owns(p_rid); }; void _light_initialize(RID p_rid, RS::LightType p_type); @@ -268,9 +261,10 @@ public: virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override; virtual uint64_t light_get_version(RID p_light) const override; + Dependency *light_get_dependency(RID p_light) const; + /* REFLECTION PROBE */ - ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); }; bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }; virtual RID reflection_probe_allocate() override; @@ -310,9 +304,10 @@ public: Color reflection_probe_get_ambient_color(RID p_probe) const; float reflection_probe_get_ambient_color_energy(RID p_probe) const; + Dependency *reflection_probe_get_dependency(RID p_probe) const; + /* LIGHTMAP */ - Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); }; bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }; virtual RID lightmap_allocate() override; @@ -332,6 +327,8 @@ public: virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override; virtual void lightmap_set_probe_capture_update_speed(float p_speed) override; + Dependency *lightmap_get_dependency(RID p_lightmap) const; + virtual float lightmap_get_probe_capture_update_speed() const override { return lightmap_probe_capture_update_speed; } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 815b7a1fda..88ce6c261c 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -926,9 +926,9 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, } /////////////////////////////////////////////////////////////////////////// -// MaterialData +// MaterialStorage::MaterialData -void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { +void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); bool uses_global_buffer = false; @@ -1007,7 +1007,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag } } -MaterialData::~MaterialData() { +MaterialStorage::MaterialData::~MaterialData() { MaterialStorage *material_storage = MaterialStorage::get_singleton(); if (global_buffer_E) { @@ -1033,14 +1033,14 @@ MaterialData::~MaterialData() { } } -void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { +void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { TextureStorage *texture_storage = TextureStorage::get_singleton(); MaterialStorage *material_storage = MaterialStorage::get_singleton(); #ifdef TOOLS_ENABLED - Texture *roughness_detect_texture = nullptr; + TextureStorage::Texture *roughness_detect_texture = nullptr; RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; - Texture *normal_detect_texture = nullptr; + TextureStorage::Texture *normal_detect_texture = nullptr; #endif bool uses_global_textures = false; @@ -1123,19 +1123,22 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet case ShaderLanguage::TYPE_SAMPLER2D: { switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: { + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_TRANSPARENT); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_ANISO); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); } break; default: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } break; } } break; @@ -1143,27 +1146,27 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet case ShaderLanguage::TYPE_SAMPLERCUBE: { switch (p_texture_uniforms[i].hint) { case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } break; default: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE); } break; } } break; case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); } break; case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: case ShaderLanguage::TYPE_SAMPLER3D: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } break; case ShaderLanguage::TYPE_ISAMPLER2DARRAY: case ShaderLanguage::TYPE_USAMPLER2DARRAY: case ShaderLanguage::TYPE_SAMPLER2DARRAY: { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } break; default: { @@ -1185,7 +1188,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet bool srgb = p_use_linear_color && p_texture_uniforms[i].use_color; for (int j = 0; j < textures.size(); j++) { - Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); + TextureStorage::Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); if (tex) { rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; @@ -1207,7 +1210,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet #endif } if (rd_texture.is_null()) { - rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } #ifdef TOOLS_ENABLED if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) { @@ -1248,14 +1251,14 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet } } -void MaterialData::free_parameters_uniform_set(RID p_uniform_set) { +void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_set) { if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr); RD::get_singleton()->free(p_uniform_set); } } -bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { +bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -2209,11 +2212,14 @@ void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int ShaderLanguage::TYPE_VEC3, // vec3 ShaderLanguage::TYPE_IVEC3, //vec3i ShaderLanguage::TYPE_MAX, //xform2d not supported here + ShaderLanguage::TYPE_VEC4, //vec4 + ShaderLanguage::TYPE_IVEC4, //vec4i ShaderLanguage::TYPE_VEC4, //plane ShaderLanguage::TYPE_VEC4, //quat ShaderLanguage::TYPE_MAX, //aabb not supported here ShaderLanguage::TYPE_MAX, //basis not supported here ShaderLanguage::TYPE_MAX, //xform not supported here + ShaderLanguage::TYPE_MAX, //projection not supported here ShaderLanguage::TYPE_VEC4 //color }; @@ -2577,6 +2583,15 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { _material_queue_update(material, true, true); } +MaterialStorage::ShaderData *MaterialStorage::material_get_shader_data(RID p_material) { + const MaterialStorage::Material *material = MaterialStorage::get_singleton()->get_material(p_material); + if (material && material->shader && material->shader->data) { + return material->shader->data; + } + + return nullptr; +} + void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); @@ -2678,12 +2693,12 @@ void MaterialStorage::material_update_dependency(RID p_material, DependencyTrack } } -void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { +void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialStorage::MaterialDataRequestFunction p_function) { ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); material_data_request_func[p_shader_type] = p_function; } -MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) { +MaterialStorage::MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) { ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr); return material_data_request_func[p_shader_type]; } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index ad40a86dd0..cb98a78bf8 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -42,161 +42,62 @@ namespace RendererRD { -class MaterialStorage; - -/* SHADER Structs */ - -enum ShaderType { - SHADER_TYPE_2D, - SHADER_TYPE_3D, - SHADER_TYPE_PARTICLES, - SHADER_TYPE_SKY, - SHADER_TYPE_FOG, - SHADER_TYPE_MAX -}; - -struct ShaderData { - virtual void set_code(const String &p_Code) = 0; - virtual void set_path_hint(const String &p_hint) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; - virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; - - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; - virtual bool is_param_texture(const StringName &p_param) const = 0; - virtual bool is_animated() const = 0; - virtual bool casts_shadows() const = 0; - virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; - virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } - - virtual ~ShaderData() {} -}; - -typedef ShaderData *(*ShaderDataRequestFunction)(); - -struct Material; - -struct Shader { - ShaderData *data = nullptr; - String code; - String path_hint; - ShaderType type; - HashMap<StringName, HashMap<int, RID>> default_texture_parameter; - HashSet<Material *> owners; -}; - -/* Material structs */ - -struct MaterialData { - void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); - - virtual void set_render_priority(int p_priority) = 0; - virtual void set_next_pass(RID p_pass) = 0; - virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; - virtual ~MaterialData(); - - //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); - void free_parameters_uniform_set(RID p_uniform_set); - -private: - friend class MaterialStorage; - RID self; - List<RID>::Element *global_buffer_E = nullptr; - List<RID>::Element *global_texture_E = nullptr; - uint64_t global_textures_pass = 0; - HashMap<StringName, uint64_t> used_global_textures; - - //internally by update_parameters_uniform_set - Vector<uint8_t> ubo_data; - RID uniform_buffer; - Vector<RID> texture_cache; -}; - -typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); - -struct Material { - RID self; - MaterialData *data = nullptr; - Shader *shader = nullptr; - //shortcut to shader data and type - ShaderType shader_type = SHADER_TYPE_MAX; - uint32_t shader_id = 0; - bool uniform_dirty = false; - bool texture_dirty = false; - HashMap<StringName, Variant> params; - int32_t priority = 0; - RID next_pass; - SelfList<Material> update_element; - - Dependency dependency; - - Material() : - update_element(this) {} -}; - -/* Global shader uniform structs */ -struct GlobalShaderUniforms { - enum { - BUFFER_DIRTY_REGION_SIZE = 1024 - }; - struct Variable { - HashSet<RID> texture_materials; // materials using this - - RS::GlobalShaderUniformType type; - Variant value; - Variant override; - int32_t buffer_index; //for vectors - int32_t buffer_elements; //for vectors +class MaterialStorage : public RendererMaterialStorage { +public: + enum ShaderType { + SHADER_TYPE_2D, + SHADER_TYPE_3D, + SHADER_TYPE_PARTICLES, + SHADER_TYPE_SKY, + SHADER_TYPE_FOG, + SHADER_TYPE_MAX }; - HashMap<StringName, Variable> variables; - - struct Value { - float x; - float y; - float z; - float w; - }; + struct ShaderData { + virtual void set_code(const String &p_Code) = 0; + virtual void set_path_hint(const String &p_hint) = 0; + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; + virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; - struct ValueInt { - int32_t x; - int32_t y; - int32_t z; - int32_t w; - }; + virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; + virtual bool is_param_texture(const StringName &p_param) const = 0; + virtual bool is_animated() const = 0; + virtual bool casts_shadows() const = 0; + virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; + virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } - struct ValueUInt { - uint32_t x; - uint32_t y; - uint32_t z; - uint32_t w; + virtual ~ShaderData() {} }; - struct ValueUsage { - uint32_t elements = 0; - }; + struct MaterialData { + void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); - List<RID> materials_using_buffer; - List<RID> materials_using_texture; + virtual void set_render_priority(int p_priority) = 0; + virtual void set_next_pass(RID p_pass) = 0; + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual ~MaterialData(); - RID buffer; - Value *buffer_values = nullptr; - ValueUsage *buffer_usage = nullptr; - bool *buffer_dirty_regions = nullptr; - uint32_t buffer_dirty_region_count = 0; + //to be used internally by update_parameters, in the most common configuration of material parameters + bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void free_parameters_uniform_set(RID p_uniform_set); - uint32_t buffer_size; + private: + friend class MaterialStorage; - bool must_update_texture_materials = false; - bool must_update_buffer_materials = false; + RID self; + List<RID>::Element *global_buffer_E = nullptr; + List<RID>::Element *global_texture_E = nullptr; + uint64_t global_textures_pass = 0; + HashMap<StringName, uint64_t> used_global_textures; - HashMap<RID, int32_t> instance_buffer_pos; -}; + //internally by update_parameters_uniform_set + Vector<uint8_t> ubo_data; + RID uniform_buffer; + Vector<RID> texture_cache; + }; -class MaterialStorage : public RendererMaterialStorage { private: - friend struct MaterialData; static MaterialStorage *singleton; /* Samplers */ @@ -211,7 +112,63 @@ private: /* GLOBAL SHADER UNIFORM API */ - GlobalShaderUniforms global_shader_uniforms; + struct GlobalShaderUniforms { + enum { + BUFFER_DIRTY_REGION_SIZE = 1024 + }; + struct Variable { + HashSet<RID> texture_materials; // materials using this + + RS::GlobalShaderUniformType type; + Variant value; + Variant override; + int32_t buffer_index; //for vectors + int32_t buffer_elements; //for vectors + }; + + HashMap<StringName, Variable> variables; + + struct Value { + float x; + float y; + float z; + float w; + }; + + struct ValueInt { + int32_t x; + int32_t y; + int32_t z; + int32_t w; + }; + + struct ValueUInt { + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; + }; + + struct ValueUsage { + uint32_t elements = 0; + }; + + List<RID> materials_using_buffer; + List<RID> materials_using_texture; + + RID buffer; + Value *buffer_values = nullptr; + ValueUsage *buffer_usage = nullptr; + bool *buffer_dirty_regions = nullptr; + uint32_t buffer_dirty_region_count = 0; + + uint32_t buffer_size; + + bool must_update_texture_materials = false; + bool must_update_buffer_materials = false; + + HashMap<RID, int32_t> instance_buffer_pos; + } global_shader_uniforms; int32_t _global_shader_uniform_allocate(uint32_t p_elements); void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value); @@ -219,12 +176,50 @@ private: /* SHADER API */ + struct Material; + + struct Shader { + ShaderData *data = nullptr; + String code; + String path_hint; + ShaderType type; + HashMap<StringName, HashMap<int, RID>> default_texture_parameter; + HashSet<Material *> owners; + }; + + typedef ShaderData *(*ShaderDataRequestFunction)(); ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner<Shader, true> shader_owner; + Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); } /* MATERIAL API */ + + typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); + + struct Material { + RID self; + MaterialData *data = nullptr; + Shader *shader = nullptr; + //shortcut to shader data and type + ShaderType shader_type = SHADER_TYPE_MAX; + uint32_t shader_id = 0; + bool uniform_dirty = false; + bool texture_dirty = false; + HashMap<StringName, Variant> params; + int32_t priority = 0; + RID next_pass; + SelfList<Material> update_element; + + Dependency dependency; + + Material() : + update_element(this) {} + }; + MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; mutable RID_Owner<Material, true> material_owner; + Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; SelfList<Material>::List material_update_list; @@ -358,7 +353,6 @@ public: /* SHADER API */ - Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }; bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }; virtual RID shader_allocate() override; @@ -379,7 +373,6 @@ public: /* MATERIAL API */ - Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }; bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }; void _material_queue_update(Material *material, bool p_uniform, bool p_texture); @@ -390,6 +383,7 @@ public: virtual void material_free(RID p_rid) override; virtual void material_set_shader(RID p_material, RID p_shader) override; + ShaderData *material_get_shader_data(RID p_material); virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override; virtual Variant material_get_param(RID p_material, const StringName &p_param) const override; diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 3875eb6615..dc3f35f942 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -758,6 +758,13 @@ bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); } +Dependency *MeshStorage::mesh_get_dependency(RID p_mesh) const { + Mesh *mesh = mesh_owner.get_or_null(p_mesh); + ERR_FAIL_COND_V(!mesh, nullptr); + + return &mesh->dependency; +} + /* MESH INSTANCE */ RID MeshStorage::mesh_instance_create(RID p_base) { @@ -1473,6 +1480,13 @@ RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const { return multimesh->mesh; } +Dependency *MeshStorage::multimesh_get_dependency(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, nullptr); + + return &multimesh->dependency; +} + Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_COND_V(!multimesh, Transform3D()); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 396fe9b6a6..5c0d019c15 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -40,240 +40,151 @@ namespace RendererRD { -/* Mesh */ - -enum DefaultRDBuffer { - DEFAULT_RD_BUFFER_VERTEX, - DEFAULT_RD_BUFFER_NORMAL, - DEFAULT_RD_BUFFER_TANGENT, - DEFAULT_RD_BUFFER_COLOR, - DEFAULT_RD_BUFFER_TEX_UV, - DEFAULT_RD_BUFFER_TEX_UV2, - DEFAULT_RD_BUFFER_CUSTOM0, - DEFAULT_RD_BUFFER_CUSTOM1, - DEFAULT_RD_BUFFER_CUSTOM2, - DEFAULT_RD_BUFFER_CUSTOM3, - DEFAULT_RD_BUFFER_BONES, - DEFAULT_RD_BUFFER_WEIGHTS, - DEFAULT_RD_BUFFER_MAX, -}; +class MeshStorage : public RendererMeshStorage { +public: + enum DefaultRDBuffer { + DEFAULT_RD_BUFFER_VERTEX, + DEFAULT_RD_BUFFER_NORMAL, + DEFAULT_RD_BUFFER_TANGENT, + DEFAULT_RD_BUFFER_COLOR, + DEFAULT_RD_BUFFER_TEX_UV, + DEFAULT_RD_BUFFER_TEX_UV2, + DEFAULT_RD_BUFFER_CUSTOM0, + DEFAULT_RD_BUFFER_CUSTOM1, + DEFAULT_RD_BUFFER_CUSTOM2, + DEFAULT_RD_BUFFER_CUSTOM3, + DEFAULT_RD_BUFFER_BONES, + DEFAULT_RD_BUFFER_WEIGHTS, + DEFAULT_RD_BUFFER_MAX, + }; -struct MeshInstance; - -struct Mesh { - struct Surface { - RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; - uint32_t format = 0; - - RID vertex_buffer; - RID attribute_buffer; - RID skin_buffer; - uint32_t vertex_count = 0; - uint32_t vertex_buffer_size = 0; - uint32_t skin_buffer_size = 0; - - // A different pipeline needs to be allocated - // depending on the inputs available in the - // material. - // There are never that many geometry/material - // combinations, so a simple array is the most - // cache-efficient structure. - - struct Version { - uint32_t input_mask = 0; - RD::VertexFormatID vertex_format = 0; - RID vertex_array; - }; +private: + static MeshStorage *singleton; - SpinLock version_lock; //needed to access versions - Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; + RID default_rd_storage_buffer; - RID index_buffer; - RID index_array; - uint32_t index_count = 0; + /* Mesh */ - struct LOD { - float edge_length = 0.0; - uint32_t index_count = 0; - RID index_buffer; - RID index_array; - }; + RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; - LOD *lods = nullptr; - uint32_t lod_count = 0; + struct MeshInstance; + + struct Mesh { + struct Surface { + RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; + uint32_t format = 0; + + RID vertex_buffer; + RID attribute_buffer; + RID skin_buffer; + uint32_t vertex_count = 0; + uint32_t vertex_buffer_size = 0; + uint32_t skin_buffer_size = 0; + + // A different pipeline needs to be allocated + // depending on the inputs available in the + // material. + // There are never that many geometry/material + // combinations, so a simple array is the most + // cache-efficient structure. + + struct Version { + uint32_t input_mask = 0; + RD::VertexFormatID vertex_format = 0; + RID vertex_array; + }; + + SpinLock version_lock; //needed to access versions + Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; - AABB aabb; + RID index_buffer; + RID index_array; + uint32_t index_count = 0; - Vector<AABB> bone_aabbs; + struct LOD { + float edge_length = 0.0; + uint32_t index_count = 0; + RID index_buffer; + RID index_array; + }; - RID blend_shape_buffer; + LOD *lods = nullptr; + uint32_t lod_count = 0; - RID material; + AABB aabb; - uint32_t render_index = 0; - uint64_t render_pass = 0; + Vector<AABB> bone_aabbs; - uint32_t multimesh_render_index = 0; - uint64_t multimesh_render_pass = 0; + RID blend_shape_buffer; - uint32_t particles_render_index = 0; - uint64_t particles_render_pass = 0; + RID material; - RID uniform_set; - }; + uint32_t render_index = 0; + uint64_t render_pass = 0; - uint32_t blend_shape_count = 0; - RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; + uint32_t multimesh_render_index = 0; + uint64_t multimesh_render_pass = 0; - Surface **surfaces = nullptr; - uint32_t surface_count = 0; + uint32_t particles_render_index = 0; + uint64_t particles_render_pass = 0; - Vector<AABB> bone_aabbs; + RID uniform_set; + }; - bool has_bone_weights = false; + uint32_t blend_shape_count = 0; + RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; - AABB aabb; - AABB custom_aabb; + Surface **surfaces = nullptr; + uint32_t surface_count = 0; - Vector<RID> material_cache; + Vector<AABB> bone_aabbs; - List<MeshInstance *> instances; + bool has_bone_weights = false; - RID shadow_mesh; - HashSet<Mesh *> shadow_owners; + AABB aabb; + AABB custom_aabb; - Dependency dependency; -}; + Vector<RID> material_cache; -/* Mesh Instance */ + List<MeshInstance *> instances; -struct MeshInstance { - Mesh *mesh = nullptr; - RID skeleton; - struct Surface { - RID vertex_buffer; - RID uniform_set; + RID shadow_mesh; + HashSet<Mesh *> shadow_owners; - Mesh::Surface::Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; + Dependency dependency; }; - LocalVector<Surface> surfaces; - LocalVector<float> blend_weights; - - RID blend_weights_buffer; - List<MeshInstance *>::Element *I = nullptr; //used to erase itself - uint64_t skeleton_version = 0; - bool dirty = false; - bool weights_dirty = false; - SelfList<MeshInstance> weight_update_list; - SelfList<MeshInstance> array_update_list; - MeshInstance() : - weight_update_list(this), array_update_list(this) {} -}; - -/* MultiMesh */ - -struct MultiMesh { - RID mesh; - int instances = 0; - RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; - bool uses_colors = false; - bool uses_custom_data = false; - int visible_instances = -1; - AABB aabb; - bool aabb_dirty = false; - bool buffer_set = false; - uint32_t stride_cache = 0; - uint32_t color_offset_cache = 0; - uint32_t custom_data_offset_cache = 0; - - Vector<float> data_cache; //used if individual setting is used - bool *data_cache_dirty_regions = nullptr; - uint32_t data_cache_used_dirty_regions = 0; - - RID buffer; //storage buffer - RID uniform_set_3d; - RID uniform_set_2d; - - bool dirty = false; - MultiMesh *dirty_list = nullptr; - - Dependency dependency; -}; -/* Skeleton */ - -struct SkeletonShader { - struct PushConstant { - uint32_t has_normal; - uint32_t has_tangent; - uint32_t has_skeleton; - uint32_t has_blend_shape; + mutable RID_Owner<Mesh, true> mesh_owner; - uint32_t vertex_count; - uint32_t vertex_stride; - uint32_t skin_stride; - uint32_t skin_weight_offset; + /* Mesh Instance API */ - uint32_t blend_shape_count; - uint32_t normalized_blend_shapes; - uint32_t pad0; - uint32_t pad1; - }; + struct MeshInstance { + Mesh *mesh = nullptr; + RID skeleton; + struct Surface { + RID vertex_buffer; + RID uniform_set; - enum { - UNIFORM_SET_INSTANCE = 0, - UNIFORM_SET_SURFACE = 1, - UNIFORM_SET_SKELETON = 2, - }; - enum { - SHADER_MODE_2D, - SHADER_MODE_3D, - SHADER_MODE_MAX + Mesh::Surface::Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + }; + LocalVector<Surface> surfaces; + LocalVector<float> blend_weights; + + RID blend_weights_buffer; + List<MeshInstance *>::Element *I = nullptr; //used to erase itself + uint64_t skeleton_version = 0; + bool dirty = false; + bool weights_dirty = false; + SelfList<MeshInstance> weight_update_list; + SelfList<MeshInstance> array_update_list; + MeshInstance() : + weight_update_list(this), array_update_list(this) {} }; - SkeletonShaderRD shader; - RID version; - RID version_shader[SHADER_MODE_MAX]; - RID pipeline[SHADER_MODE_MAX]; - - RID default_skeleton_uniform_set; -}; - -struct Skeleton { - bool use_2d = false; - int size = 0; - Vector<float> data; - RID buffer; - - bool dirty = false; - Skeleton *dirty_list = nullptr; - Transform2D base_transform_2d; - - RID uniform_set_3d; - RID uniform_set_mi; - - uint64_t version = 1; - - Dependency dependency; -}; - -class MeshStorage : public RendererMeshStorage { -private: - static MeshStorage *singleton; - - RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; - RID default_rd_storage_buffer; - - /* Mesh */ - - mutable RID_Owner<Mesh, true> mesh_owner; - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr); - /* Mesh Instance API */ - void _mesh_instance_clear(MeshInstance *mi); void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); @@ -284,6 +195,34 @@ private: /* MultiMesh */ + struct MultiMesh { + RID mesh; + int instances = 0; + RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; + bool uses_colors = false; + bool uses_custom_data = false; + int visible_instances = -1; + AABB aabb; + bool aabb_dirty = false; + bool buffer_set = false; + uint32_t stride_cache = 0; + uint32_t color_offset_cache = 0; + uint32_t custom_data_offset_cache = 0; + + Vector<float> data_cache; //used if individual setting is used + bool *data_cache_dirty_regions = nullptr; + uint32_t data_cache_used_dirty_regions = 0; + + RID buffer; //storage buffer + RID uniform_set_3d; + RID uniform_set_2d; + + bool dirty = false; + MultiMesh *dirty_list = nullptr; + + Dependency dependency; + }; + mutable RID_Owner<MultiMesh, true> multimesh_owner; MultiMesh *multimesh_dirty_list = nullptr; @@ -295,7 +234,60 @@ private: /* Skeleton */ - SkeletonShader skeleton_shader; + struct SkeletonShader { + struct PushConstant { + uint32_t has_normal; + uint32_t has_tangent; + uint32_t has_skeleton; + uint32_t has_blend_shape; + + uint32_t vertex_count; + uint32_t vertex_stride; + uint32_t skin_stride; + uint32_t skin_weight_offset; + + uint32_t blend_shape_count; + uint32_t normalized_blend_shapes; + uint32_t pad0; + uint32_t pad1; + }; + + enum { + UNIFORM_SET_INSTANCE = 0, + UNIFORM_SET_SURFACE = 1, + UNIFORM_SET_SKELETON = 2, + }; + enum { + SHADER_MODE_2D, + SHADER_MODE_3D, + SHADER_MODE_MAX + }; + + SkeletonShaderRD shader; + RID version; + RID version_shader[SHADER_MODE_MAX]; + RID pipeline[SHADER_MODE_MAX]; + + RID default_skeleton_uniform_set; + } skeleton_shader; + + struct Skeleton { + bool use_2d = false; + int size = 0; + Vector<float> data; + RID buffer; + + bool dirty = false; + Skeleton *dirty_list = nullptr; + Transform2D base_transform_2d; + + RID uniform_set_3d; + RID uniform_set_mi; + + uint64_t version = 1; + + Dependency dependency; + }; mutable RID_Owner<Skeleton, true> skeleton_owner; @@ -309,11 +301,10 @@ public: MeshStorage(); virtual ~MeshStorage(); - RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } + RID get_default_rd_storage_buffer() const { return default_rd_storage_buffer; } /* MESH API */ - Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); }; bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }; virtual RID mesh_allocate() override; @@ -542,10 +533,11 @@ public: return s->particles_render_index; } + Dependency *mesh_get_dependency(RID p_mesh) const; + /* MESH INSTANCE API */ - MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); }; - bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); }; + bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); }; virtual RID mesh_instance_create(RID p_base) override; virtual void mesh_instance_free(RID p_rid) override; @@ -556,7 +548,6 @@ public: /* MULTIMESH API */ - MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); }; bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }; virtual RID multimesh_allocate() override; @@ -654,10 +645,11 @@ public: return multimesh->uniform_set_2d; } + Dependency *multimesh_get_dependency(RID p_multimesh) const; + /* SKELETON API */ - Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); }; - bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); }; + bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); }; virtual RID skeleton_allocate() override; virtual void skeleton_initialize(RID p_skeleton) override; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 1e5511eeda..3ca648b0d0 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -54,8 +54,8 @@ ParticlesStorage::ParticlesStorage() { particles_modes.push_back(""); particles_shader.shader.initialize(particles_modes, String()); } - MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); - MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs); + MaterialStorage::get_singleton()->shader_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); + MaterialStorage::get_singleton()->material_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -134,7 +134,7 @@ void process() { material_storage->material_initialize(particles_shader.default_material); material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES)); + ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -987,14 +987,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { RID rd_tex; if (i < collision_3d_textures_used) { - Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]); - if (t && t->type == Texture::TYPE_3D) { - rd_tex = t->rd_texture; + if (TextureStorage::get_singleton()->texture_get_type(collision_3d_textures[i]) == TextureStorage::TYPE_3D) { + rd_tex = TextureStorage::get_singleton()->texture_get_rd_texture(collision_3d_textures[i]); } } if (rd_tex == RID()) { - rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE); + rd_tex = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } u.append_id(rd_tex); } @@ -1007,7 +1006,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta if (collision_heightmap_texture.is_valid()) { u.append_id(collision_heightmap_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); } @@ -1073,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES)); + ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); if (!m) { - m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES)); + m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); } ERR_FAIL_COND(!m); @@ -1228,10 +1227,10 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p void ParticlesStorage::_particles_update_buffers(Particles *particles) { uint32_t userdata_count = 0; - const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material); - if (material && material->shader && material->shader->data) { - const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data); - userdata_count = shader_data->userdata_count; + MaterialStorage::ShaderData *shader_data = MaterialStorage::get_singleton()->material_get_shader_data(particles->process_material); + if (shader_data) { + const ParticlesShaderData *particle_shader_data = static_cast<const ParticlesShaderData *>(shader_data); + userdata_count = particle_shader_data->userdata_count; } if (userdata_count != particles->userdata_count) { @@ -1503,6 +1502,13 @@ void ParticlesStorage::update_particles() { } } +Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const { + Particles *particles = particles_owner.get_or_null(p_particles); + ERR_FAIL_NULL_V(particles, nullptr); + + return &particles->dependency; +} + bool ParticlesStorage::particles_is_inactive(RID p_particles) const { ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); const Particles *particles = particles_owner.get_or_null(p_particles); @@ -1685,7 +1691,7 @@ ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() { } } -ShaderData *ParticlesStorage::_create_particles_shader_func() { +MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() { ParticlesShaderData *shader_data = memnew(ParticlesShaderData); return shader_data; } @@ -1698,7 +1704,7 @@ ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() { free_parameters_uniform_set(uniform_set); } -MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { +MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. @@ -1884,6 +1890,15 @@ bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collis return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE; } +Dependency *ParticlesStorage::particles_collision_get_dependency(RID p_particles_collision) const { + ParticlesCollision *pc = particles_collision_owner.get_or_null(p_particles_collision); + ERR_FAIL_NULL_V(pc, nullptr); + + return &pc->dependency; +} + +/* Particles collision instance */ + RID ParticlesStorage::particles_collision_instance_create(RID p_collision) { ParticlesCollisionInstance pci; pci.collision = p_collision; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 75f995deeb..04ecfcfdce 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -43,231 +43,203 @@ namespace RendererRD { -/* PARTICLES */ - -struct ParticleData { - float xform[16]; - float velocity[3]; - uint32_t active; - float color[4]; - float custom[3]; - float lifetime; -}; +class ParticlesStorage : public RendererParticlesStorage { +private: + static ParticlesStorage *singleton; -struct ParticlesFrameParams { - enum { - MAX_ATTRACTORS = 32, - MAX_COLLIDERS = 32, - MAX_3D_TEXTURES = 7 - }; + /* PARTICLES */ - enum AttractorType { - ATTRACTOR_TYPE_SPHERE, - ATTRACTOR_TYPE_BOX, - ATTRACTOR_TYPE_VECTOR_FIELD, + struct ParticleData { + float xform[16]; + float velocity[3]; + uint32_t active; + float color[4]; + float custom[3]; + float lifetime; }; - struct Attractor { - float transform[16]; - float extents[3]; //exents or radius - uint32_t type; + struct ParticlesFrameParams { + enum { + MAX_ATTRACTORS = 32, + MAX_COLLIDERS = 32, + MAX_3D_TEXTURES = 7 + }; - uint32_t texture_index; //texture index for vector field - float strength; - float attenuation; - float directionality; - }; + enum AttractorType { + ATTRACTOR_TYPE_SPHERE, + ATTRACTOR_TYPE_BOX, + ATTRACTOR_TYPE_VECTOR_FIELD, + }; - enum CollisionType { - COLLISION_TYPE_SPHERE, - COLLISION_TYPE_BOX, - COLLISION_TYPE_SDF, - COLLISION_TYPE_HEIGHT_FIELD, - COLLISION_TYPE_2D_SDF, + struct Attractor { + float transform[16]; + float extents[3]; //exents or radius + uint32_t type; - }; + uint32_t texture_index; //texture index for vector field + float strength; + float attenuation; + float directionality; + }; - struct Collider { - float transform[16]; - float extents[3]; //exents or radius - uint32_t type; + enum CollisionType { + COLLISION_TYPE_SPHERE, + COLLISION_TYPE_BOX, + COLLISION_TYPE_SDF, + COLLISION_TYPE_HEIGHT_FIELD, + COLLISION_TYPE_2D_SDF, - uint32_t texture_index; //texture index for vector field - real_t scale; - uint32_t pad[2]; - }; + }; - uint32_t emitting; - float system_phase; - float prev_system_phase; - uint32_t cycle; + struct Collider { + float transform[16]; + float extents[3]; //exents or radius + uint32_t type; - real_t explosiveness; - real_t randomness; - float time; - float delta; + uint32_t texture_index; //texture index for vector field + real_t scale; + uint32_t pad[2]; + }; - uint32_t frame; - uint32_t pad0; - uint32_t pad1; - uint32_t pad2; + uint32_t emitting; + float system_phase; + float prev_system_phase; + uint32_t cycle; - uint32_t random_seed; - uint32_t attractor_count; - uint32_t collider_count; - float particle_size; + real_t explosiveness; + real_t randomness; + float time; + float delta; - float emission_transform[16]; + uint32_t frame; + uint32_t pad0; + uint32_t pad1; + uint32_t pad2; - Attractor attractors[MAX_ATTRACTORS]; - Collider colliders[MAX_COLLIDERS]; -}; + uint32_t random_seed; + uint32_t attractor_count; + uint32_t collider_count; + float particle_size; -struct ParticleEmissionBufferData { -}; + float emission_transform[16]; -struct ParticleEmissionBuffer { - struct Data { - float xform[16]; - float velocity[3]; - uint32_t flags; - float color[4]; - float custom[4]; + Attractor attractors[MAX_ATTRACTORS]; + Collider colliders[MAX_COLLIDERS]; }; - int32_t particle_count; - int32_t particle_max; - uint32_t pad1; - uint32_t pad2; - Data data[1]; //its 2020 and empty arrays are still non standard in C++ -}; - -struct Particles { - RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; - bool inactive = true; - double inactive_time = 0.0; - bool emitting = false; - bool one_shot = false; - int amount = 0; - double lifetime = 1.0; - double pre_process_time = 0.0; - real_t explosiveness = 0.0; - real_t randomness = 0.0; - bool restart_request = false; - AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); - bool use_local_coords = true; - bool has_collision_cache = false; - - bool has_sdf_collision = false; - Transform2D sdf_collision_transform; - Rect2 sdf_collision_to_screen; - RID sdf_collision_texture; - - RID process_material; - uint32_t frame_counter = 0; - RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED; - - RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; - - Vector<RID> draw_passes; - Vector<Transform3D> trail_bind_poses; - bool trail_bind_poses_dirty = false; - RID trail_bind_pose_buffer; - RID trail_bind_pose_uniform_set; - - RID particle_buffer; - RID particle_instance_buffer; - RID frame_params_buffer; - - uint32_t userdata_count = 0; - - RID particles_material_uniform_set; - RID particles_copy_uniform_set; - RID particles_transforms_buffer_uniform_set; - RID collision_textures_uniform_set; - - RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; - uint32_t collision_3d_textures_used = 0; - RID collision_heightmap_texture; + struct ParticleEmissionBufferData { + }; - RID particles_sort_buffer; - RID particles_sort_uniform_set; + struct ParticleEmissionBuffer { + struct Data { + float xform[16]; + float velocity[3]; + uint32_t flags; + float color[4]; + float custom[4]; + }; - bool dirty = false; - Particles *update_list = nullptr; + int32_t particle_count; + int32_t particle_max; + uint32_t pad1; + uint32_t pad2; + Data data[1]; //its 2020 and empty arrays are still non standard in C++ + }; - RID sub_emitter; + struct Particles { + RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; + bool inactive = true; + double inactive_time = 0.0; + bool emitting = false; + bool one_shot = false; + int amount = 0; + double lifetime = 1.0; + double pre_process_time = 0.0; + real_t explosiveness = 0.0; + real_t randomness = 0.0; + bool restart_request = false; + AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)); + bool use_local_coords = true; + bool has_collision_cache = false; + + bool has_sdf_collision = false; + Transform2D sdf_collision_transform; + Rect2 sdf_collision_to_screen; + RID sdf_collision_texture; + + RID process_material; + uint32_t frame_counter = 0; + RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED; + + RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX; + + Vector<RID> draw_passes; + Vector<Transform3D> trail_bind_poses; + bool trail_bind_poses_dirty = false; + RID trail_bind_pose_buffer; + RID trail_bind_pose_uniform_set; + + RID particle_buffer; + RID particle_instance_buffer; + RID frame_params_buffer; - double phase = 0.0; - double prev_phase = 0.0; - uint64_t prev_ticks = 0; - uint32_t random_seed = 0; + uint32_t userdata_count = 0; - uint32_t cycle_number = 0; + RID particles_material_uniform_set; + RID particles_copy_uniform_set; + RID particles_transforms_buffer_uniform_set; + RID collision_textures_uniform_set; - double speed_scale = 1.0; + RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES]; + uint32_t collision_3d_textures_used = 0; + RID collision_heightmap_texture; - int fixed_fps = 30; - bool interpolate = true; - bool fractional_delta = false; - double frame_remainder = 0; - real_t collision_base_size = 0.01; + RID particles_sort_buffer; + RID particles_sort_uniform_set; - bool clear = true; + bool dirty = false; + Particles *update_list = nullptr; - bool force_sub_emit = false; + RID sub_emitter; - Transform3D emission_transform; + double phase = 0.0; + double prev_phase = 0.0; + uint64_t prev_ticks = 0; + uint32_t random_seed = 0; - Vector<uint8_t> emission_buffer_data; + uint32_t cycle_number = 0; - ParticleEmissionBuffer *emission_buffer = nullptr; - RID emission_storage_buffer; + double speed_scale = 1.0; - HashSet<RID> collisions; + int fixed_fps = 30; + bool interpolate = true; + bool fractional_delta = false; + double frame_remainder = 0; + real_t collision_base_size = 0.01; - Dependency dependency; + bool clear = true; - double trail_length = 1.0; - bool trails_enabled = false; - LocalVector<ParticlesFrameParams> frame_history; - LocalVector<ParticlesFrameParams> trail_params; + bool force_sub_emit = false; - Particles() { - } -}; + Transform3D emission_transform; -/* Particles Collision */ + Vector<uint8_t> emission_buffer_data; -struct ParticlesCollision { - RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT; - uint32_t cull_mask = 0xFFFFFFFF; - float radius = 1.0; - Vector3 extents = Vector3(1, 1, 1); - float attractor_strength = 1.0; - float attractor_attenuation = 1.0; - float attractor_directionality = 0.0; - RID field_texture; - RID heightfield_texture; - RID heightfield_fb; - Size2i heightfield_fb_size; + ParticleEmissionBuffer *emission_buffer = nullptr; + RID emission_storage_buffer; - RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; + HashSet<RID> collisions; - Dependency dependency; -}; + Dependency dependency; -struct ParticlesCollisionInstance { - RID collision; - Transform3D transform; - bool active = false; -}; + double trail_length = 1.0; + bool trails_enabled = false; + LocalVector<ParticlesFrameParams> frame_history; + LocalVector<ParticlesFrameParams> trail_params; -class ParticlesStorage : public RendererParticlesStorage { -private: - static ParticlesStorage *singleton; - - /* PARTICLES */ + Particles() { + } + }; void _particles_process(Particles *p_particles, double p_delta); void _particles_allocate_emission_buffer(Particles *particles); @@ -340,7 +312,7 @@ private: /* Particle Shader */ - struct ParticlesShaderData : public ShaderData { + struct ParticlesShaderData : public MaterialStorage::ShaderData { bool valid = false; RID version; bool uses_collision = false; @@ -377,12 +349,12 @@ private: virtual ~ParticlesShaderData(); }; - ShaderData *_create_particles_shader_func(); - static ShaderData *_create_particles_shader_funcs() { + MaterialStorage::ShaderData *_create_particles_shader_func(); + static MaterialStorage::ShaderData *_create_particles_shader_funcs() { return ParticlesStorage::get_singleton()->_create_particles_shader_func(); } - struct ParticlesMaterialData : public MaterialData { + struct ParticlesMaterialData : public MaterialStorage::MaterialData { ParticlesShaderData *shader_data = nullptr; RID uniform_set; @@ -392,13 +364,37 @@ private: virtual ~ParticlesMaterialData(); }; - MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); - static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) { + MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); + static MaterialStorage::MaterialData *_create_particles_material_funcs(MaterialStorage::ShaderData *p_shader) { return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); } /* Particles Collision */ + struct ParticlesCollision { + RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT; + uint32_t cull_mask = 0xFFFFFFFF; + float radius = 1.0; + Vector3 extents = Vector3(1, 1, 1); + float attractor_strength = 1.0; + float attractor_attenuation = 1.0; + float attractor_directionality = 0.0; + RID field_texture; + RID heightfield_texture; + RID heightfield_fb; + Size2i heightfield_fb_size; + + RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; + + Dependency dependency; + }; + + struct ParticlesCollisionInstance { + RID collision; + Transform3D transform; + bool active = false; + }; + mutable RID_Owner<ParticlesCollision, true> particles_collision_owner; mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner; @@ -411,7 +407,6 @@ public: /* PARTICLES */ - Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); } bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); } virtual RID particles_allocate() override; @@ -526,9 +521,10 @@ public: virtual void update_particles() override; + Dependency *particles_get_dependency(RID p_particles) const; + /* Particles Collision */ - ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); } bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); } virtual RID particles_collision_allocate() override; @@ -550,8 +546,9 @@ public: virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override; virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override; + Dependency *particles_collision_get_dependency(RID p_particles) const; + //used from 2D and 3D - ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); } bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); } virtual RID particles_collision_instance_create(RID p_collision) override; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 6d7ea5184a..e20a04ff2a 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -35,9 +35,9 @@ using namespace RendererRD; /////////////////////////////////////////////////////////////////////////// -// CanvasTexture +// TextureStorage::CanvasTexture -void CanvasTexture::clear_sets() { +void TextureStorage::CanvasTexture::clear_sets() { if (cleared_cache) { return; } @@ -52,14 +52,14 @@ void CanvasTexture::clear_sets() { cleared_cache = true; } -CanvasTexture::~CanvasTexture() { +TextureStorage::CanvasTexture::~CanvasTexture() { clear_sets(); } /////////////////////////////////////////////////////////////////////////// -// Texture +// TextureStorage::Texture -void Texture::cleanup() { +void TextureStorage::Texture::cleanup() { if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) { //erase this first, as it's a dependency of the one below RD::get_singleton()->free(rd_texture_srgb); @@ -96,6 +96,7 @@ TextureStorage::TextureStorage() { Vector<uint8_t> pv; pv.resize(16 * 4); for (int i = 0; i < 16; i++) { + // Opaque white. pv.set(i * 4 + 0, 255); pv.set(i * 4 + 1, 255); pv.set(i * 4 + 2, 255); @@ -109,6 +110,7 @@ TextureStorage::TextureStorage() { } for (int i = 0; i < 16; i++) { + // Opaque black. pv.set(i * 4 + 0, 0); pv.set(i * 4 + 1, 0); pv.set(i * 4 + 2, 0); @@ -122,6 +124,21 @@ TextureStorage::TextureStorage() { } for (int i = 0; i < 16; i++) { + // Transparent black. + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_TRANSPARENT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + // Opaque normal map "flat" color. pv.set(i * 4 + 0, 128); pv.set(i * 4 + 1, 128); pv.set(i * 4 + 2, 255); @@ -135,6 +152,7 @@ TextureStorage::TextureStorage() { } for (int i = 0; i < 16; i++) { + // Opaque flowmap "flat" color. pv.set(i * 4 + 0, 255); pv.set(i * 4 + 1, 128); pv.set(i * 4 + 2, 255); @@ -534,7 +552,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte ct = t->canvas_texture; } else { - ct = get_canvas_texture(p_texture); + ct = canvas_texture_owner.get_or_null(p_texture); } if (!ct) { @@ -657,7 +675,7 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im Texture texture; - texture.type = Texture::TYPE_2D; + texture.type = TextureStorage::TYPE_2D; texture.width = p_image->get_width(); texture.height = p_image->get_height(); @@ -753,7 +771,7 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<R Texture texture; - texture.type = Texture::TYPE_LAYERED; + texture.type = TextureStorage::TYPE_LAYERED; texture.layered_type = p_layered_type; texture.width = p_layers[0]->get_width(); @@ -883,7 +901,7 @@ void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format Texture texture; - texture.type = Texture::TYPE_3D; + texture.type = TextureStorage::TYPE_3D; texture.width = p_width; texture.height = p_height; texture.depth = p_depth; @@ -975,7 +993,7 @@ void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); ERR_FAIL_COND(p_image->get_format() != tex->format); - if (tex->type == Texture::TYPE_LAYERED) { + if (tex->type == TextureStorage::TYPE_LAYERED) { ERR_FAIL_INDEX(p_layer, tex->layers); } @@ -995,7 +1013,7 @@ void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_3D); + ERR_FAIL_COND(tex->type != TextureStorage::TYPE_3D); Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); if (verr != Image::VALIDATE_3D_OK) { @@ -1167,7 +1185,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); - ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); + ERR_FAIL_COND_V(tex->type != TextureStorage::TYPE_3D, Vector<Ref<Image>>()); Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); @@ -1243,7 +1261,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) { void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_2D); + ERR_FAIL_COND(tex->type != TextureStorage::TYPE_2D); tex->width_2d = p_width; tex->height_2d = p_height; @@ -1855,6 +1873,13 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { return AABB(-decal->extents, decal->extents * 2.0); } +Dependency *TextureStorage::decal_get_dependency(RID p_decal) { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND_V(!decal, nullptr); + + return &decal->dependency; +} + void TextureStorage::update_decal_atlas() { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); ERR_FAIL_NULL(copy_effects); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 1eb4a283ca..682c951f63 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -38,248 +38,133 @@ namespace RendererRD { -enum DefaultRDTexture { - DEFAULT_RD_TEXTURE_WHITE, - DEFAULT_RD_TEXTURE_BLACK, - DEFAULT_RD_TEXTURE_NORMAL, - DEFAULT_RD_TEXTURE_ANISO, - DEFAULT_RD_TEXTURE_DEPTH, - DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, - DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, - DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE, - DEFAULT_RD_TEXTURE_3D_WHITE, - DEFAULT_RD_TEXTURE_3D_BLACK, - DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, - DEFAULT_RD_TEXTURE_2D_UINT, - DEFAULT_RD_TEXTURE_VRS, - DEFAULT_RD_TEXTURE_MAX -}; +class LightStorage; +class MaterialStorage; -class CanvasTexture { +class TextureStorage : public RendererTextureStorage { public: - RID diffuse; - RID normal_map; - RID specular; - Color specular_color = Color(1, 1, 1, 1); - float shininess = 1.0; - - RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - - Size2i size_cache = Size2i(1, 1); - bool use_normal_cache = false; - bool use_specular_cache = false; - bool cleared_cache = true; - - void clear_sets(); - ~CanvasTexture(); -}; + enum DefaultRDTexture { + DEFAULT_RD_TEXTURE_WHITE, + DEFAULT_RD_TEXTURE_BLACK, + DEFAULT_RD_TEXTURE_TRANSPARENT, + DEFAULT_RD_TEXTURE_NORMAL, + DEFAULT_RD_TEXTURE_ANISO, + DEFAULT_RD_TEXTURE_DEPTH, + DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, + DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_3D_WHITE, + DEFAULT_RD_TEXTURE_3D_BLACK, + DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_2D_UINT, + DEFAULT_RD_TEXTURE_VRS, + DEFAULT_RD_TEXTURE_MAX + }; -class Texture { -public: - enum Type { + enum TextureType { TYPE_2D, TYPE_LAYERED, TYPE_3D }; - Type type; - RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; - - RenderingDevice::TextureType rd_type; - RID rd_texture; - RID rd_texture_srgb; - RenderingDevice::DataFormat rd_format; - RenderingDevice::DataFormat rd_format_srgb; - - RD::TextureView rd_view; - - Image::Format format; - Image::Format validated_format; - - int width; - int height; - int depth; - int layers; - int mipmaps; - - int height_2d; - int width_2d; - - struct BufferSlice3D { - Size2i size; - uint32_t offset = 0; - uint32_t buffer_size = 0; - }; - Vector<BufferSlice3D> buffer_slices_3d; - uint32_t buffer_size_3d = 0; - - bool is_render_target; - bool is_proxy; - - Ref<Image> image_cache_2d; - String path; - - RID proxy_to; - Vector<RID> proxies; - - HashSet<RID> lightmap_users; - - RS::TextureDetectCallback detect_3d_callback = nullptr; - void *detect_3d_callback_ud = nullptr; - - RS::TextureDetectCallback detect_normal_callback = nullptr; - void *detect_normal_callback_ud = nullptr; +private: + friend class LightStorage; + friend class MaterialStorage; - RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; - void *detect_roughness_callback_ud = nullptr; + static TextureStorage *singleton; - CanvasTexture *canvas_texture = nullptr; + RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; - void cleanup(); -}; + /* Canvas Texture API */ -struct DecalAtlas { - struct Texture { - int panorama_to_dp_users; - int users; - Rect2 uv_rect; + class CanvasTexture { + public: + RID diffuse; + RID normal_map; + RID specular; + Color specular_color = Color(1, 1, 1, 1); + float shininess = 1.0; + + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + + Size2i size_cache = Size2i(1, 1); + bool use_normal_cache = false; + bool use_specular_cache = false; + bool cleared_cache = true; + + void clear_sets(); + ~CanvasTexture(); }; - struct SortItem { - RID texture; - Size2i pixel_size; - Size2i size; - Point2i pos; - - bool operator<(const SortItem &p_item) const { - //sort larger to smaller - if (size.height == p_item.size.height) { - return size.width > p_item.size.width; - } else { - return size.height > p_item.size.height; - } - } - }; + RID_Owner<CanvasTexture, true> canvas_texture_owner; - HashMap<RID, Texture> textures; - bool dirty = true; - int mipmaps = 5; + /* Texture API */ - RID texture; - RID texture_srgb; - struct MipMap { - RID fb; - RID texture; - Size2i size; - }; - Vector<MipMap> texture_mipmaps; + class Texture { + public: + TextureType type; + RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY; - Size2i size; -}; + RenderingDevice::TextureType rd_type; + RID rd_texture; + RID rd_texture_srgb; + RenderingDevice::DataFormat rd_format; + RenderingDevice::DataFormat rd_format_srgb; -struct Decal { - Vector3 extents = Vector3(1, 1, 1); - RID textures[RS::DECAL_TEXTURE_MAX]; - float emission_energy = 1.0; - float albedo_mix = 1.0; - Color modulate = Color(1, 1, 1, 1); - uint32_t cull_mask = (1 << 20) - 1; - float upper_fade = 0.3; - float lower_fade = 0.3; - bool distance_fade = false; - float distance_fade_begin = 40.0; - float distance_fade_length = 10.0; - float normal_fade = 0.0; - - Dependency dependency; -}; + RD::TextureView rd_view; -struct RenderTarget { - Size2i size; - uint32_t view_count; - RID framebuffer; - RID color; + Image::Format format; + Image::Format validated_format; - //used for retrieving from CPU - RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8; - RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8; - Image::Format image_format = Image::FORMAT_L8; + int width; + int height; + int depth; + int layers; + int mipmaps; - bool is_transparent = false; + int height_2d; + int width_2d; - bool sdf_enabled = false; + struct BufferSlice3D { + Size2i size; + uint32_t offset = 0; + uint32_t buffer_size = 0; + }; + Vector<BufferSlice3D> buffer_slices_3d; + uint32_t buffer_size_3d = 0; - RID backbuffer; //used for effects - RID backbuffer_fb; - RID backbuffer_mipmap0; + bool is_render_target; + bool is_proxy; - Vector<RID> backbuffer_mipmaps; + Ref<Image> image_cache_2d; + String path; - RID framebuffer_uniform_set; - RID backbuffer_uniform_set; + RID proxy_to; + Vector<RID> proxies; - RID sdf_buffer_write; - RID sdf_buffer_write_fb; - RID sdf_buffer_process[2]; - RID sdf_buffer_read; - RID sdf_buffer_process_uniform_sets[2]; - RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT; - RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT; - Size2i process_size; + HashSet<RID> lightmap_users; - // VRS - RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED; - RID vrs_texture; + RS::TextureDetectCallback detect_3d_callback = nullptr; + void *detect_3d_callback_ud = nullptr; - //texture generated for this owner (nor RD). - RID texture; - bool was_used; + RS::TextureDetectCallback detect_normal_callback = nullptr; + void *detect_normal_callback_ud = nullptr; - //clear request - bool clear_requested; - Color clear_color; -}; + RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; + void *detect_roughness_callback_ud = nullptr; -struct RenderTargetSDF { - enum { - SHADER_LOAD, - SHADER_LOAD_SHRINK, - SHADER_PROCESS, - SHADER_PROCESS_OPTIMIZED, - SHADER_STORE, - SHADER_STORE_SHRINK, - SHADER_MAX - }; + CanvasTexture *canvas_texture = nullptr; - struct PushConstant { - int32_t size[2]; - int32_t stride; - int32_t shift; - int32_t base_size[2]; - int32_t pad[2]; + void cleanup(); }; - CanvasSdfShaderRD shader; - RID shader_version; - RID pipelines[SHADER_MAX]; -}; - -class TextureStorage : public RendererTextureStorage { -private: - static TextureStorage *singleton; - - /* Canvas Texture API */ - - RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner; - - /* Texture API */ - //textures can be created from threads, so this RID_Owner is thread safe mutable RID_Owner<Texture, true> texture_owner; + Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; struct TextureToRDFormat { RD::DataFormat format; @@ -303,13 +188,115 @@ private: /* DECAL API */ - DecalAtlas decal_atlas; + struct DecalAtlas { + struct Texture { + int panorama_to_dp_users; + int users; + Rect2 uv_rect; + }; + + struct SortItem { + RID texture; + Size2i pixel_size; + Size2i size; + Point2i pos; + + bool operator<(const SortItem &p_item) const { + //sort larger to smaller + if (size.height == p_item.size.height) { + return size.width > p_item.size.width; + } else { + return size.height > p_item.size.height; + } + } + }; + + HashMap<RID, Texture> textures; + bool dirty = true; + int mipmaps = 5; + + RID texture; + RID texture_srgb; + struct MipMap { + RID fb; + RID texture; + Size2i size; + }; + Vector<MipMap> texture_mipmaps; + + Size2i size; + } decal_atlas; + + struct Decal { + Vector3 extents = Vector3(1, 1, 1); + RID textures[RS::DECAL_TEXTURE_MAX]; + float emission_energy = 1.0; + float albedo_mix = 1.0; + Color modulate = Color(1, 1, 1, 1); + uint32_t cull_mask = (1 << 20) - 1; + float upper_fade = 0.3; + float lower_fade = 0.3; + bool distance_fade = false; + float distance_fade_begin = 40.0; + float distance_fade_length = 10.0; + float normal_fade = 0.0; + + Dependency dependency; + }; mutable RID_Owner<Decal, true> decal_owner; + Decal *get_decal(RID p_rid) const { return decal_owner.get_or_null(p_rid); }; /* RENDER TARGET API */ + struct RenderTarget { + Size2i size; + uint32_t view_count; + RID framebuffer; + RID color; + + //used for retrieving from CPU + RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8; + RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8; + Image::Format image_format = Image::FORMAT_L8; + + bool is_transparent = false; + + bool sdf_enabled = false; + + RID backbuffer; //used for effects + RID backbuffer_fb; + RID backbuffer_mipmap0; + + Vector<RID> backbuffer_mipmaps; + + RID framebuffer_uniform_set; + RID backbuffer_uniform_set; + + RID sdf_buffer_write; + RID sdf_buffer_write_fb; + RID sdf_buffer_process[2]; + RID sdf_buffer_read; + RID sdf_buffer_process_uniform_sets[2]; + RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT; + RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT; + Size2i process_size; + + // VRS + RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED; + RID vrs_texture; + + //texture generated for this owner (nor RD). + RID texture; + bool was_used; + + //clear request + bool clear_requested; + Color clear_color; + }; + mutable RID_Owner<RenderTarget> render_target_owner; + RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); }; void _clear_render_target(RenderTarget *rt); void _update_render_target(RenderTarget *rt); @@ -318,13 +305,33 @@ private: void _render_target_clear_sdf(RenderTarget *rt); Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const; - RenderTargetSDF rt_sdf; + struct RenderTargetSDF { + enum { + SHADER_LOAD, + SHADER_LOAD_SHRINK, + SHADER_PROCESS, + SHADER_PROCESS_OPTIMIZED, + SHADER_STORE, + SHADER_STORE_SHRINK, + SHADER_MAX + }; + + struct PushConstant { + int32_t size[2]; + int32_t stride; + int32_t shift; + int32_t base_size[2]; + int32_t pad[2]; + }; + + CanvasSdfShaderRD shader; + RID shader_version; + RID pipelines[SHADER_MAX]; + } rt_sdf; public: static TextureStorage *get_singleton(); - RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; - _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { return default_rd_textures[p_texture]; } @@ -334,7 +341,6 @@ public: /* Canvas Texture API */ - CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }; bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }; virtual RID canvas_texture_allocate() override; @@ -351,8 +357,7 @@ public: /* Texture API */ - Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }; - bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }; + bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); }; virtual bool can_create_resources_async() const override; @@ -394,12 +399,29 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) override; //internal usage + _FORCE_INLINE_ TextureType texture_get_type(RID p_texture) { + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); + if (tex == nullptr) { + return TYPE_2D; + } + + return tex->type; + } + + _FORCE_INLINE_ int texture_get_layers(RID p_texture) { + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); + if (tex == nullptr) { + return 1; + } + + return tex->layers; + } _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { if (p_texture.is_null()) { return RID(); } - RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); if (!tex) { return RID(); @@ -411,7 +433,7 @@ public: if (p_texture.is_null()) { return Size2i(); } - RendererRD::Texture *tex = texture_owner.get_or_null(p_texture); + RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture); if (!tex) { return Size2i(); @@ -423,8 +445,7 @@ public: void update_decal_atlas(); - Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); }; - bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); }; + bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); }; RID decal_atlas_get_texture() const; RID decal_atlas_get_texture_srgb() const; @@ -518,11 +539,11 @@ public: } virtual AABB decal_get_aabb(RID p_decal) const override; + Dependency *decal_get_dependency(RID p_decal); /* RENDER TARGET API */ - RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }; - bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }; + bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }; virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp index ce64d3c69e..5a91046628 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp +++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp @@ -138,35 +138,37 @@ bool Utilities::free(RID p_rid) { void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) { if (MeshStorage::get_singleton()->owns_mesh(p_base)) { - Mesh *mesh = MeshStorage::get_singleton()->get_mesh(p_base); - p_instance->update_dependency(&mesh->dependency); + Dependency *dependency = MeshStorage::get_singleton()->mesh_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) { - MultiMesh *multimesh = MeshStorage::get_singleton()->get_multimesh(p_base); - p_instance->update_dependency(&multimesh->dependency); - if (multimesh->mesh.is_valid()) { - base_update_dependency(multimesh->mesh, p_instance); + Dependency *dependency = MeshStorage::get_singleton()->multimesh_get_dependency(p_base); + p_instance->update_dependency(dependency); + + RID mesh = MeshStorage::get_singleton()->multimesh_get_mesh(p_base); + if (mesh.is_valid()) { + base_update_dependency(mesh, p_instance); } } else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) { - ReflectionProbe *rp = LightStorage::get_singleton()->get_reflection_probe(p_base); - p_instance->update_dependency(&rp->dependency); + Dependency *dependency = LightStorage::get_singleton()->reflection_probe_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (TextureStorage::get_singleton()->owns_decal(p_base)) { - Decal *decal = TextureStorage::get_singleton()->get_decal(p_base); - p_instance->update_dependency(&decal->dependency); + Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (GI::get_singleton()->owns_voxel_gi(p_base)) { GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base); p_instance->update_dependency(&gip->dependency); } else if (LightStorage::get_singleton()->owns_lightmap(p_base)) { - Lightmap *lm = LightStorage::get_singleton()->get_lightmap(p_base); - p_instance->update_dependency(&lm->dependency); + Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (LightStorage::get_singleton()->owns_light(p_base)) { - Light *l = LightStorage::get_singleton()->get_light(p_base); - p_instance->update_dependency(&l->dependency); + Dependency *dependency = LightStorage::get_singleton()->light_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) { - Particles *p = ParticlesStorage::get_singleton()->get_particles(p_base); - p_instance->update_dependency(&p->dependency); + Dependency *dependency = ParticlesStorage::get_singleton()->particles_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) { - ParticlesCollision *pc = ParticlesStorage::get_singleton()->get_particles_collision(p_base); - p_instance->update_dependency(&pc->dependency); + Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (Fog::get_singleton()->owns_fog_volume(p_base)) { Fog::FogVolume *fv = Fog::get_singleton()->get_fog_volume(p_base); p_instance->update_dependency(&fv->dependency); diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 2dd0f7006b..7de175647b 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -195,6 +195,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "SOURCE_COLOR", "HINT_DEFAULT_WHITE_TEXTURE", "HINT_DEFAULT_BLACK_TEXTURE", + "HINT_DEFAULT_TRANSPARENT_TEXTURE", "HINT_NORMAL_TEXTURE", "HINT_ANISOTROPY_TEXTURE", "HINT_RANGE", @@ -354,6 +355,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_NORMAL_TEXTURE, "hint_normal", CF_UNSPECIFIED, {}, {} }, { TK_HINT_DEFAULT_WHITE_TEXTURE, "hint_default_white", CF_UNSPECIFIED, {}, {} }, { TK_HINT_DEFAULT_BLACK_TEXTURE, "hint_default_black", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_DEFAULT_TRANSPARENT_TEXTURE, "hint_default_transparent", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_R, "hint_roughness_r", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_G, "hint_roughness_g", CF_UNSPECIFIED, {}, {} }, @@ -1088,6 +1090,9 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { case ShaderNode::Uniform::HINT_DEFAULT_WHITE: { result = "hint_default_white"; } break; + case ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: { + result = "hint_default_transparent"; + } break; case ShaderNode::Uniform::HINT_ANISOTROPY: { result = "hint_anisotropy"; } break; @@ -8410,6 +8415,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_HINT_DEFAULT_WHITE_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_DEFAULT_WHITE; } break; + case TK_HINT_DEFAULT_TRANSPARENT_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT; + } break; case TK_HINT_NORMAL_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_NORMAL; } break; @@ -10248,6 +10256,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ options.push_back("hint_anisotropy"); options.push_back("hint_default_black"); options.push_back("hint_default_white"); + options.push_back("hint_default_transparent"); options.push_back("hint_normal"); options.push_back("hint_roughness_a"); options.push_back("hint_roughness_b"); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 09160e2949..bfec6e1df6 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -164,6 +164,7 @@ public: TK_RENDER_MODE, TK_HINT_DEFAULT_WHITE_TEXTURE, TK_HINT_DEFAULT_BLACK_TEXTURE, + TK_HINT_DEFAULT_TRANSPARENT_TEXTURE, TK_HINT_NORMAL_TEXTURE, TK_HINT_ROUGHNESS_NORMAL_TEXTURE, TK_HINT_ROUGHNESS_R, @@ -664,6 +665,7 @@ public: HINT_ROUGHNESS_GRAY, HINT_DEFAULT_BLACK, HINT_DEFAULT_WHITE, + HINT_DEFAULT_TRANSPARENT, HINT_ANISOTROPY, HINT_MAX }; diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h index bd1c17deec..29bba86930 100644 --- a/servers/rendering/storage/environment_storage.h +++ b/servers/rendering/storage/environment_storage.h @@ -67,10 +67,10 @@ private: // Fog bool fog_enabled = false; - Color fog_light_color = Color(0.5, 0.6, 0.7); + Color fog_light_color = Color(0.518, 0.553, 0.608); float fog_light_energy = 1.0; float fog_sun_scatter = 0.0; - float fog_density = 0.001; + float fog_density = 0.01; float fog_height = 0.0; float fog_height_density = 0.0; //can be negative to invert effect float fog_aerial_perspective = 0.0; @@ -84,10 +84,10 @@ private: float volumetric_fog_anisotropy = 0.2; float volumetric_fog_length = 64.0; float volumetric_fog_detail_spread = 2.0; - float volumetric_fog_gi_inject = 0.0; + float volumetric_fog_gi_inject = 1.0; + float volumetric_fog_ambient_inject = 0.0; bool volumetric_fog_temporal_reprojection = true; float volumetric_fog_temporal_reprojection_amount = 0.9; - float volumetric_fog_ambient_inject = 0.0; // Glow bool glow_enabled = false; diff --git a/tests/core/io/test_file_access.h b/tests/core/io/test_file_access.h index f0e1cceacf..aab62955cb 100644 --- a/tests/core/io/test_file_access.h +++ b/tests/core/io/test_file_access.h @@ -78,6 +78,29 @@ TEST_CASE("[FileAccess] CSV read") { CHECK(row5[1] == "tab separated"); CHECK(row5[2] == "lines, good?"); } + +TEST_CASE("[FileAccess] Get as UTF-8 String") { + Ref<FileAccess> f_lf = FileAccess::open(TestUtils::get_data_path("line_endings_lf.test.txt"), FileAccess::READ); + String s_lf = f_lf->get_as_utf8_string(); + f_lf->seek(0); + String s_lf_nocr = f_lf->get_as_utf8_string(true); + CHECK(s_lf == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); + CHECK(s_lf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); + + Ref<FileAccess> f_crlf = FileAccess::open(TestUtils::get_data_path("line_endings_crlf.test.txt"), FileAccess::READ); + String s_crlf = f_crlf->get_as_utf8_string(); + f_crlf->seek(0); + String s_crlf_nocr = f_crlf->get_as_utf8_string(true); + CHECK(s_crlf == "Hello darkness\r\nMy old friend\r\nI've come to talk\r\nWith you again\r\n"); + CHECK(s_crlf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); + + Ref<FileAccess> f_cr = FileAccess::open(TestUtils::get_data_path("line_endings_cr.test.txt"), FileAccess::READ); + String s_cr = f_cr->get_as_utf8_string(); + f_cr->seek(0); + String s_cr_nocr = f_cr->get_as_utf8_string(true); + CHECK(s_cr == "Hello darkness\rMy old friend\rI've come to talk\rWith you again\r"); + CHECK(s_cr_nocr == "Hello darknessMy old friendI've come to talkWith you again"); +} } // namespace TestFileAccess #endif // TEST_FILE_ACCESS_H diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index 0c5704d6c9..b8b766023a 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -152,6 +152,20 @@ TEST_CASE("[String] UTF16 with BOM") { CHECK(String::utf16(cs) == s); } +TEST_CASE("[String] UTF8 with CR") { + const String base = U"Hello darkness\r\nMy old friend\nI've come to talk\rWith you again"; + + String keep_cr; + Error err = keep_cr.parse_utf8(base.utf8().get_data()); + CHECK(err == OK); + CHECK(keep_cr == base); + + String no_cr; + err = no_cr.parse_utf8(base.utf8().get_data(), -1, true); // Skip CR. + CHECK(err == OK); + CHECK(no_cr == base.replace("\r", "")); +} + TEST_CASE("[String] Invalid UTF8 (non-standard)") { ERR_PRINT_OFF static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0xF0, 0x82, 0x82, 0xAC, 0xED, 0xA0, 0x81, 0 }; diff --git a/tests/data/line_endings_cr.test.txt b/tests/data/line_endings_cr.test.txt new file mode 100644 index 0000000000..556154bb25 --- /dev/null +++ b/tests/data/line_endings_cr.test.txt @@ -0,0 +1 @@ +Hello darkness
My old friend
I've come to talk
With you again
\ No newline at end of file diff --git a/tests/data/line_endings_crlf.test.txt b/tests/data/line_endings_crlf.test.txt new file mode 100644 index 0000000000..a3cbe55b7f --- /dev/null +++ b/tests/data/line_endings_crlf.test.txt @@ -0,0 +1,4 @@ +Hello darkness
+My old friend
+I've come to talk
+With you again
diff --git a/tests/data/line_endings_lf.test.txt b/tests/data/line_endings_lf.test.txt new file mode 100644 index 0000000000..0aabcd911e --- /dev/null +++ b/tests/data/line_endings_lf.test.txt @@ -0,0 +1,4 @@ +Hello darkness +My old friend +I've come to talk +With you again diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 40fe562be1..16654181c6 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -105,7 +105,7 @@ int test_main(int argc, char *argv[]) { for (int i = 0; i < argc; i++) { args.push_back(String::utf8(argv[i])); } - OS::get_singleton()->set_cmdline("", args); + OS::get_singleton()->set_cmdline("", args, List<String>()); // Run custom test tools. if (test_commands) { |