diff options
228 files changed, 1296 insertions, 322 deletions
diff --git a/SConstruct b/SConstruct index 0245531b45..5566770148 100644 --- a/SConstruct +++ b/SConstruct @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * EnsureSConsVersion(3, 1, 2) EnsurePythonVersion(3, 6) diff --git a/core/SCsub b/core/SCsub index c8267ae960..8bda230b87 100644 --- a/core/SCsub +++ b/core/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/config/SCsub b/core/config/SCsub index bf70285490..1417a258c1 100644 --- a/core/config/SCsub +++ b/core/config/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/crypto/SCsub b/core/crypto/SCsub index 8cff3cf679..3cea6bfb47 100644 --- a/core/crypto/SCsub +++ b/core/crypto/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/debugger/SCsub b/core/debugger/SCsub index 19a6549225..ab81175894 100644 --- a/core/debugger/SCsub +++ b/core/debugger/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/error/SCsub b/core/error/SCsub index dfd6248a94..08089d31b0 100644 --- a/core/error/SCsub +++ b/core/error/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/extension/SCsub b/core/extension/SCsub index 6ab2d2b0a6..8688ca5b6e 100644 --- a/core/extension/SCsub +++ b/core/extension/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/input/SCsub b/core/input/SCsub index d8e6f33156..521f7702e4 100644 --- a/core/input/SCsub +++ b/core/input/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/input/input_builders.py b/core/input/input_builders.py index ae848f4e7c..3685e726b4 100644 --- a/core/input/input_builders.py +++ b/core/input/input_builders.py @@ -33,7 +33,7 @@ def make_default_controller_mappings(target, source, env): guid = line_parts[0] if guid in platform_mappings[current_platform]: g.write( - "// WARNING - DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format( + "// WARNING: DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format( src_path, current_platform, platform_mappings[current_platform][guid] ) ) diff --git a/core/io/SCsub b/core/io/SCsub index 19a6549225..ab81175894 100644 --- a/core/io/SCsub +++ b/core/io/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index eec27ce0aa..1340382eaa 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -102,6 +102,22 @@ void PackedData::add_pack_source(PackSource *p_source) { } } +uint8_t *PackedData::get_file_hash(const String &p_path) { + PathMD5 pmd5(p_path.md5_buffer()); + HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5); + if (!E || E->value.offset == 0) { + return nullptr; + } + + return E->value.md5; +} + +void PackedData::clear() { + files.clear(); + _free_packed_dirs(root); + root = memnew(PackedDir); +} + PackedData *PackedData::singleton = nullptr; PackedData::PackedData() { diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 595a36bca4..57b7a5f87f 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -111,6 +111,7 @@ private: public: void add_pack_source(PackSource *p_source); void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource + uint8_t *get_file_hash(const String &p_path); void set_disabled(bool p_disabled) { disabled = p_disabled; } _FORCE_INLINE_ bool is_disabled() const { return disabled; } @@ -118,6 +119,8 @@ public: static PackedData *get_singleton() { return singleton; } Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset); + void clear(); + _FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path); _FORCE_INLINE_ bool has_path(const String &p_path); diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index 0329ace313..614f81c42a 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -299,7 +299,7 @@ Ref<StreamPeer> PacketPeerStream::get_stream_peer() const { void PacketPeerStream::set_input_buffer_max_size(int p_max_size) { ERR_FAIL_COND_MSG(p_max_size < 0, "Max size of input buffer size cannot be smaller than 0."); - //warning may lose packets + // WARNING: May lose packets. ERR_FAIL_COND_MSG(ring_buffer.data_left(), "Buffer in use, resizing would cause loss of data."); ring_buffer.resize(nearest_shift(next_power_of_2(p_max_size + 4)) - 1); input_buffer.resize(next_power_of_2(p_max_size + 4)); diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index a572dd562e..1ae50d2d0d 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -507,7 +507,7 @@ bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) con for (int i = 0; i < importers.size(); i++) { if (importers[i]->get_importer_name() == pat.importer) { - if (!importers[i]->are_import_settings_valid(p_path)) { //importer thinks this is not valid + if (!importers[i]->are_import_settings_valid(p_path, pat.metadata)) { //importer thinks this is not valid return false; } } diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 6ea5d0972a..221f38494b 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -153,7 +153,7 @@ public: virtual void import_threaded_end() {} virtual Error import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) { return ERR_UNAVAILABLE; } - virtual bool are_import_settings_valid(const String &p_path) const { return true; } + virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const { return true; } virtual String get_import_settings_string() const { return String(); } }; diff --git a/core/math/SCsub b/core/math/SCsub index c8fdac207e..6ea3ab6b12 100644 --- a/core/math/SCsub +++ b/core/math/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 476577508f..1ee7d3d84f 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -39,16 +39,19 @@ class String; struct [[nodiscard]] Transform2D { - // Warning #1: basis of Transform2D is stored differently from Basis. In terms of columns array, the basis matrix looks like "on paper": + // WARNING: The basis of Transform2D is stored differently from Basis. + // In terms of columns array, the basis matrix looks like "on paper": // M = (columns[0][0] columns[1][0]) // (columns[0][1] columns[1][1]) - // This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as columns[i]. - // Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to columns[1][0] here. + // This is such that the columns, which can be interpreted as basis vectors + // of the coordinate system "painted" on the object, can be accessed as columns[i]. + // NOTE: This is the opposite of the indices in mathematical texts, + // meaning: $M_{12}$ in a math book corresponds to columns[1][0] here. // This requires additional care when working with explicit indices. // See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading. - // Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down, - // and angle is measure from +X to +Y in a clockwise-fashion. + // WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system: + // Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion. Vector2 columns[3]; diff --git a/core/object/SCsub b/core/object/SCsub index 7c00bb719e..3d0d2c14dd 100644 --- a/core/object/SCsub +++ b/core/object/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h index 1b29e1778a..86c66593bd 100644 --- a/core/object/callable_method_pointer.h +++ b/core/object/callable_method_pointer.h @@ -37,6 +37,8 @@ #include "core/variant/binder_common.h" #include "core/variant/callable.h" +#include <type_traits> + class CallableCustomMethodPointerBase : public CallableCustom { uint32_t *comp_ptr = nullptr; uint32_t comp_size; @@ -77,12 +79,13 @@ public: virtual uint32_t hash() const; }; -template <typename T, typename... P> +template <typename T, typename R, typename... P> class CallableCustomMethodPointer : public CallableCustomMethodPointerBase { struct Data { T *instance; uint64_t object_id; - void (T::*method)(P...); + R(T::*method) + (P...); } data; public: @@ -100,10 +103,14 @@ public: virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); - call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error); + if constexpr (std::is_same<R, void>::value) { + call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error); + } else { + call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); + } } - CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) { + CallableCustomMethodPointer(T *p_instance, R (T::*p_method)(P...)) { memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes. data.instance = p_instance; data.object_id = p_instance->get_instance_id(); @@ -118,7 +125,7 @@ Callable create_custom_callable_function_pointer(T *p_instance, const char *p_func_text, #endif void (T::*p_method)(P...)) { - typedef CallableCustomMethodPointer<T, P...> CCMP; // Messes with memnew otherwise. + typedef CallableCustomMethodPointer<T, void, P...> CCMP; // Messes with memnew otherwise. CCMP *ccmp = memnew(CCMP(p_instance, p_method)); #ifdef DEBUG_METHODS_ENABLED ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. @@ -126,51 +133,13 @@ Callable create_custom_callable_function_pointer(T *p_instance, return Callable(ccmp); } -// VERSION WITH RETURN - -template <typename T, typename R, typename... P> -class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { - struct Data { - T *instance; - uint64_t object_id; - R(T::*method) - (P...); - } data; - -public: - virtual ObjectID get_object() const { - if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) { - return ObjectID(); - } - return data.instance->get_instance_id(); - } - - virtual int get_argument_count(bool &r_is_valid) const { - r_is_valid = true; - return sizeof...(P); - } - - virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { - ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); - call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); - } - - CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) { - memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes. - data.instance = p_instance; - data.object_id = p_instance->get_instance_id(); - data.method = p_method; - _setup((uint32_t *)&data, sizeof(Data)); - } -}; - template <typename T, typename R, typename... P> Callable create_custom_callable_function_pointer(T *p_instance, #ifdef DEBUG_METHODS_ENABLED const char *p_func_text, #endif R (T::*p_method)(P...)) { - typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise. + typedef CallableCustomMethodPointer<T, R, P...> CCMP; // Messes with memnew otherwise. CCMP *ccmp = memnew(CCMP(p_instance, p_method)); #ifdef DEBUG_METHODS_ENABLED ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. @@ -178,10 +147,10 @@ Callable create_custom_callable_function_pointer(T *p_instance, return Callable(ccmp); } -// CONST VERSION WITH RETURN +// CONST VERSION template <typename T, typename R, typename... P> -class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase { +class CallableCustomMethodPointerC : public CallableCustomMethodPointerBase { struct Data { T *instance; uint64_t object_id; @@ -204,10 +173,14 @@ public: virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override { ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); - call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); + if constexpr (std::is_same<R, void>::value) { + call_with_variant_argsc(data.instance, data.method, p_arguments, p_argcount, r_call_error); + } else { + call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); + } } - CallableCustomMethodPointerRetC(T *p_instance, R (T::*p_method)(P...) const) { + CallableCustomMethodPointerC(T *p_instance, R (T::*p_method)(P...) const) { memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes. data.instance = p_instance; data.object_id = p_instance->get_instance_id(); @@ -216,13 +189,27 @@ public: } }; +template <typename T, typename... P> +Callable create_custom_callable_function_pointer(T *p_instance, +#ifdef DEBUG_METHODS_ENABLED + const char *p_func_text, +#endif + void (T::*p_method)(P...) const) { + typedef CallableCustomMethodPointerC<T, void, P...> CCMP; // Messes with memnew otherwise. + CCMP *ccmp = memnew(CCMP(p_instance, p_method)); +#ifdef DEBUG_METHODS_ENABLED + ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. +#endif + return Callable(ccmp); +} + template <typename T, typename R, typename... P> Callable create_custom_callable_function_pointer(T *p_instance, #ifdef DEBUG_METHODS_ENABLED const char *p_func_text, #endif R (T::*p_method)(P...) const) { - typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise. + typedef CallableCustomMethodPointerC<T, R, P...> CCMP; // Messes with memnew otherwise. CCMP *ccmp = memnew(CCMP(p_instance, p_method)); #ifdef DEBUG_METHODS_ENABLED ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. @@ -238,10 +225,11 @@ Callable create_custom_callable_function_pointer(T *p_instance, // STATIC VERSIONS -template <typename... P> +template <typename R, typename... P> class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase { struct Data { - void (*method)(P...); + R(*method) + (P...); } data; public: @@ -259,24 +247,27 @@ public: } virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override { - call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error); - r_return_value = Variant(); + if constexpr (std::is_same<R, void>::value) { + call_with_variant_args_static(data.method, p_arguments, p_argcount, r_call_error); + } else { + call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error); + } } - CallableCustomStaticMethodPointer(void (*p_method)(P...)) { + CallableCustomStaticMethodPointer(R (*p_method)(P...)) { memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes. data.method = p_method; _setup((uint32_t *)&data, sizeof(Data)); } }; -template <typename T, typename... P> +template <typename... P> Callable create_custom_callable_static_function_pointer( #ifdef DEBUG_METHODS_ENABLED const char *p_func_text, #endif void (*p_method)(P...)) { - typedef CallableCustomStaticMethodPointer<P...> CCMP; // Messes with memnew otherwise. + typedef CallableCustomStaticMethodPointer<void, P...> CCMP; // Messes with memnew otherwise. CCMP *ccmp = memnew(CCMP(p_method)); #ifdef DEBUG_METHODS_ENABLED ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. @@ -285,44 +276,12 @@ Callable create_custom_callable_static_function_pointer( } template <typename R, typename... P> -class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase { - struct Data { - R(*method) - (P...); - } data; - -public: - virtual bool is_valid() const override { - return true; - } - - virtual ObjectID get_object() const override { - return ObjectID(); - } - - virtual int get_argument_count(bool &r_is_valid) const override { - r_is_valid = true; - return sizeof...(P); - } - - virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override { - call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error); - } - - CallableCustomStaticMethodPointerRet(R (*p_method)(P...)) { - memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes. - data.method = p_method; - _setup((uint32_t *)&data, sizeof(Data)); - } -}; - -template <typename R, typename... P> Callable create_custom_callable_static_function_pointer( #ifdef DEBUG_METHODS_ENABLED const char *p_func_text, #endif R (*p_method)(P...)) { - typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP; // Messes with memnew otherwise. + typedef CallableCustomStaticMethodPointer<R, P...> CCMP; // Messes with memnew otherwise. CCMP *ccmp = memnew(CCMP(p_method)); #ifdef DEBUG_METHODS_ENABLED ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. diff --git a/core/os/SCsub b/core/os/SCsub index 19a6549225..ab81175894 100644 --- a/core/os/SCsub +++ b/core/os/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/string/SCsub b/core/string/SCsub index 3217166f18..b06e32eb88 100644 --- a/core/string/SCsub +++ b/core/string/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/templates/SCsub b/core/templates/SCsub index 8c4c843a33..7f806d5609 100644 --- a/core/templates/SCsub +++ b/core/templates/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/variant/SCsub b/core/variant/SCsub index 7f4c8b7788..8264503a22 100644 --- a/core/variant/SCsub +++ b/core/variant/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index fa49767d46..0aa49f6d68 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -466,7 +466,7 @@ void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, con return; } #endif - call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); + call_with_variant_argsc_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); } template <typename T, typename... P> @@ -830,7 +830,7 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar } template <typename... P> -void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { +void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) { #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; diff --git a/doc/classes/EditorExportPlatform.xml b/doc/classes/EditorExportPlatform.xml index d4084e84a0..8792bbedc3 100644 --- a/doc/classes/EditorExportPlatform.xml +++ b/doc/classes/EditorExportPlatform.xml @@ -42,6 +42,18 @@ Creates a PCK archive at [param path] for the specified [param preset]. </description> </method> + <method name="export_pack_patch"> + <return type="int" enum="Error" /> + <param index="0" name="preset" type="EditorExportPreset" /> + <param index="1" name="debug" type="bool" /> + <param index="2" name="path" type="String" /> + <param index="3" name="patches" type="PackedStringArray" default="PackedStringArray()" /> + <param index="4" name="flags" type="int" enum="EditorExportPlatform.DebugFlags" is_bitfield="true" default="0" /> + <description> + Creates a patch PCK archive at [param path] for the specified [param preset], containing only the files that have changed since the last patch. + [b]Note:[/b] [param patches] is an optional override of the set of patches defined in the export preset. When empty the patches defined in the export preset will be used instead. + </description> + </method> <method name="export_project"> <return type="int" enum="Error" /> <param index="0" name="preset" type="EditorExportPreset" /> @@ -75,6 +87,18 @@ Create a ZIP archive at [param path] for the specified [param preset]. </description> </method> + <method name="export_zip_patch"> + <return type="int" enum="Error" /> + <param index="0" name="preset" type="EditorExportPreset" /> + <param index="1" name="debug" type="bool" /> + <param index="2" name="path" type="String" /> + <param index="3" name="patches" type="PackedStringArray" default="PackedStringArray()" /> + <param index="4" name="flags" type="int" enum="EditorExportPlatform.DebugFlags" is_bitfield="true" default="0" /> + <description> + Create a patch ZIP archive at [param path] for the specified [param preset], containing only the files that have changed since the last patch. + [b]Note:[/b] [param patches] is an optional override of the set of patches defined in the export preset. When empty the patches defined in the export preset will be used instead. + </description> + </method> <method name="find_export_template" qualifiers="const"> <return type="Dictionary" /> <param index="0" name="template_file_name" type="String" /> @@ -151,6 +175,15 @@ If [param embed] is [code]true[/code], PCK content is appended to the end of [param path] file and return [Dictionary] additionally include following keys: [code]embedded_start: int[/code] (embedded PCK offset) and [code]embedded_size: int[/code] (embedded PCK size). </description> </method> + <method name="save_pack_patch"> + <return type="Dictionary" /> + <param index="0" name="preset" type="EditorExportPreset" /> + <param index="1" name="debug" type="bool" /> + <param index="2" name="path" type="String" /> + <description> + Saves patch PCK archive and returns [Dictionary] with the following keys: [code]result: Error[/code], [code]so_files: Array[/code] (array of the shared/static objects which contains dictionaries with the following keys: [code]path: String[/code], [code]tags: PackedStringArray[/code], and [code]target_folder: String[/code]). + </description> + </method> <method name="save_zip"> <return type="Dictionary" /> <param index="0" name="preset" type="EditorExportPreset" /> @@ -160,6 +193,15 @@ Saves ZIP archive and returns [Dictionary] with the following keys: [code]result: Error[/code], [code]so_files: Array[/code] (array of the shared/static objects which contains dictionaries with the following keys: [code]path: String[/code], [code]tags: PackedStringArray[/code], and [code]target_folder: String[/code]). </description> </method> + <method name="save_zip_patch"> + <return type="Dictionary" /> + <param index="0" name="preset" type="EditorExportPreset" /> + <param index="1" name="debug" type="bool" /> + <param index="2" name="path" type="String" /> + <description> + Saves patch ZIP archive and returns [Dictionary] with the following keys: [code]result: Error[/code], [code]so_files: Array[/code] (array of the shared/static objects which contains dictionaries with the following keys: [code]path: String[/code], [code]tags: PackedStringArray[/code], and [code]target_folder: String[/code]). + </description> + </method> <method name="ssh_push_to_remote" qualifiers="const"> <return type="int" enum="Error" /> <param index="0" name="host" type="String" /> diff --git a/doc/classes/EditorExportPlatformExtension.xml b/doc/classes/EditorExportPlatformExtension.xml index ef589e2f58..f2d14b1710 100644 --- a/doc/classes/EditorExportPlatformExtension.xml +++ b/doc/classes/EditorExportPlatformExtension.xml @@ -36,7 +36,21 @@ <description> [b]Optional.[/b] Creates a PCK archive at [param path] for the specified [param preset]. - This method is called when "Export PCK/ZIP" button is pressed in the export dialog, and PCK is selected as a file type. + This method is called when "Export PCK/ZIP" button is pressed in the export dialog, with "Export as Patch" disabled, and PCK is selected as a file type. + </description> + </method> + <method name="_export_pack_patch" qualifiers="virtual"> + <return type="int" enum="Error" /> + <param index="0" name="preset" type="EditorExportPreset" /> + <param index="1" name="debug" type="bool" /> + <param index="2" name="path" type="String" /> + <param index="3" name="patches" type="PackedStringArray" /> + <param index="4" name="flags" type="int" enum="EditorExportPlatform.DebugFlags" is_bitfield="true" /> + <description> + [b]Optional.[/b] + Creates a patch PCK archive at [param path] for the specified [param preset], containing only the files that have changed since the last patch. + This method is called when "Export PCK/ZIP" button is pressed in the export dialog, with "Export as Patch" enabled, and PCK is selected as a file type. + [b]Note:[/b] The patches provided in [param patches] have already been loaded when this method is called and are merely provided as context. When empty the patches defined in the export preset have been loaded instead. </description> </method> <method name="_export_project" qualifiers="virtual"> @@ -61,7 +75,21 @@ <description> [b]Optional.[/b] Create a ZIP archive at [param path] for the specified [param preset]. - This method is called when "Export PCK/ZIP" button is pressed in the export dialog, and ZIP is selected as a file type. + This method is called when "Export PCK/ZIP" button is pressed in the export dialog, with "Export as Patch" disabled, and ZIP is selected as a file type. + </description> + </method> + <method name="_export_zip_patch" qualifiers="virtual"> + <return type="int" enum="Error" /> + <param index="0" name="preset" type="EditorExportPreset" /> + <param index="1" name="debug" type="bool" /> + <param index="2" name="path" type="String" /> + <param index="3" name="patches" type="PackedStringArray" /> + <param index="4" name="flags" type="int" enum="EditorExportPlatform.DebugFlags" is_bitfield="true" /> + <description> + [b]Optional.[/b] + Create a ZIP archive at [param path] for the specified [param preset], containing only the files that have changed since the last patch. + This method is called when "Export PCK/ZIP" button is pressed in the export dialog, with "Export as Patch" enabled, and ZIP is selected as a file type. + [b]Note:[/b] The patches provided in [param patches] have already been loaded when this method is called and are merely provided as context. When empty the patches defined in the export preset have been loaded instead. </description> </method> <method name="_get_binary_extensions" qualifiers="virtual const"> diff --git a/doc/classes/EditorExportPreset.xml b/doc/classes/EditorExportPreset.xml index bba79364e4..314f74340a 100644 --- a/doc/classes/EditorExportPreset.xml +++ b/doc/classes/EditorExportPreset.xml @@ -109,6 +109,12 @@ Returns export option value or value of environment variable if it is set. </description> </method> + <method name="get_patches" qualifiers="const"> + <return type="PackedStringArray" /> + <description> + Returns the list of packs on which to base a patch export on. + </description> + </method> <method name="get_preset_name" qualifiers="const"> <return type="String" /> <description> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 4b2ce6f45e..a57f6adec8 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -2639,6 +2639,9 @@ - Position + Custom data: 16 floats (12 floats for Transform3D, 4 floats of custom data) - Position + Vertex color + Custom data: 20 floats (12 floats for Transform3D, 4 floats for Color, 4 floats of custom data) [/codeblock] + Instance transforms are in row-major order. Specifically: + - For [Transform2D] the float-order is: [code](x.x, y.x, padding_float, origin.x, x.y, y.y, padding_float, origin.y)[/code]. + - For [Transform3D] the float-order is: [code](basis.x.x, basis.y.x, basis.z.x, origin.x, basis.x.y, basis.y.y, basis.z.y, origin.y, basis.x.z, basis.y.z, basis.z.z, origin.z)[/code]. </description> </method> <method name="multimesh_set_buffer_interpolated"> diff --git a/drivers/SCsub b/drivers/SCsub index 44d29fb7c1..219c4451ee 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/alsa/SCsub b/drivers/alsa/SCsub index f17acb0f91..6242d0e359 100644 --- a/drivers/alsa/SCsub +++ b/drivers/alsa/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/alsamidi/SCsub b/drivers/alsamidi/SCsub index 4e1b5f2a36..69d667c57b 100644 --- a/drivers/alsamidi/SCsub +++ b/drivers/alsamidi/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/backtrace/SCsub b/drivers/backtrace/SCsub index f61fb21581..cc2cf0a6d8 100644 --- a/drivers/backtrace/SCsub +++ b/drivers/backtrace/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/coreaudio/SCsub b/drivers/coreaudio/SCsub index 4e1b5f2a36..69d667c57b 100644 --- a/drivers/coreaudio/SCsub +++ b/drivers/coreaudio/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/coremidi/SCsub b/drivers/coremidi/SCsub index 4e1b5f2a36..69d667c57b 100644 --- a/drivers/coremidi/SCsub +++ b/drivers/coremidi/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/d3d12/SCsub b/drivers/d3d12/SCsub index 482a549189..b6ceed23ac 100644 --- a/drivers/d3d12/SCsub +++ b/drivers/d3d12/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * import os from pathlib import Path diff --git a/drivers/egl/SCsub b/drivers/egl/SCsub index 1fd15b4bae..3a9b484b83 100644 --- a/drivers/egl/SCsub +++ b/drivers/egl/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub index ce6ea747b1..a2ba425990 100644 --- a/drivers/gl_context/SCsub +++ b/drivers/gl_context/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/gles3/SCsub b/drivers/gles3/SCsub index 506312df80..4f4b33de03 100644 --- a/drivers/gles3/SCsub +++ b/drivers/gles3/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/gles3/effects/SCsub b/drivers/gles3/effects/SCsub index 91e1140b75..9ad6234fbe 100644 --- a/drivers/gles3/effects/SCsub +++ b/drivers/gles3/effects/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/gles3/environment/SCsub b/drivers/gles3/environment/SCsub index 91e1140b75..9ad6234fbe 100644 --- a/drivers/gles3/environment/SCsub +++ b/drivers/gles3/environment/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index e70912cb4d..df2c515035 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/gles3/shaders/effects/SCsub b/drivers/gles3/shaders/effects/SCsub index 38b185ed88..387c317b90 100644 --- a/drivers/gles3/shaders/effects/SCsub +++ b/drivers/gles3/shaders/effects/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/gles3/storage/SCsub b/drivers/gles3/storage/SCsub index 91e1140b75..9ad6234fbe 100644 --- a/drivers/gles3/storage/SCsub +++ b/drivers/gles3/storage/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/metal/SCsub b/drivers/metal/SCsub index 30129b7806..f597580763 100644 --- a/drivers/metal/SCsub +++ b/drivers/metal/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/png/SCsub b/drivers/png/SCsub index e38f3c4760..fce37257b1 100644 --- a/drivers/png/SCsub +++ b/drivers/png/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/pulseaudio/SCsub b/drivers/pulseaudio/SCsub index f48489d787..6a76ff6d85 100644 --- a/drivers/pulseaudio/SCsub +++ b/drivers/pulseaudio/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub index 146563a3b6..bca4acfd74 100644 --- a/drivers/unix/SCsub +++ b/drivers/unix/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 32f2d7dd79..3d584341ed 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -294,7 +294,6 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) { if (!err) { return status.st_mtime; } else { - WARN_PRINT("Failed to get modified time for: " + p_file); return 0; } } diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub index 1efef5ad77..6ea7cc9a3b 100644 --- a/drivers/vulkan/SCsub +++ b/drivers/vulkan/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/wasapi/SCsub b/drivers/wasapi/SCsub index 4e1b5f2a36..69d667c57b 100644 --- a/drivers/wasapi/SCsub +++ b/drivers/wasapi/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/windows/SCsub b/drivers/windows/SCsub index 91e1140b75..9ad6234fbe 100644 --- a/drivers/windows/SCsub +++ b/drivers/windows/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 9d6aa13332..a8a2ea6b5e 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -445,7 +445,6 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) { } } - print_verbose("Failed to get modified time for: " + p_file); return 0; } diff --git a/drivers/winmidi/SCsub b/drivers/winmidi/SCsub index 4e1b5f2a36..69d667c57b 100644 --- a/drivers/winmidi/SCsub +++ b/drivers/winmidi/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/drivers/xaudio2/SCsub b/drivers/xaudio2/SCsub index 6778ad281e..cd210466a2 100644 --- a/drivers/xaudio2/SCsub +++ b/drivers/xaudio2/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/SCsub b/editor/SCsub index 029048969a..9fcaf61245 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/debugger/SCsub b/editor/debugger/SCsub index 99f1c888f0..e26d09d88b 100644 --- a/editor/debugger/SCsub +++ b/editor/debugger/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/debugger/debug_adapter/SCsub b/editor/debugger/debug_adapter/SCsub index 359d04e5df..b3cff5b9dc 100644 --- a/editor/debugger/debug_adapter/SCsub +++ b/editor/debugger/debug_adapter/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 2b51071b15..bc46d01892 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -282,6 +282,21 @@ void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_sca } for (const String &scan_file : p_scan_dir->files) { + // Optimization to skip the ResourceLoader::get_resource_type for files + // that are not scripts. Some loader get_resource_type methods read the file + // which can be very slow on large projects. + String ext = scan_file.get_extension().to_lower(); + bool is_script = false; + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + if (ScriptServer::get_language(i)->get_extension() == ext) { + is_script = true; + break; + } + } + if (!is_script) { + continue; // Not a script. + } + String path = p_scan_dir->full_path.path_join(scan_file); String type = ResourceLoader::get_resource_type(path); @@ -371,6 +386,11 @@ void EditorFileSystem::_scan_filesystem() { fc.script_class_name = split[7].get_slice("<>", 0); fc.script_class_extends = split[7].get_slice("<>", 1); fc.script_class_icon_path = split[7].get_slice("<>", 2); + fc.import_md5 = split[7].get_slice("<>", 3); + String dest_paths = split[7].get_slice("<>", 4); + if (!dest_paths.is_empty()) { + fc.import_dest_paths = dest_paths.split("<*>"); + } String deps = split[8].strip_edges(); if (deps.length()) { @@ -463,12 +483,33 @@ void EditorFileSystem::_thread_func(void *_userdata) { sd->_scan_filesystem(); } -bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_imported_files) { - if (!reimport_on_missing_imported_files && p_only_imported_files) { - return false; +bool EditorFileSystem::_is_test_for_reimport_needed(const String &p_path, uint64_t p_last_modification_time, uint64_t p_modification_time, uint64_t p_last_import_modification_time, uint64_t p_import_modification_time, const Vector<String> &p_import_dest_paths) { + // The idea here is to trust the cache. If the last modification times in the cache correspond + // to the last modification times of the files on disk, it means the files have not changed since + // the last import, and the files in .godot/imported (p_import_dest_paths) should all be valid. + if (p_last_modification_time != p_modification_time) { + return true; + } + if (p_last_import_modification_time != p_import_modification_time) { + return true; + } + if (reimport_on_missing_imported_files) { + for (const String &path : p_import_dest_paths) { + if (!FileAccess::exists(path)) { + return true; + } + } } + return false; +} - if (!FileAccess::exists(p_path + ".import")) { +bool EditorFileSystem::_test_for_reimport(const String &p_path, const String &p_expected_import_md5) { + if (p_expected_import_md5.is_empty()) { + // Marked as reimportation needed. + return true; + } + String new_md5 = FileAccess::get_md5(p_path + ".import"); + if (p_expected_import_md5 != new_md5) { return true; } @@ -489,7 +530,7 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo int lines = 0; String error_text; - List<String> to_check; + Vector<String> to_check; String importer_name; String source_file = ""; @@ -498,6 +539,7 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo String dest_md5 = ""; int version = 0; bool found_uid = false; + Variant meta; while (true) { assign = Variant(); @@ -522,8 +564,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo to_check.push_back(value); } else if (assign == "files") { Array fa = value; - for (int i = 0; i < fa.size(); i++) { - to_check.push_back(fa[i]); + for (const Variant &check_path : fa) { + to_check.push_back(check_path); } } else if (assign == "importer_version") { version = value; @@ -531,12 +573,12 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo importer_name = value; } else if (assign == "uid") { found_uid = true; - } else if (!p_only_imported_files) { - if (assign == "source_file") { - source_file = value; - } else if (assign == "dest_files") { - dest_files = value; - } + } else if (assign == "source_file") { + source_file = value; + } else if (assign == "dest_files") { + dest_files = value; + } else if (assign == "metadata") { + meta = value; } } else if (next_tag.name != "remap" && next_tag.name != "deps") { @@ -544,33 +586,40 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo } } - if (!ResourceFormatImporter::get_singleton()->are_import_settings_valid(p_path)) { - // Reimport settings are out of sync with project settings, reimport. - return true; - } - if (importer_name == "keep" || importer_name == "skip") { - return false; //keep mode, do not reimport + return false; // Keep mode, do not reimport. } if (!found_uid) { - return true; //UID not found, old format, reimport. + return true; // UID not found, old format, reimport. + } + + // Imported files are gone, reimport. + for (const String &E : to_check) { + if (!FileAccess::exists(E)) { + return true; + } } Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); if (importer.is_null()) { - return true; // the importer has possibly changed, try to reimport. + return true; // The importer has possibly changed, try to reimport. } if (importer->get_format_version() > version) { - return true; // version changed, reimport + return true; // Version changed, reimport. + } + + if (!importer->are_import_settings_valid(p_path, meta)) { + // Reimport settings are out of sync with project settings, reimport. + return true; } - // Read the md5's from a separate file (so the import parameters aren't dependent on the file version + // Read the md5's from a separate file (so the import parameters aren't dependent on the file version). String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_path); Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err); - if (md5s.is_null()) { // No md5's stored for this resource + if (md5s.is_null()) { // No md5's stored for this resource. return true; } @@ -588,50 +637,101 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo break; } else if (err != OK) { ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import.md5:" + itos(lines) + "' error '" + error_text + "'."); - return false; // parse error + return false; // Parse error. } if (!assign.is_empty()) { - if (!p_only_imported_files) { - if (assign == "source_md5") { - source_md5 = value; - } else if (assign == "dest_md5") { - dest_md5 = value; - } + if (assign == "source_md5") { + source_md5 = value; + } else if (assign == "dest_md5") { + dest_md5 = value; } } } - //imported files are gone, reimport - for (const String &E : to_check) { - if (!FileAccess::exists(E)) { + // Check source md5 matching. + if (!source_file.is_empty() && source_file != p_path) { + return true; // File was moved, reimport. + } + + if (source_md5.is_empty()) { + return true; // Lacks md5, so just reimport. + } + + String md5 = FileAccess::get_md5(p_path); + if (md5 != source_md5) { + return true; + } + + if (!dest_files.is_empty() && !dest_md5.is_empty()) { + md5 = FileAccess::get_multiple_md5(dest_files); + if (md5 != dest_md5) { return true; } } - //check source md5 matching - if (!p_only_imported_files) { - if (!source_file.is_empty() && source_file != p_path) { - return true; //file was moved, reimport - } + return false; // Nothing changed. +} - if (source_md5.is_empty()) { - return true; //lacks md5, so just reimport - } +Vector<String> EditorFileSystem::_get_import_dest_paths(const String &p_path) { + Error err; + Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err); - String md5 = FileAccess::get_md5(p_path); - if (md5 != source_md5) { - return true; + if (f.is_null()) { // No import file, reimport. + return Vector<String>(); + } + + VariantParser::StreamFile stream; + stream.f = f; + + String assign; + Variant value; + VariantParser::Tag next_tag; + + int lines = 0; + String error_text; + + Vector<String> dest_paths; + String importer_name; + + while (true) { + assign = Variant(); + next_tag.fields.clear(); + next_tag.name = String(); + + err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true); + if (err == ERR_FILE_EOF) { + break; + } else if (err != OK) { + ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import:" + itos(lines) + "' error '" + error_text + "'."); + // Parse error, skip and let user attempt manual reimport to avoid reimport loop. + return Vector<String>(); } - if (dest_files.size() && !dest_md5.is_empty()) { - md5 = FileAccess::get_multiple_md5(dest_files); - if (md5 != dest_md5) { - return true; + if (!assign.is_empty()) { + if (assign == "valid" && value.operator bool() == false) { + // Invalid import (failed previous import), skip and let user attempt manual reimport to avoid reimport loop. + return Vector<String>(); + } + if (assign.begins_with("path")) { + dest_paths.push_back(value); + } else if (assign == "files") { + Array fa = value; + for (const Variant &dest_path : fa) { + dest_paths.push_back(dest_path); + } + } else if (assign == "importer") { + importer_name = value; } + } else if (next_tag.name != "remap" && next_tag.name != "deps") { + break; } } - return false; //nothing changed + if (importer_name == "keep" || importer_name == "skip") { + return Vector<String>(); + } + + return dest_paths; } bool EditorFileSystem::_scan_import_support(const Vector<String> &reimports) { @@ -774,20 +874,9 @@ bool EditorFileSystem::_update_scan_actions() { ERR_CONTINUE(idx == -1); String full_path = ia.dir->get_file_path(idx); - bool need_reimport = _test_for_reimport(full_path, false); - // Workaround GH-94416 for the Android editor for now. - // `import_mt` seems to always be 0 and force a reimport on any fs scan. -#ifndef ANDROID_ENABLED - if (!need_reimport && FileAccess::exists(full_path + ".import")) { - uint64_t import_mt = ia.dir->get_file_import_modified_time(idx); - if (import_mt != FileAccess::get_modified_time(full_path + ".import")) { - need_reimport = true; - } - } -#endif - + bool need_reimport = _test_for_reimport(full_path, ia.dir->files[idx]->import_md5); if (need_reimport) { - //must reimport + // Must reimport. reimports.push_back(full_path); Vector<String> dependencies = _get_dependencies(full_path); for (const String &dep : dependencies) { @@ -797,10 +886,14 @@ bool EditorFileSystem::_update_scan_actions() { } } } else { - //must not reimport, all was good - //update modified times, to avoid reimport + // Must not reimport, all was good. + // Update modified times, md5 and destination paths, to avoid reimport. ia.dir->files[idx]->modified_time = FileAccess::get_modified_time(full_path); ia.dir->files[idx]->import_modified_time = FileAccess::get_modified_time(full_path + ".import"); + if (ia.dir->files[idx]->import_md5.is_empty()) { + ia.dir->files[idx]->import_md5 = FileAccess::get_md5(full_path + ".import"); + } + ia.dir->files[idx]->import_dest_paths = _get_import_dest_paths(full_path); } fs_changed = true; @@ -1029,26 +1122,36 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir, if (import_extensions.has(ext)) { //is imported - uint64_t import_mt = 0; - if (FileAccess::exists(path + ".import")) { - import_mt = FileAccess::get_modified_time(path + ".import"); - } + uint64_t import_mt = FileAccess::get_modified_time(path + ".import"); - if (fc && fc->modification_time == mt && fc->import_modification_time == import_mt && !_test_for_reimport(path, true)) { + if (fc) { fi->type = fc->type; fi->resource_script_class = fc->resource_script_class; fi->uid = fc->uid; fi->deps = fc->deps; - fi->modified_time = fc->modification_time; - fi->import_modified_time = fc->import_modification_time; - + fi->modified_time = mt; + fi->import_modified_time = import_mt; + fi->import_md5 = fc->import_md5; + fi->import_dest_paths = fc->import_dest_paths; fi->import_valid = fc->import_valid; fi->script_class_name = fc->script_class_name; fi->import_group_file = fc->import_group_file; fi->script_class_extends = fc->script_class_extends; fi->script_class_icon_path = fc->script_class_icon_path; - if (revalidate_import_files && !ResourceFormatImporter::get_singleton()->are_import_settings_valid(path)) { + // Ensures backward compatibility when the project is loaded for the first time with the added import_md5 + // and import_dest_paths properties in the file cache. + if (fc->import_md5.is_empty()) { + fi->import_md5 = FileAccess::get_md5(path + ".import"); + fi->import_dest_paths = _get_import_dest_paths(path); + } + + // The method _is_test_for_reimport_needed checks if the files were modified and ensures that + // all the destination files still exist without reading the .import file. + // If something is different, we will queue a test for reimportation that will check + // the md5 of all files and import settings and, if necessary, execute a reimportation. + if (_is_test_for_reimport_needed(path, fc->modification_time, mt, fc->import_modification_time, import_mt, fi->import_dest_paths) || + (revalidate_import_files && !ResourceFormatImporter::get_singleton()->are_import_settings_valid(path))) { ItemAction ia; ia.action = ItemAction::ACTION_FILE_TEST_REIMPORT; ia.dir = p_dir; @@ -1075,6 +1178,8 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir, fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->modified_time = 0; fi->import_modified_time = 0; + fi->import_md5 = ""; + fi->import_dest_paths = Vector<String>(); fi->import_valid = (fi->type == "TextFile" || fi->type == "OtherFile") ? true : ResourceLoader::is_import_valid(path); ItemAction ia; @@ -1089,9 +1194,11 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir, fi->type = fc->type; fi->resource_script_class = fc->resource_script_class; fi->uid = fc->uid; - fi->modified_time = fc->modification_time; + fi->modified_time = mt; fi->deps = fc->deps; fi->import_modified_time = 0; + fi->import_md5 = ""; + fi->import_dest_paths = Vector<String>(); fi->import_valid = true; fi->script_class_name = fc->script_class_name; fi->script_class_extends = fc->script_class_extends; @@ -1126,6 +1233,8 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir, fi->deps = _get_dependencies(path); fi->modified_time = mt; fi->import_modified_time = 0; + fi->import_md5 = ""; + fi->import_dest_paths = Vector<String>(); fi->import_valid = true; // Files in dep_update_list are forced for rescan to update dependencies. They don't need other updates. @@ -1269,6 +1378,8 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanPr String path = cd.path_join(fi->file); fi->modified_time = FileAccess::get_modified_time(path); fi->import_modified_time = 0; + fi->import_md5 = ""; + fi->import_dest_paths = Vector<String>(); fi->type = ResourceLoader::get_resource_type(path); fi->resource_script_class = ResourceLoader::get_resource_script_class(path); if (fi->type == "" && textfile_extensions.has(ext)) { @@ -1323,26 +1434,13 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanPr String path = cd.path_join(p_dir->files[i]->file); if (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) { - //check here if file must be imported or not - + // Check here if file must be imported or not. + // Same logic as in _process_file_system, the last modifications dates + // needs to be trusted to prevent reading all the .import files and the md5 + // each time the user switch back to Godot. uint64_t mt = FileAccess::get_modified_time(path); - - bool reimport = false; - - if (mt != p_dir->files[i]->modified_time) { - reimport = true; //it was modified, must be reimported. - } else if (!FileAccess::exists(path + ".import")) { - reimport = true; //no .import file, obviously reimport - } else { - uint64_t import_mt = FileAccess::get_modified_time(path + ".import"); - if (import_mt != p_dir->files[i]->import_modified_time) { - reimport = true; - } else if (_test_for_reimport(path, true)) { - reimport = true; - } - } - - if (reimport) { + uint64_t import_mt = FileAccess::get_modified_time(path + ".import"); + if (_is_test_for_reimport_needed(path, p_dir->files[i]->modified_time, mt, p_dir->files[i]->import_modified_time, import_mt, p_dir->files[i]->import_dest_paths)) { ItemAction ia; ia.action = ItemAction::ACTION_FILE_TEST_REIMPORT; ia.dir = p_dir; @@ -1625,7 +1723,7 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, cache_string.append(itos(file_info->import_modified_time)); cache_string.append(itos(file_info->import_valid)); cache_string.append(file_info->import_group_file); - cache_string.append(String("<>").join({ file_info->script_class_name, file_info->script_class_extends, file_info->script_class_icon_path })); + cache_string.append(String("<>").join({ file_info->script_class_name, file_info->script_class_extends, file_info->script_class_icon_path, file_info->import_md5, String("<*>").join(file_info->import_dest_paths) })); cache_string.append(String("<>").join(file_info->deps)); p_file->store_line(String("::").join(cache_string)); @@ -1879,6 +1977,10 @@ void EditorFileSystem::_update_file_icon_path(EditorFileSystemDirectory::FileInf } } + if (icon_path.is_empty() && !file_info->type.is_empty()) { + icon_path = EditorNode::get_singleton()->get_class_icon(file_info->type)->get_path(); + } + file_info->icon_path = icon_path; } @@ -2183,6 +2285,8 @@ void EditorFileSystem::update_files(const Vector<String> &p_script_paths) { fi->file = file_name; fi->import_modified_time = 0; fi->import_valid = (type == "TextFile" || type == "OtherFile") ? true : ResourceLoader::is_import_valid(file); + fi->import_md5 = ""; + fi->import_dest_paths = Vector<String>(); if (idx == fs->files.size()) { fs->files.push_back(fi); @@ -2227,7 +2331,7 @@ void EditorFileSystem::update_files(const Vector<String> &p_script_paths) { _queue_update_scene_groups(file); } - if (fs->files[cpos]->type == SNAME("Resource")) { + if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Resource"))) { files_to_update_icon_path.push_back(fs->files[cpos]); } else if (old_script_class_icon_path != fs->files[cpos]->script_class_icon_path) { update_files_icon_cache = true; @@ -2458,6 +2562,8 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector //update modified times, to avoid reimport fs->files[cpos]->modified_time = FileAccess::get_modified_time(file); fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(file + ".import"); + fs->files[cpos]->import_md5 = FileAccess::get_md5(file + ".import"); + fs->files[cpos]->import_dest_paths = dest_paths; fs->files[cpos]->deps = _get_dependencies(file); fs->files[cpos]->uid = uid; fs->files[cpos]->type = importer->get_resource_type(); @@ -2559,11 +2665,13 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin if (p_update_file_system) { fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import"); + fs->files[cpos]->import_md5 = FileAccess::get_md5(p_file + ".import"); + fs->files[cpos]->import_dest_paths = Vector<String>(); fs->files[cpos]->deps.clear(); fs->files[cpos]->type = ""; fs->files[cpos]->import_valid = false; + EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); } - EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); return OK; } Ref<ResourceImporter> importer; @@ -2729,6 +2837,8 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin // Update modified times, to avoid reimport. fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import"); + fs->files[cpos]->import_md5 = FileAccess::get_md5(p_file + ".import"); + fs->files[cpos]->import_dest_paths = dest_paths; fs->files[cpos]->deps = _get_dependencies(p_file); fs->files[cpos]->type = importer->get_resource_type(); fs->files[cpos]->uid = uid; diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index e53187c1d7..255eaff10d 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -60,6 +60,8 @@ class EditorFileSystemDirectory : public Object { ResourceUID::ID uid = ResourceUID::INVALID_ID; uint64_t modified_time = 0; uint64_t import_modified_time = 0; + String import_md5; + Vector<String> import_dest_paths; bool import_valid = false; String import_group_file; Vector<String> deps; @@ -206,6 +208,8 @@ class EditorFileSystem : public Node { ResourceUID::ID uid = ResourceUID::INVALID_ID; uint64_t modification_time = 0; uint64_t import_modification_time = 0; + String import_md5; + Vector<String> import_dest_paths; Vector<String> deps; bool import_valid = false; String import_group_file; @@ -264,7 +268,9 @@ class EditorFileSystem : public Node { Error _reimport_file(const String &p_file, const HashMap<StringName, Variant> &p_custom_options = HashMap<StringName, Variant>(), const String &p_custom_importer = String(), Variant *generator_parameters = nullptr, bool p_update_file_system = true); Error _reimport_group(const String &p_group_file, const Vector<String> &p_files); - bool _test_for_reimport(const String &p_path, bool p_only_imported_files); + bool _test_for_reimport(const String &p_path, const String &p_expected_import_md5); + bool _is_test_for_reimport_needed(const String &p_path, uint64_t p_last_modification_time, uint64_t p_modification_time, uint64_t p_last_import_modification_time, uint64_t p_import_modification_time, const Vector<String> &p_import_dest_paths); + Vector<String> _get_import_dest_paths(const String &p_path); bool reimport_on_missing_imported_files; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f248d03140..665255b9b2 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1007,9 +1007,17 @@ void EditorNode::_fs_changed() { export_preset->update_value_overrides(); if (export_defer.pack_only) { // Only export .pck or .zip data pack. if (export_path.ends_with(".zip")) { - err = platform->export_zip(export_preset, export_defer.debug, export_path); + if (export_defer.patch) { + err = platform->export_zip_patch(export_preset, export_defer.debug, export_path, export_defer.patches); + } else { + err = platform->export_zip(export_preset, export_defer.debug, export_path); + } } else if (export_path.ends_with(".pck")) { - err = platform->export_pack(export_preset, export_defer.debug, export_path); + if (export_defer.patch) { + err = platform->export_pack_patch(export_preset, export_defer.debug, export_path, export_defer.patches); + } else { + err = platform->export_pack(export_preset, export_defer.debug, export_path); + } } else { ERR_PRINT(vformat("Export path \"%s\" doesn't end with a supported extension.", export_path)); err = FAILED; @@ -5149,12 +5157,14 @@ void EditorNode::_begin_first_scan() { requested_first_scan = true; } -Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only, bool p_android_build_template) { +Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only, bool p_android_build_template, bool p_patch, const Vector<String> &p_patches) { export_defer.preset = p_preset; export_defer.path = p_path; export_defer.debug = p_debug; export_defer.pack_only = p_pack_only; export_defer.android_build_template = p_android_build_template; + export_defer.patch = p_patch; + export_defer.patches = p_patches; cmdline_export_mode = true; return OK; } diff --git a/editor/editor_node.h b/editor/editor_node.h index 7ef38b4edb..36332e3d78 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -246,6 +246,8 @@ private: bool debug = false; bool pack_only = false; bool android_build_template = false; + bool patch = false; + Vector<String> patches; } export_defer; static EditorNode *singleton; @@ -880,7 +882,7 @@ public: void _copy_warning(const String &p_str); - Error export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only, bool p_android_build_template); + Error export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only, bool p_android_build_template, bool p_patch, const Vector<String> &p_patches); bool is_project_exporting() const; Control *get_gui_base() { return gui_base; } diff --git a/editor/export/SCsub b/editor/export/SCsub index 359d04e5df..b3cff5b9dc 100644 --- a/editor/export/SCsub +++ b/editor/export/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp index 975a601ae1..6ca83c5e25 100644 --- a/editor/export/editor_export.cpp +++ b/editor/export/editor_export.cpp @@ -83,6 +83,8 @@ void EditorExport::_save() { config->set_value(section, "include_filter", preset->get_include_filter()); config->set_value(section, "exclude_filter", preset->get_exclude_filter()); config->set_value(section, "export_path", preset->get_export_path()); + config->set_value(section, "patches", preset->get_patches()); + config->set_value(section, "encryption_include_filters", preset->get_enc_in_filter()); config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter()); config->set_value(section, "encrypt_pck", preset->get_enc_pck()); @@ -303,6 +305,7 @@ void EditorExport::load_config() { preset->set_exclude_filter(config->get_value(section, "exclude_filter")); preset->set_export_path(config->get_value(section, "export_path", "")); preset->set_script_export_mode(config->get_value(section, "script_export_mode", EditorExportPreset::MODE_SCRIPT_BINARY_TOKENS_COMPRESSED)); + preset->set_patches(config->get_value(section, "patches", Vector<String>())); if (config->has_section_key(section, "encrypt_pck")) { preset->set_enc_pck(config->get_value(section, "encrypt_pck")); diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 983f4ee36a..58737c53ed 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -167,6 +167,44 @@ bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) return has_messages; } +bool EditorExportPlatform::_check_hash(const uint8_t *p_hash, const Vector<uint8_t> &p_data) { + if (p_hash == nullptr) { + return false; + } + + unsigned char hash[16]; + Error err = CryptoCore::md5(p_data.ptr(), p_data.size(), hash); + if (err != OK) { + return false; + } + + for (int i = 0; i < 16; i++) { + if (p_hash[i] != hash[i]) { + return false; + } + } + + return true; +} + +Error EditorExportPlatform::_load_patches(const Vector<String> &p_patches) { + Error err = OK; + if (!p_patches.is_empty()) { + for (const String &path : p_patches) { + err = PackedData::get_singleton()->add_pack(path, true, 0); + if (err != OK) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Patch Creation"), vformat(TTR("Could not load patch pack with path \"%s\"."), path)); + return err; + } + } + } + return err; +} + +void EditorExportPlatform::_unload_patches() { + PackedData::get_singleton()->clear(); +} + Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export."); @@ -237,6 +275,14 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa return OK; } +Error EditorExportPlatform::_save_pack_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { + if (_check_hash(PackedData::get_singleton()->get_file_hash(p_path), p_data)) { + return OK; + } + + return _save_pack_file(p_userdata, p_path, p_data, p_file, p_total, p_enc_in_filters, p_enc_ex_filters, p_key); +} + Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { ERR_FAIL_COND_V_MSG(p_total < 1, ERR_PARAMETER_RANGE_ERROR, "Must select at least one file to export."); @@ -260,6 +306,8 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat zipWriteInFileInZip(zip, p_data.ptr(), p_data.size()); zipCloseFileInZip(zip); + zd->file_count += 1; + if (zd->ep->step(TTR("Storing File:") + " " + p_path, 2 + p_file * 100 / p_total, false)) { return ERR_SKIP; } @@ -267,6 +315,14 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat return OK; } +Error EditorExportPlatform::_save_zip_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { + if (_check_hash(PackedData::get_singleton()->get_file_hash(p_path), p_data)) { + return OK; + } + + return _save_zip_file(p_userdata, p_path, p_data, p_file, p_total, p_enc_in_filters, p_enc_ex_filters, p_key); +} + Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const { Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme(); ERR_FAIL_COND_V(theme.is_null(), Ref<ImageTexture>()); @@ -1561,7 +1617,7 @@ Dictionary EditorExportPlatform::_save_pack(const Ref<EditorExportPreset> &p_pre Vector<SharedObject> so_files; int64_t embedded_start = 0; int64_t embedded_size = 0; - Error err_code = save_pack(p_preset, p_debug, p_path, &so_files, p_embed, &embedded_start, &embedded_size); + Error err_code = save_pack(p_preset, p_debug, p_path, &so_files, nullptr, p_embed, &embedded_start, &embedded_size); Dictionary ret; ret["result"] = err_code; @@ -1605,9 +1661,55 @@ Dictionary EditorExportPlatform::_save_zip(const Ref<EditorExportPreset> &p_pres return ret; } -Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { +Dictionary EditorExportPlatform::_save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) { + Vector<SharedObject> so_files; + Error err_code = save_pack_patch(p_preset, p_debug, p_path, &so_files); + + Dictionary ret; + ret["result"] = err_code; + if (err_code == OK) { + Array arr; + for (const SharedObject &E : so_files) { + Dictionary so; + so["path"] = E.path; + so["tags"] = E.tags; + so["target_folder"] = E.target; + arr.push_back(so); + } + ret["so_files"] = arr; + } + + return ret; +} + +Dictionary EditorExportPlatform::_save_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) { + Vector<SharedObject> so_files; + Error err_code = save_zip_patch(p_preset, p_debug, p_path, &so_files); + + Dictionary ret; + ret["result"] = err_code; + if (err_code == OK) { + Array arr; + for (const SharedObject &E : so_files) { + Dictionary so; + so["path"] = E.path; + so["tags"] = E.tags; + so["target_folder"] = E.target; + arr.push_back(so); + } + ret["so_files"] = arr; + } + + return ret; +} + +Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, EditorExportSaveFunction p_save_func, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { EditorProgress ep("savepack", TTR("Packing"), 102, true); + if (p_save_func == nullptr) { + p_save_func = _save_pack_file; + } + // Create the temporary export directory if it doesn't exist. Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); da->make_dir_recursive(EditorPaths::get_singleton()->get_cache_dir()); @@ -1624,7 +1726,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b pd.f = ftmp; pd.so_files = p_so_files; - Error err = export_project_files(p_preset, p_debug, _save_pack_file, &pd, _pack_add_shared_object); + Error err = export_project_files(p_preset, p_debug, p_save_func, &pd, _pack_add_shared_object); // Close temp file. pd.f.unref(); @@ -1636,6 +1738,12 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b return err; } + if (pd.file_ofs.is_empty()) { + DirAccess::remove_file_or_error(tmppath); + add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), TTR("No files or changes to export.")); + return FAILED; + } + pd.file_ofs.sort(); //do sort, so we can do binary search later Ref<FileAccess> f; @@ -1831,28 +1939,56 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b return OK; } -Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files) { +Error EditorExportPlatform::save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, bool p_embed, int64_t *r_embedded_start, int64_t *r_embedded_size) { + return save_pack(p_preset, p_debug, p_path, p_so_files, _save_pack_patch_file, p_embed, r_embedded_start, r_embedded_size); +} + +Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files, EditorExportSaveFunction p_save_func) { EditorProgress ep("savezip", TTR("Packing"), 102, true); + if (p_save_func == nullptr) { + p_save_func = _save_zip_file; + } + + String tmppath = EditorPaths::get_singleton()->get_cache_dir().path_join("packtmp"); + Ref<FileAccess> io_fa; zlib_filefunc_def io = zipio_create_io(&io_fa); - zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io); + zipFile zip = zipOpen2(tmppath.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io); ZipData zd; zd.ep = &ep; zd.zip = zip; zd.so_files = p_so_files; - Error err = export_project_files(p_preset, p_debug, _save_zip_file, &zd, _zip_add_shared_object); + Error err = export_project_files(p_preset, p_debug, p_save_func, &zd, _zip_add_shared_object); if (err != OK && err != ERR_SKIP) { add_message(EXPORT_MESSAGE_ERROR, TTR("Save ZIP"), TTR("Failed to export project files.")); } zipClose(zip, nullptr); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + + if (zd.file_count == 0) { + da->remove(tmppath); + add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), TTR("No files or changes to export.")); + return FAILED; + } + + err = da->rename(tmppath, p_path); + if (err != OK) { + da->remove(tmppath); + add_message(EXPORT_MESSAGE_ERROR, TTR("Save ZIP"), vformat(TTR("Failed to move temporary file \"%s\" to \"%s\"."), tmppath, p_path)); + } + return OK; } +Error EditorExportPlatform::save_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files) { + return save_zip(p_preset, p_debug, p_path, p_so_files, _save_zip_patch_file); +} + Error EditorExportPlatform::export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) { ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); return save_pack(p_preset, p_debug, p_path); @@ -1863,6 +1999,28 @@ Error EditorExportPlatform::export_zip(const Ref<EditorExportPreset> &p_preset, return save_zip(p_preset, p_debug, p_path); } +Error EditorExportPlatform::export_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches, BitField<EditorExportPlatform::DebugFlags> p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); + Error err = _load_patches(p_patches.is_empty() ? p_preset->get_patches() : p_patches); + if (err != OK) { + return err; + } + err = save_pack_patch(p_preset, p_debug, p_path); + _unload_patches(); + return err; +} + +Error EditorExportPlatform::export_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches, BitField<EditorExportPlatform::DebugFlags> p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); + Error err = _load_patches(p_patches.is_empty() ? p_preset->get_patches() : p_patches); + if (err != OK) { + return err; + } + err = save_zip_patch(p_preset, p_debug, p_path); + _unload_patches(); + return err; +} + Vector<String> EditorExportPlatform::gen_export_flags(BitField<EditorExportPlatform::DebugFlags> p_flags) { Vector<String> ret; String host = EDITOR_GET("network/debug/remote_host"); @@ -2115,6 +2273,8 @@ void EditorExportPlatform::_bind_methods() { ClassDB::bind_method(D_METHOD("save_pack", "preset", "debug", "path", "embed"), &EditorExportPlatform::_save_pack, DEFVAL(false)); ClassDB::bind_method(D_METHOD("save_zip", "preset", "debug", "path"), &EditorExportPlatform::_save_zip); + ClassDB::bind_method(D_METHOD("save_pack_patch", "preset", "debug", "path"), &EditorExportPlatform::_save_pack_patch); + ClassDB::bind_method(D_METHOD("save_zip_patch", "preset", "debug", "path"), &EditorExportPlatform::_save_zip_patch); ClassDB::bind_method(D_METHOD("gen_export_flags", "flags"), &EditorExportPlatform::gen_export_flags); @@ -2123,6 +2283,8 @@ void EditorExportPlatform::_bind_methods() { ClassDB::bind_method(D_METHOD("export_project", "preset", "debug", "path", "flags"), &EditorExportPlatform::export_project, DEFVAL(0)); ClassDB::bind_method(D_METHOD("export_pack", "preset", "debug", "path", "flags"), &EditorExportPlatform::export_pack, DEFVAL(0)); ClassDB::bind_method(D_METHOD("export_zip", "preset", "debug", "path", "flags"), &EditorExportPlatform::export_zip, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("export_pack_patch", "preset", "debug", "path", "patches", "flags"), &EditorExportPlatform::export_pack_patch, DEFVAL(PackedStringArray()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("export_zip_patch", "preset", "debug", "path", "patches", "flags"), &EditorExportPlatform::export_zip_patch, DEFVAL(PackedStringArray()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("clear_messages"), &EditorExportPlatform::clear_messages); ClassDB::bind_method(D_METHOD("add_message", "type", "category", "message"), &EditorExportPlatform::add_message); diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h index 95f21ceafb..ef3274c5e4 100644 --- a/editor/export/editor_export_platform.h +++ b/editor/export/editor_export_platform.h @@ -101,6 +101,7 @@ private: void *zip = nullptr; EditorProgress *ep = nullptr; Vector<SharedObject> *so_files = nullptr; + int file_count = 0; }; Vector<ExportMessage> messages; @@ -109,10 +110,14 @@ private: void _export_find_customized_resources(const Ref<EditorExportPreset> &p_preset, EditorFileSystemDirectory *p_dir, EditorExportPreset::FileExportMode p_mode, HashSet<String> &p_paths); void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths); + static bool _check_hash(const uint8_t *p_hash, const Vector<uint8_t> &p_data); + static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error _save_pack_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); static Error _pack_add_shared_object(void *p_userdata, const SharedObject &p_so); static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error _save_zip_patch_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); static Error _zip_add_shared_object(void *p_userdata, const SharedObject &p_so); struct ScriptCallbackData { @@ -188,6 +193,9 @@ protected: Error ssh_run_on_remote_no_wait(const String &p_host, const String &p_port, const Vector<String> &p_ssh_args, const String &p_cmd_args, OS::ProcessID *r_pid = nullptr, int p_port_fwd = -1) const; Error ssh_push_to_remote(const String &p_host, const String &p_port, const Vector<String> &p_scp_args, const String &p_src_file, const String &p_dst_file) const; + Error _load_patches(const Vector<String> &p_patches); + void _unload_patches(); + public: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0; @@ -284,8 +292,14 @@ public: Dictionary _save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, bool p_embed = false); Dictionary _save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); - Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); - Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr); + Dictionary _save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); + Dictionary _save_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); + + Error save_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, EditorExportSaveFunction p_save_func = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); + Error save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, EditorExportSaveFunction p_save_func = nullptr); + + Error save_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr, bool p_embed = false, int64_t *r_embedded_start = nullptr, int64_t *r_embedded_size = nullptr); + Error save_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, Vector<SharedObject> *p_so_files = nullptr); virtual bool poll_export() { return false; } virtual int get_options_count() const { return 0; } @@ -307,6 +321,8 @@ public: virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) = 0; virtual Error export_pack(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0); virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0); + virtual Error export_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0); + virtual Error export_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0); virtual void get_platform_features(List<String> *r_features) const = 0; virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) {} virtual String get_debug_protocol() const { return "tcp://"; } diff --git a/editor/export/editor_export_platform_extension.cpp b/editor/export/editor_export_platform_extension.cpp index 808a2076e2..5b75ff19a4 100644 --- a/editor/export/editor_export_platform_extension.cpp +++ b/editor/export/editor_export_platform_extension.cpp @@ -71,6 +71,8 @@ void EditorExportPlatformExtension::_bind_methods() { GDVIRTUAL_BIND(_export_project, "preset", "debug", "path", "flags"); GDVIRTUAL_BIND(_export_pack, "preset", "debug", "path", "flags"); GDVIRTUAL_BIND(_export_zip, "preset", "debug", "path", "flags"); + GDVIRTUAL_BIND(_export_pack_patch, "preset", "debug", "path", "patches", "flags"); + GDVIRTUAL_BIND(_export_zip_patch, "preset", "debug", "path", "patches", "flags"); GDVIRTUAL_BIND(_get_platform_features); @@ -291,6 +293,44 @@ Error EditorExportPlatformExtension::export_zip(const Ref<EditorExportPreset> &p return save_zip(p_preset, p_debug, p_path); } +Error EditorExportPlatformExtension::export_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches, BitField<EditorExportPlatform::DebugFlags> p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); + + Error err = _load_patches(p_patches.is_empty() ? p_preset->get_patches() : p_patches); + if (err != OK) { + return err; + } + + Error ret = FAILED; + if (GDVIRTUAL_CALL(_export_pack_patch, p_preset, p_debug, p_path, p_patches, p_flags, ret)) { + _unload_patches(); + return ret; + } + + err = save_pack_patch(p_preset, p_debug, p_path); + _unload_patches(); + return err; +} + +Error EditorExportPlatformExtension::export_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches, BitField<EditorExportPlatform::DebugFlags> p_flags) { + ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); + + Error err = _load_patches(p_patches.is_empty() ? p_preset->get_patches() : p_patches); + if (err != OK) { + return err; + } + + Error ret = FAILED; + if (GDVIRTUAL_CALL(_export_zip_patch, p_preset, p_debug, p_path, p_patches, p_flags, ret)) { + _unload_patches(); + return ret; + } + + err = save_zip_patch(p_preset, p_debug, p_path); + _unload_patches(); + return err; +} + void EditorExportPlatformExtension::get_platform_features(List<String> *r_features) const { Vector<String> ret; if (GDVIRTUAL_REQUIRED_CALL(_get_platform_features, ret) && r_features) { diff --git a/editor/export/editor_export_platform_extension.h b/editor/export/editor_export_platform_extension.h index 6391e65ac1..d1db922698 100644 --- a/editor/export/editor_export_platform_extension.h +++ b/editor/export/editor_export_platform_extension.h @@ -136,6 +136,12 @@ public: virtual Error export_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override; GDVIRTUAL4R(Error, _export_zip, Ref<EditorExportPreset>, bool, const String &, BitField<EditorExportPlatform::DebugFlags>); + virtual Error export_pack_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override; + GDVIRTUAL5R(Error, _export_pack_patch, Ref<EditorExportPreset>, bool, const String &, const Vector<String> &, BitField<EditorExportPlatform::DebugFlags>); + + virtual Error export_zip_patch(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, const Vector<String> &p_patches = Vector<String>(), BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override; + GDVIRTUAL5R(Error, _export_zip_patch, Ref<EditorExportPreset>, bool, const String &, const Vector<String> &, BitField<EditorExportPlatform::DebugFlags>); + virtual void get_platform_features(List<String> *r_features) const override; GDVIRTUAL0RC(Vector<String>, _get_platform_features); diff --git a/editor/export/editor_export_platform_pc.cpp b/editor/export/editor_export_platform_pc.cpp index 24d89b7f34..31a5b60d77 100644 --- a/editor/export/editor_export_platform_pc.cpp +++ b/editor/export/editor_export_platform_pc.cpp @@ -194,7 +194,7 @@ Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset> int64_t embedded_pos; int64_t embedded_size; - Error err = save_pack(p_preset, p_debug, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); + Error err = save_pack(p_preset, p_debug, pck_path, &so_files, nullptr, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size); if (err == OK && p_preset->get("binary_format/embed_pck")) { if (embedded_size >= 0x100000000 && String(p_preset->get("binary_format/architecture")).contains("32")) { add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB.")); diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp index 9f805666d0..1ca72348e2 100644 --- a/editor/export/editor_export_preset.cpp +++ b/editor/export/editor_export_preset.cpp @@ -79,6 +79,7 @@ void EditorExportPreset::_bind_methods() { ClassDB::bind_method(D_METHOD("get_include_filter"), &EditorExportPreset::get_include_filter); ClassDB::bind_method(D_METHOD("get_exclude_filter"), &EditorExportPreset::get_exclude_filter); ClassDB::bind_method(D_METHOD("get_custom_features"), &EditorExportPreset::get_custom_features); + ClassDB::bind_method(D_METHOD("get_patches"), &EditorExportPreset::get_patches); ClassDB::bind_method(D_METHOD("get_export_path"), &EditorExportPreset::get_export_path); ClassDB::bind_method(D_METHOD("get_encryption_in_filter"), &EditorExportPreset::get_enc_in_filter); ClassDB::bind_method(D_METHOD("get_encryption_ex_filter"), &EditorExportPreset::get_enc_ex_filter); @@ -366,6 +367,42 @@ EditorExportPreset::FileExportMode EditorExportPreset::get_file_export_mode(cons return p_default; } +void EditorExportPreset::add_patch(const String &p_path, int p_at_pos) { + ERR_FAIL_COND_EDMSG(patches.has(p_path), vformat("Failed to add patch \"%s\". Patches must be unique.", p_path)); + + if (p_at_pos < 0) { + patches.push_back(p_path); + } else { + patches.insert(p_at_pos, p_path); + } + + EditorExport::singleton->save_presets(); +} + +void EditorExportPreset::set_patch(int p_index, const String &p_path) { + remove_patch(p_index); + add_patch(p_path, p_index); +} + +String EditorExportPreset::get_patch(int p_index) { + ERR_FAIL_INDEX_V(p_index, patches.size(), String()); + return patches[p_index]; +} + +void EditorExportPreset::remove_patch(int p_index) { + ERR_FAIL_INDEX(p_index, patches.size()); + patches.remove_at(p_index); + EditorExport::singleton->save_presets(); +} + +void EditorExportPreset::set_patches(const Vector<String> &p_patches) { + patches = p_patches; +} + +Vector<String> EditorExportPreset::get_patches() const { + return patches; +} + void EditorExportPreset::set_custom_features(const String &p_custom_features) { custom_features = p_custom_features; EditorExport::singleton->save_presets(); diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h index f220477461..af3a23fc50 100644 --- a/editor/export/editor_export_preset.h +++ b/editor/export/editor_export_preset.h @@ -74,6 +74,8 @@ private: bool advanced_options_enabled = false; bool dedicated_server = false; + Vector<String> patches; + friend class EditorExport; friend class EditorExportPlatform; @@ -144,6 +146,13 @@ public: void set_exclude_filter(const String &p_exclude); String get_exclude_filter() const; + void add_patch(const String &p_path, int p_at_pos = -1); + void set_patch(int p_index, const String &p_path); + String get_patch(int p_index); + void remove_patch(int p_index); + void set_patches(const Vector<String> &p_patches); + Vector<String> get_patches() const; + void set_custom_features(const String &p_custom_features); String get_custom_features() const; diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index be9e0f78ec..f9137082d7 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -102,11 +102,13 @@ void ProjectExportDialog::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate"))); delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove"))); + patch_add_btn->set_icon(get_editor_theme_icon(SNAME("Add"))); } break; case NOTIFICATION_READY: { duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate"))); delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove"))); + patch_add_btn->set_icon(get_editor_theme_icon(SNAME("Add"))); connect(SceneStringName(confirmed), callable_mp(this, &ProjectExportDialog::_export_pck_zip)); _update_export_all(); } break; @@ -248,6 +250,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { duplicate_preset->set_disabled(true); delete_preset->set_disabled(true); sections->hide(); + patches->clear(); export_error->hide(); export_templates_error->hide(); return; @@ -292,6 +295,21 @@ void ProjectExportDialog::_edit_preset(int p_index) { exclude_filters->set_text(current->get_exclude_filter()); server_strip_message->set_visible(current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED); + patches->clear(); + TreeItem *patch_root = patches->create_item(); + Vector<String> patch_list = current->get_patches(); + for (int i = 0; i < patch_list.size(); i++) { + TreeItem *patch = patches->create_item(patch_root); + const String &patch_path = patch_list[i]; + patch->set_cell_mode(0, TreeItem::CELL_MODE_STRING); + patch->set_editable(0, true); + patch->set_text(0, patch_path.get_file()); + patch->set_tooltip_text(0, patch_path); + patch->set_metadata(0, i); + patch->add_button(0, get_editor_theme_icon(SNAME("Remove")), 0); + patch->add_button(0, get_editor_theme_icon(SNAME("FileBrowse")), 1); + } + _fill_resource_tree(); bool needs_templates; @@ -664,6 +682,7 @@ void ProjectExportDialog::_duplicate_preset() { preset->set_export_filter(current->get_export_filter()); preset->set_include_filter(current->get_include_filter()); preset->set_exclude_filter(current->get_exclude_filter()); + preset->set_patches(current->get_patches()); preset->set_custom_features(current->get_custom_features()); for (const KeyValue<StringName, Variant> &E : current->get_values()) { @@ -720,8 +739,22 @@ Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_ return d; } - } + } else if (p_from == patches) { + TreeItem *item = patches->get_item_at_position(p_point); + + if (item) { + int item_metadata = item->get_metadata(0); + Dictionary d; + d["type"] = "export_patch"; + d["patch"] = item_metadata; + Label *label = memnew(Label); + label->set_text(item->get_text(0)); + patches->set_drag_preview(label); + + return d; + } + } return Variant(); } @@ -735,6 +768,18 @@ bool ProjectExportDialog::can_drop_data_fw(const Point2 &p_point, const Variant if (presets->get_item_at_position(p_point, true) < 0 && !presets->is_pos_at_end_of_items(p_point)) { return false; } + } else if (p_from == patches) { + Dictionary d = p_data; + if (d.get("type", "") != "export_patch") { + return false; + } + + TreeItem *item = patches->get_item_at_position(p_point); + if (!item) { + return false; + } + + patches->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN); } return true; @@ -771,6 +816,31 @@ void ProjectExportDialog::drop_data_fw(const Point2 &p_point, const Variant &p_d } else { _edit_preset(presets->get_item_count() - 1); } + } else if (p_from == patches) { + Dictionary d = p_data; + int from_pos = d["patch"]; + + TreeItem *item = patches->get_item_at_position(p_point); + if (!item) { + return; + } + + int to_pos = item->get_metadata(0); + + if (patches->get_drop_section_at_position(p_point) > 0) { + to_pos++; + } + + if (to_pos > from_pos) { + to_pos--; + } + + Ref<EditorExportPreset> preset = get_current_preset(); + String patch = preset->get_patch(from_pos); + preset->remove_patch(from_pos); + preset->add_patch(patch, to_pos); + + _update_current_preset(); } } @@ -1026,6 +1096,75 @@ void ProjectExportDialog::_set_file_export_mode(int p_id) { _propagate_file_export_mode(include_files->get_root(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED); } +void ProjectExportDialog::_patch_tree_button_clicked(Object *p_item, int p_column, int p_id, int p_mouse_button_index) { + TreeItem *ti = Object::cast_to<TreeItem>(p_item); + + patch_index = ti->get_metadata(0); + + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + if (p_id == 0) { + Vector<String> preset_patches = current->get_patches(); + ERR_FAIL_INDEX(patch_index, preset_patches.size()); + patch_erase->set_text(vformat(TTR("Delete patch '%s' from list?"), preset_patches[patch_index].get_file())); + patch_erase->popup_centered(); + } else { + patch_dialog->popup_file_dialog(); + } +} + +void ProjectExportDialog::_patch_tree_item_edited() { + TreeItem *item = patches->get_edited(); + if (!item) { + return; + } + + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + int index = item->get_metadata(0); + String patch_path = item->get_text(0); + + current->set_patch(index, patch_path); + item->set_tooltip_text(0, patch_path); +} + +void ProjectExportDialog::_patch_file_selected(const String &p_path) { + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + String relative_path = ProjectSettings::get_singleton()->get_resource_path().path_to_file(p_path); + + Vector<String> preset_patches = current->get_patches(); + if (patch_index >= preset_patches.size()) { + current->add_patch(relative_path); + } else { + current->set_patch(patch_index, relative_path); + } + + _update_current_preset(); +} + +void ProjectExportDialog::_patch_delete_confirmed() { + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + Vector<String> preset_patches = current->get_patches(); + if (patch_index < preset_patches.size()) { + current->remove_patch(patch_index); + _update_current_preset(); + } +} + +void ProjectExportDialog::_patch_add_pack_pressed() { + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + patch_index = current->get_patches().size(); + patch_dialog->popup_file_dialog(); +} + void ProjectExportDialog::_export_pck_zip() { Ref<EditorExportPreset> current = get_current_preset(); ERR_FAIL_COND(current.is_null()); @@ -1044,11 +1183,20 @@ void ProjectExportDialog::_export_pck_zip_selected(const String &p_path) { const Dictionary &fd_option = export_pck_zip->get_selected_options(); bool export_debug = fd_option.get(TTR("Export With Debug"), true); + bool export_as_patch = fd_option.get(TTR("Export As Patch"), true); if (p_path.ends_with(".zip")) { - platform->export_zip(current, export_debug, p_path); + if (export_as_patch) { + platform->export_zip_patch(current, export_debug, p_path); + } else { + platform->export_zip(current, export_debug, p_path); + } } else if (p_path.ends_with(".pck")) { - platform->export_pack(current, export_debug, p_path); + if (export_as_patch) { + platform->export_pack_patch(current, export_debug, p_path); + } else { + platform->export_pack(current, export_debug, p_path); + } } else { ERR_FAIL_MSG("Path must end with .pck or .zip"); } @@ -1386,6 +1534,40 @@ ProjectExportDialog::ProjectExportDialog() { exclude_filters); exclude_filters->connect(SceneStringName(text_changed), callable_mp(this, &ProjectExportDialog::_filter_changed)); + // Patch packages. + + VBoxContainer *patch_vb = memnew(VBoxContainer); + sections->add_child(patch_vb); + patch_vb->set_name(TTR("Patches")); + + patches = memnew(Tree); + patches->set_v_size_flags(Control::SIZE_EXPAND_FILL); + patches->set_hide_root(true); + patches->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + patches->connect("button_clicked", callable_mp(this, &ProjectExportDialog::_patch_tree_button_clicked)); + patches->connect("item_edited", callable_mp(this, &ProjectExportDialog::_patch_tree_item_edited)); + SET_DRAG_FORWARDING_GCD(patches, ProjectExportDialog); + patches->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); + patch_vb->add_margin_child(TTR("Base Packs:"), patches, true); + + patch_dialog = memnew(EditorFileDialog); + patch_dialog->add_filter("*.pck", TTR("Godot Project Pack")); + patch_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); + patch_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + patch_dialog->connect("file_selected", callable_mp(this, &ProjectExportDialog::_patch_file_selected)); + add_child(patch_dialog); + + patch_erase = memnew(ConfirmationDialog); + patch_erase->set_ok_button_text(TTR("Delete")); + patch_erase->connect(SceneStringName(confirmed), callable_mp(this, &ProjectExportDialog::_patch_delete_confirmed)); + add_child(patch_erase); + + patch_add_btn = memnew(Button); + patch_add_btn->set_text(TTR("Add Pack")); + patch_add_btn->set_h_size_flags(Control::SIZE_SHRINK_CENTER); + patch_add_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectExportDialog::_patch_add_pack_pressed)); + patch_vb->add_child(patch_add_btn); + // Feature tags. VBoxContainer *feature_vb = memnew(VBoxContainer); @@ -1569,6 +1751,7 @@ ProjectExportDialog::ProjectExportDialog() { export_project->add_option(TTR("Export With Debug"), Vector<String>(), true); export_pck_zip->add_option(TTR("Export With Debug"), Vector<String>(), true); + export_pck_zip->add_option(TTR("Export As Patch"), Vector<String>(), true); set_hide_on_ok(false); diff --git a/editor/export/project_export.h b/editor/export/project_export.h index c3499177f3..e360596be6 100644 --- a/editor/export/project_export.h +++ b/editor/export/project_export.h @@ -105,6 +105,13 @@ class ProjectExportDialog : public ConfirmationDialog { AcceptDialog *export_all_dialog = nullptr; RBSet<String> feature_set; + + Tree *patches = nullptr; + int patch_index = -1; + EditorFileDialog *patch_dialog = nullptr; + ConfirmationDialog *patch_erase = nullptr; + Button *patch_add_btn = nullptr; + LineEdit *custom_features = nullptr; RichTextLabel *custom_feature_display = nullptr; @@ -148,6 +155,12 @@ class ProjectExportDialog : public ConfirmationDialog { void _tree_popup_edited(bool p_arrow_clicked); void _set_file_export_mode(int p_id); + void _patch_tree_button_clicked(Object *p_item, int p_column, int p_id, int p_mouse_button_index); + void _patch_tree_item_edited(); + void _patch_file_selected(const String &p_path); + void _patch_delete_confirmed(); + void _patch_add_pack_pressed(); + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); diff --git a/editor/gui/SCsub b/editor/gui/SCsub index 359d04e5df..b3cff5b9dc 100644 --- a/editor/gui/SCsub +++ b/editor/gui/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/icons/SCsub b/editor/icons/SCsub index 0d9ac43c46..a66ef56699 100644 --- a/editor/icons/SCsub +++ b/editor/icons/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/import/SCsub b/editor/import/SCsub index a8c06cc406..3d3b7780ba 100644 --- a/editor/import/SCsub +++ b/editor/import/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index 552815a6af..72d715ac2d 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -431,22 +431,20 @@ String ResourceImporterLayeredTexture::get_import_settings_string() const { return s; } -bool ResourceImporterLayeredTexture::are_import_settings_valid(const String &p_path) const { +bool ResourceImporterLayeredTexture::are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const { //will become invalid if formats are missing to import - Dictionary meta = ResourceFormatImporter::get_singleton()->get_resource_metadata(p_path); - - if (!meta.has("vram_texture")) { + if (!p_meta.has("vram_texture")) { return false; } - bool vram = meta["vram_texture"]; + bool vram = p_meta["vram_texture"]; if (!vram) { return true; //do not care about non vram } Vector<String> formats_imported; - if (meta.has("imported_formats")) { - formats_imported = meta["imported_formats"]; + if (p_meta.has("imported_formats")) { + formats_imported = p_meta["imported_formats"]; } int index = 0; diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 5a21651de3..26495eed8d 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -114,7 +114,7 @@ public: virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - virtual bool are_import_settings_valid(const String &p_path) const override; + virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const override; virtual String get_import_settings_string() const override; void set_mode(Mode p_mode) { mode = p_mode; } diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 487b8fc175..a205123df1 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -740,10 +740,8 @@ String ResourceImporterTexture::get_import_settings_string() const { return s; } -bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) const { - Dictionary meta = ResourceFormatImporter::get_singleton()->get_resource_metadata(p_path); - - if (meta.has("has_editor_variant")) { +bool ResourceImporterTexture::are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const { + if (p_meta.has("has_editor_variant")) { String imported_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_path); if (!FileAccess::exists(imported_path)) { return false; @@ -760,19 +758,19 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) co } } - if (!meta.has("vram_texture")) { + if (!p_meta.has("vram_texture")) { return false; } - bool vram = meta["vram_texture"]; + bool vram = p_meta["vram_texture"]; if (!vram) { return true; // Do not care about non-VRAM. } // Will become invalid if formats are missing to import. Vector<String> formats_imported; - if (meta.has("imported_formats")) { - formats_imported = meta["imported_formats"]; + if (p_meta.has("imported_formats")) { + formats_imported = p_meta["imported_formats"]; } int index = 0; diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index f2539a8f52..6d74c4e2f9 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -104,7 +104,7 @@ public: void update_imports(); - virtual bool are_import_settings_valid(const String &p_path) const override; + virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const override; virtual String get_import_settings_string() const override; ResourceImporterTexture(bool p_singleton = false); diff --git a/editor/plugins/SCsub b/editor/plugins/SCsub index 4b6abf18f9..2d3066c7c9 100644 --- a/editor/plugins/SCsub +++ b/editor/plugins/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/plugins/gizmos/SCsub b/editor/plugins/gizmos/SCsub index 359d04e5df..b3cff5b9dc 100644 --- a/editor/plugins/gizmos/SCsub +++ b/editor/plugins/gizmos/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/plugins/tiles/SCsub b/editor/plugins/tiles/SCsub index 359d04e5df..b3cff5b9dc 100644 --- a/editor/plugins/tiles/SCsub +++ b/editor/plugins/tiles/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index 957f768429..c1a8338f81 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -177,7 +177,7 @@ private: DRAG_TYPE_MAY_POPUP_MENU, - // Warning: keep in this order. + // WARNING: Keep in this order. DRAG_TYPE_RESIZE_TOP_LEFT, DRAG_TYPE_RESIZE_TOP, DRAG_TYPE_RESIZE_TOP_RIGHT, diff --git a/editor/project_manager/SCsub b/editor/project_manager/SCsub index 359d04e5df..b3cff5b9dc 100644 --- a/editor/project_manager/SCsub +++ b/editor/project_manager/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/editor/themes/SCsub b/editor/themes/SCsub index e8f96e4299..5a9949dfa7 100644 --- a/editor/themes/SCsub +++ b/editor/themes/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/main/SCsub b/main/SCsub index f3807167a2..71bee465f5 100644 --- a/main/SCsub +++ b/main/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/main/main.cpp b/main/main.cpp index 75797e31de..9014bfad29 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -612,7 +612,9 @@ void Main::print_help(const char *p_binary) { print_help_option("--position <X>,<Y>", "Request window position.\n"); print_help_option("--screen <N>", "Request window screen.\n"); print_help_option("--single-window", "Use a single window (no separate subwindows).\n"); +#ifndef _3D_DISABLED print_help_option("--xr-mode <mode>", "Select XR (Extended Reality) mode [\"default\", \"off\", \"on\"].\n"); +#endif print_help_title("Debug options"); print_help_option("-d, --debug", "Debug (local stdout debugger).\n"); @@ -659,6 +661,8 @@ void Main::print_help(const char *p_binary) { print_help_option("", "The target directory must exist.\n"); print_help_option("--export-debug <preset> <path>", "Export the project in debug mode using the given preset and output path. See --export-release description for other considerations.\n", CLI_OPTION_AVAILABILITY_EDITOR); print_help_option("--export-pack <preset> <path>", "Export the project data only using the given preset and output path. The <path> extension determines whether it will be in PCK or ZIP format.\n", CLI_OPTION_AVAILABILITY_EDITOR); + print_help_option("--export-patch <preset> <path>", "Export pack with changed files only. See --export-pack description for other considerations.\n", CLI_OPTION_AVAILABILITY_EDITOR); + print_help_option("--patches <paths>", "List of patches to use with --export-patch. The list is comma-separated.\n", CLI_OPTION_AVAILABILITY_EDITOR); print_help_option("--install-android-build-template", "Install the Android build template. Used in conjunction with --export-release or --export-debug.\n", CLI_OPTION_AVAILABILITY_EDITOR); #ifndef DISABLE_DEPRECATED // Commands are long; split the description to a second line. @@ -1478,12 +1482,23 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph wait_for_import = true; quit_after = 1; } else if (arg == "--export-release" || arg == "--export-debug" || - arg == "--export-pack") { // Export project + arg == "--export-pack" || arg == "--export-patch") { // Export project // Actually handling is done in start(). editor = true; cmdline_tool = true; wait_for_import = true; main_args.push_back(arg); + } else if (arg == "--patches") { + if (N) { + // Actually handling is done in start(). + main_args.push_back(arg); + main_args.push_back(N->get()); + + N = N->next(); + } else { + OS::get_singleton()->print("Missing comma-separated list of patches after --patches, aborting.\n"); + goto error; + } #ifndef DISABLE_DEPRECATED } else if (arg == "--export") { // For users used to 3.x syntax. OS::get_singleton()->print("The Godot 3 --export option was changed to more explicit --export-release / --export-debug / --export-pack options.\nSee the --help output for details.\n"); @@ -2558,6 +2573,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF("display/window/ios/hide_status_bar", true); GLOBAL_DEF("display/window/ios/suppress_ui_gesture", true); +#ifndef _3D_DISABLED // XR project settings. GLOBAL_DEF_RST_BASIC("xr/openxr/enabled", false); GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "xr/openxr/default_action_map", PROPERTY_HINT_FILE, "*.tres"), "res://openxr_action_map.tres"); @@ -2586,7 +2602,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // editor settings (it seems we're too early in the process when setting up rendering, to access editor settings...) // EDITOR_DEF_RST("xr/openxr/in_editor", false); // GLOBAL_DEF("xr/openxr/in_editor", false); -#endif +#endif // TOOLS_ENABLED +#endif // _3D_DISABLED Engine::get_singleton()->set_frame_delay(frame_delay); @@ -3489,9 +3506,11 @@ int Main::start() { bool doc_tool_implicit_cwd = false; BitField<DocTools::GenerateFlags> gen_flags; String _export_preset; + Vector<String> patches; bool export_debug = false; bool export_pack_only = false; bool install_android_build_template = false; + bool export_patch = false; #ifdef MODULE_GDSCRIPT_ENABLED String gdscript_docs_path; #endif @@ -3581,6 +3600,14 @@ int Main::start() { editor = true; _export_preset = E->next()->get(); export_pack_only = true; + } else if (E->get() == "--export-patch") { + ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting."); + editor = true; + _export_preset = E->next()->get(); + export_pack_only = true; + export_patch = true; + } else if (E->get() == "--patches") { + patches = E->next()->get().split(",", false); #endif } else { // The parameter does not match anything known, don't skip the next argument @@ -3984,7 +4011,7 @@ int Main::start() { sml->get_root()->add_child(editor_node); if (!_export_preset.is_empty()) { - editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only, install_android_build_template); + editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only, install_android_build_template, export_patch, patches); game_path = ""; // Do not load anything. } diff --git a/misc/utility/scons_hints.py b/misc/utility/scons_hints.py new file mode 100644 index 0000000000..fe380e399d --- /dev/null +++ b/misc/utility/scons_hints.py @@ -0,0 +1,98 @@ +""" +Adds type hints to SCons scripts. Implemented via +`from misc.utility.scons_hints import *`. + +This is NOT a 1-1 representation of what the defines will represent in an +SCons build, as proxies are almost always utilized instead. Rather, this is +a means of tracing back what those proxies are calling to in the first place. +""" + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + # ruff: noqa: F401 + from SCons.Action import Action + from SCons.Builder import Builder + from SCons.Defaults import Chmod, Copy, CScan, DefaultEnvironment, Delete, DirScanner, Mkdir, Move, Touch + from SCons.Environment import Base + from SCons.Platform import Platform + from SCons.Platform.virtualenv import Virtualenv + from SCons.Scanner import FindPathDirs, ScannerBase + from SCons.Script import ARGLIST, ARGUMENTS, BUILD_TARGETS, COMMAND_LINE_TARGETS, DEFAULT_TARGETS + from SCons.Script.Main import ( + AddOption, + BuildTask, + CleanTask, + DebugOptions, + GetBuildFailures, + GetOption, + PrintHelp, + Progress, + QuestionTask, + SetOption, + ValidateOptions, + ) + from SCons.Script.SConscript import Configure, Return, SConsEnvironment, call_stack + from SCons.Script.SConscript import SConsEnvironment as Environment + from SCons.Subst import SetAllowableExceptions as AllowSubstExceptions + from SCons.Tool import CScanner, DScanner, ProgramScanner, SourceFileScanner, Tool + from SCons.Util import AddMethod, WhereIs + from SCons.Variables import BoolVariable, EnumVariable, ListVariable, PackageVariable, PathVariable, Variables + + # Global functions + GetSConsVersion = SConsEnvironment.GetSConsVersion + EnsurePythonVersion = SConsEnvironment.EnsurePythonVersion + EnsureSConsVersion = SConsEnvironment.EnsureSConsVersion + Exit = SConsEnvironment.Exit + GetLaunchDir = SConsEnvironment.GetLaunchDir + SConscriptChdir = SConsEnvironment.SConscriptChdir + + # SConsEnvironment functions + Default = SConsEnvironment(DefaultEnvironment()).Default + Export = SConsEnvironment(DefaultEnvironment()).Export + Help = SConsEnvironment(DefaultEnvironment()).Help + Import = SConsEnvironment(DefaultEnvironment()).Import + SConscript = SConsEnvironment(DefaultEnvironment()).SConscript + + # Environment functions + AddPostAction = DefaultEnvironment().AddPostAction + AddPreAction = DefaultEnvironment().AddPreAction + Alias = DefaultEnvironment().Alias + AlwaysBuild = DefaultEnvironment().AlwaysBuild + CacheDir = DefaultEnvironment().CacheDir + Clean = DefaultEnvironment().Clean + Command = DefaultEnvironment().Command + Decider = DefaultEnvironment().Decider + Depends = DefaultEnvironment().Depends + Dir = DefaultEnvironment().Dir + Entry = DefaultEnvironment().Entry + Execute = DefaultEnvironment().Execute + File = DefaultEnvironment().File + FindFile = DefaultEnvironment().FindFile + FindInstalledFiles = DefaultEnvironment().FindInstalledFiles + FindSourceFiles = DefaultEnvironment().FindSourceFiles + Flatten = DefaultEnvironment().Flatten + GetBuildPath = DefaultEnvironment().GetBuildPath + Glob = DefaultEnvironment().Glob + Ignore = DefaultEnvironment().Ignore + Install = DefaultEnvironment().Install + InstallAs = DefaultEnvironment().InstallAs + InstallVersionedLib = DefaultEnvironment().InstallVersionedLib + Literal = DefaultEnvironment().Literal + Local = DefaultEnvironment().Local + NoCache = DefaultEnvironment().NoCache + NoClean = DefaultEnvironment().NoClean + ParseDepends = DefaultEnvironment().ParseDepends + Precious = DefaultEnvironment().Precious + PyPackageDir = DefaultEnvironment().PyPackageDir + Repository = DefaultEnvironment().Repository + Requires = DefaultEnvironment().Requires + SConsignFile = DefaultEnvironment().SConsignFile + SideEffect = DefaultEnvironment().SideEffect + Split = DefaultEnvironment().Split + Tag = DefaultEnvironment().Tag + Value = DefaultEnvironment().Value + VariantDir = DefaultEnvironment().VariantDir + + env: SConsEnvironment + env_modules: SConsEnvironment diff --git a/modules/SCsub b/modules/SCsub index e16cc17b67..fea2f2eeb8 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * import os diff --git a/modules/astcenc/SCsub b/modules/astcenc/SCsub index 691c74b4a7..23e9fa87fc 100644 --- a/modules/astcenc/SCsub +++ b/modules/astcenc/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/basis_universal/SCsub b/modules/basis_universal/SCsub index 80bfd7e858..0142317e1e 100644 --- a/modules/basis_universal/SCsub +++ b/modules/basis_universal/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/betsy/SCsub b/modules/betsy/SCsub index ed5dcbf58b..2735116cc3 100644 --- a/modules/betsy/SCsub +++ b/modules/betsy/SCsub @@ -1,4 +1,6 @@ -# !/ usr / bin / env python +#!/usr/bin/env python +from misc.utility.scons_hints import * + Import("env") Import("env_modules") diff --git a/modules/bmp/SCsub b/modules/bmp/SCsub index 9d317887c3..cc3684b94b 100644 --- a/modules/bmp/SCsub +++ b/modules/bmp/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/camera/SCsub b/modules/camera/SCsub index ba7fca8794..aed5efd0d2 100644 --- a/modules/camera/SCsub +++ b/modules/camera/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/csg/SCsub b/modules/csg/SCsub index 1cf9974fc1..f71618ab22 100644 --- a/modules/csg/SCsub +++ b/modules/csg/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp index de949e30d8..19e6be4be1 100644 --- a/modules/csg/register_types.cpp +++ b/modules/csg/register_types.cpp @@ -30,8 +30,6 @@ #include "register_types.h" -#ifndef _3D_DISABLED - #include "csg_shape.h" #ifdef TOOLS_ENABLED @@ -62,5 +60,3 @@ void uninitialize_csg_module(ModuleInitializationLevel p_level) { return; } } - -#endif // _3D_DISABLED diff --git a/modules/cvtt/SCsub b/modules/cvtt/SCsub index 1d5a7ff6a3..44e56ab6a7 100644 --- a/modules/cvtt/SCsub +++ b/modules/cvtt/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/dds/SCsub b/modules/dds/SCsub index 06980bd670..d1c67c31ea 100644 --- a/modules/dds/SCsub +++ b/modules/dds/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/enet/SCsub b/modules/enet/SCsub index 580e5a3eb0..0c31638e46 100644 --- a/modules/enet/SCsub +++ b/modules/enet/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/etcpak/SCsub b/modules/etcpak/SCsub index 2d3b69be75..a872e1cd03 100644 --- a/modules/etcpak/SCsub +++ b/modules/etcpak/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/fbx/SCsub b/modules/fbx/SCsub index 6a791094c6..6f9fbba0b4 100644 --- a/modules/fbx/SCsub +++ b/modules/fbx/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index 2813eaecd5..5edce96680 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index 61accd4fc9..8f50bf9588 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/gdscript/editor/script_templates/SCsub b/modules/gdscript/editor/script_templates/SCsub index 5db7e3fc3b..28a27db3fa 100644 --- a/modules/gdscript/editor/script_templates/SCsub +++ b/modules/gdscript/editor/script_templates/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index eebf282633..f4f445e096 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2629,9 +2629,10 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP return err; } -// Prepares given script, and inner class scripts, for compilation. It populates class members and initializes method -// RPC info for its base classes first, then for itself, then for inner classes. -// Warning: this function cannot initiate compilation of other classes, or it will result in cyclic dependency issues. +// Prepares given script, and inner class scripts, for compilation. It populates class members and +// initializes method RPC info for its base classes first, then for itself, then for inner classes. +// WARNING: This function cannot initiate compilation of other classes, or it will result in +// cyclic dependency issues. Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { if (parsed_classes.has(p_script)) { return OK; diff --git a/modules/glslang/SCsub b/modules/glslang/SCsub index 3068377e60..b6e3da2316 100644 --- a/modules/glslang/SCsub +++ b/modules/glslang/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/gltf/SCsub b/modules/gltf/SCsub index 9d263cccac..1075116863 100644 --- a/modules/gltf/SCsub +++ b/modules/gltf/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/gltf/extensions/SCsub b/modules/gltf/extensions/SCsub index fdf14300f1..e403cd6fdc 100644 --- a/modules/gltf/extensions/SCsub +++ b/modules/gltf/extensions/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/godot_physics_2d/SCsub b/modules/godot_physics_2d/SCsub index 5d93da5ecf..39eb469978 100644 --- a/modules/godot_physics_2d/SCsub +++ b/modules/godot_physics_2d/SCsub @@ -1,5 +1,6 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * -Import('env') +Import("env") env.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/godot_physics_2d/godot_body_pair_2d.cpp b/modules/godot_physics_2d/godot_body_pair_2d.cpp index 6c2d28dc92..98f11d6c07 100644 --- a/modules/godot_physics_2d/godot_body_pair_2d.cpp +++ b/modules/godot_physics_2d/godot_body_pair_2d.cpp @@ -161,11 +161,13 @@ void GodotBodyPair2D::_validate_contacts() { } } -// _test_ccd prevents tunneling by slowing down a high velocity body that is about to collide so that next frame it will be at an appropriate location to collide (i.e. slight overlap) -// Warning: the way velocity is adjusted down to cause a collision means the momentum will be weaker than it should for a bounce! -// Process: only proceed if body A's motion is high relative to its size. -// cast forward along motion vector to see if A is going to enter/pass B's collider next frame, only proceed if it does. -// adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it. +// `_test_ccd` prevents tunneling by slowing down a high velocity body that is about to collide so +// that next frame it will be at an appropriate location to collide (i.e. slight overlap). +// WARNING: The way velocity is adjusted down to cause a collision means the momentum will be +// weaker than it should for a bounce! +// Process: Only proceed if body A's motion is high relative to its size. +// Cast forward along motion vector to see if A is going to enter/pass B's collider next frame, only proceed if it does. +// Adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it. bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A, const Transform2D &p_xform_A, GodotBody2D *p_B, int p_shape_B, const Transform2D &p_xform_B) { Vector2 motion = p_A->get_linear_velocity() * p_step; real_t mlen = motion.length(); diff --git a/modules/godot_physics_2d/godot_step_2d.cpp b/modules/godot_physics_2d/godot_step_2d.cpp index bbaec8be2b..418b9313e8 100644 --- a/modules/godot_physics_2d/godot_step_2d.cpp +++ b/modules/godot_physics_2d/godot_step_2d.cpp @@ -251,14 +251,14 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) { /* PRE-SOLVE CONSTRAINT ISLANDS */ - // Warning: This doesn't run on threads, because it involves thread-unsafe processing. + // WARNING: This doesn't run on threads, because it involves thread-unsafe processing. for (uint32_t island_index = 0; island_index < island_count; ++island_index) { _pre_solve_island(constraint_islands[island_index]); } /* SOLVE CONSTRAINT ISLANDS */ - // Warning: _solve_island modifies the constraint islands for optimization purpose, + // WARNING: `_solve_island` modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics2DConstraintSolveIslands")); WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); diff --git a/modules/godot_physics_3d/SCsub b/modules/godot_physics_3d/SCsub index 41a59cd24e..1502eb39ee 100644 --- a/modules/godot_physics_3d/SCsub +++ b/modules/godot_physics_3d/SCsub @@ -1,6 +1,7 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * -Import('env') +Import("env") env.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/godot_physics_3d/godot_body_pair_3d.cpp b/modules/godot_physics_3d/godot_body_pair_3d.cpp index 84fae73616..d689271ac7 100644 --- a/modules/godot_physics_3d/godot_body_pair_3d.cpp +++ b/modules/godot_physics_3d/godot_body_pair_3d.cpp @@ -161,11 +161,13 @@ void GodotBodyPair3D::validate_contacts() { } } -// _test_ccd prevents tunneling by slowing down a high velocity body that is about to collide so that next frame it will be at an appropriate location to collide (i.e. slight overlap) -// Warning: the way velocity is adjusted down to cause a collision means the momentum will be weaker than it should for a bounce! -// Process: only proceed if body A's motion is high relative to its size. -// cast forward along motion vector to see if A is going to enter/pass B's collider next frame, only proceed if it does. -// adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it. +// `_test_ccd` prevents tunneling by slowing down a high velocity body that is about to collide so +// that next frame it will be at an appropriate location to collide (i.e. slight overlap). +// WARNING: The way velocity is adjusted down to cause a collision means the momentum will be +// weaker than it should for a bounce! +// Process: Only proceed if body A's motion is high relative to its size. +// Cast forward along motion vector to see if A is going to enter/pass B's collider next frame, only proceed if it does. +// Adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it. bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B) { GodotShape3D *shape_A_ptr = p_A->get_shape(p_shape_A); diff --git a/modules/godot_physics_3d/godot_step_3d.cpp b/modules/godot_physics_3d/godot_step_3d.cpp index d09a3b4e6d..b6cec4ba59 100644 --- a/modules/godot_physics_3d/godot_step_3d.cpp +++ b/modules/godot_physics_3d/godot_step_3d.cpp @@ -355,14 +355,14 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) { /* PRE-SOLVE CONSTRAINT ISLANDS */ - // Warning: This doesn't run on threads, because it involves thread-unsafe processing. + // WARNING: This doesn't run on threads, because it involves thread-unsafe processing. for (uint32_t island_index = 0; island_index < island_count; ++island_index) { _pre_solve_island(constraint_islands[island_index]); } /* SOLVE CONSTRAINT ISLANDS */ - // Warning: _solve_island modifies the constraint islands for optimization purpose, + // WARNING: `_solve_island` modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics3DConstraintSolveIslands")); WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); diff --git a/modules/godot_physics_3d/joints/SCsub b/modules/godot_physics_3d/joints/SCsub index 5d93da5ecf..39eb469978 100644 --- a/modules/godot_physics_3d/joints/SCsub +++ b/modules/godot_physics_3d/joints/SCsub @@ -1,5 +1,6 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * -Import('env') +Import("env") env.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/gridmap/SCsub b/modules/gridmap/SCsub index 282d772592..d4baa9000e 100644 --- a/modules/gridmap/SCsub +++ b/modules/gridmap/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/hdr/SCsub b/modules/hdr/SCsub index 10629bda3c..739b2caecf 100644 --- a/modules/hdr/SCsub +++ b/modules/hdr/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/interactive_music/SCsub b/modules/interactive_music/SCsub index 2950a30854..f2546747a0 100644 --- a/modules/interactive_music/SCsub +++ b/modules/interactive_music/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/jpg/SCsub b/modules/jpg/SCsub index b840542c1b..2d948d3355 100644 --- a/modules/jpg/SCsub +++ b/modules/jpg/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/jsonrpc/SCsub b/modules/jsonrpc/SCsub index 8ee4f8bfea..923567b138 100644 --- a/modules/jsonrpc/SCsub +++ b/modules/jsonrpc/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/ktx/SCsub b/modules/ktx/SCsub index c4cb732498..f4c394d734 100644 --- a/modules/ktx/SCsub +++ b/modules/ktx/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/lightmapper_rd/SCsub b/modules/lightmapper_rd/SCsub index fe9737b36f..157381ae98 100644 --- a/modules/lightmapper_rd/SCsub +++ b/modules/lightmapper_rd/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/mbedtls/SCsub b/modules/mbedtls/SCsub index 90ce98c751..e217ca5ca4 100644 --- a/modules/mbedtls/SCsub +++ b/modules/mbedtls/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/meshoptimizer/SCsub b/modules/meshoptimizer/SCsub index 3f86bb4f00..b335b5db3a 100644 --- a/modules/meshoptimizer/SCsub +++ b/modules/meshoptimizer/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/minimp3/SCsub b/modules/minimp3/SCsub index 09e84f71e9..e9491bb72f 100644 --- a/modules/minimp3/SCsub +++ b/modules/minimp3/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/mobile_vr/SCsub b/modules/mobile_vr/SCsub index e6c43228b4..b237f31209 100644 --- a/modules/mobile_vr/SCsub +++ b/modules/mobile_vr/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/mono/SCsub b/modules/mono/SCsub index d267df938a..f74f0fb9c1 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * import build_scripts.mono_configure as mono_configure diff --git a/modules/mono/editor/script_templates/SCsub b/modules/mono/editor/script_templates/SCsub index 01c293c25d..f465374758 100644 --- a/modules/mono/editor/script_templates/SCsub +++ b/modules/mono/editor/script_templates/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/modules/msdfgen/SCsub b/modules/msdfgen/SCsub index f4316a74e7..844b0980ac 100644 --- a/modules/msdfgen/SCsub +++ b/modules/msdfgen/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/multiplayer/SCsub b/modules/multiplayer/SCsub index e89038c3e0..97f91c5674 100644 --- a/modules/multiplayer/SCsub +++ b/modules/multiplayer/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/navigation/SCsub b/modules/navigation/SCsub index 02d3b7487e..ab578252c1 100644 --- a/modules/navigation/SCsub +++ b/modules/navigation/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/noise/SCsub b/modules/noise/SCsub index f309fd2dd4..dcf51b03e3 100644 --- a/modules/noise/SCsub +++ b/modules/noise/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/ogg/SCsub b/modules/ogg/SCsub index f15525648f..fabd4f936a 100644 --- a/modules/ogg/SCsub +++ b/modules/ogg/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index 77922045eb..dd6a921440 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/openxr/action_map/SCsub b/modules/openxr/action_map/SCsub index 7a493011ec..d659be1d99 100644 --- a/modules/openxr/action_map/SCsub +++ b/modules/openxr/action_map/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_openxr") diff --git a/modules/openxr/editor/SCsub b/modules/openxr/editor/SCsub index ccf67a80d0..39eb469978 100644 --- a/modules/openxr/editor/SCsub +++ b/modules/openxr/editor/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/modules/openxr/extensions/SCsub b/modules/openxr/extensions/SCsub index 1bd9cfaa22..95b75ccd65 100644 --- a/modules/openxr/extensions/SCsub +++ b/modules/openxr/extensions/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_openxr") diff --git a/modules/openxr/scene/SCsub b/modules/openxr/scene/SCsub index 7a493011ec..d659be1d99 100644 --- a/modules/openxr/scene/SCsub +++ b/modules/openxr/scene/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_openxr") diff --git a/modules/raycast/SCsub b/modules/raycast/SCsub index f3a8e30763..bbf5ff7983 100644 --- a/modules/raycast/SCsub +++ b/modules/raycast/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/regex/SCsub b/modules/regex/SCsub index f5e2dd5dfc..5d70604e76 100644 --- a/modules/regex/SCsub +++ b/modules/regex/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/squish/SCsub b/modules/squish/SCsub index c9e29911d8..d8e7fbc142 100644 --- a/modules/squish/SCsub +++ b/modules/squish/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/svg/SCsub b/modules/svg/SCsub index a32be0e41a..af8f6c14f4 100644 --- a/modules/svg/SCsub +++ b/modules/svg/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 4112b81622..304a09515c 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct index effed1e772..8f4f2cba40 100644 --- a/modules/text_server_adv/gdextension_build/SConstruct +++ b/modules/text_server_adv/gdextension_build/SConstruct @@ -1,4 +1,6 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * + import atexit import sys import time diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub index fc0a8727c6..b56df192c2 100644 --- a/modules/text_server_fb/SCsub +++ b/modules/text_server_fb/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct index a3c2052040..dc849d5814 100644 --- a/modules/text_server_fb/gdextension_build/SConstruct +++ b/modules/text_server_fb/gdextension_build/SConstruct @@ -1,4 +1,6 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * + import atexit import sys import time diff --git a/modules/tga/SCsub b/modules/tga/SCsub index ccd7d2ee37..c7f58e87f7 100644 --- a/modules/tga/SCsub +++ b/modules/tga/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/theora/SCsub b/modules/theora/SCsub index ca666050dd..be557c1c24 100644 --- a/modules/theora/SCsub +++ b/modules/theora/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/tinyexr/SCsub b/modules/tinyexr/SCsub index bf9242cc16..434e99bf84 100644 --- a/modules/tinyexr/SCsub +++ b/modules/tinyexr/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/upnp/SCsub b/modules/upnp/SCsub index 98c03e9ee9..6657d75cae 100644 --- a/modules/upnp/SCsub +++ b/modules/upnp/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/vhacd/SCsub b/modules/vhacd/SCsub index 1ff4122114..926cc5b16f 100644 --- a/modules/vhacd/SCsub +++ b/modules/vhacd/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/vorbis/SCsub b/modules/vorbis/SCsub index 322314487f..f063d97fee 100644 --- a/modules/vorbis/SCsub +++ b/modules/vorbis/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/webp/SCsub b/modules/webp/SCsub index dde4450c23..a939e2f90e 100644 --- a/modules/webp/SCsub +++ b/modules/webp/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/webrtc/SCsub b/modules/webrtc/SCsub index e315633f55..0c5f2c9dda 100644 --- a/modules/webrtc/SCsub +++ b/modules/webrtc/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub index 8b469fe5be..acaa0d3ceb 100644 --- a/modules/websocket/SCsub +++ b/modules/websocket/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/webxr/SCsub b/modules/webxr/SCsub index 81caa4a279..9fe4e03ea6 100644 --- a/modules/webxr/SCsub +++ b/modules/webxr/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/xatlas_unwrap/SCsub b/modules/xatlas_unwrap/SCsub index aa6bdaea33..ae82a53bd9 100644 --- a/modules/xatlas_unwrap/SCsub +++ b/modules/xatlas_unwrap/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/modules/zip/SCsub b/modules/zip/SCsub index b7710123fd..0bab3ff5f9 100644 --- a/modules/zip/SCsub +++ b/modules/zip/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") Import("env_modules") diff --git a/platform/SCsub b/platform/SCsub index cdaa6074ba..7c9d07f6ef 100644 --- a/platform/SCsub +++ b/platform/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * from glob import glob from pathlib import Path diff --git a/platform/android/SCsub b/platform/android/SCsub index 8c88b419b3..3bc8959351 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * import subprocess import sys diff --git a/platform/ios/SCsub b/platform/ios/SCsub index cff7dcc1fd..959a657aac 100644 --- a/platform/ios/SCsub +++ b/platform/ios/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub index 0802b528f4..4def765e9c 100644 --- a/platform/linuxbsd/SCsub +++ b/platform/linuxbsd/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/linuxbsd/wayland/SCsub b/platform/linuxbsd/wayland/SCsub index 89b586845c..1a8e243728 100644 --- a/platform/linuxbsd/wayland/SCsub +++ b/platform/linuxbsd/wayland/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub index 75fe584ad5..b76b98447f 100644 --- a/platform/linuxbsd/x11/SCsub +++ b/platform/linuxbsd/x11/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/macos/SCsub b/platform/macos/SCsub index a10262c524..3924e79fb6 100644 --- a/platform/macos/SCsub +++ b/platform/macos/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/web/SCsub b/platform/web/SCsub index e81f2ec516..b30bf20f26 100644 --- a/platform/web/SCsub +++ b/platform/web/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * from methods import print_error diff --git a/platform/windows/SCsub b/platform/windows/SCsub index f8ed8b73f5..1d17e7b325 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index ed9d5244a3..5b166d0075 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -3962,9 +3962,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } - // WARNING: we get called with events before the window is registered in our collection + // WARNING: We get called with events before the window is registered in our collection // specifically, even the call to CreateWindowEx already calls here while still on the stack, - // so there is no way to store the window handle in our collection before we get here + // so there is no way to store the window handle in our collection before we get here. if (!window_created) { // don't let code below operate on incompletely initialized window objects or missing window_id return _handle_early_window_message(hWnd, uMsg, wParam, lParam); diff --git a/platform/windows/gl_manager_windows_native.cpp b/platform/windows/gl_manager_windows_native.cpp index 8590c46d12..af703f4dfa 100644 --- a/platform/windows/gl_manager_windows_native.cpp +++ b/platform/windows/gl_manager_windows_native.cpp @@ -452,8 +452,8 @@ Error GLManagerNative_Windows::window_create(DisplayServer::WindowID p_window_id return FAILED; } - // WARNING: p_window_id is an eternally growing integer since popup windows keep coming and going - // and each of them has a higher id than the previous, so it must be used in a map not a vector + // WARNING: `p_window_id` is an eternally growing integer since popup windows keep coming and going + // and each of them has a higher id than the previous, so it must be used in a map not a vector. _windows[p_window_id] = win; // make current diff --git a/pyproject.toml b/pyproject.toml index 78c8d8c20e..a4bfd27816 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,19 @@ extend-select = [ [tool.ruff.lint.per-file-ignores] "{SConstruct,SCsub}" = [ "E402", # Module level import not at top of file - "F821", # Undefined name + "F403", # Undefined local with import star + "F405", # Undefined local with import star usage +] + +[tool.ruff.lint.isort] +sections = { metadata = ["misc.utility.scons_hints"] } +section-order = [ + "future", + "metadata", + "standard-library", + "third-party", + "first-party", + "local-folder", ] [tool.codespell] diff --git a/scene/2d/SCsub b/scene/2d/SCsub index 94e1ab6c96..6f6bf9818c 100644 --- a/scene/2d/SCsub +++ b/scene/2d/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/2d/physics/SCsub b/scene/2d/physics/SCsub index e7fd3fe643..5f9747514a 100644 --- a/scene/2d/physics/SCsub +++ b/scene/2d/physics/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/2d/physics/joints/SCsub b/scene/2d/physics/joints/SCsub index fc61250247..374dc2119d 100644 --- a/scene/2d/physics/joints/SCsub +++ b/scene/2d/physics/joints/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/3d/SCsub b/scene/3d/SCsub index 94e1ab6c96..6f6bf9818c 100644 --- a/scene/3d/SCsub +++ b/scene/3d/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/3d/physics/SCsub b/scene/3d/physics/SCsub index e7fd3fe643..5f9747514a 100644 --- a/scene/3d/physics/SCsub +++ b/scene/3d/physics/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/3d/physics/joints/SCsub b/scene/3d/physics/joints/SCsub index fc61250247..374dc2119d 100644 --- a/scene/3d/physics/joints/SCsub +++ b/scene/3d/physics/joints/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/SCsub b/scene/SCsub index b4b2d6dd0a..1eb4ffa53d 100644 --- a/scene/SCsub +++ b/scene/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/animation/SCsub b/scene/animation/SCsub index d0aa0bc8aa..dd2b22c2e3 100644 --- a/scene/animation/SCsub +++ b/scene/animation/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/audio/SCsub b/scene/audio/SCsub index fc61250247..374dc2119d 100644 --- a/scene/audio/SCsub +++ b/scene/audio/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/debugger/SCsub b/scene/debugger/SCsub index fc61250247..374dc2119d 100644 --- a/scene/debugger/SCsub +++ b/scene/debugger/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/gui/SCsub b/scene/gui/SCsub index fc61250247..374dc2119d 100644 --- a/scene/gui/SCsub +++ b/scene/gui/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/main/SCsub b/scene/main/SCsub index fc61250247..374dc2119d 100644 --- a/scene/main/SCsub +++ b/scene/main/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/resources/2d/SCsub b/scene/resources/2d/SCsub index fdf20e0bde..408aa3cf7e 100644 --- a/scene/resources/2d/SCsub +++ b/scene/resources/2d/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/resources/3d/SCsub b/scene/resources/3d/SCsub index fdf20e0bde..408aa3cf7e 100644 --- a/scene/resources/3d/SCsub +++ b/scene/resources/3d/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/resources/SCsub b/scene/resources/SCsub index 2b6aa88d2c..46f6251b91 100644 --- a/scene/resources/SCsub +++ b/scene/resources/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/theme/SCsub b/scene/theme/SCsub index 2372d1820a..fb0914c0ee 100644 --- a/scene/theme/SCsub +++ b/scene/theme/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/theme/icons/SCsub b/scene/theme/icons/SCsub index 1f3b7f6d17..19aca74e57 100644 --- a/scene/theme/icons/SCsub +++ b/scene/theme/icons/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/SCsub b/servers/SCsub index 28180a7bb2..7abe53b9e1 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/audio/SCsub b/servers/audio/SCsub index 5021e578c3..7d293c628d 100644 --- a/servers/audio/SCsub +++ b/servers/audio/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/audio/effects/SCsub b/servers/audio/effects/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/audio/effects/SCsub +++ b/servers/audio/effects/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/camera/SCsub b/servers/camera/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/camera/SCsub +++ b/servers/camera/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/debugger/SCsub b/servers/debugger/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/debugger/SCsub +++ b/servers/debugger/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/display/SCsub b/servers/display/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/display/SCsub +++ b/servers/display/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/extensions/SCsub b/servers/extensions/SCsub index 95c7f5d319..e7bb57e9f3 100644 --- a/servers/extensions/SCsub +++ b/servers/extensions/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/movie_writer/SCsub b/servers/movie_writer/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/movie_writer/SCsub +++ b/servers/movie_writer/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/navigation/SCsub b/servers/navigation/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/navigation/SCsub +++ b/servers/navigation/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub index cf26ca029d..9971761818 100644 --- a/servers/rendering/SCsub +++ b/servers/rendering/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/dummy/SCsub b/servers/rendering/dummy/SCsub index aa688af6cd..3e1f338227 100644 --- a/servers/rendering/dummy/SCsub +++ b/servers/rendering/dummy/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/dummy/storage/SCsub b/servers/rendering/dummy/storage/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/rendering/dummy/storage/SCsub +++ b/servers/rendering/dummy/storage/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index a27439e931..c6d9e3ef36 100644 --- a/servers/rendering/renderer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/effects/SCsub b/servers/rendering/renderer_rd/effects/SCsub index 8e13715447..9f330c9f0f 100644 --- a/servers/rendering/renderer_rd/effects/SCsub +++ b/servers/rendering/renderer_rd/effects/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/environment/SCsub b/servers/rendering/renderer_rd/environment/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/rendering/renderer_rd/environment/SCsub +++ b/servers/rendering/renderer_rd/environment/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/forward_clustered/SCsub b/servers/rendering/renderer_rd/forward_clustered/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/rendering/renderer_rd/forward_clustered/SCsub +++ b/servers/rendering/renderer_rd/forward_clustered/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/forward_mobile/SCsub b/servers/rendering/renderer_rd/forward_mobile/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/rendering/renderer_rd/forward_mobile/SCsub +++ b/servers/rendering/renderer_rd/forward_mobile/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 7d6d5018d0..0c21fec282 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1131,6 +1131,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render scene_data.cam_orthogonal = p_camera_data->is_orthogonal; scene_data.camera_visible_layers = p_camera_data->visible_layers; scene_data.taa_jitter = p_camera_data->taa_jitter; + scene_data.taa_frame_count = p_camera_data->taa_frame_count; scene_data.main_cam_transform = p_camera_data->main_transform; scene_data.flip_y = !p_reflection_probe.is_valid(); diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub index 5405985741..e102b839b5 100644 --- a/servers/rendering/renderer_rd/shaders/SCsub +++ b/servers/rendering/renderer_rd/shaders/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/shaders/effects/SCsub b/servers/rendering/renderer_rd/shaders/effects/SCsub index 810f781340..e5517e52eb 100644 --- a/servers/rendering/renderer_rd/shaders/effects/SCsub +++ b/servers/rendering/renderer_rd/shaders/effects/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub b/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub index 5b8bbc343b..53f3ee3977 100644 --- a/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub +++ b/servers/rendering/renderer_rd/shaders/effects/fsr2/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl index 8c50bb544d..41a262b2e8 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl @@ -50,11 +50,14 @@ const int num_taps[5] = { 3, 5, 12, 0, 0 }; // #define SSAO_DETAIL_AO_ENABLE_AT_QUALITY_PRESET (1) // whether to use detail; to disable simply set to 99 or similar // -#define SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2) // !!warning!! the MIP generation on the C++ side will be enabled on quality preset 2 regardless of this value, so if changing here, change the C++ side too +// WARNING: The MIP generation on the C++ side will be enabled on quality preset 2 regardless of +// this value, so if changing here, change the C++ side too. +#define SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2) #define SSAO_DEPTH_MIPS_GLOBAL_OFFSET (-4.3) // best noise/quality/performance tradeoff, found empirically // -// !!warning!! the edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, on the C++ side; while toggling it here will work for -// testing purposes, it will not yield performance gains (or correct results) +// WARNING: The edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, +// on the C++ side; while toggling it here will work for testing purposes, it will not yield +// performance gains (or correct results). #define SSAO_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET (1) // #define SSAO_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET (1) diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl index 0b623c1d4e..6dbd6c82cb 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl @@ -49,8 +49,9 @@ const int num_taps[5] = { 3, 5, 12, 0, 0 }; #define SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2) #define SSIL_DEPTH_MIPS_GLOBAL_OFFSET (-4.3) // best noise/quality/performance tradeoff, found empirically // -// !!warning!! the edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, on the C++ side; while toggling it here will work for -// testing purposes, it will not yield performance gains (or correct results) +// WARNING: The edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, +// on the C++ side; while toggling it here will work for testing purposes, it will not yield +// performance gains (or correct results). #define SSIL_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET (1) // #define SSIL_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET (1) diff --git a/servers/rendering/renderer_rd/shaders/environment/SCsub b/servers/rendering/renderer_rd/shaders/environment/SCsub index f06a2d86e2..2c3e7d39ef 100644 --- a/servers/rendering/renderer_rd/shaders/environment/SCsub +++ b/servers/rendering/renderer_rd/shaders/environment/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub index f06a2d86e2..2c3e7d39ef 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index a441b1667d..400451ec36 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -1886,7 +1886,7 @@ void fragment_shader(in SceneData scene_data) { float range_begin = directional_lights.data[i].shadow_range_begin.x; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); blend_count++; } @@ -1902,7 +1902,7 @@ void fragment_shader(in SceneData scene_data) { float range_begin = directional_lights.data[i].shadow_range_begin.y; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; - float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); if (blend_count == 0) { shadow = s; @@ -1927,7 +1927,7 @@ void fragment_shader(in SceneData scene_data) { float range_begin = directional_lights.data[i].shadow_range_begin.z; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; - float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); if (blend_count == 0) { shadow = s; @@ -1952,7 +1952,7 @@ void fragment_shader(in SceneData scene_data) { float range_begin = directional_lights.data[i].shadow_range_begin.w; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; - float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); if (blend_count == 0) { shadow = s; @@ -2003,7 +2003,7 @@ void fragment_shader(in SceneData scene_data) { pssm_coord /= pssm_coord.w; - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor + (1.0 - blur_factor) * float(directional_lights.data[i].blend_splits)), pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor + (1.0 - blur_factor) * float(directional_lights.data[i].blend_splits)), pssm_coord, scene_data.taa_frame_count); if (directional_lights.data[i].blend_splits) { float pssm_blend; @@ -2037,7 +2037,7 @@ void fragment_shader(in SceneData scene_data) { pssm_coord /= pssm_coord.w; - float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor2 + (1.0 - blur_factor2) * float(directional_lights.data[i].blend_splits)), pssm_coord); + float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor2 + (1.0 - blur_factor2) * float(directional_lights.data[i].blend_splits)), pssm_coord, scene_data.taa_frame_count); shadow = mix(shadow, shadow2, pssm_blend); } } @@ -2220,7 +2220,7 @@ void fragment_shader(in SceneData scene_data) { continue; // Statically baked light and object uses lightmap, skip } - float shadow = light_process_omni_shadow(light_index, vertex, normal); + float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count); shadow = blur_shadow(shadow); @@ -2292,7 +2292,7 @@ void fragment_shader(in SceneData scene_data) { continue; // Statically baked light and object uses lightmap, skip } - float shadow = light_process_spot_shadow(light_index, vertex, normal); + float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count); shadow = blur_shadow(shadow); diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub index f06a2d86e2..2c3e7d39ef 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 92a8e2be32..17c7b756c3 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -1450,9 +1450,9 @@ void main() { float range_begin = directional_lights.data[i].shadow_range_begin.x; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord, scene_data.taa_frame_count); } } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { vec4 v = vec4(vertex, 1.0); @@ -1467,9 +1467,9 @@ void main() { float range_begin = directional_lights.data[i].shadow_range_begin.y; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord, scene_data.taa_frame_count); } } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { vec4 v = vec4(vertex, 1.0); @@ -1484,9 +1484,9 @@ void main() { float range_begin = directional_lights.data[i].shadow_range_begin.z; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord, scene_data.taa_frame_count); } } else { vec4 v = vec4(vertex, 1.0); @@ -1501,9 +1501,9 @@ void main() { float range_begin = directional_lights.data[i].shadow_range_begin.w; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; - shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); } else { - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord, scene_data.taa_frame_count); } } @@ -1522,9 +1522,9 @@ void main() { float range_begin = directional_lights.data[i].shadow_range_begin.y; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); } else { - shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord, scene_data.taa_frame_count); } pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); @@ -1539,9 +1539,9 @@ void main() { float range_begin = directional_lights.data[i].shadow_range_begin.z; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); } else { - shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord, scene_data.taa_frame_count); } pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); @@ -1555,9 +1555,9 @@ void main() { float range_begin = directional_lights.data[i].shadow_range_begin.w; float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; - shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); + shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale, scene_data.taa_frame_count); } else { - shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); + shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord, scene_data.taa_frame_count); } pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); @@ -1627,7 +1627,7 @@ void main() { pssm_coord /= pssm_coord.w; - shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor + (1.0 - blur_factor) * float(directional_lights.data[i].blend_splits)), pssm_coord); + shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor + (1.0 - blur_factor) * float(directional_lights.data[i].blend_splits)), pssm_coord, scene_data.taa_frame_count); if (directional_lights.data[i].blend_splits) { float pssm_blend; @@ -1661,7 +1661,7 @@ void main() { pssm_coord /= pssm_coord.w; - float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor2 + (1.0 - blur_factor2) * float(directional_lights.data[i].blend_splits)), pssm_coord); + float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * (blur_factor2 + (1.0 - blur_factor2) * float(directional_lights.data[i].blend_splits)), pssm_coord, scene_data.taa_frame_count); shadow = mix(shadow, shadow2, pssm_blend); } @@ -1767,7 +1767,7 @@ void main() { break; } - float shadow = light_process_omni_shadow(light_index, vertex, normal); + float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count); shadow = blur_shadow(shadow); @@ -1812,7 +1812,7 @@ void main() { break; } - float shadow = light_process_spot_shadow(light_index, vertex, normal); + float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count); shadow = blur_shadow(shadow); diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl index 67542d61fd..a2fef216f5 100644 --- a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl @@ -52,11 +52,11 @@ struct SceneData { uint fog_mode; highp float fog_density; highp float fog_height; - highp float fog_height_density; + highp float fog_height_density; highp float fog_depth_curve; - highp float pad; highp float fog_depth_begin; + highp float taa_frame_count; mediump vec3 fog_light_color; highp float fog_depth_end; 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 748fb59531..14a4dc7089 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -264,7 +264,7 @@ float quick_hash(vec2 pos) { return fract(magic.z * fract(dot(pos, magic.xy))); } -float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { +float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord, float taa_frame_count) { vec2 pos = coord.xy; float depth = coord.z; @@ -275,7 +275,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve mat2 disk_rotation; { - float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float r = quick_hash(gl_FragCoord.xy + vec2(taa_frame_count * 5.588238)) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); @@ -290,7 +290,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve return avg * (1.0 / float(sc_directional_soft_shadow_samples)); } -float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) { +float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord, float taa_frame_count) { vec2 pos = coord.xy; float depth = coord.z; @@ -301,7 +301,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) { mat2 disk_rotation; { - float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float r = quick_hash(gl_FragCoord.xy + vec2(taa_frame_count * 5.588238)) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); @@ -316,7 +316,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) { return avg * (1.0 / float(sc_soft_shadow_samples)); } -float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth) { +float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth, float taa_frame_count) { //if only one sample is taken, take it from the center if (sc_soft_shadow_samples == 0) { vec2 pos = coord * 0.5 + 0.5; @@ -326,7 +326,7 @@ float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec mat2 disk_rotation; { - float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float r = quick_hash(gl_FragCoord.xy + vec2(taa_frame_count * 5.588238)) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); @@ -359,14 +359,14 @@ float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec return avg * (1.0 / float(sc_soft_shadow_samples)); } -float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) { +float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale, float taa_frame_count) { //find blocker float blocker_count = 0.0; float blocker_average = 0.0; mat2 disk_rotation; { - float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float r = quick_hash(gl_FragCoord.xy + vec2(taa_frame_count * 5.588238)) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); @@ -412,7 +412,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) { return nd * pow(max(distance, 0.0001), -decay); } -float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { +float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal, float taa_frame_count) { #ifndef SHADOWS_DISABLED if (omni_lights.data[idx].shadow_opacity > 0.001) { // there is a shadowmap @@ -444,7 +444,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { mat2 disk_rotation; { - float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float r = quick_hash(gl_FragCoord.xy + vec2(taa_frame_count * 5.588238)) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); @@ -537,7 +537,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { float depth = shadow_len - omni_lights.data[idx].shadow_bias; depth *= omni_lights.data[idx].inv_radius; depth = 1.0 - depth; - shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity); + shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth, taa_frame_count), omni_lights.data[idx].shadow_opacity); } return shadow; @@ -698,7 +698,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v specular_light); } -float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { +float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal, float taa_frame_count) { #ifndef SHADOWS_DISABLED if (spot_lights.data[idx].shadow_opacity > 0.001) { vec3 light_rel_vec = spot_lights.data[idx].position - vertex; @@ -729,7 +729,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { mat2 disk_rotation; { - float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI; + float r = quick_hash(gl_FragCoord.xy + vec2(taa_frame_count * 5.588238)) * 2.0 * M_PI; float sr = sin(r); float cr = cos(r); disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr)); @@ -770,7 +770,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { } else { //hard shadow vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z); - shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv), spot_lights.data[idx].shadow_opacity); + shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv, taa_frame_count), spot_lights.data[idx].shadow_opacity); } return shadow; diff --git a/servers/rendering/renderer_rd/spirv-reflect/SCsub b/servers/rendering/renderer_rd/spirv-reflect/SCsub index 4c27e5bef7..8d3d8560a5 100644 --- a/servers/rendering/renderer_rd/spirv-reflect/SCsub +++ b/servers/rendering/renderer_rd/spirv-reflect/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/storage_rd/SCsub b/servers/rendering/renderer_rd/storage_rd/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/rendering/renderer_rd/storage_rd/SCsub +++ b/servers/rendering/renderer_rd/storage_rd/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index 148a556b46..660836facf 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -112,6 +112,7 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p ubo.taa_jitter[0] = taa_jitter.x; ubo.taa_jitter[1] = taa_jitter.y; + ubo.taa_frame_count = taa_frame_count; ubo.z_far = z_far; ubo.z_near = z_near; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h index b2c93acd44..4a70482d72 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -48,6 +48,7 @@ public: Transform3D cam_transform; Projection cam_projection; Vector2 taa_jitter; + float taa_frame_count = 0.0f; uint32_t camera_visible_layers; bool cam_orthogonal = false; bool flip_y = false; @@ -148,8 +149,8 @@ private: float fog_height_density; float fog_depth_curve; - float pad; float fog_depth_begin; + float taa_frame_count; // Used to add break up samples over multiple frames. Value is an integer from 0 to taa_phase_count -1. float fog_light_color[3]; float fog_depth_end; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 286944641c..43abb22e3d 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2700,6 +2700,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu ERR_FAIL_NULL(camera); Vector2 jitter; + float taa_frame_count = 0.0f; if (p_jitter_phase_count > 0) { uint32_t current_jitter_count = camera_jitter_array.size(); if (p_jitter_phase_count != current_jitter_count) { @@ -2713,6 +2714,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } jitter = camera_jitter_array[RSG::rasterizer->get_frame_number() % p_jitter_phase_count] / p_viewport_size; + taa_frame_count = float(RSG::rasterizer->get_frame_number() % p_jitter_phase_count); } RendererSceneRender::CameraData camera_data; @@ -2755,7 +2757,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } break; } - camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, camera->visible_layers); + camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, taa_frame_count, camera->visible_layers); } else { // Setup our camera for our XR interface. // We can support multiple views here each with their own camera @@ -2777,7 +2779,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } if (view_count == 1) { - camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter, camera->visible_layers); + camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers); } else if (view_count == 2) { camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect); } else { diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index 76c779900f..797ba7eaf7 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -33,7 +33,7 @@ ///////////////////////////////////////////////////////////////////////////// // CameraData -void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter, const uint32_t p_visible_layers) { +void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter, float p_taa_frame_count, const uint32_t p_visible_layers) { view_count = 1; is_orthogonal = p_is_orthogonal; vaspect = p_vaspect; @@ -45,6 +45,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, view_offset[0] = Transform3D(); view_projection[0] = p_projection; taa_jitter = p_taa_jitter; + taa_frame_count = p_taa_frame_count; } void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) { diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 3446f5dd1b..72ccbcdf11 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -307,8 +307,9 @@ public: Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS]; Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; Vector2 taa_jitter; + float taa_frame_count = 0.0f; - void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), uint32_t p_visible_layers = 0xFFFFFFFF); + void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), float p_taa_frame_count = 0.0f, uint32_t p_visible_layers = 0xFFFFFFFF); void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect); }; diff --git a/servers/rendering/storage/SCsub b/servers/rendering/storage/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/rendering/storage/SCsub +++ b/servers/rendering/storage/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/text/SCsub b/servers/text/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/text/SCsub +++ b/servers/text/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/servers/xr/SCsub b/servers/xr/SCsub index 86681f9c74..98f918b245 100644 --- a/servers/xr/SCsub +++ b/servers/xr/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/tests/SCsub b/tests/SCsub index d96a1142e4..169c7c1efa 100644 --- a/tests/SCsub +++ b/tests/SCsub @@ -1,4 +1,5 @@ -#!/usr/bin/python +#!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") |
