diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 288eea3b22..24f3573baa 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -179,6 +179,7 @@ /modules/regex/tests/ @godotengine/core @godotengine/tests /modules/zip/ @godotengine/core /modules/zip/doc_classes/ @godotengine/core @godotengine/documentation +/modules/zip/tests @godotengine/core @godotengine/tests # Platform diff --git a/.github/actions/godot-api-dump/action.yml b/.github/actions/godot-api-dump/action.yml deleted file mode 100644 index dee70298c4..0000000000 --- a/.github/actions/godot-api-dump/action.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Dump Godot API -description: Dump Godot API for GDExtension - -inputs: - bin: - description: The path to the Godot executable - required: true - -runs: - using: composite - steps: - # Dump GDExtension interface and API - - name: Dump GDExtension interface and API for godot-cpp build - shell: sh - run: | - ${{ inputs.bin }} --headless --dump-gdextension-interface --dump-extension-api - mkdir godot-api - cp -f gdextension_interface.h godot-api/ - cp -f extension_api.json godot-api/ - - - name: Upload API dump - uses: ./.github/actions/upload-artifact - with: - name: godot-api-dump - path: ./godot-api/* diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index 1745bf1c37..4e7375bd18 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -46,6 +46,7 @@ jobs: - name: Class reference schema checks run: | + sudo apt update sudo apt install -y libxml2-utils xmllint --quiet --noout --schema doc/class.xsd doc/classes/*.xml modules/*/doc_classes/*.xml platform/*/doc_classes/*.xml diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml index a339c7d0cf..acb599ae8f 100644 --- a/.github/workflows/windows_builds.yml +++ b/.github/workflows/windows_builds.yml @@ -7,6 +7,7 @@ on: env: SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=yes strict_checks=yes "angle_libs=${{ github.workspace }}/" "accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.15.1/" SCONS_CACHE_MSVC_CONFIG: true + PYTHONIOENCODING: utf8 jobs: build-windows: diff --git a/SConstruct b/SConstruct index 3d0d4b3918..a5ae571227 100644 --- a/SConstruct +++ b/SConstruct @@ -159,27 +159,38 @@ opts = Variables(customs, ARGUMENTS) # Target build options opts.Add((["platform", "p"], "Target platform (%s)" % "|".join(platform_list), "")) -opts.Add(EnumVariable("target", "Compilation target", "editor", ("editor", "template_release", "template_debug"))) -opts.Add(EnumVariable("arch", "CPU architecture", "auto", ["auto"] + architectures, architecture_aliases)) +opts.Add( + EnumVariable( + "target", "Compilation target", "editor", ["editor", "template_release", "template_debug"], ignorecase=2 + ) +) +opts.Add(EnumVariable("arch", "CPU architecture", "auto", ["auto"] + architectures, architecture_aliases, ignorecase=2)) opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False)) opts.Add( EnumVariable( "optimize", "Optimization level (by default inferred from 'target' and 'dev_build')", "auto", - ("auto", "none", "custom", "debug", "speed", "speed_trace", "size", "size_extra"), + ["auto", "none", "custom", "debug", "speed", "speed_trace", "size", "size_extra"], + ignorecase=2, ) ) opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", False)) opts.Add(BoolVariable("separate_debug_symbols", "Extract debugging symbols to a separate file", False)) opts.Add(BoolVariable("debug_paths_relative", "Make file paths in debug symbols relative (if supported)", False)) -opts.Add(EnumVariable("lto", "Link-time optimization (production builds)", "none", ("none", "auto", "thin", "full"))) +opts.Add( + EnumVariable( + "lto", "Link-time optimization (production builds)", "none", ["none", "auto", "thin", "full"], ignorecase=2 + ) +) opts.Add(BoolVariable("production", "Set defaults to build Redot for use in production", False)) opts.Add(BoolVariable("threads", "Enable threading support", True)) # Components opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated and removed features", True)) -opts.Add(EnumVariable("precision", "Set the floating-point precision level", "single", ("single", "double"))) +opts.Add( + EnumVariable("precision", "Set the floating-point precision level", "single", ["single", "double"], ignorecase=2) +) opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True)) opts.Add(BoolVariable("brotli", "Enable Brotli for decompression and WOFF2 fonts support", True)) opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver on supported platforms", False)) @@ -213,7 +224,9 @@ opts.Add( ) opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False)) opts.Add(BoolVariable("progress", "Show a progress indicator during compilation", True)) -opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extra", "all", "moderate", "no"))) +opts.Add( + EnumVariable("warnings", "Level of compilation warnings", "all", ["extra", "all", "moderate", "no"], ignorecase=2) +) opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", False)) opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all generated binary files", "") opts.Add("object_prefix", "Custom prefix added to the base filename of all generated object files", "") @@ -718,7 +731,7 @@ if env["arch"] == "x86_32": if env.msvc: env.Append(CCFLAGS=["/arch:SSE2"]) else: - env.Append(CCFLAGS=["-msse2"]) + env.Append(CCFLAGS=["-msse2", "-mfpmath=sse", "-mstackrealign"]) # Explicitly specify colored output. if methods.using_gcc(env): @@ -877,7 +890,7 @@ if env.msvc and not methods.using_clang(env): # MSVC env.AppendUnique(LINKFLAGS=["/WX"]) else: # GCC, Clang - common_warnings = [] + common_warnings = ["-Wenum-conversion"] if methods.using_gcc(env): common_warnings += ["-Wshadow", "-Wno-misleading-indentation"] diff --git a/core/config/engine.cpp b/core/config/engine.cpp index 681589c0f1..8e5d58638e 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -453,8 +453,6 @@ String Engine::get_shader_cache_path() const { return shader_cache_path; } -Engine *Engine::singleton = nullptr; - Engine *Engine::get_singleton() { return singleton; } diff --git a/core/config/engine.h b/core/config/engine.h index c92b58f7a3..9c702ff0cf 100644 --- a/core/config/engine.h +++ b/core/config/engine.h @@ -92,7 +92,7 @@ private: bool _print_header = true; - static Engine *singleton; + static inline Engine *singleton = nullptr; String write_movie_path; String shader_cache_path; diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 320f07a7dc..3d67ede8d2 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -50,10 +50,6 @@ #include "modules/modules_enabled.gen.h" // For mono. #endif // TOOLS_ENABLED -const String ProjectSettings::PROJECT_DATA_DIR_NAME_SUFFIX = "godot"; - -ProjectSettings *ProjectSettings::singleton = nullptr; - ProjectSettings *ProjectSettings::get_singleton() { return singleton; } @@ -302,6 +298,8 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < custom_feature_array.size(); i++) { custom_features.insert(custom_feature_array[i]); } + + _version++; _queue_changed(); return true; } @@ -347,6 +345,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { } } + _version++; _queue_changed(); return true; } @@ -1412,8 +1411,7 @@ void ProjectSettings::load_scene_groups_cache() { Ref cf; cf.instantiate(); if (cf->load(get_scene_groups_cache_path()) == OK) { - List scene_paths; - cf->get_sections(&scene_paths); + Vector scene_paths = cf->get_sections(); for (const String &E : scene_paths) { Array scene_groups = cf->get_value(E, "groups", Array()); HashSet cache; diff --git a/core/config/project_settings.h b/core/config/project_settings.h index 8dc5d85985..95a7f4e5b9 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -44,9 +44,13 @@ class ProjectSettings : public Object { bool is_changed = false; + // Starting version from 1 ensures that all callers can reset their tested version to 0, + // and will always detect the initial project settings as a "change". + uint32_t _version = 1; + public: typedef HashMap CustomMap; - static const String PROJECT_DATA_DIR_NAME_SUFFIX; + static inline const String PROJECT_DATA_DIR_NAME_SUFFIX = "godot"; // Properties that are not for built in values begin from this value, so builtin ones are displayed first. constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16; @@ -118,7 +122,7 @@ protected: void _queue_changed(); void _emit_changed(); - static ProjectSettings *singleton; + static inline ProjectSettings *singleton = nullptr; Error _load_settings_text(const String &p_path); Error _load_settings_binary(const String &p_path); @@ -220,6 +224,9 @@ public: String get_scene_groups_cache_path() const; void load_scene_groups_cache(); + // Testing a version allows fast cached GET_GLOBAL macros. + uint32_t get_version() const { return _version; } + #ifdef TOOLS_ENABLED virtual void get_argument_options(const StringName &p_function, int p_idx, List *r_options) const override; #endif @@ -245,3 +252,26 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p #define GLOBAL_DEF_RST_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true, true) #define GLOBAL_DEF_INTERNAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, false, true) + +///////////////////////////////////////////////////////////////////////////////////////// +// Cached versions of GLOBAL_GET. +// Cached but uses a typed variable for storage, this can be more efficient. +// Variables prefixed with _ggc_ to avoid shadowing warnings. +#define GLOBAL_GET_CACHED(m_type, m_setting_name) ([](const char *p_name) -> m_type {\ +static_assert(std::is_trivially_destructible::value, "GLOBAL_GET_CACHED must use a trivial type that allows static lifetime.");\ +static m_type _ggc_local_var;\ +static uint32_t _ggc_local_version = 0;\ +static SpinLock _ggc_spin;\ +uint32_t _ggc_new_version = ProjectSettings::get_singleton()->get_version();\ +if (_ggc_local_version != _ggc_new_version) {\ + _ggc_spin.lock();\ + _ggc_local_version = _ggc_new_version;\ + _ggc_local_var = ProjectSettings::get_singleton()->get_setting_with_override(p_name);\ + m_type _ggc_temp = _ggc_local_var;\ + _ggc_spin.unlock();\ + return _ggc_temp;\ +}\ +_ggc_spin.lock();\ +m_type _ggc_temp2 = _ggc_local_var;\ +_ggc_spin.unlock();\ +return _ggc_temp2; })(m_setting_name) diff --git a/core/core_bind.cpp b/core/core_bind.cpp index e067cb8c9f..caace3334f 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -48,8 +48,6 @@ namespace CoreBind { ////// ResourceLoader ////// -ResourceLoader *ResourceLoader::singleton = nullptr; - Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, CacheMode p_cache_mode) { return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads, ResourceFormatLoader::CacheMode(p_cache_mode)); } @@ -171,6 +169,10 @@ Error ResourceSaver::save(const Ref &p_resource, const String &p_path, return ::ResourceSaver::save(p_resource, p_path, p_flags); } +Error ResourceSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) { + return ::ResourceSaver::set_uid(p_path, p_uid); +} + Vector ResourceSaver::get_recognized_extensions(const Ref &p_resource) { List exts; ::ResourceSaver::get_recognized_extensions(p_resource, &exts); @@ -193,10 +195,9 @@ ResourceUID::ID ResourceSaver::get_resource_id_for_path(const String &p_path, bo return ::ResourceSaver::get_resource_id_for_path(p_path, p_generate); } -ResourceSaver *ResourceSaver::singleton = nullptr; - void ResourceSaver::_bind_methods() { ClassDB::bind_method(D_METHOD("save", "resource", "path", "flags"), &ResourceSaver::save, DEFVAL(""), DEFVAL((uint32_t)FLAG_NONE)); + ClassDB::bind_method(D_METHOD("set_uid", "resource", "uid"), &ResourceSaver::set_uid); ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions); ClassDB::bind_method(D_METHOD("add_resource_format_saver", "format_saver", "at_front"), &ResourceSaver::add_resource_format_saver, DEFVAL(false)); ClassDB::bind_method(D_METHOD("remove_resource_format_saver", "format_saver"), &ResourceSaver::remove_resource_format_saver); @@ -719,8 +720,6 @@ void OS::remove_logger(const Ref &p_logger) { logger_bind->loggers.erase(p_logger); } -OS *OS::singleton = nullptr; - void OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_entropy", "size"), &OS::get_entropy); ClassDB::bind_method(D_METHOD("get_system_ca_certificates"), &OS::get_system_ca_certificates); @@ -874,8 +873,6 @@ OS::~OS() { ////// Geometry2D ////// -Geometry2D *Geometry2D::singleton = nullptr; - Geometry2D *Geometry2D::get_singleton() { return singleton; } @@ -1135,8 +1132,6 @@ void Geometry2D::_bind_methods() { ////// Geometry3D ////// -Geometry3D *Geometry3D::singleton = nullptr; - Geometry3D *Geometry3D::get_singleton() { return singleton; } @@ -1279,8 +1274,6 @@ void Geometry3D::_bind_methods() { ////// Marshalls ////// -Marshalls *Marshalls::singleton = nullptr; - Marshalls *Marshalls::get_singleton() { return singleton; } @@ -2140,8 +2133,6 @@ void Engine::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "physics_jitter_fix"), "set_physics_jitter_fix", "get_physics_jitter_fix"); } -Engine *Engine::singleton = nullptr; - ////// EngineDebugger ////// bool EngineDebugger::is_active() { @@ -2287,8 +2278,6 @@ EngineDebugger::~EngineDebugger() { captures.clear(); } -EngineDebugger *EngineDebugger::singleton = nullptr; - void EngineDebugger::_bind_methods() { ClassDB::bind_method(D_METHOD("is_active"), &EngineDebugger::is_active); diff --git a/core/core_bind.h b/core/core_bind.h index 95deb25fd8..4949c40b57 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -50,7 +50,7 @@ class ResourceLoader : public Object { protected: static void _bind_methods(); - static ResourceLoader *singleton; + static inline ResourceLoader *singleton = nullptr; public: enum ThreadLoadStatus { @@ -95,7 +95,7 @@ class ResourceSaver : public Object { protected: static void _bind_methods(); - static ResourceSaver *singleton; + static inline ResourceSaver *singleton = nullptr; public: enum SaverFlags { @@ -112,6 +112,7 @@ public: static ResourceSaver *get_singleton() { return singleton; } Error save(const Ref &p_resource, const String &p_path, BitField p_flags); + Error set_uid(const String &p_path, ResourceUID::ID p_uid); Vector get_recognized_extensions(const Ref &p_resource); void add_resource_format_saver(Ref p_format_saver, bool p_at_front); void remove_resource_format_saver(Ref p_format_saver); @@ -163,7 +164,7 @@ class OS : public Object { protected: static void _bind_methods(); - static OS *singleton; + static inline OS *singleton = nullptr; #ifndef DISABLE_DEPRECATED Dictionary _execute_with_pipe_bind_compat_94434(const String &p_path, const Vector &p_arguments); @@ -323,7 +324,7 @@ public: class Geometry2D : public Object { GDCLASS(Geometry2D, Object); - static Geometry2D *singleton; + static inline Geometry2D *singleton = nullptr; protected: static void _bind_methods(); @@ -389,7 +390,7 @@ public: class Geometry3D : public Object { GDCLASS(Geometry3D, Object); - static Geometry3D *singleton; + static inline Geometry3D *singleton = nullptr; protected: static void _bind_methods(); @@ -420,7 +421,7 @@ public: class Marshalls : public Object { GDCLASS(Marshalls, Object); - static Marshalls *singleton; + static inline Marshalls *singleton = nullptr; protected: static void _bind_methods(); @@ -571,7 +572,7 @@ class Engine : public Object { protected: static void _bind_methods(); - static Engine *singleton; + static inline Engine *singleton = nullptr; public: static Engine *get_singleton() { return singleton; } @@ -654,7 +655,7 @@ class EngineDebugger : public Object { protected: static void _bind_methods(); - static EngineDebugger *singleton; + static inline EngineDebugger *singleton = nullptr; public: static EngineDebugger *get_singleton() { return singleton; } diff --git a/core/core_globals.h b/core/core_globals.h index 78448cb466..0f52ffa90e 100644 --- a/core/core_globals.h +++ b/core/core_globals.h @@ -37,7 +37,7 @@ class CoreGlobals { public: - static bool leak_reporting_enabled; - static bool print_line_enabled; - static bool print_error_enabled; + static inline bool leak_reporting_enabled = true; + static inline bool print_line_enabled = true; + static inline bool print_error_enabled = true; }; diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index ed8d1c71fc..e7f2978ee9 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -38,13 +38,6 @@ #include "core/debugger/script_debugger.h" #include "core/os/os.h" -EngineDebugger *EngineDebugger::singleton = nullptr; -ScriptDebugger *EngineDebugger::script_debugger = nullptr; - -HashMap EngineDebugger::profilers; -HashMap EngineDebugger::captures; -HashMap EngineDebugger::protocols; - void (*EngineDebugger::allow_focus_steal_fn)(); void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) { diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index 19d11f3339..c860933230 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -93,12 +93,12 @@ private: uint32_t poll_every = 0; protected: - static EngineDebugger *singleton; - static ScriptDebugger *script_debugger; + static inline EngineDebugger *singleton = nullptr; + static inline ScriptDebugger *script_debugger = nullptr; - static HashMap profilers; - static HashMap captures; - static HashMap protocols; + static inline HashMap profilers; + static inline HashMap captures; + static inline HashMap protocols; static void (*allow_focus_steal_fn)(); diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp index 585572b3ae..0ba9fd2f17 100644 --- a/core/debugger/script_debugger.cpp +++ b/core/debugger/script_debugger.cpp @@ -34,9 +34,6 @@ #include "core/debugger/engine_debugger.h" -thread_local int ScriptDebugger::lines_left = -1; -thread_local int ScriptDebugger::depth = -1; -thread_local ScriptLanguage *ScriptDebugger::break_lang = nullptr; thread_local Vector ScriptDebugger::error_stack_info; void ScriptDebugger::set_lines_left(int p_left) { diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h index 16b32a76a5..78128cd0ca 100644 --- a/core/debugger/script_debugger.h +++ b/core/debugger/script_debugger.h @@ -45,9 +45,9 @@ class ScriptDebugger { HashMap> breakpoints; - static thread_local int lines_left; - static thread_local int depth; - static thread_local ScriptLanguage *break_lang; + static inline thread_local int lines_left = -1; + static inline thread_local int depth = -1; + static inline thread_local ScriptLanguage *break_lang = nullptr; static thread_local Vector error_stack_info; public: diff --git a/core/error/error_macros.h b/core/error/error_macros.h index 2957e2269b..495fa6de80 100644 --- a/core/error/error_macros.h +++ b/core/error/error_macros.h @@ -36,6 +36,10 @@ #include // IWYU pragma: keep // Used in macro. We'd normally use `safe_refcount.h`, but that would cause circular includes. +#ifdef _MSC_VER +#include // `__fastfail()`. +#endif + class String; class ObjectID; @@ -87,7 +91,7 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file, /** * Don't use GENERATE_TRAP() directly, should only be used be the macros below. */ -#define GENERATE_TRAP() __debugbreak() +#define GENERATE_TRAP() __fastfail(7 /* FAST_FAIL_FATAL_APP_EXIT */) #else /** * Don't use GENERATE_TRAP() directly, should only be used be the macros below. @@ -828,10 +832,14 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file, #endif #ifdef DEV_ENABLED -#define DEV_CHECK_ONCE(m_cond) \ - if (unlikely(!(m_cond))) { \ - ERR_PRINT_ONCE("DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \ - } else \ +#define DEV_CHECK_ONCE(m_cond) \ + if (true) { \ + static bool first_print = true; \ + if (first_print && unlikely(!(m_cond))) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \ + first_print = false; \ + } \ + } else \ ((void)0) #else #define DEV_CHECK_ONCE(m_cond) diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 0bd12f3715..23fcba1733 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -688,8 +688,6 @@ void GDExtension::_register_get_classes_used_callback(GDExtensionClassLibraryPtr #endif } -HashMap GDExtension::gdextension_interface_functions; - void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) { ERR_FAIL_COND_MSG(gdextension_interface_functions.has(p_function_name), vformat("Attempt to register interface function '%s', which appears to be already registered.", p_function_name)); gdextension_interface_functions.insert(p_function_name, p_function_pointer); @@ -1052,10 +1050,6 @@ PackedStringArray GDExtension::get_classes_used() const { return ret; } -Vector GDExtensionEditorPlugins::extension_classes; -GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_add_plugin = nullptr; -GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr; - void GDExtensionEditorPlugins::add_extension_class(const StringName &p_class_name) { if (editor_node_add_plugin) { editor_node_add_plugin(p_class_name); @@ -1072,9 +1066,6 @@ void GDExtensionEditorPlugins::remove_extension_class(const StringName &p_class_ } } -GDExtensionEditorHelp::EditorHelpLoadXmlBufferFunc GDExtensionEditorHelp::editor_help_load_xml_buffer = nullptr; -GDExtensionEditorHelp::EditorHelpRemoveClassFunc GDExtensionEditorHelp::editor_help_remove_class = nullptr; - void GDExtensionEditorHelp::load_xml_buffer(const uint8_t *p_buffer, int p_size) { ERR_FAIL_NULL(editor_help_load_xml_buffer); editor_help_load_xml_buffer(p_buffer, p_size); diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h index 27b3f6aa1f..f7f2c77242 100644 --- a/core/extension/gdextension.h +++ b/core/extension/gdextension.h @@ -117,7 +117,7 @@ class GDExtension : public Resource { void clear_instance_bindings(); #endif - static HashMap gdextension_interface_functions; + static inline HashMap gdextension_interface_functions; protected: static void _bind_methods(); @@ -191,7 +191,7 @@ public: #ifdef TOOLS_ENABLED class GDExtensionEditorPlugins { private: - static Vector extension_classes; + static inline Vector extension_classes; protected: friend class EditorNode; @@ -199,8 +199,8 @@ protected: // Since this in core, we can't directly reference EditorNode, so it will // set these function pointers in its constructor. typedef void (*EditorPluginRegisterFunc)(const StringName &p_class_name); - static EditorPluginRegisterFunc editor_node_add_plugin; - static EditorPluginRegisterFunc editor_node_remove_plugin; + static inline EditorPluginRegisterFunc editor_node_add_plugin = nullptr; + static inline EditorPluginRegisterFunc editor_node_remove_plugin = nullptr; public: static void add_extension_class(const StringName &p_class_name); @@ -220,10 +220,10 @@ protected: // is initialized even _before_ it gets instantiated, as we need to rely on // this method while initializing the engine. typedef void (*EditorHelpLoadXmlBufferFunc)(const uint8_t *p_buffer, int p_size); - static EditorHelpLoadXmlBufferFunc editor_help_load_xml_buffer; + static inline EditorHelpLoadXmlBufferFunc editor_help_load_xml_buffer = nullptr; typedef void (*EditorHelpRemoveClassFunc)(const String &p_class); - static EditorHelpRemoveClassFunc editor_help_remove_class; + static inline EditorHelpRemoveClassFunc editor_help_remove_class = nullptr; public: static void load_xml_buffer(const uint8_t *p_buffer, int p_size); diff --git a/core/extension/gdextension_library_loader.cpp b/core/extension/gdextension_library_loader.cpp index 9897338193..2008c59e63 100644 --- a/core/extension/gdextension_library_loader.cpp +++ b/core/extension/gdextension_library_loader.cpp @@ -40,8 +40,7 @@ Vector GDExtensionLibraryLoader::find_extension_dependencies(const String &p_path, Ref p_config, std::function p_has_feature) { Vector dependencies_shared_objects; if (p_config->has_section("dependencies")) { - List config_dependencies; - p_config->get_section_keys("dependencies", &config_dependencies); + Vector config_dependencies = p_config->get_section_keys("dependencies"); for (const String &dependency : config_dependencies) { Vector dependency_tags = dependency.split("."); @@ -75,8 +74,7 @@ Vector GDExtensionLibraryLoader::find_extension_dependencies(const String GDExtensionLibraryLoader::find_extension_library(const String &p_path, Ref p_config, std::function p_has_feature, PackedStringArray *r_tags) { // First, check the explicit libraries. if (p_config->has_section("libraries")) { - List libraries; - p_config->get_section_keys("libraries", &libraries); + Vector libraries = p_config->get_section_keys("libraries"); // Iterate the libraries, finding the best matching tags. String best_library_path; @@ -380,8 +378,7 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) { // Handle icons if any are specified. if (config->has_section("icons")) { - List keys; - config->get_section_keys("icons", &keys); + Vector keys = config->get_section_keys("icons"); for (const String &key : keys) { String icon_path = config->get_value("icons", key); if (icon_path.is_relative_path()) { diff --git a/core/extension/gdextension_loader.h b/core/extension/gdextension_loader.h index c74eeebe4d..72eb8a62bd 100644 --- a/core/extension/gdextension_loader.h +++ b/core/extension/gdextension_loader.h @@ -37,7 +37,7 @@ class GDExtension; class GDExtensionLoader : public RefCounted { - GDSOFTCLASS(GDExtensionLoader, GDExtensionLoader); + GDSOFTCLASS(GDExtensionLoader, RefCounted); public: virtual Error open_library(const String &p_path) = 0; diff --git a/core/extension/gdextension_manager.cpp b/core/extension/gdextension_manager.cpp index 847145dc40..426ad3f952 100644 --- a/core/extension/gdextension_manager.cpp +++ b/core/extension/gdextension_manager.cpp @@ -413,8 +413,6 @@ void GDExtensionManager::_bind_methods() { ADD_SIGNAL(MethodInfo("extension_unloading", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, "GDExtension"))); } -GDExtensionManager *GDExtensionManager::singleton = nullptr; - GDExtensionManager::GDExtensionManager() { ERR_FAIL_COND(singleton != nullptr); singleton = this; diff --git a/core/extension/gdextension_manager.h b/core/extension/gdextension_manager.h index 128c1ad385..03e2189949 100644 --- a/core/extension/gdextension_manager.h +++ b/core/extension/gdextension_manager.h @@ -43,7 +43,7 @@ class GDExtensionManager : public Object { static void _bind_methods(); - static GDExtensionManager *singleton; + static inline GDExtensionManager *singleton = nullptr; public: enum LoadStatus { diff --git a/core/extension/gdextension_special_compat_hashes.cpp b/core/extension/gdextension_special_compat_hashes.cpp index 389c8c3250..04d43fe600 100644 --- a/core/extension/gdextension_special_compat_hashes.cpp +++ b/core/extension/gdextension_special_compat_hashes.cpp @@ -37,8 +37,6 @@ #include "core/object/class_db.h" #include "core/variant/variant.h" -HashMap> GDExtensionSpecialCompatHashes::mappings; - bool GDExtensionSpecialCompatHashes::lookup_current_hash(const StringName &p_class, const StringName &p_method, uint32_t p_legacy_hash, uint32_t *r_current_hash) { LocalVector *methods = mappings.getptr(p_class); if (!methods) { diff --git a/core/extension/gdextension_special_compat_hashes.h b/core/extension/gdextension_special_compat_hashes.h index 05a4421436..01b27b54d4 100644 --- a/core/extension/gdextension_special_compat_hashes.h +++ b/core/extension/gdextension_special_compat_hashes.h @@ -49,7 +49,7 @@ class GDExtensionSpecialCompatHashes { uint32_t current_hash; }; - static HashMap> mappings; + static inline HashMap> mappings; public: static void initialize(); diff --git a/core/input/input.cpp b/core/input/input.cpp index 6246ebf631..d4f1f9a7fa 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -75,8 +75,6 @@ static const char *_joy_axes[(size_t)JoyAxis::SDL_MAX] = { "righttrigger", }; -Input *Input::singleton = nullptr; - void (*Input::set_mouse_mode_func)(Input::MouseMode) = nullptr; Input::MouseMode (*Input::get_mouse_mode_func)() = nullptr; void (*Input::set_mouse_mode_override_func)(Input::MouseMode) = nullptr; diff --git a/core/input/input.h b/core/input/input.h index 554955bd77..d9a8c3823f 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -43,7 +43,7 @@ class Input : public Object { GDCLASS(Input, Object); _THREAD_SAFE_CLASS_ - static Input *singleton; + static inline Input *singleton = nullptr; static constexpr uint64_t MAX_EVENT = 32; @@ -80,9 +80,7 @@ public: CURSOR_MAX }; - enum { - JOYPADS_MAX = 16, - }; + static constexpr int32_t JOYPADS_MAX = 16; typedef void (*EventDispatchFunc)(const Ref &p_event); diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 9a471d7f32..a1f8781248 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -37,9 +37,6 @@ #include "core/os/keyboard.h" #include "core/os/os.h" -const int InputEvent::DEVICE_ID_EMULATION = -1; -const int InputEvent::DEVICE_ID_INTERNAL = -2; - void InputEvent::set_device(int p_device) { device = p_device; emit_changed(); diff --git a/core/input/input_event.h b/core/input/input_event.h index d482bd7ebe..6b11bd0ad9 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -63,8 +63,8 @@ protected: static void _bind_methods(); public: - static const int DEVICE_ID_EMULATION; - static const int DEVICE_ID_INTERNAL; + static constexpr int DEVICE_ID_EMULATION = -1; + static constexpr int DEVICE_ID_INTERNAL = -2; void set_device(int p_device); int get_device() const; diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index bfbbb6df01..3d6191e465 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -39,10 +39,6 @@ #include "core/os/os.h" #include "core/variant/typed_array.h" -InputMap *InputMap::singleton = nullptr; - -int InputMap::ALL_DEVICES = -1; - void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action); ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions); diff --git a/core/input/input_map.h b/core/input/input_map.h index 2638b75890..06d4170cb7 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -47,7 +47,7 @@ public: /** * A special value used to signify that a given Action can be triggered by any device */ - static int ALL_DEVICES; + static constexpr int ALL_DEVICES = -1; struct Action { int id; @@ -60,7 +60,7 @@ public: static constexpr float DEFAULT_TOGGLE_DEADZONE = 0.5f; private: - static InputMap *singleton; + static inline InputMap *singleton = nullptr; mutable HashMap input_map; HashMap>> default_builtin_cache; diff --git a/core/io/compression.cpp b/core/io/compression.cpp index b05059b442..4307972251 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -37,7 +37,6 @@ #include "thirdparty/misc/fastlz.h" -#include #include #ifdef BROTLI_ENABLED @@ -366,10 +365,3 @@ int Compression::decompress_dynamic(Vector *p_dst_vect, int p_max_dst_s return Z_OK; } } - -int Compression::zlib_level = Z_DEFAULT_COMPRESSION; -int Compression::gzip_level = Z_DEFAULT_COMPRESSION; -int Compression::zstd_level = 3; -bool Compression::zstd_long_distance_matching = false; -int Compression::zstd_window_log_size = 27; // ZSTD_WINDOWLOG_LIMIT_DEFAULT -int Compression::gzip_chunk = 16384; diff --git a/core/io/compression.h b/core/io/compression.h index 90a791602d..23b5a0f744 100644 --- a/core/io/compression.h +++ b/core/io/compression.h @@ -35,14 +35,16 @@ #include "core/templates/vector.h" #include "core/typedefs.h" +#include + class Compression { public: - static int zlib_level; - static int gzip_level; - static int zstd_level; - static bool zstd_long_distance_matching; - static int zstd_window_log_size; - static int gzip_chunk; + static inline int zlib_level = Z_DEFAULT_COMPRESSION; + static inline int gzip_level = Z_DEFAULT_COMPRESSION; + static inline int zstd_level = 3; + static inline bool zstd_long_distance_matching = false; + static inline int zstd_window_log_size = 27; // ZSTD_WINDOWLOG_LIMIT_DEFAULT + static inline int gzip_chunk = 16384; enum Mode : int32_t { MODE_FASTLZ, diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 7dd1cfae64..3d36c50494 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -36,32 +36,6 @@ #include "core/string/string_builder.h" #include "core/variant/variant_parser.h" -PackedStringArray ConfigFile::_get_sections() const { - List s; - get_sections(&s); - PackedStringArray arr; - arr.resize(s.size()); - int idx = 0; - for (const String &E : s) { - arr.set(idx++, E); - } - - return arr; -} - -PackedStringArray ConfigFile::_get_section_keys(const String &p_section) const { - List s; - get_section_keys(p_section, &s); - PackedStringArray arr; - arr.resize(s.size()); - int idx = 0; - for (const String &E : s) { - arr.set(idx++, E); - } - - return arr; -} - void ConfigFile::set_value(const String &p_section, const String &p_key, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { // Erase key. if (!values.has(p_section)) { @@ -103,18 +77,33 @@ bool ConfigFile::has_section_key(const String &p_section, const String &p_key) c return values[p_section].has(p_key); } -void ConfigFile::get_sections(List *r_sections) const { +Vector ConfigFile::get_sections() const { + Vector sections; + sections.resize(values.size()); + + int i = 0; + String *sections_write = sections.ptrw(); for (const KeyValue> &E : values) { - r_sections->push_back(E.key); + sections_write[i++] = E.key; } + + return sections; } -void ConfigFile::get_section_keys(const String &p_section, List *r_keys) const { - ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot get keys from nonexistent section \"%s\".", p_section)); +Vector ConfigFile::get_section_keys(const String &p_section) const { + Vector keys; + ERR_FAIL_COND_V_MSG(!values.has(p_section), keys, vformat("Cannot get keys from nonexistent section \"%s\".", p_section)); - for (const KeyValue &E : values[p_section]) { - r_keys->push_back(E.key); + const HashMap &keys_map = values[p_section]; + keys.resize(keys_map.size()); + + int i = 0; + String *keys_write = keys.ptrw(); + for (const KeyValue &E : keys_map) { + keys_write[i++] = E.key; } + + return keys; } void ConfigFile::erase_section(const String &p_section) { @@ -327,8 +316,8 @@ void ConfigFile::_bind_methods() { ClassDB::bind_method(D_METHOD("has_section", "section"), &ConfigFile::has_section); ClassDB::bind_method(D_METHOD("has_section_key", "section", "key"), &ConfigFile::has_section_key); - ClassDB::bind_method(D_METHOD("get_sections"), &ConfigFile::_get_sections); - ClassDB::bind_method(D_METHOD("get_section_keys", "section"), &ConfigFile::_get_section_keys); + ClassDB::bind_method(D_METHOD("get_sections"), &ConfigFile::get_sections); + ClassDB::bind_method(D_METHOD("get_section_keys", "section"), &ConfigFile::get_section_keys); ClassDB::bind_method(D_METHOD("erase_section", "section"), &ConfigFile::erase_section); ClassDB::bind_method(D_METHOD("erase_section_key", "section", "key"), &ConfigFile::erase_section_key); diff --git a/core/io/config_file.h b/core/io/config_file.h index a77913ac79..43ad2ac669 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -42,8 +42,6 @@ class ConfigFile : public RefCounted { HashMap> values; - PackedStringArray _get_sections() const; - PackedStringArray _get_section_keys(const String &p_section) const; Error _internal_load(const String &p_path, Ref f); Error _internal_save(Ref file); @@ -59,8 +57,8 @@ public: bool has_section(const String &p_section) const; bool has_section_key(const String &p_section, const String &p_key) const; - void get_sections(List *r_sections) const; - void get_section_keys(const String &p_section, List *r_keys) const; + Vector get_sections() const; + Vector get_section_keys(const String &p_section) const; void erase_section(const String &p_section); void erase_section_key(const String &p_section, const String &p_key); diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index f8a49b34e3..55b1dedc53 100644 --- a/core/io/dir_access.cpp +++ b/core/io/dir_access.cpp @@ -38,8 +38,6 @@ #include "core/os/time.h" #include "core/templates/local_vector.h" -thread_local Error DirAccess::last_dir_open_error = OK; - String DirAccess::_get_root_path() const { switch (_access_type) { case ACCESS_RESOURCES: diff --git a/core/io/dir_access.h b/core/io/dir_access.h index 3fb7e25dc2..700fc1e9a8 100644 --- a/core/io/dir_access.h +++ b/core/io/dir_access.h @@ -58,7 +58,7 @@ private: Error _copy_dir(Ref &p_target_da, const String &p_to, int p_chmod_flags, bool p_copy_links); PackedStringArray _get_contents(bool p_directories); - thread_local static Error last_dir_open_error; + static inline thread_local Error last_dir_open_error = OK; bool include_navigational = false; bool include_hidden = false; diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp index 7497e4d915..98b34a153c 100644 --- a/core/io/dtls_server.cpp +++ b/core/io/dtls_server.cpp @@ -32,9 +32,6 @@ #include "dtls_server.h" -DTLSServer *(*DTLSServer::_create)(bool p_notify_postinitialize) = nullptr; -bool DTLSServer::available = false; - DTLSServer *DTLSServer::create(bool p_notify_postinitialize) { if (_create) { return _create(p_notify_postinitialize); diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h index 5e2143ff01..06e738e5ba 100644 --- a/core/io/dtls_server.h +++ b/core/io/dtls_server.h @@ -39,10 +39,10 @@ class DTLSServer : public RefCounted { GDCLASS(DTLSServer, RefCounted); protected: - static DTLSServer *(*_create)(bool p_notify_postinitialize); + static inline DTLSServer *(*_create)(bool p_notify_postinitialize) = nullptr; static void _bind_methods(); - static bool available; + static inline bool available = false; public: static bool is_available(); diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index 50b7d834f9..227c226d02 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -42,13 +42,6 @@ #include "core/os/os.h" #include "core/os/time.h" -FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = {}; - -FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr; - -bool FileAccess::backup_save = false; -thread_local Error FileAccess::last_file_open_error = OK; - Ref FileAccess::create(AccessType p_access) { ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr); ERR_FAIL_NULL_V(create_func[p_access], nullptr); diff --git a/core/io/file_access.h b/core/io/file_access.h index ed3e74f8d4..c57b8fba1b 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -114,7 +114,7 @@ protected: virtual int64_t _get_size(const String &p_file) = 0; virtual void _set_access_type(AccessType p_access); - static FileCloseFailNotify close_fail_notify; + static inline FileCloseFailNotify close_fail_notify = nullptr; #ifndef DISABLE_DEPRECATED static Ref _open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector &p_key); @@ -138,11 +138,11 @@ protected: #endif private: - static bool backup_save; - thread_local static Error last_file_open_error; + static inline bool backup_save = false; + static inline thread_local Error last_file_open_error = OK; AccessType _access_type = ACCESS_FILESYSTEM; - static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */ + static inline CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */ template static Ref _create_builtin() { return memnew(T); diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 202deb2f0e..f3c04cf277 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -160,8 +160,6 @@ void PackedData::clear() { root = memnew(PackedDir); } -PackedData *PackedData::singleton = nullptr; - PackedData::PackedData() { singleton = this; root = memnew(PackedDir); diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 858e64fdef..ae676da496 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -104,7 +104,7 @@ private: PackedDir *root = nullptr; - static PackedData *singleton; + static inline PackedData *singleton = nullptr; bool disabled = false; void _free_packed_dirs(PackedDir *p_dir); diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 3c8b7b9de9..b203d5bf34 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -36,8 +36,6 @@ #include "core/io/file_access.h" -ZipArchive *ZipArchive::instance = nullptr; - extern "C" { struct ZipData { diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index 3c65b95e21..e67c730c16 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -55,7 +55,7 @@ private: HashMap files; - static ZipArchive *instance; + static inline ZipArchive *instance = nullptr; public: void close_handle(unzFile p_file) const; diff --git a/core/io/image.cpp b/core/io/image.cpp index 8beae8cdb9..c1ad21619a 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -40,8 +40,6 @@ #include "core/templates/hash_map.h" #include "core/variant/dictionary.h" -#include - const char *Image::format_names[Image::FORMAT_MAX] = { "Lum8", "LumAlpha8", @@ -84,32 +82,6 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "ASTC_8x8_HDR", }; -// External saver function pointers. - -SavePNGFunc Image::save_png_func = nullptr; -SaveJPGFunc Image::save_jpg_func = nullptr; -SaveEXRFunc Image::save_exr_func = nullptr; -SaveWebPFunc Image::save_webp_func = nullptr; -SaveDDSFunc Image::save_dds_func = nullptr; - -SavePNGBufferFunc Image::save_png_buffer_func = nullptr; -SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr; -SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr; -SaveWebPBufferFunc Image::save_webp_buffer_func = nullptr; -SaveDDSBufferFunc Image::save_dds_buffer_func = nullptr; - -// External loader function pointers. - -ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_png_mem_unpacker_func = nullptr; -ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; -ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr; -ImageMemLoadFunc Image::_dds_mem_loader_func = nullptr; - // External VRAM compression function pointers. void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr; @@ -4420,12 +4392,12 @@ Dictionary Image::compute_image_metrics(const Ref p_compared_image, bool image_metric_mean = CLAMP(sum / total_values, 0.0f, 255.0f); image_metric_mean_squared = CLAMP(sum2 / total_values, 0.0f, 255.0f * 255.0f); - image_metric_root_mean_squared = sqrt(image_metric_mean_squared); + image_metric_root_mean_squared = std::sqrt(image_metric_mean_squared); if (!image_metric_root_mean_squared) { image_metric_peak_snr = 1e+10f; } else { - image_metric_peak_snr = CLAMP(log10(255.0f / image_metric_root_mean_squared) * 20.0f, 0.0f, 500.0f); + image_metric_peak_snr = CLAMP(std::log10(255.0f / image_metric_root_mean_squared) * 20.0f, 0.0f, 500.0f); } result["max"] = image_metric_max; result["mean"] = image_metric_mean; diff --git a/core/io/image.h b/core/io/image.h index ea7352b7f4..1ba09c49ec 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -186,28 +186,28 @@ public: // External saver function pointers. - static SavePNGFunc save_png_func; - static SaveJPGFunc save_jpg_func; - static SaveEXRFunc save_exr_func; - static SaveWebPFunc save_webp_func; - static SaveDDSFunc save_dds_func; - static SavePNGBufferFunc save_png_buffer_func; - static SaveEXRBufferFunc save_exr_buffer_func; - static SaveJPGBufferFunc save_jpg_buffer_func; - static SaveWebPBufferFunc save_webp_buffer_func; - static SaveDDSBufferFunc save_dds_buffer_func; + static inline SavePNGFunc save_png_func = nullptr; + static inline SaveJPGFunc save_jpg_func = nullptr; + static inline SaveEXRFunc save_exr_func = nullptr; + static inline SaveWebPFunc save_webp_func = nullptr; + static inline SaveDDSFunc save_dds_func = nullptr; + static inline SavePNGBufferFunc save_png_buffer_func = nullptr; + static inline SaveEXRBufferFunc save_exr_buffer_func = nullptr; + static inline SaveJPGBufferFunc save_jpg_buffer_func = nullptr; + static inline SaveWebPBufferFunc save_webp_buffer_func = nullptr; + static inline SaveDDSBufferFunc save_dds_buffer_func = nullptr; // External loader function pointers. - static ImageMemLoadFunc _png_mem_loader_func; - static ImageMemLoadFunc _png_mem_unpacker_func; - static ImageMemLoadFunc _jpg_mem_loader_func; - static ImageMemLoadFunc _webp_mem_loader_func; - static ImageMemLoadFunc _tga_mem_loader_func; - static ImageMemLoadFunc _bmp_mem_loader_func; - static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func; - static ImageMemLoadFunc _ktx_mem_loader_func; - static ImageMemLoadFunc _dds_mem_loader_func; + static inline ImageMemLoadFunc _png_mem_loader_func = nullptr; + static inline ImageMemLoadFunc _png_mem_unpacker_func = nullptr; + static inline ImageMemLoadFunc _jpg_mem_loader_func = nullptr; + static inline ImageMemLoadFunc _webp_mem_loader_func = nullptr; + static inline ImageMemLoadFunc _tga_mem_loader_func = nullptr; + static inline ImageMemLoadFunc _bmp_mem_loader_func = nullptr; + static inline ScalableImageMemLoadFunc _svg_scalable_mem_loader_func = nullptr; + static inline ImageMemLoadFunc _ktx_mem_loader_func = nullptr; + static inline ImageMemLoadFunc _dds_mem_loader_func = nullptr; // External VRAM compression function pointers. diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index a811629a45..b8ce260604 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -126,8 +126,6 @@ Ref ImageLoader::recognize(const String &p_extension) { return nullptr; } -Vector> ImageLoader::loader; - void ImageLoader::add_image_format_loader(Ref p_loader) { loader.push_back(p_loader); } diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 0514036d06..2fcd312b9e 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -87,7 +87,7 @@ public: }; class ImageLoader { - static Vector> loader; + static inline Vector> loader; friend class ResourceFormatLoaderImage; protected: diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 381436dc7a..3dc3efc3b8 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -326,8 +326,6 @@ void IP::_bind_methods() { BIND_ENUM_CONSTANT(TYPE_ANY); } -IP *IP::singleton = nullptr; - IP *IP::get_singleton() { return singleton; } diff --git a/core/io/ip.h b/core/io/ip.h index 83be1c954a..f75790fb87 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -69,7 +69,7 @@ private: _IP_ResolverPrivate *resolver = nullptr; protected: - static IP *singleton; + static inline IP *singleton = nullptr; static void _bind_methods(); PackedStringArray _get_local_addresses() const; diff --git a/core/io/json.cpp b/core/io/json.cpp index 4e1a276ed3..6b94b9922f 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -80,7 +80,7 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_ return String("0.0"); } - double magnitude = log10(Math::abs(num)); + double magnitude = std::log10(Math::abs(num)); int total_digits = p_full_precision ? 17 : 14; int precision = MAX(1, total_digits - (int)Math::floor(magnitude)); diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 115226f827..c98588ce0a 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -51,8 +51,6 @@ bool Logger::should_log(bool p_err) { return (!p_err || CoreGlobals::print_error_enabled) && (p_err || CoreGlobals::print_line_enabled); } -bool Logger::_flush_stdout_on_print = true; - void Logger::set_flush_stdout_on_print(bool value) { _flush_stdout_on_print = value; } diff --git a/core/io/logger.h b/core/io/logger.h index 105a2b635b..67f71ed696 100644 --- a/core/io/logger.h +++ b/core/io/logger.h @@ -45,7 +45,7 @@ class Logger { protected: bool should_log(bool p_err); - static bool _flush_stdout_on_print; + static inline bool _flush_stdout_on_print = true; public: enum ErrorType { diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp index ca920d72eb..1a29fea4b3 100644 --- a/core/io/packet_peer_dtls.cpp +++ b/core/io/packet_peer_dtls.cpp @@ -32,9 +32,6 @@ #include "packet_peer_dtls.h" -PacketPeerDTLS *(*PacketPeerDTLS::_create)(bool p_notify_postinitialize) = nullptr; -bool PacketPeerDTLS::available = false; - PacketPeerDTLS *PacketPeerDTLS::create(bool p_notify_postinitialize) { if (_create) { return _create(p_notify_postinitialize); diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h index 6dbcda33a0..102b4537b1 100644 --- a/core/io/packet_peer_dtls.h +++ b/core/io/packet_peer_dtls.h @@ -39,10 +39,10 @@ class PacketPeerDTLS : public PacketPeer { GDCLASS(PacketPeerDTLS, PacketPeer); protected: - static PacketPeerDTLS *(*_create)(bool p_notify_postinitialize); + static inline PacketPeerDTLS *(*_create)(bool p_notify_postinitialize) = nullptr; static void _bind_methods(); - static bool available; + static inline bool available = false; public: enum Status { diff --git a/core/io/plist.cpp b/core/io/plist.cpp index f9adac73f6..31b1b287b5 100644 --- a/core/io/plist.cpp +++ b/core/io/plist.cpp @@ -527,11 +527,11 @@ Ref PList::read_bplist_obj(Ref p_file, uint64_t p_offset_ } break; case 0x10: { node->data_type = PL_NODE_TYPE_INTEGER; - node->data_int = static_cast(read_bplist_var_size_int(p_file, pow(2, marker_size))); + node->data_int = static_cast(read_bplist_var_size_int(p_file, std::pow(2, marker_size))); } break; case 0x20: { node->data_type = PL_NODE_TYPE_REAL; - node->data_int = static_cast(read_bplist_var_size_int(p_file, pow(2, marker_size))); + node->data_int = static_cast(read_bplist_var_size_int(p_file, std::pow(2, marker_size))); } break; case 0x30: { node->data_type = PL_NODE_TYPE_DATE; @@ -541,7 +541,7 @@ Ref PList::read_bplist_obj(Ref p_file, uint64_t p_offset_ case 0x40: { if (marker_size == 0x0F) { uint8_t ext = p_file->get_8() & 0xF; - marker_size = read_bplist_var_size_int(p_file, pow(2, ext)); + marker_size = read_bplist_var_size_int(p_file, std::pow(2, ext)); } node->data_type = PL_NODE_TYPE_DATA; PackedByteArray buf; @@ -552,7 +552,7 @@ Ref PList::read_bplist_obj(Ref p_file, uint64_t p_offset_ case 0x50: { if (marker_size == 0x0F) { uint8_t ext = p_file->get_8() & 0xF; - marker_size = read_bplist_var_size_int(p_file, pow(2, ext)); + marker_size = read_bplist_var_size_int(p_file, std::pow(2, ext)); } node->data_type = PL_NODE_TYPE_STRING; node->data_string.resize(marker_size + 1); @@ -561,7 +561,7 @@ Ref PList::read_bplist_obj(Ref p_file, uint64_t p_offset_ case 0x60: { if (marker_size == 0x0F) { uint8_t ext = p_file->get_8() & 0xF; - marker_size = read_bplist_var_size_int(p_file, pow(2, ext)); + marker_size = read_bplist_var_size_int(p_file, std::pow(2, ext)); } Char16String cs16; cs16.resize(marker_size + 1); @@ -579,7 +579,7 @@ Ref PList::read_bplist_obj(Ref p_file, uint64_t p_offset_ case 0xC0: { if (marker_size == 0x0F) { uint8_t ext = p_file->get_8() & 0xF; - marker_size = read_bplist_var_size_int(p_file, pow(2, ext)); + marker_size = read_bplist_var_size_int(p_file, std::pow(2, ext)); } uint64_t pos = p_file->get_position(); @@ -596,7 +596,7 @@ Ref PList::read_bplist_obj(Ref p_file, uint64_t p_offset_ case 0xD0: { if (marker_size == 0x0F) { uint8_t ext = p_file->get_8() & 0xF; - marker_size = read_bplist_var_size_int(p_file, pow(2, ext)); + marker_size = read_bplist_var_size_int(p_file, std::pow(2, ext)); } uint64_t pos = p_file->get_position(); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 7e7a9959a1..e53fce3139 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -2508,8 +2508,6 @@ void ResourceFormatSaverBinary::get_recognized_extensions(const Ref &p } } -ResourceFormatSaverBinary *ResourceFormatSaverBinary::singleton = nullptr; - ResourceFormatSaverBinary::ResourceFormatSaverBinary() { singleton = this; } diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index abca8c4a84..a1efc74097 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -182,7 +182,7 @@ public: class ResourceFormatSaverBinary : public ResourceFormatSaver { public: - static ResourceFormatSaverBinary *singleton; + static inline ResourceFormatSaverBinary *singleton = nullptr; virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; virtual Error set_uid(const String &p_path, ResourceUID::ID p_uid) override; virtual bool recognize(const Ref &p_resource) const override; diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index cb3c05894b..6c6c408f8d 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -38,8 +38,6 @@ #include "core/os/os.h" #include "core/variant/variant_parser.h" -ResourceFormatImporterLoadOnStartup ResourceImporter::load_on_startup = nullptr; - bool ResourceFormatImporter::SortImporterByName::operator()(const Ref &p_a, const Ref &p_b) const { return p_a->get_importer_name() < p_b->get_importer_name(); } @@ -547,8 +545,6 @@ String ResourceFormatImporter::get_import_settings_hash() const { return hash.md5_text(); } -ResourceFormatImporter *ResourceFormatImporter::singleton = nullptr; - ResourceFormatImporter::ResourceFormatImporter() { singleton = this; } diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 7da0fcdfda..1c6cc8707c 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -52,7 +52,7 @@ class ResourceFormatImporter : public ResourceFormatLoader { Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool p_load, bool *r_valid = nullptr) const; - static ResourceFormatImporter *singleton; + static inline ResourceFormatImporter *singleton = nullptr; //need them to stay in order to compute the settings hash struct SortImporterByName { @@ -111,7 +111,7 @@ protected: static void _bind_methods(); public: - static ResourceFormatImporterLoadOnStartup load_on_startup; + static inline ResourceFormatImporterLoadOnStartup load_on_startup = nullptr; virtual String get_importer_name() const = 0; virtual String get_visible_name() const = 0; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index a49f9d2163..277992dff9 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -264,7 +264,7 @@ void Basis::scale_orthogonal(const Vector3 &p_scale) { Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { Basis m = *this; Vector3 s = Vector3(-1, -1, -1) + p_scale; - bool sign = signbit(s.x + s.y + s.z); + bool sign = std::signbit(s.x + s.y + s.z); Basis b = m.orthonormalized(); s = b.xform_inv(s); Vector3 dots; @@ -273,7 +273,7 @@ Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { dots[j] += s[i] * Math::abs(m.get_column(i).normalized().dot(b.get_column(j))); } } - if (sign != signbit(dots.x + dots.y + dots.z)) { + if (sign != std::signbit(dots.x + dots.y + dots.z)) { dots = -dots; } m.scale_local(Vector3(1, 1, 1) + dots); @@ -479,7 +479,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { if (rows[1][0] == 0 && rows[0][1] == 0 && rows[1][2] == 0 && rows[2][1] == 0 && rows[1][1] == 1) { // return the simplest form (human friendlier in editor and scripts) euler.x = 0; - euler.y = atan2(rows[0][2], rows[0][0]); + euler.y = std::atan2(rows[0][2], rows[0][0]); euler.z = 0; } else { euler.x = Math::atan2(-rows[1][2], rows[2][2]); @@ -544,22 +544,22 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { // is this a pure X rotation? if (rows[1][0] == 0 && rows[0][1] == 0 && rows[0][2] == 0 && rows[2][0] == 0 && rows[0][0] == 1) { // return the simplest form (human friendlier in editor and scripts) - euler.x = atan2(-m12, rows[1][1]); + euler.x = std::atan2(-m12, rows[1][1]); euler.y = 0; euler.z = 0; } else { - euler.x = asin(-m12); - euler.y = atan2(rows[0][2], rows[2][2]); - euler.z = atan2(rows[1][0], rows[1][1]); + euler.x = std::asin(-m12); + euler.y = std::atan2(rows[0][2], rows[2][2]); + euler.z = std::atan2(rows[1][0], rows[1][1]); } } else { // m12 == -1 euler.x = Math::PI * 0.5f; - euler.y = atan2(rows[0][1], rows[0][0]); + euler.y = std::atan2(rows[0][1], rows[0][0]); euler.z = 0; } } else { // m12 == 1 euler.x = -Math::PI * 0.5f; - euler.y = -atan2(rows[0][1], rows[0][0]); + euler.y = -std::atan2(rows[0][1], rows[0][0]); euler.z = 0; } diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 095a9a650c..55b91beba1 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -36,37 +36,37 @@ #include "core/math/math_defs.h" #include "core/typedefs.h" -#include -#include +#include +#include namespace Math { _ALWAYS_INLINE_ double sin(double p_x) { - return ::sin(p_x); + return std::sin(p_x); } _ALWAYS_INLINE_ float sin(float p_x) { - return ::sinf(p_x); + return std::sin(p_x); } _ALWAYS_INLINE_ double cos(double p_x) { - return ::cos(p_x); + return std::cos(p_x); } _ALWAYS_INLINE_ float cos(float p_x) { - return ::cosf(p_x); + return std::cos(p_x); } _ALWAYS_INLINE_ double tan(double p_x) { - return ::tan(p_x); + return std::tan(p_x); } _ALWAYS_INLINE_ float tan(float p_x) { - return ::tanf(p_x); + return std::tan(p_x); } _ALWAYS_INLINE_ double sinh(double p_x) { - return ::sinh(p_x); + return std::sinh(p_x); } _ALWAYS_INLINE_ float sinh(float p_x) { - return ::sinhf(p_x); + return std::sinh(p_x); } _ALWAYS_INLINE_ double sinc(double p_x) { @@ -84,212 +84,156 @@ _ALWAYS_INLINE_ float sincn(float p_x) { } _ALWAYS_INLINE_ double cosh(double p_x) { - return ::cosh(p_x); + return std::cosh(p_x); } _ALWAYS_INLINE_ float cosh(float p_x) { - return ::coshf(p_x); + return std::cosh(p_x); } _ALWAYS_INLINE_ double tanh(double p_x) { - return ::tanh(p_x); + return std::tanh(p_x); } _ALWAYS_INLINE_ float tanh(float p_x) { - return ::tanhf(p_x); + return std::tanh(p_x); } // Always does clamping so always safe to use. _ALWAYS_INLINE_ double asin(double p_x) { - return p_x < -1 ? (-PI / 2) : (p_x > 1 ? (PI / 2) : ::asin(p_x)); + return p_x < -1 ? (-PI / 2) : (p_x > 1 ? (PI / 2) : std::asin(p_x)); } _ALWAYS_INLINE_ float asin(float p_x) { - return p_x < -1 ? (-(float)PI / 2) : (p_x > 1 ? ((float)PI / 2) : ::asinf(p_x)); + return p_x < -1 ? (-(float)PI / 2) : (p_x > 1 ? ((float)PI / 2) : std::asin(p_x)); } // Always does clamping so always safe to use. _ALWAYS_INLINE_ double acos(double p_x) { - return p_x < -1 ? PI : (p_x > 1 ? 0 : ::acos(p_x)); + return p_x < -1 ? PI : (p_x > 1 ? 0 : std::acos(p_x)); } _ALWAYS_INLINE_ float acos(float p_x) { - return p_x < -1 ? (float)PI : (p_x > 1 ? 0 : ::acosf(p_x)); + return p_x < -1 ? (float)PI : (p_x > 1 ? 0 : std::acos(p_x)); } _ALWAYS_INLINE_ double atan(double p_x) { - return ::atan(p_x); + return std::atan(p_x); } _ALWAYS_INLINE_ float atan(float p_x) { - return ::atanf(p_x); + return std::atan(p_x); } _ALWAYS_INLINE_ double atan2(double p_y, double p_x) { - return ::atan2(p_y, p_x); + return std::atan2(p_y, p_x); } _ALWAYS_INLINE_ float atan2(float p_y, float p_x) { - return ::atan2f(p_y, p_x); + return std::atan2(p_y, p_x); } _ALWAYS_INLINE_ double asinh(double p_x) { - return ::asinh(p_x); + return std::asinh(p_x); } _ALWAYS_INLINE_ float asinh(float p_x) { - return ::asinhf(p_x); + return std::asinh(p_x); } // Always does clamping so always safe to use. _ALWAYS_INLINE_ double acosh(double p_x) { - return p_x < 1 ? 0 : ::acosh(p_x); + return p_x < 1 ? 0 : std::acosh(p_x); } _ALWAYS_INLINE_ float acosh(float p_x) { - return p_x < 1 ? 0 : ::acoshf(p_x); + return p_x < 1 ? 0 : std::acosh(p_x); } // Always does clamping so always safe to use. _ALWAYS_INLINE_ double atanh(double p_x) { - return p_x <= -1 ? -INF : (p_x >= 1 ? INF : ::atanh(p_x)); + return p_x <= -1 ? -INF : (p_x >= 1 ? INF : std::atanh(p_x)); } _ALWAYS_INLINE_ float atanh(float p_x) { - return p_x <= -1 ? (float)-INF : (p_x >= 1 ? (float)INF : ::atanhf(p_x)); + return p_x <= -1 ? (float)-INF : (p_x >= 1 ? (float)INF : std::atanh(p_x)); } _ALWAYS_INLINE_ double sqrt(double p_x) { - return ::sqrt(p_x); + return std::sqrt(p_x); } _ALWAYS_INLINE_ float sqrt(float p_x) { - return ::sqrtf(p_x); + return std::sqrt(p_x); } _ALWAYS_INLINE_ double fmod(double p_x, double p_y) { - return ::fmod(p_x, p_y); + return std::fmod(p_x, p_y); } _ALWAYS_INLINE_ float fmod(float p_x, float p_y) { - return ::fmodf(p_x, p_y); + return std::fmod(p_x, p_y); } _ALWAYS_INLINE_ double modf(double p_x, double *r_y) { - return ::modf(p_x, r_y); + return std::modf(p_x, r_y); } _ALWAYS_INLINE_ float modf(float p_x, float *r_y) { - return ::modff(p_x, r_y); + return std::modf(p_x, r_y); } _ALWAYS_INLINE_ double floor(double p_x) { - return ::floor(p_x); + return std::floor(p_x); } _ALWAYS_INLINE_ float floor(float p_x) { - return ::floorf(p_x); + return std::floor(p_x); } _ALWAYS_INLINE_ double ceil(double p_x) { - return ::ceil(p_x); + return std::ceil(p_x); } _ALWAYS_INLINE_ float ceil(float p_x) { - return ::ceilf(p_x); + return std::ceil(p_x); } _ALWAYS_INLINE_ double pow(double p_x, double p_y) { - return ::pow(p_x, p_y); + return std::pow(p_x, p_y); } _ALWAYS_INLINE_ float pow(float p_x, float p_y) { - return ::powf(p_x, p_y); + return std::pow(p_x, p_y); } _ALWAYS_INLINE_ double log(double p_x) { - return ::log(p_x); + return std::log(p_x); } _ALWAYS_INLINE_ float log(float p_x) { - return ::logf(p_x); + return std::log(p_x); } _ALWAYS_INLINE_ double log1p(double p_x) { - return ::log1p(p_x); + return std::log1p(p_x); } _ALWAYS_INLINE_ float log1p(float p_x) { - return ::log1pf(p_x); + return std::log1p(p_x); } _ALWAYS_INLINE_ double log2(double p_x) { - return ::log2(p_x); + return std::log2(p_x); } _ALWAYS_INLINE_ float log2(float p_x) { - return ::log2f(p_x); + return std::log2(p_x); } _ALWAYS_INLINE_ double exp(double p_x) { - return ::exp(p_x); + return std::exp(p_x); } _ALWAYS_INLINE_ float exp(float p_x) { - return ::expf(p_x); + return std::exp(p_x); } _ALWAYS_INLINE_ bool is_nan(double p_val) { -#ifdef _MSC_VER - return _isnan(p_val); -#elif defined(__GNUC__) && __GNUC__ < 6 - union { - uint64_t u; - double f; - } ieee754; - ieee754.f = p_val; - // (unsigned)(0x7ff0000000000001 >> 32) : 0x7ff00000 - return ((((unsigned)(ieee754.u >> 32) & 0x7fffffff) + ((unsigned)ieee754.u != 0)) > 0x7ff00000); -#else - return isnan(p_val); -#endif + return std::isnan(p_val); } _ALWAYS_INLINE_ bool is_nan(float p_val) { -#ifdef _MSC_VER - return _isnan(p_val); -#elif defined(__GNUC__) && __GNUC__ < 6 - union { - uint32_t u; - float f; - } ieee754; - ieee754.f = p_val; - // ----------------------------------- - // (single-precision floating-point) - // NaN : s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx - // : (> 0x7f800000) - // where, - // s : sign - // x : non-zero number - // ----------------------------------- - return ((ieee754.u & 0x7fffffff) > 0x7f800000); -#else - return isnan(p_val); -#endif + return std::isnan(p_val); } _ALWAYS_INLINE_ bool is_inf(double p_val) { -#ifdef _MSC_VER - return !_finite(p_val); -// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era -#elif defined(__GNUC__) && __GNUC__ < 6 - union { - uint64_t u; - double f; - } ieee754; - ieee754.f = p_val; - return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 && - ((unsigned)ieee754.u == 0); -#else - return isinf(p_val); -#endif + return std::isinf(p_val); } _ALWAYS_INLINE_ bool is_inf(float p_val) { -#ifdef _MSC_VER - return !_finite(p_val); -// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era -#elif defined(__GNUC__) && __GNUC__ < 6 - union { - uint32_t u; - float f; - } ieee754; - ieee754.f = p_val; - return (ieee754.u & 0x7fffffff) == 0x7f800000; -#else - return isinf(p_val); -#endif + return std::isinf(p_val); } // These methods assume (p_num + p_den) doesn't overflow. @@ -309,24 +253,17 @@ _ALWAYS_INLINE_ uint64_t division_round_up(uint64_t p_num, uint64_t p_den) { } _ALWAYS_INLINE_ bool is_finite(double p_val) { - return isfinite(p_val); + return std::isfinite(p_val); } _ALWAYS_INLINE_ bool is_finite(float p_val) { - return isfinite(p_val); -} - -_ALWAYS_INLINE_ double absd(double p_value) { - return ::fabs(p_value); -} -_ALWAYS_INLINE_ float absf(float p_value) { - return ::fabsf(p_value); + return std::isfinite(p_val); } _ALWAYS_INLINE_ double abs(double p_value) { - return absd(p_value); + return std::abs(p_value); } _ALWAYS_INLINE_ float abs(float p_value) { - return absf(p_value); + return std::abs(p_value); } _ALWAYS_INLINE_ int8_t abs(int8_t p_value) { return p_value > 0 ? p_value : -p_value; @@ -335,10 +272,10 @@ _ALWAYS_INLINE_ int16_t abs(int16_t p_value) { return p_value > 0 ? p_value : -p_value; } _ALWAYS_INLINE_ int32_t abs(int32_t p_value) { - return ::abs(p_value); + return std::abs(p_value); } _ALWAYS_INLINE_ int64_t abs(int64_t p_value) { - return ::llabs(p_value); + return std::abs(p_value); } _ALWAYS_INLINE_ double fposmod(double p_x, double p_y) { @@ -688,10 +625,10 @@ _ALWAYS_INLINE_ float db_to_linear(float p_db) { } _ALWAYS_INLINE_ double round(double p_val) { - return ::round(p_val); + return std::round(p_val); } _ALWAYS_INLINE_ float round(float p_val) { - return ::roundf(p_val); + return std::round(p_val); } _ALWAYS_INLINE_ double wrapf(double p_value, double p_min, double p_max) { @@ -762,8 +699,7 @@ int random(int p_from, int p_to); // This function should be as fast as possible and rounding mode should not matter. _ALWAYS_INLINE_ int fast_ftoi(float p_value) { - // Assuming every supported compiler has `lrint()`. - return lrintf(p_value); + return std::rint(p_value); } _ALWAYS_INLINE_ uint32_t halfbits_to_floatbits(uint16_t p_half) { diff --git a/core/math/projection.cpp b/core/math/projection.cpp index c15ca58274..43c0d98af7 100644 --- a/core/math/projection.cpp +++ b/core/math/projection.cpp @@ -284,7 +284,7 @@ void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t real_t left, right, modeltranslation, ymax, xmax, frustumshift; - ymax = p_z_near * tan(Math::deg_to_rad(p_fovy_degrees / 2.0)); + ymax = p_z_near * std::tan(Math::deg_to_rad(p_fovy_degrees / 2.0)); xmax = ymax * p_aspect; frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist; diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp index 07c08a51a0..7098187af1 100644 --- a/core/math/quaternion.cpp +++ b/core/math/quaternion.cpp @@ -150,7 +150,7 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, real_t p_weight) const { real_t dot = from.dot(p_to); - if (Math::absf(dot) > 0.9999f) { + if (Math::abs(dot) > 0.9999f) { return from; } @@ -182,11 +182,11 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const post_q = Basis(post_q).get_rotation_quaternion(); // Flip quaternions to shortest path if necessary. - bool flip1 = signbit(from_q.dot(pre_q)); + bool flip1 = std::signbit(from_q.dot(pre_q)); pre_q = flip1 ? -pre_q : pre_q; - bool flip2 = signbit(from_q.dot(to_q)); + bool flip2 = std::signbit(from_q.dot(to_q)); to_q = flip2 ? -to_q : to_q; - bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : signbit(to_q.dot(post_q)); + bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : std::signbit(to_q.dot(post_q)); post_q = flip3 ? -post_q : post_q; // Calc by Expmap in from_q space. @@ -233,11 +233,11 @@ Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b post_q = Basis(post_q).get_rotation_quaternion(); // Flip quaternions to shortest path if necessary. - bool flip1 = signbit(from_q.dot(pre_q)); + bool flip1 = std::signbit(from_q.dot(pre_q)); pre_q = flip1 ? -pre_q : pre_q; - bool flip2 = signbit(from_q.dot(to_q)); + bool flip2 = std::signbit(from_q.dot(to_q)); to_q = flip2 ? -to_q : to_q; - bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : signbit(to_q.dot(post_q)); + bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : std::signbit(to_q.dot(post_q)); post_q = flip3 ? -post_q : post_q; // Calc by Expmap in from_q space. diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index 020cf55f72..5c6e87e3dc 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -32,12 +32,10 @@ #pragma once -#include "core/math/math_defs.h" +#include "core/math/math_funcs.h" #include "thirdparty/misc/pcg.h" -#include - #if defined(__GNUC__) #define CLZ32(x) __builtin_clz(x) #elif defined(_MSC_VER) @@ -48,16 +46,6 @@ static int __bsr_clz32(uint32_t x) { return 31 - index; } #define CLZ32(x) __bsr_clz32(x) -#else -#endif - -#if defined(__GNUC__) -#define LDEXP(s, e) __builtin_ldexp(s, e) -#define LDEXPF(s, e) __builtin_ldexpf(s, e) -#else -#include -#define LDEXP(s, e) ldexp(s, e) -#define LDEXPF(s, e) ldexp(s, e) #endif template @@ -112,7 +100,7 @@ public: return 0; } uint64_t significand = (((uint64_t)rand()) << 32) | rand() | 0x8000000000000001U; - return LDEXP((double)significand, -64 - CLZ32(proto_exp_offset)); + return std::ldexp((double)significand, -64 - CLZ32(proto_exp_offset)); #else #pragma message("RandomPCG::randd - intrinsic clz is not available, falling back to bit truncation") return (double)(((((uint64_t)rand()) << 32) | rand()) & 0x1FFFFFFFFFFFFFU) / (double)0x1FFFFFFFFFFFFFU; @@ -124,7 +112,7 @@ public: if (unlikely(proto_exp_offset == 0)) { return 0; } - return LDEXPF((float)(rand() | 0x80000001), -32 - CLZ32(proto_exp_offset)); + return std::ldexp((float)(rand() | 0x80000001), -32 - CLZ32(proto_exp_offset)); #else #pragma message("RandomPCG::randf - intrinsic clz is not available, falling back to bit truncation") return (float)(rand() & 0xFFFFFF) / (float)0xFFFFFF; @@ -136,14 +124,14 @@ public: if (temp < CMP_EPSILON) { temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function. } - return p_mean + p_deviation * (cos(Math::TAU * randd()) * sqrt(-2.0 * log(temp))); // Box-Muller transform. + return p_mean + p_deviation * (std::cos(Math::TAU * randd()) * std::sqrt(-2.0 * std::log(temp))); // Box-Muller transform. } _FORCE_INLINE_ float randfn(float p_mean, float p_deviation) { float temp = randf(); if (temp < CMP_EPSILON) { temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function. } - return p_mean + p_deviation * (cos((float)Math::TAU * randf()) * sqrt(-2.0 * log(temp))); // Box-Muller transform. + return p_mean + p_deviation * (std::cos((float)Math::TAU * randf()) * std::sqrt(-2.0 * std::log(temp))); // Box-Muller transform. } double random(double p_from, double p_to); diff --git a/core/object/object.cpp b/core/object/object.cpp index eb65b1dcfc..68246e8e4b 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -980,7 +980,9 @@ String Object::to_string() { String ret; GDExtensionBool is_valid; _extension->to_string(_extension_instance, &is_valid, &ret); - return ret; + if (is_valid) { + return ret; + } } return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; } @@ -2226,6 +2228,16 @@ void Object::detach_from_objectdb() { } } +void Object::assign_class_name_static(const Span &p_name, StringName &r_target) { + static BinaryMutex _mutex; + MutexLock lock(_mutex); + if (r_target) { + // Already assigned while we were waiting for the mutex. + return; + } + r_target = StringName(p_name.ptr(), true); +} + Object::~Object() { if (script_instance) { memdelete(script_instance); diff --git a/core/object/object.h b/core/object/object.h index 3472fa8935..1ea8216c1b 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -427,7 +427,7 @@ public: static const StringName &get_class_static() { \ static StringName _class_name_static; \ if (unlikely(!_class_name_static)) { \ - StringName::assign_static_unique_class_name(&_class_name_static, #m_class); \ + assign_class_name_static(#m_class, _class_name_static); \ } \ return _class_name_static; \ } \ @@ -813,10 +813,12 @@ public: }; /* TYPE API */ + static void assign_class_name_static(const Span &p_name, StringName &r_target); + static const StringName &get_class_static() { static StringName _class_name_static; if (unlikely(!_class_name_static)) { - StringName::assign_static_unique_class_name(&_class_name_static, "Object"); + assign_class_name_static("Object", _class_name_static); } return _class_name_static; } diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index 2c86af8b1a..086a0bde8f 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -550,11 +550,6 @@ Vector> ScriptServer::capture_script_backtraces(bool p_incl //////////////////// -ScriptCodeCompletionCache *ScriptCodeCompletionCache::singleton = nullptr; -ScriptCodeCompletionCache::ScriptCodeCompletionCache() { - singleton = this; -} - void ScriptLanguage::get_core_type_words(List *p_core_type_words) const { p_core_type_words->push_back("String"); p_core_type_words->push_back("Vector2"); diff --git a/core/object/script_language.h b/core/object/script_language.h index d482757696..6241c02f7a 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -198,17 +198,6 @@ public: Script() {} }; -class ScriptCodeCompletionCache { - static ScriptCodeCompletionCache *singleton; - -public: - static ScriptCodeCompletionCache *get_singleton() { return singleton; } - - ScriptCodeCompletionCache(); - - virtual ~ScriptCodeCompletionCache() {} -}; - class ScriptLanguage : public Object { GDCLASS(ScriptLanguage, Object) diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 10e75bb8a4..2e7ba67ca5 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -820,7 +820,9 @@ public: virtual void get_property_state(List> &state) override { if (native_info->get_property_state_func) { native_info->get_property_state_func(instance, _add_property_with_state, &state); + return; } + ScriptInstance::get_property_state(state); } virtual void get_method_list(List *p_list) const override { diff --git a/core/os/memory.cpp b/core/os/memory.cpp index 1ad552221a..de02ab8a91 100644 --- a/core/os/memory.cpp +++ b/core/os/memory.cpp @@ -64,8 +64,6 @@ SafeNumeric Memory::mem_usage; SafeNumeric Memory::max_usage; #endif -SafeNumeric Memory::alloc_count; - void *Memory::alloc_aligned_static(size_t p_bytes, size_t p_alignment) { DEV_ASSERT(is_power_of_2(p_alignment)); @@ -109,8 +107,6 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { ERR_FAIL_NULL_V(mem, nullptr); - alloc_count.increment(); - if (prepad) { uint8_t *s8 = (uint8_t *)mem; @@ -188,8 +184,6 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) { bool prepad = p_pad_align; #endif - alloc_count.decrement(); - if (prepad) { mem -= DATA_OFFSET; diff --git a/core/os/memory.h b/core/os/memory.h index 60f7f0e452..7d988e9154 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -45,8 +45,6 @@ class Memory { static SafeNumeric max_usage; #endif - static SafeNumeric alloc_count; - public: // Alignment: ↓ max_align_t ↓ uint64_t ↓ max_align_t // ┌─────────────────┬──┬────────────────┬──┬───────────... diff --git a/core/string/fuzzy_search.cpp b/core/string/fuzzy_search.cpp index 57b82ac829..22343aa267 100644 --- a/core/string/fuzzy_search.cpp +++ b/core/string/fuzzy_search.cpp @@ -340,9 +340,10 @@ bool FuzzySearch::search(const String &p_target, FuzzySearchResult &p_result) co void FuzzySearch::search_all(const PackedStringArray &p_targets, Vector &p_results) const { p_results.clear(); - for (const String &target : p_targets) { + for (int i = 0; i < p_targets.size(); i++) { FuzzySearchResult result; - if (search(target, result)) { + result.original_index = i; + if (search(p_targets[i], result)) { p_results.append(result); } } diff --git a/core/string/fuzzy_search.h b/core/string/fuzzy_search.h index 6c1559778c..be58f3b6fd 100644 --- a/core/string/fuzzy_search.h +++ b/core/string/fuzzy_search.h @@ -78,6 +78,7 @@ class FuzzySearchResult { public: String target; int score = 0; + int original_index = -1; int dir_index = -1; Vector token_matches; }; diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 3c3573753a..fb72dde2ff 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -32,41 +32,36 @@ #include "string_name.h" +#include "core/os/mutex.h" #include "core/os/os.h" #include "core/string/print_string.h" -bool StringName::_Data::operator==(const String &p_name) const { - return name == p_name; -} +struct StringName::Table { + constexpr static uint32_t TABLE_BITS = 16; + constexpr static uint32_t TABLE_LEN = 1 << TABLE_BITS; + constexpr static uint32_t TABLE_MASK = TABLE_LEN - 1; -bool StringName::_Data::operator!=(const String &p_name) const { - return !operator==(p_name); -} - -bool StringName::_Data::operator==(const char *p_name) const { - return name == p_name; -} - -bool StringName::_Data::operator!=(const char *p_name) const { - return !operator==(p_name); -} + static inline _Data *table[TABLE_LEN]; + static inline BinaryMutex mutex; + static inline PagedAllocator<_Data> allocator; +}; void StringName::setup() { ERR_FAIL_COND(configured); - for (int i = 0; i < STRING_TABLE_LEN; i++) { - _table[i] = nullptr; + for (uint32_t i = 0; i < Table::TABLE_LEN; i++) { + Table::table[i] = nullptr; } configured = true; } void StringName::cleanup() { - MutexLock lock(mutex); + MutexLock lock(Table::mutex); #ifdef DEBUG_ENABLED if (unlikely(debug_stringname)) { Vector<_Data *> data; - for (int i = 0; i < STRING_TABLE_LEN; i++) { - _Data *d = _table[i]; + for (uint32_t i = 0; i < Table::TABLE_LEN; i++) { + _Data *d = Table::table[i]; while (d) { data.push_back(d); d = d->next; @@ -79,7 +74,7 @@ void StringName::cleanup() { int unreferenced_stringnames = 0; int rarely_referenced_stringnames = 0; for (int i = 0; i < data.size(); i++) { - print_line(itos(i + 1) + ": " + data[i]->get_name() + " - " + itos(data[i]->debug_references)); + print_line(itos(i + 1) + ": " + data[i]->name + " - " + itos(data[i]->debug_references)); if (data[i]->debug_references == 0) { unreferenced_stringnames += 1; } else if (data[i]->debug_references < 5) { @@ -92,9 +87,9 @@ void StringName::cleanup() { } #endif int lost_strings = 0; - for (int i = 0; i < STRING_TABLE_LEN; i++) { - while (_table[i]) { - _Data *d = _table[i]; + for (uint32_t i = 0; i < Table::TABLE_LEN; i++) { + while (Table::table[i]) { + _Data *d = Table::table[i]; if (d->static_count.get() != d->refcount.get()) { lost_strings++; @@ -103,8 +98,8 @@ void StringName::cleanup() { } } - _table[i] = _table[i]->next; - memdelete(d); + Table::table[i] = Table::table[i]->next; + Table::allocator.free(d); } } if (lost_strings) { @@ -117,7 +112,7 @@ void StringName::unref() { ERR_FAIL_COND(!configured); if (_data && _data->refcount.unref()) { - MutexLock lock(mutex); + MutexLock lock(Table::mutex); if (CoreGlobals::leak_reporting_enabled && _data->static_count.get() > 0) { ERR_PRINT("BUG: Unreferenced static string to 0: " + _data->name); @@ -125,16 +120,14 @@ void StringName::unref() { if (_data->prev) { _data->prev->next = _data->next; } else { - if (_table[_data->idx] != _data) { - ERR_PRINT("BUG!"); - } - _table[_data->idx] = _data->next; + const uint32_t idx = _data->hash & Table::TABLE_MASK; + Table::table[idx] = _data->next; } if (_data->next) { _data->next->prev = _data->prev; } - memdelete(_data); + Table::allocator.free(_data); } _data = nullptr; @@ -147,7 +140,7 @@ uint32_t StringName::get_empty_hash() { bool StringName::operator==(const String &p_name) const { if (_data) { - return _data->operator==(p_name); + return _data->name == p_name; } return p_name.is_empty(); @@ -155,7 +148,7 @@ bool StringName::operator==(const String &p_name) const { bool StringName::operator==(const char *p_name) const { if (_data) { - return _data->operator==(p_name); + return _data->name == p_name; } return p_name[0] == 0; @@ -186,14 +179,6 @@ int StringName::length() const { return 0; } -bool StringName::is_empty() const { - if (_data) { - return _data->name.is_empty(); - } - - return true; -} - StringName &StringName::operator=(const StringName &p_name) { if (this == &p_name) { return *this; @@ -218,13 +203,6 @@ StringName::StringName(const StringName &p_name) { } } -void StringName::assign_static_unique_class_name(StringName *ptr, const char *p_name) { - MutexLock lock(mutex); - if (*ptr == StringName()) { - *ptr = StringName(p_name, true); - } -} - StringName::StringName(const char *p_name, bool p_static) { _data = nullptr; @@ -235,14 +213,14 @@ StringName::StringName(const char *p_name, bool p_static) { } const uint32_t hash = String::hash(p_name); - const uint32_t idx = hash & STRING_TABLE_MASK; + const uint32_t idx = hash & Table::TABLE_MASK; - MutexLock lock(mutex); - _data = _table[idx]; + MutexLock lock(Table::mutex); + _data = Table::table[idx]; while (_data) { // compare hash first - if (_data->hash == hash && _data->operator==(p_name)) { + if (_data->hash == hash && _data->name == p_name) { break; } _data = _data->next; @@ -261,13 +239,12 @@ StringName::StringName(const char *p_name, bool p_static) { return; } - _data = memnew(_Data); + _data = Table::allocator.alloc(); _data->name = p_name; _data->refcount.init(); _data->static_count.set(p_static ? 1 : 0); _data->hash = hash; - _data->idx = idx; - _data->next = _table[idx]; + _data->next = Table::table[idx]; _data->prev = nullptr; #ifdef DEBUG_ENABLED @@ -277,10 +254,10 @@ StringName::StringName(const char *p_name, bool p_static) { _data->static_count.increment(); } #endif - if (_table[idx]) { - _table[idx]->prev = _data; + if (Table::table[idx]) { + Table::table[idx]->prev = _data; } - _table[idx] = _data; + Table::table[idx] = _data; } StringName::StringName(const String &p_name, bool p_static) { @@ -293,13 +270,13 @@ StringName::StringName(const String &p_name, bool p_static) { } const uint32_t hash = p_name.hash(); - const uint32_t idx = hash & STRING_TABLE_MASK; + const uint32_t idx = hash & Table::TABLE_MASK; - MutexLock lock(mutex); - _data = _table[idx]; + MutexLock lock(Table::mutex); + _data = Table::table[idx]; while (_data) { - if (_data->hash == hash && _data->operator==(p_name)) { + if (_data->hash == hash && _data->name == p_name) { break; } _data = _data->next; @@ -318,13 +295,12 @@ StringName::StringName(const String &p_name, bool p_static) { return; } - _data = memnew(_Data); + _data = Table::allocator.alloc(); _data->name = p_name; _data->refcount.init(); _data->static_count.set(p_static ? 1 : 0); _data->hash = hash; - _data->idx = idx; - _data->next = _table[idx]; + _data->next = Table::table[idx]; _data->prev = nullptr; #ifdef DEBUG_ENABLED if (unlikely(debug_stringname)) { @@ -334,10 +310,10 @@ StringName::StringName(const String &p_name, bool p_static) { } #endif - if (_table[idx]) { - _table[idx]->prev = _data; + if (Table::table[idx]) { + Table::table[idx]->prev = _data; } - _table[idx] = _data; + Table::table[idx] = _data; } StringName StringName::search(const char *p_name) { @@ -349,14 +325,14 @@ StringName StringName::search(const char *p_name) { } const uint32_t hash = String::hash(p_name); - const uint32_t idx = hash & STRING_TABLE_MASK; + const uint32_t idx = hash & Table::TABLE_MASK; - MutexLock lock(mutex); - _Data *_data = _table[idx]; + MutexLock lock(Table::mutex); + _Data *_data = Table::table[idx]; while (_data) { // compare hash first - if (_data->hash == hash && _data->operator==(p_name)) { + if (_data->hash == hash && _data->name == p_name) { break; } _data = _data->next; @@ -384,14 +360,14 @@ StringName StringName::search(const char32_t *p_name) { } const uint32_t hash = String::hash(p_name); - const uint32_t idx = hash & STRING_TABLE_MASK; + const uint32_t idx = hash & Table::TABLE_MASK; - MutexLock lock(mutex); - _Data *_data = _table[idx]; + MutexLock lock(Table::mutex); + _Data *_data = Table::table[idx]; while (_data) { // compare hash first - if (_data->hash == hash && _data->operator==(p_name)) { + if (_data->hash == hash && _data->name == p_name) { break; } _data = _data->next; @@ -408,14 +384,14 @@ StringName StringName::search(const String &p_name) { ERR_FAIL_COND_V(p_name.is_empty(), StringName()); const uint32_t hash = p_name.hash(); - const uint32_t idx = hash & STRING_TABLE_MASK; + const uint32_t idx = hash & Table::TABLE_MASK; - MutexLock lock(mutex); - _Data *_data = _table[idx]; + MutexLock lock(Table::mutex); + _Data *_data = Table::table[idx]; while (_data) { // compare hash first - if (_data->hash == hash && _data->operator==(p_name)) { + if (_data->hash == hash && _data->name == p_name) { break; } _data = _data->next; diff --git a/core/string/string_name.h b/core/string/string_name.h index 3bb102ed9f..03fdfa3aa7 100644 --- a/core/string/string_name.h +++ b/core/string/string_name.h @@ -32,7 +32,6 @@ #pragma once -#include "core/os/mutex.h" #include "core/string/ustring.h" #include "core/templates/safe_refcount.h" @@ -41,11 +40,7 @@ class Main; class StringName { - enum { - STRING_TABLE_BITS = 16, - STRING_TABLE_LEN = 1 << STRING_TABLE_BITS, - STRING_TABLE_MASK = STRING_TABLE_LEN - 1 - }; + struct Table; struct _Data { SafeRefCount refcount; @@ -54,28 +49,19 @@ class StringName { #ifdef DEBUG_ENABLED uint32_t debug_references = 0; #endif - const String &get_name() const { return name; } - bool operator==(const String &p_name) const; - bool operator!=(const String &p_name) const; - bool operator==(const char *p_name) const; - bool operator!=(const char *p_name) const; - int idx = 0; uint32_t hash = 0; _Data *prev = nullptr; _Data *next = nullptr; _Data() {} }; - static inline _Data *_table[STRING_TABLE_LEN]; - _Data *_data = nullptr; void unref(); friend void register_core_types(); friend void unregister_core_types(); friend class Main; - static inline Mutex mutex; static void setup(); static void cleanup(); static uint32_t get_empty_hash(); @@ -93,7 +79,7 @@ class StringName { StringName(_Data *p_data) { _data = p_data; } public: - explicit operator bool() const { return _data && !_data->name.is_empty(); } + _FORCE_INLINE_ explicit operator bool() const { return _data; } bool operator==(const String &p_name) const; bool operator==(const char *p_name) const; @@ -103,7 +89,7 @@ public: const char32_t *get_data() const { return _data ? _data->name.ptr() : U""; } char32_t operator[](int p_index) const; int length() const; - bool is_empty() const; + _FORCE_INLINE_ bool is_empty() const { return !_data; } _FORCE_INLINE_ bool is_node_unique_name() const { if (!_data) { @@ -193,8 +179,6 @@ public: StringName(const String &p_name, bool p_static = false); StringName() {} - static void assign_static_unique_class_name(StringName *ptr, const char *p_name); - #ifdef SIZE_EXTRA _NO_INLINE_ #else diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 46eececfad..cd48d6c97d 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -59,11 +59,6 @@ static _FORCE_INLINE_ char32_t lower_case(char32_t c) { return (is_ascii_upper_case(c) ? (c + ('a' - 'A')) : c); } -const char CharString::_null = 0; -const char16_t Char16String::_null = 0; -const char32_t String::_null = 0; -const char32_t String::_replacement_char = 0xfffd; - bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) { const String &s = p_s; int beg = CLAMP(p_col, 0, s.length()); @@ -92,135 +87,6 @@ bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) { } } -/*************************************************************************/ -/* Char16String */ -/*************************************************************************/ - -bool Char16String::operator<(const Char16String &p_right) const { - if (length() == 0) { - return p_right.length() != 0; - } - - return str_compare(get_data(), p_right.get_data()) < 0; -} - -Char16String &Char16String::operator+=(char16_t p_char) { - const int lhs_len = length(); - resize(lhs_len + 2); - - char16_t *dst = ptrw(); - dst[lhs_len] = p_char; - dst[lhs_len + 1] = 0; - - return *this; -} - -void Char16String::operator=(const char16_t *p_cstr) { - copy_from(p_cstr); -} - -const char16_t *Char16String::get_data() const { - if (size()) { - return &operator[](0); - } else { - return u""; - } -} - -void Char16String::copy_from(const char16_t *p_cstr) { - if (!p_cstr) { - resize(0); - return; - } - - const char16_t *s = p_cstr; - for (; *s; s++) { - } - size_t len = s - p_cstr; - - if (len == 0) { - resize(0); - return; - } - - Error err = resize(++len); // include terminating null char - - ERR_FAIL_COND_MSG(err != OK, "Failed to copy char16_t string."); - - memcpy(ptrw(), p_cstr, len * sizeof(char16_t)); -} - -/*************************************************************************/ -/* CharString */ -/*************************************************************************/ - -bool CharString::operator<(const CharString &p_right) const { - if (length() == 0) { - return p_right.length() != 0; - } - - return str_compare(get_data(), p_right.get_data()) < 0; -} - -bool CharString::operator==(const CharString &p_right) const { - if (length() == 0) { - // True if both have length 0, false if only p_right has a length - return p_right.length() == 0; - } else if (p_right.length() == 0) { - // False due to unequal length - return false; - } - - return strcmp(ptr(), p_right.ptr()) == 0; -} - -CharString &CharString::operator+=(char p_char) { - const int lhs_len = length(); - resize(lhs_len + 2); - - char *dst = ptrw(); - dst[lhs_len] = p_char; - dst[lhs_len + 1] = 0; - - return *this; -} - -void CharString::operator=(const char *p_cstr) { - copy_from(p_cstr); -} - -const char *CharString::get_data() const { - if (size()) { - return &operator[](0); - } else { - return ""; - } -} - -void CharString::copy_from(const char *p_cstr) { - if (!p_cstr) { - resize(0); - return; - } - - size_t len = strlen(p_cstr); - - if (len == 0) { - resize(0); - return; - } - - Error err = resize(++len); // include terminating null char - - ERR_FAIL_COND_MSG(err != OK, "Failed to copy C-string."); - - memcpy(ptrw(), p_cstr, len); -} - -/*************************************************************************/ -/* String */ -/*************************************************************************/ - Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path, String &r_fragment) const { // Splits the URL into scheme, host, port, path, fragment. Strip credentials when present. String base = *this; @@ -1581,7 +1447,7 @@ String String::num(double p_num, int p_decimals) { } if (Math::is_inf(p_num)) { - if (signbit(p_num)) { + if (std::signbit(p_num)) { return "-inf"; } else { return "inf"; @@ -1594,7 +1460,7 @@ String String::num(double p_num, int p_decimals) { if (abs_num > 10) { // We want to align the digits to the above reasonable default, so we only // need to subtract log10 for numbers with a positive power of ten. - p_decimals -= (int)floor(log10(abs_num)); + p_decimals -= (int)std::floor(std::log10(abs_num)); } } if (p_decimals > MAX_DECIMALS) { @@ -1760,7 +1626,7 @@ String String::num_real(double p_num, bool p_trailing) { // to subtract log10 for numbers with a positive power of ten magnitude. const double abs_num = Math::abs(p_num); if (abs_num > 10) { - decimals -= (int)floor(log10(abs_num)); + decimals -= (int)std::floor(std::log10(abs_num)); } return num(p_num, decimals); @@ -1783,7 +1649,7 @@ String String::num_real(float p_num, bool p_trailing) { // to subtract log10 for numbers with a positive power of ten magnitude. const float abs_num = Math::abs(p_num); if (abs_num > 10) { - decimals -= (int)floor(log10(abs_num)); + decimals -= (int)std::floor(std::log10(abs_num)); } return num(p_num, decimals); } @@ -3999,7 +3865,7 @@ String String::format(const Variant &values, const String &placeholder) const { new_string = new_string.replace(placeholder.replace("_", key), val); } else { - ERR_PRINT(String("STRING.format Inner Array size != 2 ").ascii().get_data()); + ERR_PRINT(vformat("Invalid format: the inner Array at index %d needs to contain only 2 elements, as a key-value pair.", i).ascii().get_data()); } } else { //Array structure ["RobotGuy","Logis","rookie"] Variant v_val = values_arr[i]; @@ -5757,7 +5623,7 @@ String String::sprintf(const Array &values, bool *error) const { } double value = values[value_index]; - bool is_negative = signbit(value); + bool is_negative = std::signbit(value); String str = String::num(Math::abs(value), min_decimals); const bool is_finite = Math::is_finite(value); diff --git a/core/string/ustring.h b/core/string/ustring.h index fa560208d9..8ecbee622d 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -40,6 +40,10 @@ #include "core/typedefs.h" #include "core/variant/array.h" +class String; +template +class CharStringT; + /*************************************************************************/ /* Utility Functions */ /*************************************************************************/ @@ -99,19 +103,33 @@ constexpr size_t _strlen_clipped(const char32_t *p_str, int p_clip_to_len) { return len; } +template +constexpr int64_t str_compare(const L *l_ptr, const R *r_ptr) { + while (true) { + const char32_t l = *l_ptr; + const char32_t r = *r_ptr; + + if (l == 0 || l != r) { + return static_cast(l) - static_cast(r); + } + + l_ptr++; + r_ptr++; + } +} + /*************************************************************************/ /* CharProxy */ /*************************************************************************/ template class CharProxy { - friend class Char16String; - friend class CharString; - friend class String; + friend String; + friend CharStringT; const int _index; CowData &_cowdata; - static const T _null = 0; + static constexpr T _null = 0; _FORCE_INLINE_ CharProxy(const int &p_index, CowData &p_cowdata) : _index(p_index), @@ -144,106 +162,109 @@ public: }; /*************************************************************************/ -/* Char16String */ +/* CharStringT */ /*************************************************************************/ -class Char16String { - CowData _cowdata; - static const char16_t _null; +template +class CharStringT { + CowData _cowdata; + static constexpr T _null = 0; public: - _FORCE_INLINE_ char16_t *ptrw() { return _cowdata.ptrw(); } - _FORCE_INLINE_ const char16_t *ptr() const { return _cowdata.ptr(); } + _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } + _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } _FORCE_INLINE_ int size() const { return _cowdata.size(); } - _FORCE_INLINE_ operator Span() const { return Span(ptr(), length()); } - _FORCE_INLINE_ Span span() const { return Span(ptr(), length()); } + _FORCE_INLINE_ operator Span() const { return Span(ptr(), length()); } + _FORCE_INLINE_ Span span() const { return Span(ptr(), length()); } - Error resize(int p_size) { return _cowdata.resize(p_size); } + _FORCE_INLINE_ Error resize(int p_size) { return _cowdata.resize(p_size); } - _FORCE_INLINE_ char16_t get(int p_index) const { return _cowdata.get(p_index); } - _FORCE_INLINE_ void set(int p_index, const char16_t &p_elem) { _cowdata.set(p_index, p_elem); } - _FORCE_INLINE_ const char16_t &operator[](int p_index) const { + _FORCE_INLINE_ T get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } + _FORCE_INLINE_ const T &operator[](int p_index) const { if (unlikely(p_index == _cowdata.size())) { return _null; } - return _cowdata.get(p_index); } - _FORCE_INLINE_ CharProxy operator[](int p_index) { return CharProxy(p_index, _cowdata); } + _FORCE_INLINE_ CharProxy operator[](int p_index) { return CharProxy(p_index, _cowdata); } - _FORCE_INLINE_ Char16String() {} - _FORCE_INLINE_ Char16String(const Char16String &p_str) = default; - _FORCE_INLINE_ Char16String(Char16String &&p_str) = default; - _FORCE_INLINE_ void operator=(const Char16String &p_str) { _cowdata = p_str._cowdata; } - _FORCE_INLINE_ void operator=(Char16String &&p_str) { _cowdata = std::move(p_str._cowdata); } - _FORCE_INLINE_ Char16String(const char16_t *p_cstr) { copy_from(p_cstr); } + _FORCE_INLINE_ CharStringT() = default; + _FORCE_INLINE_ CharStringT(const CharStringT &p_str) = default; + _FORCE_INLINE_ CharStringT(CharStringT &&p_str) = default; + _FORCE_INLINE_ void operator=(const CharStringT &p_str) { _cowdata = p_str._cowdata; } + _FORCE_INLINE_ void operator=(CharStringT &&p_str) { _cowdata = std::move(p_str._cowdata); } + _FORCE_INLINE_ CharStringT(const T *p_cstr) { copy_from(p_cstr); } + _FORCE_INLINE_ void operator=(const T *p_cstr) { copy_from(p_cstr); } - void operator=(const char16_t *p_cstr); - bool operator<(const Char16String &p_right) const; - Char16String &operator+=(char16_t p_char); - int length() const { return size() ? size() - 1 : 0; } - const char16_t *get_data() const; + _FORCE_INLINE_ bool operator==(const CharStringT &p_other) const { + if (length() != p_other.length()) { + return false; + } + return memcmp(ptr(), p_other.ptr(), length() * sizeof(T)) == 0; + } + _FORCE_INLINE_ bool operator!=(const CharStringT &p_other) const { return !(*this == p_other); } + _FORCE_INLINE_ bool operator<(const CharStringT &p_other) const { + if (length() == 0) { + return p_other.length() != 0; + } + return str_compare(get_data(), p_other.get_data()) < 0; + } + _FORCE_INLINE_ CharStringT &operator+=(T p_char) { + const int lhs_len = length(); + resize(lhs_len + 2); + + T *dst = ptrw(); + dst[lhs_len] = p_char; + dst[lhs_len + 1] = _null; + + return *this; + } + + _FORCE_INLINE_ int length() const { return size() ? size() - 1 : 0; } + _FORCE_INLINE_ const T *get_data() const { + if (size()) { + return &operator[](0); + } + return &_null; + } protected: - void copy_from(const char16_t *p_cstr); -}; - -/*************************************************************************/ -/* CharString */ -/*************************************************************************/ - -class CharString { - CowData _cowdata; - static const char _null; - -public: - _FORCE_INLINE_ char *ptrw() { return _cowdata.ptrw(); } - _FORCE_INLINE_ const char *ptr() const { return _cowdata.ptr(); } - _FORCE_INLINE_ int size() const { return _cowdata.size(); } - - _FORCE_INLINE_ operator Span() const { return Span(ptr(), length()); } - _FORCE_INLINE_ Span span() const { return Span(ptr(), length()); } - - Error resize(int p_size) { return _cowdata.resize(p_size); } - - _FORCE_INLINE_ char get(int p_index) const { return _cowdata.get(p_index); } - _FORCE_INLINE_ void set(int p_index, const char &p_elem) { _cowdata.set(p_index, p_elem); } - _FORCE_INLINE_ const char &operator[](int p_index) const { - if (unlikely(p_index == _cowdata.size())) { - return _null; + void copy_from(const T *p_cstr) { + if (!p_cstr) { + resize(0); + return; } - return _cowdata.get(p_index); + size_t len = strlen(p_cstr); + if (len == 0) { + resize(0); + return; + } + + Error err = resize(++len); // include terminating null char. + + ERR_FAIL_COND_MSG(err != OK, "Failed to copy C-string."); + + memcpy(ptrw(), p_cstr, len * sizeof(T)); } - _FORCE_INLINE_ CharProxy operator[](int p_index) { return CharProxy(p_index, _cowdata); } - - _FORCE_INLINE_ CharString() {} - _FORCE_INLINE_ CharString(const CharString &p_str) = default; - _FORCE_INLINE_ CharString(CharString &&p_str) = default; - _FORCE_INLINE_ void operator=(const CharString &p_str) { _cowdata = p_str._cowdata; } - _FORCE_INLINE_ void operator=(CharString &&p_str) { _cowdata = std::move(p_str._cowdata); } - _FORCE_INLINE_ CharString(const char *p_cstr) { copy_from(p_cstr); } - - void operator=(const char *p_cstr); - bool operator<(const CharString &p_right) const; - bool operator==(const CharString &p_right) const; - CharString &operator+=(char p_char); - int length() const { return size() ? size() - 1 : 0; } - const char *get_data() const; - -protected: - void copy_from(const char *p_cstr); }; +template +struct is_zero_constructible> : std::true_type {}; + +using CharString = CharStringT; +using Char16String = CharStringT; + /*************************************************************************/ /* String */ /*************************************************************************/ class String { CowData _cowdata; - static const char32_t _null; - static const char32_t _replacement_char; + static constexpr char32_t _null = 0; + static constexpr char32_t _replacement_char = 0xfffd; // Known-length copy. void copy_from_unchecked(const char32_t *p_char, int p_length); @@ -686,21 +707,6 @@ struct FileNoCaseComparator { } }; -template -_FORCE_INLINE_ int64_t str_compare(const L *l_ptr, const R *r_ptr) { - while (true) { - const char32_t l = *l_ptr; - const char32_t r = *r_ptr; - - if (l == 0 || l != r) { - return static_cast(l) - static_cast(r); - } - - l_ptr++; - r_ptr++; - } -} - /* end of namespace */ // Tool translate (TTR and variants) for the editor UI, diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h index 813e7b8d42..9c1a73950e 100644 --- a/core/templates/cowdata.h +++ b/core/templates/cowdata.h @@ -87,14 +87,6 @@ private: // internal helpers - static _FORCE_INLINE_ SafeNumeric *_get_refcount_ptr(uint8_t *p_ptr) { - return (SafeNumeric *)(p_ptr + REF_COUNT_OFFSET); - } - - static _FORCE_INLINE_ USize *_get_size_ptr(uint8_t *p_ptr) { - return (USize *)(p_ptr + SIZE_OFFSET); - } - static _FORCE_INLINE_ T *_get_data_ptr(uint8_t *p_ptr) { return (T *)(p_ptr + DATA_OFFSET); } @@ -148,8 +140,23 @@ private: void _unref(); void _ref(const CowData *p_from); void _ref(const CowData &p_from); - USize _copy_on_write(); - Error _realloc(Size p_alloc_size); + + // Ensures that the backing buffer is at least p_size wide, and that this CowData instance is + // the only reference to it. The buffer is populated with as many element copies from the old + // array as possible. + // It is the responsibility of the caller to populate newly allocated space up to p_size. + Error _fork_allocate(USize p_size); + Error _copy_on_write() { return _fork_allocate(size()); } + + // Allocates a backing array of the given capacity. The reference count is initialized to 1. + // It is the responsibility of the caller to populate the array and the new size property. + Error _alloc(USize p_alloc_size); + + // Re-allocates the backing array to the given capacity. The reference count is initialized to 1. + // It is the responsibility of the caller to populate the array and the new size property. + // The caller must also make sure there are no other references to the data, as pointers may + // be invalidated. + Error _realloc(USize p_alloc_size); public: void operator=(const CowData &p_from) { _ref(p_from); } @@ -181,7 +188,7 @@ public: } } - _FORCE_INLINE_ void clear() { resize(0); } + _FORCE_INLINE_ void clear() { _unref(); } _FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; } _FORCE_INLINE_ void set(Size p_index, const T &p_elem) { @@ -255,7 +262,8 @@ void CowData::_unref() { _ptr = nullptr; return; } - // Clean up. + // We had the only reference; destroy the data. + // First, invalidate our own reference. // NOTE: It is required to do so immediately because it must not be observable outside of this // function after refcount has already been reduced to 0. @@ -273,48 +281,89 @@ void CowData::_unref() { } } - // free mem + // Free memory. Memory::free_static((uint8_t *)prev_ptr - DATA_OFFSET, false); } template -typename CowData::USize CowData::_copy_on_write() { - if (!_ptr) { - return 0; +Error CowData::_fork_allocate(USize p_size) { + if (p_size == 0) { + // Wants to clean up. + _unref(); + return OK; } - SafeNumeric *refc = _get_refcount(); + USize alloc_size; + ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); - USize rc = refc->get(); - if (unlikely(rc > 1)) { - /* in use by more than me */ - USize current_size = *_get_size(); + const USize prev_size = size(); - uint8_t *mem_new = (uint8_t *)Memory::alloc_static(_get_alloc_size(current_size) + DATA_OFFSET, false); - ERR_FAIL_NULL_V(mem_new, 0); + if (!_ptr) { + // We had no data before; just allocate a new array. + const Error error = _alloc(alloc_size); + if (error) { + return error; + } + } else if (_get_refcount()->get() == 1) { + // Resize in-place. + // NOTE: This case is not just an optimization, but required, as some callers depend on + // `_copy_on_write()` calls not changing the pointer after the first fork + // (e.g. mutable iterators). + if (p_size == prev_size) { + // We can shortcut here; we don't need to do anything. + return OK; + } - SafeNumeric *_refc_ptr = _get_refcount_ptr(mem_new); - USize *_size_ptr = _get_size_ptr(mem_new); - T *_data_ptr = _get_data_ptr(mem_new); - - new (_refc_ptr) SafeNumeric(1); //refcount - *(_size_ptr) = current_size; //size - - // initialize new elements - if constexpr (std::is_trivially_copyable_v) { - memcpy((uint8_t *)_data_ptr, _ptr, current_size * sizeof(T)); - } else { - for (USize i = 0; i < current_size; i++) { - memnew_placement(&_data_ptr[i], T(_ptr[i])); + // Destroy extraneous elements. + if constexpr (!std::is_trivially_destructible_v) { + for (USize i = prev_size; i > p_size; i--) { + _ptr[i - 1].~T(); } } - _unref(); - _ptr = _data_ptr; + if (alloc_size != _get_alloc_size(prev_size)) { + const Error error = _realloc(alloc_size); + if (error) { + // Out of memory; the current array is still valid though. + return error; + } + } + } else { + // Resize by forking. - rc = 1; + // Create a temporary CowData to hold ownership over our _ptr. + // It will be used to copy elements from the old buffer over to our new buffer. + // At the end of the block, it will be automatically destructed by going out of scope. + const CowData prev_data; + prev_data._ptr = _ptr; + _ptr = nullptr; + + const Error error = _alloc(alloc_size); + if (error) { + // On failure to allocate, just give up the old data and return. + // We could recover our old pointer from prev_data, but by just dropping our data, we + // consciously invite early failure for the case that the caller does not handle this + // case gracefully. + return error; + } + + // Copy over elements. + const USize copied_element_count = MIN(prev_size, p_size); + if (copied_element_count > 0) { + if constexpr (std::is_trivially_copyable_v) { + memcpy((uint8_t *)_ptr, (uint8_t *)prev_data._ptr, copied_element_count * sizeof(T)); + } else { + for (USize i = 0; i < copied_element_count; i++) { + memnew_placement(&_ptr[i], T(prev_data._ptr[i])); + } + } + } } - return rc; + + // Set our new size. + *_get_size() = p_size; + + return OK; } template @@ -322,87 +371,46 @@ template Error CowData::resize(Size p_size) { ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); - Size current_size = size(); - - if (p_size == current_size) { + const Size prev_size = size(); + if (p_size == prev_size) { return OK; } - if (p_size == 0) { - // Wants to clean up. - _unref(); // Resets _ptr to nullptr. - return OK; + const Error error = _fork_allocate(p_size); + if (error) { + return error; } - // possibly changing size, copy on write - _copy_on_write(); - - USize current_alloc_size = _get_alloc_size(current_size); - USize alloc_size; - ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); - - if (p_size > current_size) { - if (alloc_size != current_alloc_size) { - if (current_size == 0) { - // alloc from scratch - uint8_t *mem_new = (uint8_t *)Memory::alloc_static(alloc_size + DATA_OFFSET, false); - ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); - - SafeNumeric *_refc_ptr = _get_refcount_ptr(mem_new); - USize *_size_ptr = _get_size_ptr(mem_new); - T *_data_ptr = _get_data_ptr(mem_new); - - new (_refc_ptr) SafeNumeric(1); //refcount - *(_size_ptr) = 0; //size, currently none - - _ptr = _data_ptr; - - } else { - const Error error = _realloc(alloc_size); - if (error) { - return error; - } - } - } - - // construct the newly created elements - memnew_arr_placement(_ptr + current_size, p_size - current_size); - - *_get_size() = p_size; - - } else if (p_size < current_size) { - if constexpr (!std::is_trivially_destructible_v) { - // deinitialize no longer needed elements - for (USize i = p_size; i < *_get_size(); i++) { - T *t = &_ptr[i]; - t->~T(); - } - } - - if (alloc_size != current_alloc_size) { - const Error error = _realloc(alloc_size); - if (error) { - return error; - } - } - - *_get_size() = p_size; + if (p_size > prev_size) { + memnew_arr_placement(_ptr + prev_size, p_size - prev_size); } return OK; } template -Error CowData::_realloc(Size p_alloc_size) { +Error CowData::_alloc(USize p_alloc_size) { + uint8_t *mem_new = (uint8_t *)Memory::alloc_static(p_alloc_size + DATA_OFFSET, false); + ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); + + _ptr = _get_data_ptr(mem_new); + + // If we alloc, we're guaranteed to be the only reference. + new (_get_refcount()) SafeNumeric(1); + + return OK; +} + +template +Error CowData::_realloc(USize p_alloc_size) { uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, p_alloc_size + DATA_OFFSET, false); ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); - SafeNumeric *_refc_ptr = _get_refcount_ptr(mem_new); - T *_data_ptr = _get_data_ptr(mem_new); + _ptr = _get_data_ptr(mem_new); // If we realloc, we're guaranteed to be the only reference. - new (_refc_ptr) SafeNumeric(1); - _ptr = _data_ptr; + // So the reference was 1 and was copied to be 1 again. + DEV_ASSERT(_get_refcount()->get() == 1); return OK; } diff --git a/core/templates/fixed_vector.h b/core/templates/fixed_vector.h new file mode 100644 index 0000000000..10f2a62599 --- /dev/null +++ b/core/templates/fixed_vector.h @@ -0,0 +1,165 @@ +/**************************************************************************/ +/* fixed_vector.h */ +/**************************************************************************/ +/* This file is part of: */ +/* REDOT ENGINE */ +/* https://redotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2024-present Redot Engine contributors */ +/* (see REDOT_AUTHORS.md) */ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +/** + * A high performance Vector of fixed capacity. + * Especially useful if you need to create an array on the stack, to + * prevent dynamic allocations (especially in bottleneck code). + * + * Choose CAPACITY such that it is enough for all elements that could be added through all branches. + * + */ +template +class FixedVector { + // This declaration allows us to access other FixedVector's private members. + template + friend class FixedVector; + + uint32_t _size = 0; + alignas(T) uint8_t _data[CAPACITY * sizeof(T)]; + + constexpr static uint32_t DATA_PADDING = MAX(alignof(T), alignof(uint32_t)) - alignof(uint32_t); + +public: + _FORCE_INLINE_ constexpr FixedVector() = default; + constexpr FixedVector(std::initializer_list p_init) { + ERR_FAIL_COND(p_init.size() > CAPACITY); + for (const T &element : p_init) { + memnew_placement(ptr() + _size++, T(element)); + } + } + + template + constexpr FixedVector(const FixedVector &p_from) { + ERR_FAIL_COND(p_from.size() > CAPACITY); + if constexpr (std::is_trivially_copyable_v) { + // Copy size and all provided elements at once. + memcpy((void *)&_size, (void *)&p_from._size, sizeof(_size) + DATA_PADDING + p_from.size() * sizeof(T)); + } else { + for (const T &element : p_from) { + memnew_placement(ptr() + _size++, T(element)); + } + } + } + + template + constexpr FixedVector(FixedVector &&p_from) { + ERR_FAIL_COND(p_from.size() > CAPACITY); + // Copy size and all provided elements at once. + // Note: Assumes trivial relocatability. + memcpy((void *)&_size, (void *)&p_from._size, sizeof(_size) + DATA_PADDING + p_from.size() * sizeof(T)); + p_from._size = 0; + } + + ~FixedVector() { + if constexpr (!std::is_trivially_destructible_v) { + for (uint32_t i = 0; i < _size; i++) { + ptr()[i].~T(); + } + } + } + + _FORCE_INLINE_ constexpr T *ptr() { return (T *)(_data); } + _FORCE_INLINE_ constexpr const T *ptr() const { return (const T *)(_data); } + + _FORCE_INLINE_ constexpr operator Span() const { return Span(ptr(), size()); } + _FORCE_INLINE_ constexpr Span span() const { return operator Span(); } + + _FORCE_INLINE_ constexpr uint32_t size() const { return _size; } + _FORCE_INLINE_ constexpr bool is_empty() const { return !_size; } + _FORCE_INLINE_ constexpr bool is_full() const { return _size == CAPACITY; } + _FORCE_INLINE_ constexpr uint32_t capacity() const { return CAPACITY; } + + _FORCE_INLINE_ constexpr void clear() { resize_initialized(0); } + + /// Changes the size of the vector. + /// If p_size > size(), constructs new elements. + /// If p_size < size(), destructs new elements. + constexpr Error resize_initialized(uint32_t p_size) { + if (p_size > _size) { + ERR_FAIL_COND_V(p_size > CAPACITY, ERR_OUT_OF_MEMORY); + memnew_arr_placement(ptr() + _size, p_size - _size); + } else if (p_size < _size) { + if constexpr (!std::is_trivially_destructible_v) { + for (uint32_t i = p_size; i < _size; i++) { + ptr()[i].~T(); + } + } + } + + _size = p_size; + return OK; + } + + /// Changes the size of the vector. + /// The initializer of new elements is skipped, making this function faster than resize_initialized. + /// The caller is required to initialize the new values. + constexpr Error resize_uninitialized(uint32_t p_size) { + static_assert(std::is_trivially_destructible_v, "resize_uninitialized is unsafe to call if T is not trivially destructible."); + ERR_FAIL_COND_V(p_size > CAPACITY, ERR_OUT_OF_MEMORY); + _size = p_size; + return OK; + } + + constexpr void push_back(const T &p_val) { + ERR_FAIL_COND(_size >= CAPACITY); + memnew_placement(ptr() + _size, T(p_val)); + _size++; + } + + constexpr void pop_back() { + ERR_FAIL_COND(_size == 0); + _size--; + ptr()[_size].~T(); + } + + // NOTE: Subscripts sanity check the bounds to avoid undefined behavior. + // This is slower than direct buffer access and can prevent autovectorization. + // If the bounds are known, use ptr() subscript instead. + constexpr const T &operator[](uint32_t p_index) const { + CRASH_COND(p_index >= _size); + return ptr()[p_index]; + } + + constexpr T &operator[](uint32_t p_index) { + CRASH_COND(p_index >= _size); + return ptr()[p_index]; + } + + _FORCE_INLINE_ constexpr T *begin() { return ptr(); } + _FORCE_INLINE_ constexpr T *end() { return ptr() + _size; } + + _FORCE_INLINE_ constexpr const T *begin() const { return ptr(); } + _FORCE_INLINE_ constexpr const T *end() const { return ptr() + _size; } +}; diff --git a/core/templates/interpolated_property.cpp b/core/templates/interpolated_property.cpp new file mode 100644 index 0000000000..787fb97900 --- /dev/null +++ b/core/templates/interpolated_property.cpp @@ -0,0 +1,51 @@ +/**************************************************************************/ +/* interpolated_property.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* REDOT ENGINE */ +/* https://redotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2024-present Redot Engine contributors */ +/* (see REDOT_AUTHORS.md) */ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "interpolated_property.h" + +#include "core/math/vector2.h" + +namespace InterpolatedPropertyFuncs { + +float lerp(float p_a, float p_b, float p_fraction) { + return Math::lerp(p_a, p_b, p_fraction); +} + +double lerp(double p_a, double p_b, float p_fraction) { + return Math::lerp(p_a, p_b, (double)p_fraction); +} + +Vector2 lerp(const Vector2 &p_a, const Vector2 &p_b, float p_fraction) { + return p_a.lerp(p_b, p_fraction); +} + +} //namespace InterpolatedPropertyFuncs diff --git a/core/templates/interpolated_property.h b/core/templates/interpolated_property.h new file mode 100644 index 0000000000..70ef0f18eb --- /dev/null +++ b/core/templates/interpolated_property.h @@ -0,0 +1,109 @@ +/**************************************************************************/ +/* interpolated_property.h */ +/**************************************************************************/ +/* This file is part of: */ +/* REDOT ENGINE */ +/* https://redotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2024-present Redot Engine contributors */ +/* (see REDOT_AUTHORS.md) */ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +struct Vector2; + +namespace InterpolatedPropertyFuncs { +float lerp(float p_a, float p_b, float p_fraction); +double lerp(double p_a, double p_b, float p_fraction); +Vector2 lerp(const Vector2 &p_a, const Vector2 &p_b, float p_fraction); +} //namespace InterpolatedPropertyFuncs + +// This class is intended to reduce the boiler plate involved to +// support custom properties to be physics interpolated. + +template +class InterpolatedProperty { + // Only needs interpolating / updating the servers when + // curr and prev are different. + bool _needs_interpolating = false; + T _interpolated; + T curr; + T prev; + +public: + // FTI depends on the constant flow between current values + // (on the current tick) and stored previous values (on the previous tick). + // These should be updated both on each tick, and also on resets. + void pump() { + prev = curr; + _needs_interpolating = false; + } + void reset() { pump(); } + + void set_interpolated_value(const T &p_val) { + _interpolated = p_val; + } + const T &interpolated() const { return _interpolated; } + bool needs_interpolating() const { return _needs_interpolating; } + + bool interpolate(float p_interpolation_fraction) { + if (_needs_interpolating) { + _interpolated = InterpolatedPropertyFuncs::lerp(prev, curr, p_interpolation_fraction); + return true; + } + return false; + } + + operator T() const { + return curr; + } + + bool operator==(const T &p_o) const { + return p_o == curr; + } + + bool operator!=(const T &p_o) const { + return p_o != curr; + } + + InterpolatedProperty &operator=(T p_val) { + curr = p_val; + _interpolated = p_val; + _needs_interpolating = true; + return *this; + } + InterpolatedProperty(T p_val) { + curr = p_val; + _interpolated = p_val; + pump(); + } + InterpolatedProperty() { + // Ensure either the constructor is run, + // or the memory is zeroed if using a fundamental type. + _interpolated = T{}; + curr = T{}; + prev = T{}; + } +}; diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index 6c97bd97ff..4503cbfce6 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -227,7 +227,7 @@ bool Dictionary::has_all(const Array &p_keys) const { for (int i = 0; i < p_keys.size(); i++) { Variant key = p_keys[i]; ERR_FAIL_COND_V(!_p->typed_key.validate(key, "use 'has_all'"), false); - if (!has(key)) { + if (!_p->variant_map.has(key)) { return false; } } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 889c7cf1ff..a558ca7198 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -760,7 +760,7 @@ struct _VariantCall { String s; if (p_instance->size() > 0) { const uint8_t *r = p_instance->ptr(); - s.append_utf16((const char16_t *)r, floor((double)p_instance->size() / (double)sizeof(char16_t))); + s.append_utf16((const char16_t *)r, std::floor((double)p_instance->size() / (double)sizeof(char16_t))); } return s; } @@ -769,7 +769,7 @@ struct _VariantCall { String s; if (p_instance->size() > 0) { const uint8_t *r = p_instance->ptr(); - s.append_utf32(Span((const char32_t *)r, floor((double)p_instance->size() / (double)sizeof(char32_t)))); + s.append_utf32(Span((const char32_t *)r, std::floor((double)p_instance->size() / (double)sizeof(char32_t)))); } return s; } @@ -779,9 +779,9 @@ struct _VariantCall { if (p_instance->size() > 0) { const uint8_t *r = p_instance->ptr(); #ifdef WINDOWS_ENABLED - s.append_utf16((const char16_t *)r, floor((double)p_instance->size() / (double)sizeof(char16_t))); + s.append_utf16((const char16_t *)r, std::floor((double)p_instance->size() / (double)sizeof(char16_t))); #else - s.append_utf32(Span((const char32_t *)r, floor((double)p_instance->size() / (double)sizeof(char32_t)))); + s.append_utf32(Span((const char32_t *)r, std::floor((double)p_instance->size() / (double)sizeof(char32_t)))); #endif } return s; diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 109a164cfb..a0dd0ba0e9 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -1939,9 +1939,9 @@ Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, static String rtos_fix(double p_value, bool p_compat) { if (p_value == 0.0) { return "0"; //avoid negative zero (-0) being written, which may annoy git, svn, etc. for changes when they don't exist. - } else if (isnan(p_value)) { + } else if (std::isnan(p_value)) { return "nan"; - } else if (isinf(p_value)) { + } else if (std::isinf(p_value)) { if (p_value > 0) { return "inf"; } else if (p_compat) { diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 4a3772035c..9504f3b5d9 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -250,7 +250,7 @@ Variant VariantUtilityFunctions::abs(const Variant &x, Callable::CallError &r_er return Math::abs(VariantInternalAccessor::get(&x)); } break; case Variant::FLOAT: { - return Math::absd(VariantInternalAccessor::get(&x)); + return Math::abs(VariantInternalAccessor::get(&x)); } break; case Variant::VECTOR2: { return VariantInternalAccessor::get(&x).abs(); @@ -280,7 +280,7 @@ Variant VariantUtilityFunctions::abs(const Variant &x, Callable::CallError &r_er } double VariantUtilityFunctions::absf(double x) { - return Math::absd(x); + return Math::abs(x); } int64_t VariantUtilityFunctions::absi(int64_t x) { diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index ec00486661..65488e303c 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1401,7 +1401,7 @@ sqrt(10.24) # Returns 3.2 sqrt(-1) # Returns NaN [/codeblock] - [b]Note:[/b] Negative values of [param x] return NaN ("Not a Number"). in C#, if you need negative inputs, use [code]System.Numerics.Complex[/code]. + [b]Note:[/b] Negative values of [param x] return NaN ("Not a Number"). In C#, if you need negative inputs, use [code]System.Numerics.Complex[/code]. @@ -2927,6 +2927,7 @@ If a property is [String], hints that the property represents a particular type (class). This allows to select a type from the create dialog. The property will store the selected type as a string. If a property is [Array], hints the editor how to show elements. The [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code]. + If a property is [Dictionary], hints the editor how to show elements. The [code]hint_string[/code] is the same as [Array], with a [code]";"[/code] separating the key and value. [codeblocks] [gdscript] # Array of elem_type. @@ -3001,10 +3002,12 @@ Hints that an [int] property is a pointer. Used by GDExtension. - Hints that a property is an [Array] with the stored type specified in the hint string. + Hints that a property is an [Array] with the stored type specified in the hint string. The hint string contains the type of the array (e.g. [code]"String"[/code]). + Use the hint string format from [constant PROPERTY_HINT_TYPE_STRING] for more control over the stored type. Hints that a property is a [Dictionary] with the stored types specified in the hint string. The hint string contains the key and value types separated by a semicolon (e.g. [code]"int;String"[/code]). + Use the hint string format from [constant PROPERTY_HINT_TYPE_STRING] for more control over the stored types. Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country. diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml index 5298727b0f..838aab1ac4 100644 --- a/doc/classes/AnimationNode.xml +++ b/doc/classes/AnimationNode.xml @@ -9,9 +9,9 @@ You can access the time information as read-only parameter which is processed and stored in the previous frame for all nodes except [AnimationNodeOutput]. [b]Note:[/b] If multiple inputs exist in the [AnimationNode], which time information takes precedence depends on the type of [AnimationNode]. [codeblock] - var current_length = $AnimationTree[parameters/AnimationNodeName/current_length] - var current_position = $AnimationTree[parameters/AnimationNodeName/current_position] - var current_delta = $AnimationTree[parameters/AnimationNodeName/current_delta] + var current_length = $AnimationTree["parameters/AnimationNodeName/current_length"] + var current_position = $AnimationTree["parameters/AnimationNodeName/current_position"] + var current_delta = $AnimationTree["parameters/AnimationNodeName/current_delta"] [/codeblock] diff --git a/doc/classes/AnimationNodeBlendTree.xml b/doc/classes/AnimationNodeBlendTree.xml index e1f0fe96df..3764909b7c 100644 --- a/doc/classes/AnimationNodeBlendTree.xml +++ b/doc/classes/AnimationNodeBlendTree.xml @@ -44,6 +44,12 @@ Returns the sub animation node with the specified [param name]. + + + + Returns a list containing the names of all sub animation nodes in this blend tree. + + diff --git a/doc/classes/AnimationNodeStateMachine.xml b/doc/classes/AnimationNodeStateMachine.xml index e80b1f00b0..3f8c77d670 100644 --- a/doc/classes/AnimationNodeStateMachine.xml +++ b/doc/classes/AnimationNodeStateMachine.xml @@ -51,6 +51,12 @@ Returns the animation node with the given name. + + + + Returns a list containing the names of all animation nodes in this state machine. + + diff --git a/doc/classes/BoneAttachment3D.xml b/doc/classes/BoneAttachment3D.xml index 1e2f308977..7ddded9410 100644 --- a/doc/classes/BoneAttachment3D.xml +++ b/doc/classes/BoneAttachment3D.xml @@ -59,5 +59,6 @@ Whether the BoneAttachment3D node will override the bone pose of the bone it is attached to. When set to [code]true[/code], the BoneAttachment3D node can change the pose of the bone. When set to [code]false[/code], the BoneAttachment3D will always be set to the bone's transform. [b]Note:[/b] This override performs interruptively in the skeleton update process using signals due to the old design. It may cause unintended behavior when used at the same time with [SkeletonModifier3D]. + diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 47c45bedea..682c5f7985 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -406,7 +406,7 @@ - Returns the mouse cursor shape the control displays on mouse hover. See [enum CursorShape]. + Returns the mouse cursor shape for this control when hovered over [param position] in local coordinates. For most controls, this is the same as [member mouse_default_cursor_shape], but some built-in controls implement more complex logic. See [enum CursorShape]. diff --git a/doc/classes/FoldableContainer.xml b/doc/classes/FoldableContainer.xml index 677a65fcf9..7b1509fa72 100644 --- a/doc/classes/FoldableContainer.xml +++ b/doc/classes/FoldableContainer.xml @@ -44,7 +44,7 @@ - The [FoldableGroup] associated with the container. + The [FoldableGroup] associated with the container. When multiple [FoldableContainer] nodes share the same group, only one of them is allowed to be unfolded. If [code]true[/code], the container will becomes folded and will hide all its children. @@ -53,14 +53,8 @@ Language code used for text shaping algorithms. If left empty, current locale is used instead. - - The Container's title text. - - - Base text writing direction. - - - Defines the behavior of the [FoldableContainer] when the text is longer than the available space. + + The container's title text. Title's horizontal text alignment as defined in the [enum HorizontalAlignment] enum. @@ -68,6 +62,12 @@ Title's position as defined in the [enum TitlePosition] enum. + + Title text writing direction. + + + Defines the behavior of the title when the text is longer than the available space. + diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index bf753e915b..dd63ffa1ed 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -444,7 +444,7 @@ - Resizes the image to the nearest power of 2 for the width and height. If [param square] is [code]true[/code] then set width and height to be the same. New pixels are calculated using the [param interpolation] mode defined via [enum Interpolation] constants. + Resizes the image to the nearest power of 2 for the width and height. If [param square] is [code]true[/code], sets width and height to be the same. New pixels are calculated using the [param interpolation] mode defined via [enum Interpolation] constants. @@ -495,7 +495,7 @@ Saves the image as an EXR file to a byte array. If [param grayscale] is [code]true[/code] and the image has only one channel, it will be saved explicitly as monochrome rather than one red channel. This function will return an empty byte array if Redot was compiled without the TinyEXR module. - [b]Note:[/b] The TinyEXR module is disabled in non-editor builds, which means [method save_exr] will return an empty byte array when it is called from an exported project. + [b]Note:[/b] The TinyEXR module is disabled in non-editor builds, which means [method save_exr_to_buffer] will return an empty byte array when it is called from an exported project. diff --git a/doc/classes/LabelSettings.xml b/doc/classes/LabelSettings.xml index 610f10574b..03d75066d6 100644 --- a/doc/classes/LabelSettings.xml +++ b/doc/classes/LabelSettings.xml @@ -8,6 +8,127 @@ + + + + + + Adds a new stacked outline to the label at the given [param index]. If [param index] is [code]-1[/code], the new stacked outline will be added at the end of the list. + + + + + + + Adds a new stacked shadow to the label at the given [param index]. If [param index] is [code]-1[/code], the new stacked shadow will be added at the end of the list. + + + + + + + Returns the color of the stacked outline at [param index]. + + + + + + + Returns the size of the stacked outline at [param index]. + + + + + + + Returns the color of the stacked shadow at [param index]. + + + + + + + Returns the offset of the stacked shadow at [param index]. + + + + + + + Returns the outline size of the stacked shadow at [param index]. + + + + + + + + Moves the stacked outline at index [param from_index] to the given position [param to_position] in the array. + + + + + + + + Moves the stacked shadow at index [param from_index] to the given position [param to_position] in the array. + + + + + + + Removes the stacked outline at index [param index]. + + + + + + + Removes the stacked shadow at index [param index]. + + + + + + + + Sets the color of the stacked outline identified by the given [param index] to [param color]. + + + + + + + + Sets the size of the stacked outline identified by the given [param index] to [param size]. + + + + + + + + Sets the color of the stacked shadow identified by the given [param index] to [param color]. + + + + + + + + Sets the offset of the stacked shadow identified by the given [param index] to [param offset]. + + + + + + + + Sets the outline size of the stacked shadow identified by the given [param index] to [param size]. + + + [Font] used for the text. @@ -39,5 +160,11 @@ Size of the shadow effect. + + The number of stacked outlines. + + + Returns the stacked shadow count. + diff --git a/doc/classes/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml index a0a773b90a..9bdab5b753 100644 --- a/doc/classes/MeshInstance3D.xml +++ b/doc/classes/MeshInstance3D.xml @@ -4,7 +4,7 @@ Node that instances meshes into a scenario. - MeshInstance3D is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used render 3D geometry and can be used to instance a single [Mesh] in many places. This allows reusing geometry, which can save on resources. When a [Mesh] has to be instantiated more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance3D] instead. + MeshInstance3D is a node that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used to render 3D geometry and can be used to instance a single [Mesh] in many places. This allows reusing geometry, which can save on resources. When a [Mesh] has to be instantiated more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance3D] instead. https://godotengine.org/asset-library/asset/2742 diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 7fd6510774..289b184382 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -506,6 +506,13 @@ Fetches a node by [NodePath]. Similar to [method get_node], but does not generate an error if [param path] does not point to a valid node. + + + + Returns object IDs of all orphan nodes (nodes outside the [SceneTree]). Used for debugging. + [b]Note:[/b] [method get_orphan_node_ids] only works in debug builds. When called in a project exported in release mode, [method get_orphan_node_ids] will return an empty array. + + diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 3bd3d1a549..8ed1ee2df8 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1931,14 +1931,6 @@ Sets the visibility range values for the given geometry instance. Equivalent to [member GeometryInstance3D.visibility_range_begin] and related properties. - - - - - Prevents physics interpolation for the current physics tick. - This is useful when moving an instance to a new location, to give an instantaneous change rather than interpolation from the previous location. - - @@ -1980,14 +1972,6 @@ If [code]true[/code], ignores both frustum and occlusion culling on the specified 3D geometry instance. This is not the same as [member GeometryInstance3D.ignore_occlusion_culling], which only ignores occlusion culling and leaves frustum culling intact. - - - - - - Turns on and off physics interpolation for the instance. - - diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml index 05c749bc24..92ab5efeb2 100644 --- a/doc/classes/ResourceSaver.xml +++ b/doc/classes/ResourceSaver.xml @@ -53,6 +53,15 @@ [b]Note:[/b] When the project is running, any generated UID associated with the resource will not be saved as the required code is only executed in editor mode. + + + + + + Sets the UID of the given [param resource] path to [param uid]. You can generate a new UID using [method ResourceUID.create_id]. + Since resources will normally get a UID automatically, this method is only useful in very specific cases. + + diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 2786879d35..0665c9e62c 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -106,6 +106,14 @@ [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded. + + + + + Returns the height of the line found at the provided index. + [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether the document is fully loaded. + + @@ -123,6 +131,14 @@ [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded. + + + + + Returns the width of the line found at the provided index. + [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether the document is fully loaded. + + diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 5e556048b6..2cc9273023 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -234,6 +234,7 @@ Sets a custom [MultiplayerAPI] with the given [param root_path] (controlling also the relative subpaths), or override the default one if [param root_path] is empty. [b]Note:[/b] No [MultiplayerAPI] must be configured for the subpath containing [param root_path], nested custom multiplayers are not allowed. I.e. if one is configured for [code]"/root/Foo"[/code] setting one for [code]"/root/Foo/Bar"[/code] will cause an error. + [b]Note:[/b] [method set_multiplayer] should be called [i]before[/i] the child nodes are ready at the given [param root_path]. If multiplayer nodes like [MultiplayerSpawner] or [MultiplayerSynchronizer] are added to the tree before the custom multiplayer API is set, they will not work. diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 4f19f7a7c4..eeb5e4b072 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -474,7 +474,7 @@ - Returns [code]true[/code] if this string does not contain characters that are not allowed in file names ([code]:[/code] [code]/[/code] [code]\[/code] [code]?[/code] [code]*[/code] [code]"[/code] [code]|[/code] [code]%[/code] [code]<[/code] [code]>[/code]). + Returns [code]true[/code] if this string is a valid file name. A valid file name cannot be empty, begin or end with space characters, or contain characters that are not allowed ([code]:[/code] [code]/[/code] [code]\[/code] [code]?[/code] [code]*[/code] [code]"[/code] [code]|[/code] [code]%[/code] [code]<[/code] [code]>[/code]). diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml index 1c880bafca..506311f082 100644 --- a/doc/classes/StringName.xml +++ b/doc/classes/StringName.xml @@ -449,7 +449,7 @@ - Returns [code]true[/code] if this string does not contain characters that are not allowed in file names ([code]:[/code] [code]/[/code] [code]\[/code] [code]?[/code] [code]*[/code] [code]"[/code] [code]|[/code] [code]%[/code] [code]<[/code] [code]>[/code]). + Returns [code]true[/code] if this string is a valid file name. A valid file name cannot be empty, begin or end with space characters, or contain characters that are not allowed ([code]:[/code] [code]/[/code] [code]\[/code] [code]?[/code] [code]*[/code] [code]"[/code] [code]|[/code] [code]%[/code] [code]<[/code] [code]>[/code]). diff --git a/doc/classes/VehicleWheel3D.xml b/doc/classes/VehicleWheel3D.xml index ff472e409f..ace35830f4 100644 --- a/doc/classes/VehicleWheel3D.xml +++ b/doc/classes/VehicleWheel3D.xml @@ -64,6 +64,7 @@ [b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. A negative value will result in the wheel reversing. + The steering angle for the wheel, in radians. Setting this to a non-zero value will result in the vehicle turning when it's moving. diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp index fe1b5d2177..29f67b4879 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -4471,10 +4471,10 @@ void RenderingDeviceDriverD3D12::_command_bind_uniform_set(CommandBufferID p_cmd } #endif - last_bind->root_tables.resources.reserve(shader_set.num_root_params.resources); last_bind->root_tables.resources.clear(); - last_bind->root_tables.samplers.reserve(shader_set.num_root_params.samplers); last_bind->root_tables.samplers.clear(); + last_bind->root_tables.resources.reserve(shader_set.num_root_params.resources); + last_bind->root_tables.samplers.reserve(shader_set.num_root_params.samplers); last_bind->uses++; struct { diff --git a/drivers/gles3/effects/cubemap_filter.cpp b/drivers/gles3/effects/cubemap_filter.cpp index 8c0b49ea8e..ab154abd5a 100644 --- a/drivers/gles3/effects/cubemap_filter.cpp +++ b/drivers/gles3/effects/cubemap_filter.cpp @@ -94,13 +94,13 @@ CubemapFilter::~CubemapFilter() { Vector3 importance_sample_GGX(Vector2 xi, float roughness4) { // Compute distribution direction float phi = 2.0 * Math::PI * xi.x; - float cos_theta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); - float sin_theta = sqrt(1.0 - cos_theta * cos_theta); + float cos_theta = std::sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); + float sin_theta = std::sqrt(1.0 - cos_theta * cos_theta); // Convert to spherical direction Vector3 half_vector; - half_vector.x = sin_theta * cos(phi); - half_vector.y = sin_theta * sin(phi); + half_vector.x = sin_theta * std::cos(phi); + half_vector.y = sin_theta * std::sin(phi); half_vector.z = cos_theta; return half_vector; @@ -184,7 +184,7 @@ void CubemapFilter::filter_radiance(GLuint p_source_cubemap, GLuint p_dest_cubem float solid_angle_sample = 1.0 / (float(sample_count) * pdf + 0.0001); - float mip_level = MAX(0.5 * log2(solid_angle_sample / solid_angle_texel) + float(MAX(1, p_layer - 3)), 1.0); + float mip_level = MAX(0.5 * std::log2(solid_angle_sample / solid_angle_texel) + float(MAX(1, p_layer - 3)), 1.0); sample_directions[index * 4 + 3] = mip_level; weight += light_vec.z; diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index f2980b7c5b..6350e0c202 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -102,7 +102,7 @@ void RasterizerGLES3::begin_frame(double frame_step) { time_total += frame_step; - double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs"); + double time_roll_over = GLOBAL_GET_CACHED(double, "rendering/limits/time/time_rollover_secs"); time_total = Math::fmod(time_total, time_roll_over); canvas->set_time(time_total); diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 310db788c7..929bf04226 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -568,6 +568,12 @@ void main() { vec2 uv = uv_interp; vec2 vertex = vertex_interp; +#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) + vec4 region_rect = read_draw_data_src_rect; +#else + vec4 region_rect = vec4(0.0, 0.0, 1.0 / read_draw_data_color_texture_pixel_size); +#endif + #if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) #ifdef USE_NINEPATCH diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 727eaa6575..f2292dee68 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -157,7 +157,7 @@ float acos_approx(float p_x) { float x = abs(p_x); float res = -0.156583f * x + (M_PI / 2.0); res *= sqrt(1.0f - x); - return (p_x >= 0) ? res : M_PI - res; + return (p_x >= 0.0) ? res : M_PI - res; } // Based on https://math.stackexchange.com/questions/1098487/atan2-faster-approximation diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 5883ea4fb3..0ce8ed9b11 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1164,6 +1164,7 @@ MaterialStorage::MaterialStorage() { actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture"; actions.renames["SPECULAR_SHININESS"] = "specular_shininess"; actions.renames["SCREEN_UV"] = "screen_uv"; + actions.renames["REGION_RECT"] = "region_rect"; actions.renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; actions.renames["POINT_COORD"] = "gl_PointCoord"; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 4136c77881..84fca48e28 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -140,21 +140,20 @@ Error AudioDriverPulseAudio::detect_channels(bool input) { } } - char dev[1024]; if (device == "Default") { - strcpy(dev, input ? default_input_device.utf8().get_data() : default_output_device.utf8().get_data()); - } else { - strcpy(dev, device.utf8().get_data()); + device = input ? default_input_device : default_output_device; } - print_verbose("PulseAudio: Detecting channels for device: " + String(dev)); + print_verbose("PulseAudio: Detecting channels for device: " + device); + + CharString device_utf8 = device.utf8(); // Now using the device name get the amount of channels pa_status = 0; pa_operation *pa_op; if (input) { - pa_op = pa_context_get_source_info_by_name(pa_ctx, dev, &AudioDriverPulseAudio::pa_source_info_cb, (void *)this); + pa_op = pa_context_get_source_info_by_name(pa_ctx, device_utf8.get_data(), &AudioDriverPulseAudio::pa_source_info_cb, (void *)this); } else { - pa_op = pa_context_get_sink_info_by_name(pa_ctx, dev, &AudioDriverPulseAudio::pa_sink_info_cb, (void *)this); + pa_op = pa_context_get_sink_info_by_name(pa_ctx, device_utf8.get_data(), &AudioDriverPulseAudio::pa_sink_info_cb, (void *)this); } if (pa_op) { diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 4b01cb151e..3bc14bfc4c 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -582,7 +582,7 @@ Dictionary OS_Unix::get_memory_info() const { return meminfo; } -#ifndef __GLIBC__ +#if !defined(__GLIBC__) && !defined(WEB_ENABLED) void OS_Unix::_load_iconv() { #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) String iconv_lib_aliases[] = { "/usr/lib/libiconv.2.dylib" }; @@ -634,7 +634,7 @@ String OS_Unix::multibyte_to_string(const String &p_encoding, const PackedByteAr ERR_FAIL_COND_V_MSG(!_iconv_ok, String(), "Conversion failed: Unable to load libiconv"); LocalVector chars; -#ifdef __GLIBC__ +#if defined(__GLIBC__) || defined(WEB_ENABLED) gd_iconv_t ctx = gd_iconv_open("UTF-8", p_encoding.is_empty() ? nl_langinfo(CODESET) : p_encoding.utf8().get_data()); #else gd_iconv_t ctx = gd_iconv_open("UTF-8", p_encoding.is_empty() ? gd_locale_charset() : p_encoding.utf8().get_data()); @@ -671,7 +671,7 @@ PackedByteArray OS_Unix::string_to_multibyte(const String &p_encoding, const Str CharString charstr = p_string.utf8(); PackedByteArray ret; -#ifdef __GLIBC__ +#if defined(__GLIBC__) || defined(WEB_ENABLED) gd_iconv_t ctx = gd_iconv_open(p_encoding.is_empty() ? nl_langinfo(CODESET) : p_encoding.utf8().get_data(), "UTF-8"); #else gd_iconv_t ctx = gd_iconv_open(p_encoding.is_empty() ? gd_locale_charset() : p_encoding.utf8().get_data(), "UTF-8"); @@ -1238,7 +1238,7 @@ void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, i UnixTerminalLogger::~UnixTerminalLogger() {} OS_Unix::OS_Unix() { -#ifndef __GLIBC__ +#if !defined(__GLIBC__) && !defined(WEB_ENABLED) _load_iconv(); #endif diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 6b44f3719d..35fd8b6fb9 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -37,7 +37,7 @@ #include "core/os/os.h" #include "drivers/unix/ip_unix.h" -#ifdef __GLIBC__ +#if defined(__GLIBC__) || defined(WEB_ENABLED) #include #include #define gd_iconv_t iconv_t @@ -60,7 +60,7 @@ class OS_Unix : public OS { HashMap *process_map = nullptr; Mutex process_map_mutex; -#ifdef __GLIBC__ +#if defined(__GLIBC__) || defined(WEB_ENABLED) bool _iconv_ok = true; #else bool _iconv_ok = false; diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index d707771c32..45fb6cc537 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -1434,7 +1434,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { float track_h = animation->bezier_track_interpolate(i, time); float track_height = _bezier_h_to_pixel(track_h); - if (abs(mb->get_position().y - track_height) < 10) { + if (std::abs(mb->get_position().y - track_height) < 10) { set_animation_and_track(animation, i, read_only); break; } @@ -1450,7 +1450,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (!read_only) { - if (moving_selection && (abs(moving_selection_offset.x) > CMP_EPSILON || abs(moving_selection_offset.y) > CMP_EPSILON)) { + if (moving_selection && (std::abs(moving_selection_offset.x) > CMP_EPSILON || std::abs(moving_selection_offset.y) > CMP_EPSILON)) { // Commit it. EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(TTR("Move Bezier Points")); @@ -1725,7 +1725,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { float snapped_time = editor->snap_time(moving_selection_pivot + time_delta); float time_offset = 0.0; - if (abs(moving_selection_offset.x) > CMP_EPSILON || (snapped_time > moving_selection_pivot && time_delta > CMP_EPSILON) || (snapped_time < moving_selection_pivot && time_delta < -CMP_EPSILON)) { + if (std::abs(moving_selection_offset.x) > CMP_EPSILON || (snapped_time > moving_selection_pivot && time_delta > CMP_EPSILON) || (snapped_time < moving_selection_pivot && time_delta < -CMP_EPSILON)) { time_offset = snapped_time - moving_selection_pivot; } diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 008c2502d7..2fb7a974ab 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3189,7 +3189,7 @@ void AnimationTrackEdit::gui_input(const Ref &p_event) { if (!mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { moving_selection_attempt = false; if (moving_selection && moving_selection_effective) { - if (abs(editor->get_moving_selection_offset()) > CMP_EPSILON) { + if (std::abs(editor->get_moving_selection_offset()) > CMP_EPSILON) { emit_signal(SNAME("move_selection_commit")); } } else if (select_single_attempt != -1) { @@ -3270,7 +3270,7 @@ void AnimationTrackEdit::gui_input(const Ref &p_event) { float snapped_time = editor->snap_time(moving_selection_pivot + delta); float offset = 0.0; - if (abs(editor->get_moving_selection_offset()) > CMP_EPSILON || (snapped_time > moving_selection_pivot && delta > CMP_EPSILON) || (snapped_time < moving_selection_pivot && delta < -CMP_EPSILON)) { + if (std::abs(editor->get_moving_selection_offset()) > CMP_EPSILON || (snapped_time > moving_selection_pivot && delta > CMP_EPSILON) || (snapped_time < moving_selection_pivot && delta < -CMP_EPSILON)) { offset = snapped_time - moving_selection_pivot; moving_selection_effective = true; } @@ -6932,8 +6932,8 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { if (is_using_angle) { real_t a = from_v; real_t b = to_v; - real_t to_diff = fmod(b - a, Math::TAU); - to_v = a + fmod(2.0 * to_diff, Math::TAU) - to_diff; + real_t to_diff = std::fmod(b - a, Math::TAU); + to_v = a + std::fmod(2.0 * to_diff, Math::TAU) - to_diff; } Variant delta_v = Animation::subtract_variant(to_v, from_v); double duration = to_t - from_t; diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 94a5e21d79..bc4bf210b8 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -140,10 +140,7 @@ void FindReplaceBar::_notification(int p_what) { case NOTIFICATION_READY: { find_prev->set_button_icon(get_editor_theme_icon(SNAME("MoveUp"))); find_next->set_button_icon(get_editor_theme_icon(SNAME("MoveDown"))); - hide_button->set_texture_normal(get_editor_theme_icon(SNAME("Close"))); - hide_button->set_texture_hover(get_editor_theme_icon(SNAME("Close"))); - hide_button->set_texture_pressed(get_editor_theme_icon(SNAME("Close"))); - hide_button->set_custom_minimum_size(hide_button->get_texture_normal()->get_size()); + hide_button->set_button_icon(get_editor_theme_icon(SNAME("Close"))); _update_toggle_replace_button(replace_text->is_visible_in_tree()); } break; @@ -761,7 +758,7 @@ FindReplaceBar::FindReplaceBar() { toggle_replace_button->set_focus_mode(FOCUS_NONE); toggle_replace_button->connect(SceneStringName(pressed), callable_mp(this, &FindReplaceBar::_toggle_replace_pressed)); - vbc_lineedit = memnew(VBoxContainer); + VBoxContainer *vbc_lineedit = memnew(VBoxContainer); add_child(vbc_lineedit); vbc_lineedit->set_alignment(BoxContainer::ALIGNMENT_CENTER); vbc_lineedit->set_h_size_flags(SIZE_EXPAND_FILL); @@ -771,18 +768,20 @@ FindReplaceBar::FindReplaceBar() { add_child(vbc_option); HBoxContainer *hbc_button_search = memnew(HBoxContainer); - vbc_button->add_child(hbc_button_search); + hbc_button_search->set_v_size_flags(SIZE_EXPAND_FILL); hbc_button_search->set_alignment(BoxContainer::ALIGNMENT_END); + vbc_button->add_child(hbc_button_search); hbc_button_replace = memnew(HBoxContainer); - vbc_button->add_child(hbc_button_replace); + hbc_button_replace->set_v_size_flags(SIZE_EXPAND_FILL); hbc_button_replace->set_alignment(BoxContainer::ALIGNMENT_END); + vbc_button->add_child(hbc_button_replace); HBoxContainer *hbc_option_search = memnew(HBoxContainer); vbc_option->add_child(hbc_option_search); hbc_option_replace = memnew(HBoxContainer); vbc_option->add_child(hbc_option_replace); - // Search toolbar + // Search toolbar. search_text = memnew(LineEdit); search_text->set_keep_editing_on_text_submit(true); vbc_lineedit->add_child(search_text); @@ -826,7 +825,7 @@ FindReplaceBar::FindReplaceBar() { whole_words->set_focus_mode(FOCUS_NONE); whole_words->connect(SceneStringName(toggled), callable_mp(this, &FindReplaceBar::_search_options_changed)); - // Replace toolbar + // Replace toolbar. replace_text = memnew(LineEdit); vbc_lineedit->add_child(replace_text); replace_text->set_placeholder(TTR("Replace")); @@ -851,13 +850,14 @@ FindReplaceBar::FindReplaceBar() { selection_only->set_focus_mode(FOCUS_NONE); selection_only->connect(SceneStringName(toggled), callable_mp(this, &FindReplaceBar::_search_options_changed)); - hide_button = memnew(TextureButton); - add_child(hide_button); + hide_button = memnew(Button); + hide_button->set_flat(true); hide_button->set_tooltip_text(TTR("Hide")); hide_button->set_accessibility_name(TTRC("Hide")); hide_button->set_focus_mode(FOCUS_NONE); hide_button->connect(SceneStringName(pressed), callable_mp(this, &FindReplaceBar::_hide_bar)); hide_button->set_v_size_flags(SIZE_SHRINK_CENTER); + add_child(hide_button); } /*** CODE EDITOR ****/ @@ -942,7 +942,7 @@ void CodeTextEditor::_text_editor_gui_input(const Ref &p_event) { #ifndef ANDROID_ENABLED Ref magnify_gesture = p_event; if (magnify_gesture.is_valid()) { - _zoom_to(zoom_factor * powf(magnify_gesture->get_factor(), 0.25f)); + _zoom_to(zoom_factor * std::pow(magnify_gesture->get_factor(), 0.25f)); accept_event(); return; } @@ -1511,7 +1511,15 @@ Variant CodeTextEditor::get_navigation_state() { } void CodeTextEditor::set_error(const String &p_error) { - error->set_text(p_error); + // Trim the error message if it is more than 2 lines long. + if (p_error.count("\n") >= 2) { + Vector splits = p_error.split("\n"); + String trimmed_error = String("\n").join(splits.slice(0, 2)); + error->set_text(trimmed_error + "..."); + } else { + error->set_text(p_error); + } + if (!p_error.is_empty()) { error->set_default_cursor_shape(CURSOR_POINTING_HAND); } else { @@ -1690,9 +1698,9 @@ void CodeTextEditor::set_error_count(int p_error_count) { error_button->set_text(itos(p_error_count)); error_button->set_visible(p_error_count > 0); if (p_error_count > 0) { - _set_show_errors_panel(false); idle->set_wait_time(idle_time_with_errors); // Parsing should happen sooner. } else { + _set_show_errors_panel(false); idle->set_wait_time(idle_time); } } diff --git a/editor/code_editor.h b/editor/code_editor.h index ce7320825a..4db506c97a 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -81,14 +81,13 @@ class FindReplaceBar : public HBoxContainer { Button *find_next = nullptr; CheckBox *case_sensitive = nullptr; CheckBox *whole_words = nullptr; - TextureButton *hide_button = nullptr; + Button *hide_button = nullptr; LineEdit *replace_text = nullptr; Button *replace = nullptr; Button *replace_all = nullptr; CheckBox *selection_only = nullptr; - VBoxContainer *vbc_lineedit = nullptr; HBoxContainer *hbc_button_replace = nullptr; HBoxContainer *hbc_option_replace = nullptr; diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index f0aef67d15..d13ae47ca7 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -1493,10 +1493,12 @@ void ConnectionsDock::update_tree() { for (const MethodInfo &signal : base_signals) { base_signal_names.insert(signal.name); } - for (List::Element *F = class_signals.front(); F; F = F->next()) { + for (List::Element *F = class_signals.front(); F;) { + List::Element *N = F->next(); if (base_signal_names.has(F->get().name)) { class_signals.erase(F); } + F = N; } } diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 4cf423f0b9..dca974012b 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -84,10 +84,23 @@ void CreateDialog::_fill_type_list() { ScriptServer::get_global_class_list(&complete_type_list); EditorData &ed = EditorNode::get_editor_data(); + HashMap &class_docs_list = EditorHelp::get_doc_data()->class_list; for (const StringName &type : complete_type_list) { if (!_should_hide_type(type)) { - type_list.push_back(type); + TypeInfo type_info; + type_info.type_name = type; + + const DocData::ClassDoc *class_docs = class_docs_list.getptr(type); + if (class_docs) { + type_info.search_keywords = class_docs->keywords.split(","); + + for (int i = 0; i < type_info.search_keywords.size(); i++) { + type_info.search_keywords.set(i, type_info.search_keywords[i].strip_edges()); + } + } + + type_info_list.push_back(type_info); if (!ed.get_custom_types().has(type)) { continue; @@ -97,11 +110,23 @@ void CreateDialog::_fill_type_list() { for (int i = 0; i < ct.size(); i++) { custom_type_parents[ct[i].name] = type; custom_type_indices[ct[i].name] = i; - type_list.push_back(ct[i].name); + + TypeInfo custom_type_info; + custom_type_info.type_name = ct[i].name; + type_info_list.push_back(custom_type_info); } } } - type_list.sort_custom(); + + struct TypeInfoCompare { + StringName::AlphCompare compare; + + _FORCE_INLINE_ bool operator()(const TypeInfo &l, const TypeInfo &r) const { + return compare(l.type_name, r.type_name); + } + }; + + type_info_list.sort_custom(); } bool CreateDialog::_is_type_preferred(const String &p_type) const { @@ -209,31 +234,47 @@ void CreateDialog::_update_search() { root->set_text(0, base_type); root->set_icon(0, search_options->get_editor_theme_icon(icon_fallback)); search_options_types[base_type] = root; - _configure_search_option_item(root, base_type, ClassDB::class_exists(base_type) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE); + _configure_search_option_item(root, base_type, ClassDB::class_exists(base_type) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE, ""); const String search_text = search_box->get_text(); - bool empty_search = search_text.is_empty(); float highest_score = 0.0f; StringName best_match; - for (const StringName &candidate : type_list) { - if (empty_search || search_text.is_subsequence_ofn(candidate)) { - _add_type(candidate, ClassDB::class_exists(candidate) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE); + for (const TypeInfo &candidate : type_info_list) { + String match_keyword; - // Determine the best match for an non-empty search. - if (!empty_search) { - float score = _score_type(candidate.operator String().get_slicec(' ', 0), search_text); - if (score > highest_score) { - highest_score = score; - best_match = candidate; + // First check if the name matches. If it does not, try the search keywords. + float score = _score_type(candidate.type_name, search_text); + if (score < 0.0f) { + for (const String &keyword : candidate.search_keywords) { + score = _score_type(keyword, search_text); + + // Reduce the score of keywords, since they are an indirect match. + score *= 0.1f; + + if (score >= 0.0f) { + match_keyword = keyword; + break; } } } + + // Search did not match. + if (score < 0.0f) { + continue; + } + + _add_type(candidate.type_name, ClassDB::class_exists(candidate.type_name) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE, match_keyword); + + if (score > highest_score) { + highest_score = score; + best_match = candidate.type_name; + } } // Select the best result. - if (empty_search) { + if (search_text.is_empty()) { select_type(base_type); } else if (best_match != StringName()) { select_type(best_match); @@ -245,7 +286,7 @@ void CreateDialog::_update_search() { } } -void CreateDialog::_add_type(const StringName &p_type, TypeCategory p_type_category) { +void CreateDialog::_add_type(const StringName &p_type, TypeCategory p_type_category, const String &p_match_keyword) { if (search_options_types.has(p_type)) { return; } @@ -296,23 +337,29 @@ void CreateDialog::_add_type(const StringName &p_type, TypeCategory p_type_categ // Should never happen, but just in case... ERR_FAIL_COND(inherits == StringName()); - _add_type(inherits, inherited_type); + _add_type(inherits, inherited_type, ""); TreeItem *item = search_options->create_item(search_options_types[inherits]); search_options_types[p_type] = item; - _configure_search_option_item(item, p_type, p_type_category); + _configure_search_option_item(item, p_type, p_type_category, p_match_keyword); } -void CreateDialog::_configure_search_option_item(TreeItem *r_item, const StringName &p_type, TypeCategory p_type_category) { +void CreateDialog::_configure_search_option_item(TreeItem *r_item, const StringName &p_type, TypeCategory p_type_category, const String &p_match_keyword) { bool script_type = ScriptServer::is_global_class(p_type); bool is_abstract = false; + bool is_custom_type = false; + String type_name; + String text; if (p_type_category == TypeCategory::CPP_TYPE) { - r_item->set_text(0, p_type); + type_name = p_type; + text = p_type; } else if (p_type_category == TypeCategory::PATH_TYPE) { - r_item->set_text(0, "\"" + p_type + "\""); + type_name = "\"" + p_type + "\""; + text = "\"" + p_type + "\""; } else if (script_type) { - r_item->set_metadata(0, p_type); - r_item->set_text(0, p_type); + is_custom_type = true; + type_name = p_type; + text = p_type; is_abstract = ScriptServer::is_global_class_abstract(p_type); @@ -327,10 +374,21 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const StringN r_item->set_button_color(0, button_index, get_theme_color(SNAME("accent_color"), EditorStringName(Editor))); } } else { - r_item->set_metadata(0, custom_type_parents[p_type]); - r_item->set_text(0, p_type); + is_custom_type = true; + type_name = custom_type_parents[p_type]; + text = p_type; } + if (!p_match_keyword.is_empty()) { + text += " - " + TTR(vformat("Matches the \"%s\" keyword.", p_match_keyword)); + } + r_item->set_text(0, text); + + Array meta; + meta.append(is_custom_type); + meta.append(type_name); + r_item->set_metadata(0, meta); + bool can_instantiate = (p_type_category == TypeCategory::CPP_TYPE && ClassDB::can_instantiate(p_type)) || (p_type_category == TypeCategory::OTHER_TYPE && !is_abstract); bool instantiable = can_instantiate && !(ClassDB::class_exists(p_type) && ClassDB::is_virtual(p_type)); @@ -377,32 +435,43 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const StringN } float CreateDialog::_score_type(const String &p_type, const String &p_search) const { + if (p_search.is_empty()) { + return 0.0f; + } + + // Determine the best match for a non-empty search. + if (!p_search.is_subsequence_ofn(p_type)) { + return -1.0f; + } + if (p_type == p_search) { // Always favor an exact match (case-sensitive), since clicking a favorite will set the search text to the type. return 1.0f; } - float inverse_length = 1.f / float(p_type.length()); + const String &type_name = p_type.get_slicec(' ', 0); + + float inverse_length = 1.f / float(type_name.length()); // Favor types where search term is a substring close to the start of the type. float w = 0.5f; - int pos = p_type.findn(p_search); + int pos = type_name.findn(p_search); float score = (pos > -1) ? 1.0f - w * MIN(1, 3 * pos * inverse_length) : MAX(0.f, .9f - w); // Favor shorter items: they resemble the search term more. w = 0.9f; score *= (1 - w) + w * MIN(1.0f, p_search.length() * inverse_length); - score *= _is_type_preferred(p_type) ? 1.0f : 0.9f; + score *= _is_type_preferred(type_name) ? 1.0f : 0.9f; // Add score for being a favorite type. - score *= favorite_list.has(p_type) ? 1.0f : 0.8f; + score *= favorite_list.has(type_name) ? 1.0f : 0.8f; // Look through at most 5 recent items bool in_recent = false; constexpr int RECENT_COMPLETION_SIZE = 5; for (int i = 0; i < MIN(RECENT_COMPLETION_SIZE - 1, recent->get_item_count()); i++) { - if (recent->get_item_text(i) == p_type) { + if (recent->get_item_text(i) == type_name) { in_recent = true; break; } @@ -413,7 +482,7 @@ float CreateDialog::_score_type(const String &p_type, const String &p_search) co } void CreateDialog::_cleanup() { - type_list.clear(); + type_info_list.clear(); favorite_list.clear(); favorites->clear(); recent->clear(); @@ -556,21 +625,24 @@ Variant CreateDialog::instantiate_selected() { return Variant(); } - Variant md = selected->get_metadata(0); + Array meta = selected->get_metadata(0).operator Array(); + ERR_FAIL_COND_V(meta.size() != 2, Variant()); + + bool is_custom_type = meta[0].operator bool(); + String type_name = meta[1].operator String(); Variant obj; - if (md.get_type() != Variant::NIL) { - String custom = md; - if (ScriptServer::is_global_class(custom)) { - obj = EditorNode::get_editor_data().script_class_instance(custom); + if (is_custom_type) { + if (ScriptServer::is_global_class(type_name)) { + obj = EditorNode::get_editor_data().script_class_instance(type_name); Node *n = Object::cast_to(obj); if (n) { - n->set_name(custom); + n->set_name(type_name); } } else { - obj = EditorNode::get_editor_data().instantiate_custom_type(selected->get_text(0), custom); + obj = EditorNode::get_editor_data().instantiate_custom_type(selected->get_text(0), type_name); } } else { - obj = ClassDB::instantiate(selected->get_text(0)); + obj = ClassDB::instantiate(type_name); } EditorNode::get_editor_data().instantiate_object_properties(obj); diff --git a/editor/create_dialog.h b/editor/create_dialog.h index 468fe1efcd..48cbeef2bd 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -48,6 +48,11 @@ class CreateDialog : public ConfirmationDialog { OTHER_TYPE }; + struct TypeInfo { + StringName type_name; + PackedStringArray search_keywords; + }; + LineEdit *search_box = nullptr; Tree *search_options = nullptr; @@ -65,14 +70,14 @@ class CreateDialog : public ConfirmationDialog { HashMap search_options_types; HashMap custom_type_parents; HashMap custom_type_indices; - List type_list; + List type_info_list; HashSet type_blacklist; HashSet custom_type_blocklist; void _update_search(); bool _should_hide_type(const StringName &p_type) const; - void _add_type(const StringName &p_type, TypeCategory p_type_category); - void _configure_search_option_item(TreeItem *r_item, const StringName &p_type, TypeCategory p_type_category); + void _add_type(const StringName &p_type, TypeCategory p_type_category, const String &p_match_keyword); + void _configure_search_option_item(TreeItem *r_item, const StringName &p_type, TypeCategory p_type_category, const String &p_match_keyword); float _score_type(const String &p_type, const String &p_search) const; bool _is_type_preferred(const String &p_type) const; void _script_button_clicked(TreeItem *p_item, int p_column, int p_button_id, MouseButton p_mouse_button_index); diff --git a/editor/credits_roll.cpp b/editor/credits_roll.cpp index 48c946aabf..4f58d401cc 100644 --- a/editor/credits_roll.cpp +++ b/editor/credits_roll.cpp @@ -54,6 +54,7 @@ Label *CreditsRoll::_create_label(const String &p_with_text, LabelSize p_size) { switch (p_size) { case LabelSize::NORMAL: { label->add_theme_font_size_override(SceneStringName(font_size), font_size_normal); + label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); } break; case LabelSize::HEADER: { @@ -194,6 +195,7 @@ void CreditsRoll::roll_credits() { _create_nothing(); project_manager = _create_label(TTR("Project Manager", "Job Title"), LabelSize::HEADER); + project_manager->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); _create_label(_build_string(AUTHORS_PROJECT_MANAGERS)); _create_nothing(); diff --git a/editor/debugger/editor_file_server.cpp b/editor/debugger/editor_file_server.cpp index 5922b52f72..5f12f78b42 100644 --- a/editor/debugger/editor_file_server.cpp +++ b/editor/debugger/editor_file_server.cpp @@ -71,8 +71,7 @@ void EditorFileServer::_scan_files_changed(EditorFileSystemDirectory *efd, const continue; } - List remaps; - cf->get_section_keys("remap", &remaps); + Vector remaps = cf->get_section_keys("remap"); for (const String &remap : remaps) { if (remap == "path") { diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index ef7313593a..3bacb71b9d 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -917,6 +917,14 @@ void ScriptEditorDebugger::_msg_window_title(uint64_t p_thread_id, const Array & emit_signal(SNAME("remote_window_title_changed"), p_data[0]); } +void ScriptEditorDebugger::_msg_embed_suspend_toggle(uint64_t p_thread_id, const Array &p_data) { + emit_signal(SNAME("embed_shortcut_requested"), EMBED_SUSPEND_TOGGLE); +} + +void ScriptEditorDebugger::_msg_embed_next_frame(uint64_t p_thread_id, const Array &p_data) { + emit_signal(SNAME("embed_shortcut_requested"), EMBED_NEXT_FRAME); +} + void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread_id, const Array &p_data) { emit_signal(SNAME("debug_data"), p_msg, p_data); @@ -965,6 +973,8 @@ void ScriptEditorDebugger::_init_parse_message_handlers() { parse_message_handlers["filesystem:update_file"] = &ScriptEditorDebugger::_msg_filesystem_update_file; parse_message_handlers["evaluation_return"] = &ScriptEditorDebugger::_msg_evaluation_return; parse_message_handlers["window:title"] = &ScriptEditorDebugger::_msg_window_title; + parse_message_handlers["request_embed_suspend_toggle"] = &ScriptEditorDebugger::_msg_embed_suspend_toggle; + parse_message_handlers["request_embed_next_frame"] = &ScriptEditorDebugger::_msg_embed_next_frame; } void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType p_type) { @@ -1907,6 +1917,7 @@ void ScriptEditorDebugger::_bind_methods() { ADD_SIGNAL(MethodInfo("set_breakpoint", PropertyInfo("script"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::BOOL, "enabled"))); ADD_SIGNAL(MethodInfo("clear_breakpoints")); ADD_SIGNAL(MethodInfo("errors_cleared")); + ADD_SIGNAL(MethodInfo("embed_shortcut_requested", PropertyInfo(Variant::INT, "embed_shortcut_action"))); } void ScriptEditorDebugger::add_debugger_tab(Control *p_control) { diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index 8c0d6d5dfc..7054659e7c 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -228,6 +228,8 @@ private: void _msg_filesystem_update_file(uint64_t p_thread_id, const Array &p_data); void _msg_evaluation_return(uint64_t p_thread_id, const Array &p_data); void _msg_window_title(uint64_t p_thread_id, const Array &p_data); + void _msg_embed_suspend_toggle(uint64_t p_thread_id, const Array &p_data); + void _msg_embed_next_frame(uint64_t p_thread_id, const Array &p_data); void _parse_message(const String &p_msg, uint64_t p_thread_id, const Array &p_data); void _set_reason_text(const String &p_reason, MessageType p_type); @@ -289,6 +291,11 @@ protected: static void _bind_methods(); public: + enum EmbedShortcutAction { + EMBED_SUSPEND_TOGGLE, + EMBED_NEXT_FRAME, + }; + void request_remote_objects(const TypedArray &p_obj_ids, bool p_update_selection = true); void update_remote_object(ObjectID p_obj_id, const String &p_prop, const Variant &p_value, const String &p_field = ""); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 7a768a9bb0..8928ae32f9 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -304,9 +304,9 @@ void DependencyEditorOwners::_list_rmb_clicked(int p_item, const Vector2 &p_pos, } if (only_scenes_selected) { - file_options->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRN("Open Scene", "Open Scenes", selected_items.size()), FILE_OPEN); + file_options->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRN("Open Scene", "Open Scenes", selected_items.size()), FILE_MENU_OPEN); } else if (selected_items.size() == 1) { - file_options->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTR("Open"), FILE_OPEN); + file_options->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTR("Open"), FILE_MENU_OPEN); } else { return; } @@ -335,7 +335,7 @@ void DependencyEditorOwners::_empty_clicked(const Vector2 &p_pos, MouseButton p_ void DependencyEditorOwners::_file_option(int p_option) { switch (p_option) { - case FILE_OPEN: { + case FILE_MENU_OPEN: { PackedInt32Array selected_items = owners->get_selected_items(); for (int i = 0; i < selected_items.size(); i++) { int item_idx = selected_items[i]; diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h index 641a6e01d5..e816483180 100644 --- a/editor/dependency_editor.h +++ b/editor/dependency_editor.h @@ -66,10 +66,6 @@ public: DependencyEditor(); }; -#ifdef MINGW_ENABLED -#undef FILE_OPEN -#endif - class DependencyEditorOwners : public AcceptDialog { GDCLASS(DependencyEditorOwners, AcceptDialog); @@ -86,7 +82,7 @@ class DependencyEditorOwners : public AcceptDialog { private: enum FileMenu { - FILE_OPEN + FILE_MENU_OPEN, }; public: diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index db3d66a2fe..2482bcd1d2 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -42,13 +42,36 @@ #include "editor/gui/editor_version_button.h" #include "editor/themes/editor_scale.h" #include "scene/gui/item_list.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/scroll_container.h" #include "scene/gui/separator.h" #include "scene/gui/split_container.h" #include "scene/gui/tab_container.h" +#include "scene/gui/texture_rect.h" +#include "scene/gui/tree.h" #include "scene/resources/style_box.h" void EditorAbout::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_TRANSLATION_CHANGED: { + _about_text_label->set_text( + String(U"© 2024-present ") + TTR("Redot Engine contributors") + ".\n" + + String(U"© 2014-present ") + TTR("Godot Engine contributors") + ".\n" + + String(U"© 2007-2014 Juan Linietsky, Ariel Manzur.\n")); + + _redot_project_manager_label->set_text(TTR("Project Manager", "Job Title")); + _project_manager_label->set_text(TTR("Project Manager", "Job Title")); + + for (ItemList *il : name_lists) { + for (int i = 0; i < il->get_item_count(); i++) { + const Variant val = il->get_item_metadata(i); + if (val.get_type() == Variant::STRING) { + il->set_item_tooltip(i, val.operator String() + "\n\n" + TTR("Double-click to open in browser.")); + } + } + } + } break; + case NOTIFICATION_THEME_CHANGED: { const Ref font = get_theme_font(SNAME("source"), EditorStringName(EditorFonts)); const int font_size = get_theme_font_size(SNAME("source_size"), EditorStringName(EditorFonts)); @@ -85,23 +108,22 @@ void EditorAbout::_license_tree_selected() { _tpl_text->set_text(selected->get_metadata(0)); } -void EditorAbout::_project_manager_clicked() { - if (!EditorNode::get_singleton()) { - // Don't allow in Project Manager. - return; - } +void EditorAbout::_item_activated(int p_idx, ItemList *p_il) { + const Variant val = p_il->get_item_metadata(p_idx); + if (val.get_type() == Variant::STRING) { + OS::get_singleton()->shell_open(val); + } else { + // Easter egg :D + if (!EditorNode::get_singleton()) { + // Don't allow in Project Manager. + return; + } - if (!credits_roll) { - credits_roll = memnew(CreditsRoll); - add_child(credits_roll); - } - credits_roll->roll_credits(); -} - -void EditorAbout::_item_with_website_selected(int p_id, ItemList *p_il) { - const String website = p_il->get_item_metadata(p_id); - if (!website.is_empty()) { - OS::get_singleton()->shell_open(website); + if (!credits_roll) { + credits_roll = memnew(CreditsRoll); + add_child(credits_roll); + } + credits_roll->roll_credits(); } } @@ -109,101 +131,73 @@ void EditorAbout::_item_list_resized(ItemList *p_il) { p_il->set_fixed_column_width(p_il->get_size().x / 3.0 - 16 * EDSCALE * 2.5); // Weird. Should be 3.0 and that's it?. } -ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List &p_sections, const char *const *const p_src[], const int p_single_column_flags, const bool p_allow_website, const String &p_easter_egg_section) { - ScrollContainer *sc = memnew(ScrollContainer); - sc->set_name(p_name); - sc->set_v_size_flags(Control::SIZE_EXPAND); +Label *EditorAbout::_create_section(Control *p_parent, const String &p_name, const char *const *p_src, BitField p_flags) { + Label *lbl = memnew(Label(p_name)); + lbl->set_theme_type_variation("HeaderSmall"); + lbl->set_focus_mode(Control::FOCUS_ACCESSIBILITY); + p_parent->add_child(lbl); - VBoxContainer *vbc = memnew(VBoxContainer); - vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); - sc->add_child(vbc); + ItemList *il = memnew(ItemList); + il->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + il->set_h_size_flags(Control::SIZE_EXPAND_FILL); + il->set_same_column_width(true); + il->set_auto_height(true); + il->set_max_columns(p_flags.has_flag(FLAG_SINGLE_COLUMN) ? 1 : 16); + il->add_theme_constant_override("h_separation", 16 * EDSCALE); - Ref empty_stylebox = memnew(StyleBoxEmpty); + if (p_flags.has_flag(FLAG_ALLOW_WEBSITE) || (p_flags.has_flag(FLAG_EASTER_EGG) && EditorNode::get_singleton())) { + Ref empty_stylebox = memnew(StyleBoxEmpty); + il->add_theme_style_override("focus", empty_stylebox); + il->add_theme_style_override("selected", empty_stylebox); - int i = 0; - for (List::ConstIterator itr = p_sections.begin(); itr != p_sections.end(); ++itr, ++i) { - bool single_column = p_single_column_flags & (1 << i); - const char *const *names_ptr = p_src[i]; - if (*names_ptr) { - const String §ion_name = *itr; + il->connect("item_activated", callable_mp(this, &EditorAbout::_item_activated).bind(il)); + } else { + il->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); + il->set_focus_mode(Control::FOCUS_NONE); + } - Label *lbl = memnew(Label); - lbl->set_focus_mode(Control::FOCUS_ACCESSIBILITY); - lbl->set_theme_type_variation("HeaderSmall"); - lbl->set_text(section_name); - vbc->add_child(lbl); + const char *const *names_ptr = p_src; + if (p_flags.has_flag(FLAG_ALLOW_WEBSITE)) { + il->connect(SceneStringName(resized), callable_mp(this, &EditorAbout::_item_list_resized).bind(il)); + il->connect(SceneStringName(focus_exited), callable_mp(il, &ItemList::deselect_all)); - ItemList *il = memnew(ItemList); - il->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); - il->set_h_size_flags(Control::SIZE_EXPAND_FILL); - il->set_same_column_width(true); - il->set_auto_height(true); - il->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - il->set_focus_mode(Control::FOCUS_NONE); - il->add_theme_constant_override("h_separation", 16 * EDSCALE); - if (p_allow_website) { - il->set_focus_mode(Control::FOCUS_CLICK); - il->set_mouse_filter(Control::MOUSE_FILTER_PASS); + while (*names_ptr) { + const String name = String::utf8(*names_ptr++); + const String identifier = name.get_slicec('<', 0); + const String website = name.get_slice_count("<") == 1 ? "" : name.get_slicec('<', 1).trim_suffix(">"); - il->connect("item_activated", callable_mp(this, &EditorAbout::_item_with_website_selected).bind(il)); - il->connect(SceneStringName(resized), callable_mp(this, &EditorAbout::_item_list_resized).bind(il)); - il->connect(SceneStringName(focus_exited), callable_mp(il, &ItemList::deselect_all)); + il->add_item(identifier, nullptr, !website.is_empty()); - il->add_theme_style_override("focus", empty_stylebox); - il->add_theme_style_override("selected", empty_stylebox); - - while (*names_ptr) { - const String name = String::utf8(*names_ptr++); - const String identifier = name.get_slicec('<', 0); - const String website = name.get_slice_count("<") == 1 ? "" : name.get_slicec('<', 1).trim_suffix(">"); - - const int name_item_id = il->add_item(identifier, nullptr, false); - il->set_item_tooltip_enabled(name_item_id, false); - - if (!website.is_empty()) { - il->set_item_selectable(name_item_id, true); - il->set_item_metadata(name_item_id, website); - il->set_item_tooltip(name_item_id, website + "\n\n" + TTR("Double-click to open in browser.")); - il->set_item_tooltip_enabled(name_item_id, true); - } - - if (!*names_ptr && name.contains(" anonymous ")) { - il->set_item_disabled(name_item_id, true); - } - } + if (website.is_empty()) { + il->set_item_tooltip_enabled(-1, false); } else { - if (section_name == p_easter_egg_section) { - // Easter egg :D - il->set_focus_mode(Control::FOCUS_CLICK); - il->set_mouse_filter(Control::MOUSE_FILTER_PASS); - - il->connect("item_activated", callable_mp(this, &EditorAbout::_project_manager_clicked).unbind(1), CONNECT_DEFERRED); - - il->add_theme_style_override("focus", empty_stylebox); - il->add_theme_style_override("selected", empty_stylebox); - } - - while (*names_ptr) { - il->add_item(String::utf8(*names_ptr++), nullptr, false); - } + il->set_item_metadata(-1, website); } - il->set_max_columns(single_column ? 1 : 16); - name_lists.append(il); - - vbc->add_child(il); - - HSeparator *hs = memnew(HSeparator); - hs->set_modulate(Color(0, 0, 0, 0)); - vbc->add_child(hs); + if (!*names_ptr && name.contains(" anonymous ")) { + il->set_item_disabled(-1, true); + } + } + } else { + while (*names_ptr) { + il->add_item(String::utf8(*names_ptr++), nullptr, false); + il->set_item_tooltip_enabled(-1, false); } } - return sc; + name_lists.append(il); + + p_parent->add_child(il); + + HSeparator *hs = memnew(HSeparator); + hs->set_modulate(Color(0, 0, 0, 0)); + p_parent->add_child(hs); + + return lbl; } EditorAbout::EditorAbout() { - set_title(TTR("Thanks from the Redot community!")); + set_title(TTRC("Thanks from the Redot community!")); set_hide_on_ok(true); VBoxContainer *vbc = memnew(VBoxContainer); @@ -227,14 +221,11 @@ EditorAbout::EditorAbout() { version_info_vbc->add_child(memnew(EditorVersionButton(EditorVersionButton::FORMAT_WITH_NAME_AND_BUILD))); - Label *about_text = memnew(Label); - about_text->set_focus_mode(Control::FOCUS_ACCESSIBILITY); - about_text->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - about_text->set_text( - String::utf8("\xc2\xa9 2024-present ") + TTR("Redot Engine contributors") + "." + - String::utf8("\n\xc2\xa9 2014-present ") + TTR("Godot Engine contributors") + "." + - String::utf8("\n\xc2\xa9 2007-2014 Juan Linietsky, Ariel Manzur.\n")); - version_info_vbc->add_child(about_text); + _about_text_label = memnew(Label); + _about_text_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY); + _about_text_label->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + _about_text_label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + version_info_vbc->add_child(_about_text_label); hbc->add_child(version_info_vbc); @@ -245,67 +236,68 @@ EditorAbout::EditorAbout() { tc->set_theme_type_variation("TabContainerOdd"); vbc->add_child(tc); - // Authors. + { + ScrollContainer *sc = memnew(ScrollContainer); + sc->set_name(TTRC("Authors")); + sc->set_v_size_flags(Control::SIZE_EXPAND); + tc->add_child(sc); - List dev_sections; - dev_sections.push_back(TTR("Project Founders")); - dev_sections.push_back(TTR("Lead Developer")); - // TRANSLATORS: This refers to a job title. - const String project_manager = TTR("Project Manager", "Job Title"); - dev_sections.push_back(project_manager); - dev_sections.push_back(TTR("Developers")); - const char *const *dev_src[] = { - REDOT_AUTHORS_FOUNDERS, - REDOT_AUTHORS_LEAD_DEVELOPERS, - REDOT_AUTHORS_PROJECT_MANAGERS, - REDOT_AUTHORS_DEVELOPERS, - }; - tc->add_child(_populate_list(TTR("Authors"), dev_sections, dev_src, 0b1)); // First section (Project Founders) is always one column. + VBoxContainer *vb = memnew(VBoxContainer); + vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sc->add_child(vb); - // Godot Authors. + _create_section(vb, TTRC("Project Founders"), REDOT_AUTHORS_FOUNDERS, FLAG_SINGLE_COLUMN); + _create_section(vb, TTRC("Lead Developer"), REDOT_AUTHORS_LEAD_DEVELOPERS); + // The section title will be updated in NOTIFICATION_TRANSLATION_CHANGED. + _redot_project_manager_label = _create_section(vb, "", REDOT_AUTHORS_PROJECT_MANAGERS, FLAG_EASTER_EGG); + _redot_project_manager_label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + _create_section(vb, TTRC("Developers"), REDOT_AUTHORS_DEVELOPERS); + } - List godot_dev_sections; - godot_dev_sections.push_back(TTR("Project Founders")); - godot_dev_sections.push_back(TTR("Lead Developer")); - // TRANSLATORS: This refers to a job title. - godot_dev_sections.push_back(TTR("Project Manager", "Job Title")); - godot_dev_sections.push_back(TTR("Developers")); - const char *const *godot_dev_src[] = { - AUTHORS_FOUNDERS, - AUTHORS_LEAD_DEVELOPERS, - AUTHORS_PROJECT_MANAGERS, - AUTHORS_DEVELOPERS, - }; - tc->add_child(_populate_list(TTR("Godot Authors"), godot_dev_sections, godot_dev_src, 0b1, false, project_manager)); // First section (Project Founders) is always one column. + { + ScrollContainer *sc = memnew(ScrollContainer); + sc->set_name(TTRC("Godot Authors")); + sc->set_v_size_flags(Control::SIZE_EXPAND); + tc->add_child(sc); - // Godot Donors. + VBoxContainer *vb = memnew(VBoxContainer); + vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sc->add_child(vb); - List donor_sections; - donor_sections.push_back(TTR("Patrons")); - donor_sections.push_back(TTR("Platinum Sponsors")); - donor_sections.push_back(TTR("Gold Sponsors")); - donor_sections.push_back(TTR("Silver Sponsors")); - donor_sections.push_back(TTR("Diamond Members")); - donor_sections.push_back(TTR("Titanium Members")); - donor_sections.push_back(TTR("Platinum Members")); - donor_sections.push_back(TTR("Gold Members")); - const char *const *donor_src[] = { - DONORS_PATRONS, - DONORS_SPONSORS_PLATINUM, - DONORS_SPONSORS_GOLD, - DONORS_SPONSORS_SILVER, - DONORS_MEMBERS_DIAMOND, - DONORS_MEMBERS_TITANIUM, - DONORS_MEMBERS_PLATINUM, - DONORS_MEMBERS_GOLD, - }; - tc->add_child(_populate_list(TTR("Godot Donors"), donor_sections, donor_src, 0b1, true)); // First section (Patron) is one column. + _create_section(vb, TTRC("Project Founders"), AUTHORS_FOUNDERS, FLAG_SINGLE_COLUMN); + _create_section(vb, TTRC("Lead Developer"), AUTHORS_LEAD_DEVELOPERS); + // The section title will be updated in NOTIFICATION_TRANSLATION_CHANGED. + _project_manager_label = _create_section(vb, "", AUTHORS_PROJECT_MANAGERS, FLAG_EASTER_EGG); + _project_manager_label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + _create_section(vb, TTRC("Developers"), AUTHORS_DEVELOPERS); + } + + { + ScrollContainer *sc = memnew(ScrollContainer); + sc->set_name(TTRC("Donors")); + sc->set_v_size_flags(Control::SIZE_EXPAND); + tc->add_child(sc); + + VBoxContainer *vb = memnew(VBoxContainer); + vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sc->add_child(vb); + + _create_section(vb, TTRC("Patrons"), DONORS_PATRONS, FLAG_ALLOW_WEBSITE | FLAG_SINGLE_COLUMN); + _create_section(vb, TTRC("Platinum Sponsors"), DONORS_SPONSORS_PLATINUM, FLAG_ALLOW_WEBSITE); + _create_section(vb, TTRC("Gold Sponsors"), DONORS_SPONSORS_GOLD, FLAG_ALLOW_WEBSITE); + _create_section(vb, TTRC("Silver Sponsors"), DONORS_SPONSORS_SILVER, FLAG_ALLOW_WEBSITE); + _create_section(vb, TTRC("Diamond Members"), DONORS_MEMBERS_DIAMOND, FLAG_ALLOW_WEBSITE); + _create_section(vb, TTRC("Titanium Members"), DONORS_MEMBERS_TITANIUM, FLAG_ALLOW_WEBSITE); + _create_section(vb, TTRC("Platinum Members"), DONORS_MEMBERS_PLATINUM, FLAG_ALLOW_WEBSITE); + _create_section(vb, TTRC("Gold Members"), DONORS_MEMBERS_GOLD, FLAG_ALLOW_WEBSITE); + } // License. license_text_label = memnew(RichTextLabel); + license_text_label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); license_text_label->set_threaded(true); - license_text_label->set_name(TTR("License")); + license_text_label->set_name(TTRC("License")); license_text_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); license_text_label->set_v_size_flags(Control::SIZE_EXPAND_FILL); license_text_label->set_text(String::utf8(GODOT_LICENSE_TEXT)); @@ -314,35 +306,37 @@ EditorAbout::EditorAbout() { // Thirdparty License. VBoxContainer *license_thirdparty = memnew(VBoxContainer); - license_thirdparty->set_name(TTR("Third-party Licenses")); + license_thirdparty->set_name(TTRC("Third-party Licenses")); license_thirdparty->set_h_size_flags(Control::SIZE_EXPAND_FILL); tc->add_child(license_thirdparty); - Label *tpl_label = memnew(Label); + Label *tpl_label = memnew(Label(TTRC("Godot Engine relies on a number of third-party free and open source libraries, all compatible with the terms of its MIT license. The following is an exhaustive list of all such third-party components with their respective copyright statements and license terms."))); tpl_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY); tpl_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); tpl_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); - tpl_label->set_text(TTR("Redot Engine relies on a number of third-party free and open source libraries, all compatible with the terms of its MIT license. The following is an exhaustive list of all such third-party components with their respective copyright statements and license terms.")); tpl_label->set_size(Size2(630, 1) * EDSCALE); license_thirdparty->add_child(tpl_label); HSplitContainer *tpl_hbc = memnew(HSplitContainer); + tpl_hbc->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tpl_hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); tpl_hbc->set_v_size_flags(Control::SIZE_EXPAND_FILL); tpl_hbc->set_split_offset(240 * EDSCALE); license_thirdparty->add_child(tpl_hbc); _tpl_tree = memnew(Tree); - _tpl_tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); _tpl_tree->set_hide_root(true); TreeItem *root = _tpl_tree->create_item(); TreeItem *tpl_ti_all = _tpl_tree->create_item(root); - tpl_ti_all->set_text(0, TTR("All Components")); + tpl_ti_all->set_text(0, TTRC("All Components")); + tpl_ti_all->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_ALWAYS); TreeItem *tpl_ti_tp = _tpl_tree->create_item(root); - tpl_ti_tp->set_text(0, TTR("Components")); + tpl_ti_tp->set_text(0, TTRC("Components")); + tpl_ti_tp->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_ALWAYS); tpl_ti_tp->set_selectable(0, false); TreeItem *tpl_ti_lc = _tpl_tree->create_item(root); - tpl_ti_lc->set_text(0, TTR("Licenses")); + tpl_ti_lc->set_text(0, TTRC("Licenses")); + tpl_ti_lc->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_ALWAYS); tpl_ti_lc->set_selectable(0, false); String long_text = ""; for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) { diff --git a/editor/editor_about.h b/editor/editor_about.h index d298187cf4..68cbe11e84 100644 --- a/editor/editor_about.h +++ b/editor/editor_about.h @@ -33,13 +33,13 @@ #pragma once #include "scene/gui/dialogs.h" -#include "scene/gui/item_list.h" -#include "scene/gui/rich_text_label.h" -#include "scene/gui/scroll_container.h" -#include "scene/gui/texture_rect.h" -#include "scene/gui/tree.h" class CreditsRoll; +class ItemList; +class Label; +class RichTextLabel; +class TextureRect; +class Tree; /** * NOTE: Do not assume the EditorNode singleton to be available in this class' methods. @@ -49,12 +49,20 @@ class EditorAbout : public AcceptDialog { GDCLASS(EditorAbout, AcceptDialog); private: - void _license_tree_selected(); - void _project_manager_clicked(); - void _item_with_website_selected(int p_id, ItemList *p_il); - void _item_list_resized(ItemList *p_il); - ScrollContainer *_populate_list(const String &p_name, const List &p_sections, const char *const *const p_src[], int p_single_column_flags = 0, bool p_allow_website = false, const String &p_easter_egg_section = String()); + enum SectionFlags { + FLAG_SINGLE_COLUMN = 1 << 0, + FLAG_ALLOW_WEBSITE = 1 << 1, + FLAG_EASTER_EGG = 1 << 2, + }; + void _license_tree_selected(); + void _item_activated(int p_idx, ItemList *p_il); + void _item_list_resized(ItemList *p_il); + Label *_create_section(Control *p_parent, const String &p_name, const char *const *p_src, BitField p_flags = 0); + + Label *_about_text_label = nullptr; + Label *_project_manager_label = nullptr; + Label *_redot_project_manager_label = nullptr; Tree *_tpl_tree = nullptr; RichTextLabel *license_text_label = nullptr; RichTextLabel *_tpl_text = nullptr; diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index c109c52a91..79b4659d5d 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -2587,8 +2587,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector } if (config->has_section("params")) { - List sk; - config->get_section_keys("params", &sk); + Vector sk = config->get_section_keys("params"); for (const String ¶m : sk) { Variant value = config->get_value("params", param); //override with whatever is in file @@ -2771,8 +2770,7 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMapload(p_file + ".import"); if (err == OK) { if (cf->has_section("params")) { - List sk; - cf->get_section_keys("params", &sk); + Vector sk = cf->get_section_keys("params"); for (const String &E : sk) { if (!params.has(E)) { params[E] = cf->get_value("params", E); @@ -3410,8 +3408,7 @@ void EditorFileSystem::_move_group_files(EditorFileSystemDirectory *efd, const S config->set_value("remap", "group_file", p_new_location); } - List sk; - config->get_section_keys("params", &sk); + Vector sk = config->get_section_keys("params"); for (const String ¶m : sk) { //not very clean, but should work String value = config->get_value("params", param); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index b9124e92c1..8721bb07a3 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -4534,7 +4534,7 @@ Control *EditorHelpBitTooltip::show_tooltip(Control *p_target, const String &p_s // Copy-paste from `Viewport::_gui_show_tooltip()`. void EditorHelpBitTooltip::popup_under_cursor() { Point2 mouse_pos = get_mouse_position(); - Point2 tooltip_offset = GLOBAL_GET("display/mouse_cursor/tooltip_position_offset"); + Point2 tooltip_offset = GLOBAL_GET_CACHED(Point2, "display/mouse_cursor/tooltip_position_offset"); Rect2 r(mouse_pos + tooltip_offset, get_contents_minimum_size()); r.size = r.size.min(get_max_size()); diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp index 75f13f273a..72a502e482 100644 --- a/editor/editor_layouts_dialog.cpp +++ b/editor/editor_layouts_dialog.cpp @@ -97,8 +97,7 @@ void EditorLayoutsDialog::_post_popup() { return; } - List layouts; - config.ptr()->get_sections(&layouts); + Vector layouts = config->get_sections(); for (const String &E : layouts) { layout_names->add_item(E); diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp index 781b9083d2..60ec57cac5 100644 --- a/editor/editor_locale_dialog.cpp +++ b/editor/editor_locale_dialog.cpp @@ -244,7 +244,7 @@ void EditorLocaleDialog::_update_tree() { int filter = SHOW_ALL_LOCALES; if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) { - filter = GLOBAL_GET("internationalization/locale/locale_filter_mode"); + filter = GLOBAL_GET_CACHED(int, "internationalization/locale/locale_filter_mode"); } Array f_lang_all; if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 26644298e8..e0702cd027 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -861,7 +861,7 @@ void EditorNode::_notification(int p_what) { } break; case NOTIFICATION_WM_CLOSE_REQUEST: { - _menu_option_confirm(FILE_QUIT, false); + _menu_option_confirm(SCENE_QUIT, false); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { @@ -1395,8 +1395,8 @@ void EditorNode::_titlebar_resized() { void EditorNode::_update_undo_redo_allowed() { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - file_menu->set_item_disabled(file_menu->get_item_index(FILE_UNDO), !undo_redo->has_undo()); - file_menu->set_item_disabled(file_menu->get_item_index(FILE_REDO), !undo_redo->has_redo()); + file_menu->set_item_disabled(file_menu->get_item_index(SCENE_UNDO), !undo_redo->has_undo()); + file_menu->set_item_disabled(file_menu->get_item_index(SCENE_REDO), !undo_redo->has_redo()); } void EditorNode::_node_renamed() { @@ -1651,8 +1651,7 @@ void EditorNode::_load_editor_plugin_states_from_config(const Ref &p return; } - List esl; - p_config_file->get_section_keys("editor_states", &esl); + Vector esl = p_config_file->get_section_keys("editor_states"); Dictionary md; for (const String &E : esl) { @@ -2117,8 +2116,8 @@ void EditorNode::save_scene_list(const HashSet &p_scene_paths) { } void EditorNode::save_before_run() { - current_menu_option = FILE_SAVE_AND_RUN; - _menu_option_confirm(FILE_SAVE_AS_SCENE, true); + current_menu_option = SAVE_AND_RUN; + _menu_option_confirm(SCENE_SAVE_AS_SCENE, true); file->set_title(TTR("Save scene before running...")); } @@ -2134,7 +2133,7 @@ void EditorNode::try_autosave() { _save_scene_with_preview(scene->get_scene_file_path()); } } - _menu_option(FILE_SAVE_ALL_SCENES); + _menu_option(SCENE_SAVE_ALL_SCENES); editor_data.save_editor_external_data(); } @@ -2213,16 +2212,16 @@ bool EditorNode::_is_scene_unsaved(int p_idx) { void EditorNode::_dialog_action(String p_file) { switch (current_menu_option) { - case FILE_NEW_INHERITED_SCENE: { + case SCENE_NEW_INHERITED_SCENE: { Node *scene = editor_data.get_edited_scene_root(); // If the previous scene is rootless, just close it in favor of the new one. if (!scene) { - _menu_option_confirm(FILE_CLOSE, true); + _menu_option_confirm(SCENE_CLOSE, true); } load_scene(p_file, false, true); } break; - case FILE_OPEN_SCENE: { + case SCENE_OPEN_SCENE: { load_scene(p_file); } break; case SETTINGS_PICK_MAIN_SCENE: { @@ -2232,12 +2231,12 @@ void EditorNode::_dialog_action(String p_file) { project_run_bar->play_main_scene((bool)pick_main_scene->get_meta("from_native", false)); } break; - case FILE_CLOSE: + case SCENE_CLOSE: case SCENE_TAB_CLOSE: - case FILE_SAVE_SCENE: - case FILE_MULTI_SAVE_AS_SCENE: - case FILE_SAVE_AS_SCENE: { - int scene_idx = (current_menu_option == FILE_SAVE_SCENE || current_menu_option == FILE_SAVE_AS_SCENE || current_menu_option == FILE_MULTI_SAVE_AS_SCENE) ? -1 : tab_closing_idx; + case SCENE_SAVE_SCENE: + case SCENE_MULTI_SAVE_AS_SCENE: + case SCENE_SAVE_AS_SCENE: { + int scene_idx = (current_menu_option == SCENE_SAVE_SCENE || current_menu_option == SCENE_SAVE_AS_SCENE || current_menu_option == SCENE_MULTI_SAVE_AS_SCENE) ? -1 : tab_closing_idx; if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { bool same_open_scene = false; @@ -2265,13 +2264,13 @@ void EditorNode::_dialog_action(String p_file) { } } - if (current_menu_option == FILE_MULTI_SAVE_AS_SCENE) { + if (current_menu_option == SCENE_MULTI_SAVE_AS_SCENE) { _proceed_save_asing_scene_tabs(); } } break; - case FILE_SAVE_AND_RUN: { + case SAVE_AND_RUN: { if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { save_default_environment(); _save_scene_with_preview(p_file); @@ -2279,7 +2278,7 @@ void EditorNode::_dialog_action(String p_file) { } } break; - case FILE_SAVE_AND_RUN_MAIN_SCENE: { + case SAVE_AND_RUN_MAIN_SCENE: { ProjectSettings::get_singleton()->set("application/run/main_scene", ResourceUID::path_to_uid(p_file)); ProjectSettings::get_singleton()->save(); @@ -2381,8 +2380,7 @@ void EditorNode::_dialog_action(String p_file) { } // Erase key values. - List keys; - config->get_section_keys(p_file, &keys); + Vector keys = config->get_section_keys(p_file); for (const String &key : keys) { config->set_value(p_file, key, Variant()); } @@ -2878,12 +2876,12 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } switch (p_option) { - case FILE_NEW_SCENE: { + case SCENE_NEW_SCENE: { new_scene(); } break; - case FILE_NEW_INHERITED_SCENE: - case FILE_OPEN_SCENE: { + case SCENE_NEW_INHERITED_SCENE: + case SCENE_OPEN_SCENE: { file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); List extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions); @@ -2896,20 +2894,20 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (scene) { file->set_current_path(scene->get_scene_file_path()); }; - file->set_title(p_option == FILE_OPEN_SCENE ? TTR("Open Scene") : TTR("Open Base Scene")); + file->set_title(p_option == SCENE_OPEN_SCENE ? TTR("Open Scene") : TTR("Open Base Scene")); file->popup_file_dialog(); } break; - case FILE_QUICK_OPEN: { + case SCENE_QUICK_OPEN: { quick_open_dialog->popup_dialog({ "Resource" }, callable_mp(this, &EditorNode::_quick_opened)); } break; - case FILE_QUICK_OPEN_SCENE: { + case SCENE_QUICK_OPEN_SCENE: { quick_open_dialog->popup_dialog({ "PackedScene" }, callable_mp(this, &EditorNode::_quick_opened)); } break; - case FILE_QUICK_OPEN_SCRIPT: { + case SCENE_QUICK_OPEN_SCRIPT: { quick_open_dialog->popup_dialog({ "Script" }, callable_mp(this, &EditorNode::_quick_opened)); } break; - case FILE_OPEN_PREV: { + case SCENE_OPEN_PREV: { if (!prev_closed_scenes.is_empty()) { load_scene(prev_closed_scenes.back()->get()); } @@ -2938,12 +2936,12 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } _proceed_closing_scene_tabs(); } break; - case FILE_CLOSE: { + case SCENE_CLOSE: { _scene_tab_closed(editor_data.get_edited_scene()); } break; case SCENE_TAB_CLOSE: - case FILE_SAVE_SCENE: { - int scene_idx = (p_option == FILE_SAVE_SCENE) ? -1 : tab_closing_idx; + case SCENE_SAVE_SCENE: { + int scene_idx = (p_option == SCENE_SAVE_SCENE) ? -1 : tab_closing_idx; Node *scene = editor_data.get_edited_scene_root(scene_idx); if (scene && !scene->get_scene_file_path().is_empty()) { if (DirAccess::exists(scene->get_scene_file_path().get_base_dir())) { @@ -2964,14 +2962,14 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } [[fallthrough]]; } - case FILE_MULTI_SAVE_AS_SCENE: - case FILE_SAVE_AS_SCENE: { - int scene_idx = (p_option == FILE_SAVE_SCENE || p_option == FILE_SAVE_AS_SCENE || p_option == FILE_MULTI_SAVE_AS_SCENE) ? -1 : tab_closing_idx; + case SCENE_MULTI_SAVE_AS_SCENE: + case SCENE_SAVE_AS_SCENE: { + int scene_idx = (p_option == SCENE_SAVE_SCENE || p_option == SCENE_SAVE_AS_SCENE || p_option == SCENE_MULTI_SAVE_AS_SCENE) ? -1 : tab_closing_idx; Node *scene = editor_data.get_edited_scene_root(scene_idx); if (!scene) { - if (p_option == FILE_SAVE_SCENE) { + if (p_option == SCENE_SAVE_SCENE) { // Pressing Ctrl + S saves the current script if a scene is currently open, but it won't if the scene has no root node. // Work around this by explicitly saving the script in this case (similar to pressing Ctrl + Alt + S). ScriptEditor::get_singleton()->save_current_script(); @@ -2980,7 +2978,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { const int saved = _save_external_resources(true); if (saved > 0) { EditorToaster::get_singleton()->popup_str(vformat(TTR("The current scene has no root node, but %d modified external resource(s) and/or plugin data were saved anyway."), saved), EditorToaster::SEVERITY_INFO); - } else if (p_option == FILE_SAVE_AS_SCENE) { + } else if (p_option == SCENE_SAVE_AS_SCENE) { // Don't show this dialog when pressing Ctrl + S to avoid interfering with script saving. show_accept( TTR("A root node is required to save the scene. You can add a root node using the Scene tree dock."), @@ -3022,7 +3020,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; - case FILE_SAVE_ALL_SCENES: { + case SCENE_SAVE_ALL_SCENES: { _save_all_scenes(); } break; @@ -3043,7 +3041,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { file_pack_zip->popup_file_dialog(); } break; - case FILE_UNDO: { + case SCENE_UNDO: { if ((int)Input::get_singleton()->get_mouse_button_mask() & 0x7) { log->add_message(TTR("Can't undo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR); } else { @@ -3066,7 +3064,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } } break; - case FILE_REDO: { + case SCENE_REDO: { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); if ((int)Input::get_singleton()->get_mouse_button_mask() & 0x7) { log->add_message(TTR("Can't redo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR); @@ -3093,7 +3091,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } break; - case FILE_RELOAD_SAVED_SCENE: { + case SCENE_RELOAD_SAVED_SCENE: { Node *scene = get_edited_scene(); if (!scene) { @@ -3184,7 +3182,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { OS::get_singleton()->ensure_user_data_dir(); OS::get_singleton()->shell_show_in_file_manager(OS::get_singleton()->get_user_data_dir(), true); } break; - case FILE_QUIT: + case SCENE_QUIT: case PROJECT_QUIT_TO_PROJECT_MANAGER: case PROJECT_RELOAD_CURRENT_PROJECT: { if (p_confirmed && plugin_to_save) { @@ -3265,7 +3263,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { save_confirmation->set_text(TTR("Save changes to the following scene(s) before reloading?") + unsaved_scenes); } else { save_confirmation->set_ok_button_text(TTR("Save & Quit")); - save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes to the following scene(s) before opening Project Manager?")) + unsaved_scenes); + save_confirmation->set_text((p_option == SCENE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes to the following scene(s) before opening Project Manager?")) + unsaved_scenes); } save_confirmation->reset_size(); save_confirmation->popup_centered(); @@ -3595,7 +3593,7 @@ void EditorNode::unload_editor_addons() { void EditorNode::_discard_changes(const String &p_str) { switch (current_menu_option) { - case FILE_CLOSE: + case SCENE_CLOSE: case SCENE_TAB_CLOSE: { Node *scene = editor_data.get_edited_scene_root(tab_closing_idx); if (scene != nullptr) { @@ -3609,7 +3607,7 @@ void EditorNode::_discard_changes(const String &p_str) { } _proceed_closing_scene_tabs(); } break; - case FILE_RELOAD_SAVED_SCENE: { + case SCENE_RELOAD_SAVED_SCENE: { Node *scene = get_edited_scene(); String scene_filename = scene->get_scene_file_path(); @@ -3628,7 +3626,7 @@ void EditorNode::_discard_changes(const String &p_str) { confirmation->hide(); } break; - case FILE_QUIT: { + case SCENE_QUIT: { project_run_bar->stop_playing(); _exit_editor(EXIT_SUCCESS); @@ -3651,18 +3649,18 @@ void EditorNode::_update_file_menu_opened() { } } if (has_unsaved) { - file_menu->set_item_disabled(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), false); - file_menu->set_item_tooltip(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), String()); + file_menu->set_item_disabled(file_menu->get_item_index(SCENE_SAVE_ALL_SCENES), false); + file_menu->set_item_tooltip(file_menu->get_item_index(SCENE_SAVE_ALL_SCENES), String()); } else { - file_menu->set_item_disabled(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), true); - file_menu->set_item_tooltip(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), TTR("All scenes are already saved.")); + file_menu->set_item_disabled(file_menu->get_item_index(SCENE_SAVE_ALL_SCENES), true); + file_menu->set_item_tooltip(file_menu->get_item_index(SCENE_SAVE_ALL_SCENES), TTR("All scenes are already saved.")); } _update_undo_redo_allowed(); } void EditorNode::_palette_quick_open_dialog() { quick_open_color_palette->popup_dialog({ "ColorPalette" }, palette_file_selected_callback); - quick_open_color_palette->set_title(TTR("Quick Open Color Palette...")); + quick_open_color_palette->set_title(TTRC("Quick Open Color Palette...")); } void EditorNode::replace_resources_in_object(Object *p_object, const Vector> &p_source_resources, const Vector> &p_target_resource) { @@ -4749,7 +4747,7 @@ String EditorNode::get_multiwindow_support_tooltip_text() const { } void EditorNode::_inherit_request(String p_file) { - current_menu_option = FILE_NEW_INHERITED_SCENE; + current_menu_option = SCENE_NEW_INHERITED_SCENE; _dialog_action(p_file); } @@ -4773,7 +4771,7 @@ void EditorNode::_update_prev_closed_scenes(const String &p_scene_path, bool p_a } else { prev_closed_scenes.erase(p_scene_path); } - file_menu->set_item_disabled(file_menu->get_item_index(FILE_OPEN_PREV), prev_closed_scenes.is_empty()); + file_menu->set_item_disabled(file_menu->get_item_index(SCENE_OPEN_PREV), prev_closed_scenes.is_empty()); } } @@ -4989,8 +4987,8 @@ void EditorNode::_pick_main_scene_custom_action(const String &p_custom_action_na pick_main_scene->hide(); if (!FileAccess::exists(scene->get_scene_file_path())) { - current_menu_option = FILE_SAVE_AND_RUN_MAIN_SCENE; - _menu_option_confirm(FILE_SAVE_AS_SCENE, true); + current_menu_option = SAVE_AND_RUN_MAIN_SCENE; + _menu_option_confirm(SCENE_SAVE_AS_SCENE, true); file->set_title(TTR("Save scene before running...")); } else { current_menu_option = SETTINGS_PICK_MAIN_SCENE; @@ -5667,11 +5665,11 @@ bool EditorNode::has_scenes_in_session() { } void EditorNode::undo() { - _menu_option_confirm(FILE_UNDO, true); + _menu_option_confirm(SCENE_UNDO, true); } void EditorNode::redo() { - _menu_option_confirm(FILE_REDO, true); + _menu_option_confirm(SCENE_REDO, true); } bool EditorNode::ensure_main_scene(bool p_from_native) { @@ -5780,8 +5778,7 @@ void EditorNode::_update_layouts_menu() { return; // No config. } - List layouts; - config.ptr()->get_sections(&layouts); + Vector layouts = config->get_sections(); for (const String &layout : layouts) { if (layout == TTR("Default")) { @@ -5862,11 +5859,11 @@ void EditorNode::_proceed_save_asing_scene_tabs() { int scene_idx = scenes_to_save_as.front()->get(); scenes_to_save_as.pop_front(); _set_current_scene(scene_idx); - _menu_option_confirm(FILE_MULTI_SAVE_AS_SCENE, false); + _menu_option_confirm(SCENE_MULTI_SAVE_AS_SCENE, false); } bool EditorNode::_is_closing_editor() const { - return tab_closing_menu_option == FILE_QUIT || tab_closing_menu_option == PROJECT_QUIT_TO_PROJECT_MANAGER || tab_closing_menu_option == PROJECT_RELOAD_CURRENT_PROJECT; + return tab_closing_menu_option == SCENE_QUIT || tab_closing_menu_option == PROJECT_QUIT_TO_PROJECT_MANAGER || tab_closing_menu_option == PROJECT_RELOAD_CURRENT_PROJECT; } void EditorNode::_restart_editor(bool p_goto_project_manager) { @@ -7602,7 +7599,7 @@ EditorNode::EditorNode() { save_accept = memnew(AcceptDialog); save_accept->set_unparent_when_invisible(true); - save_accept->connect(SceneStringName(confirmed), callable_mp(this, &EditorNode::_menu_option).bind((int)MenuOptions::FILE_SAVE_AS_SCENE)); + save_accept->connect(SceneStringName(confirmed), callable_mp(this, &EditorNode::_menu_option).bind((int)MenuOptions::SCENE_SAVE_AS_SCENE)); project_export = memnew(ProjectExportDialog); gui_base->add_child(project_export); @@ -7659,27 +7656,27 @@ EditorNode::EditorNode() { command_palette->set_title(TTR("Command Palette")); gui_base->add_child(command_palette); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTRC("New Scene"), KeyModifierMask::CMD_OR_CTRL + Key::N), FILE_NEW_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTRC("New Inherited Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::N), FILE_NEW_INHERITED_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTRC("Open Scene..."), KeyModifierMask::CMD_OR_CTRL + Key::O), FILE_OPEN_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTRC("Reopen Closed Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::T), FILE_OPEN_PREV); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTRC("New Scene"), KeyModifierMask::CMD_OR_CTRL + Key::N), SCENE_NEW_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTRC("New Inherited Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::N), SCENE_NEW_INHERITED_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTRC("Open Scene..."), KeyModifierMask::CMD_OR_CTRL + Key::O), SCENE_OPEN_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTRC("Reopen Closed Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::T), SCENE_OPEN_PREV); recent_scenes = memnew(PopupMenu); recent_scenes->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); - file_menu->add_submenu_node_item(TTR("Open Recent"), recent_scenes, FILE_OPEN_RECENT); + file_menu->add_submenu_node_item(TTR("Open Recent"), recent_scenes, SCENE_OPEN_RECENT); recent_scenes->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_open_recent_scene)); file_menu->add_separator(); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTRC("Save Scene"), KeyModifierMask::CMD_OR_CTRL + Key::S), FILE_SAVE_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTRC("Save Scene As..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::S), FILE_SAVE_AS_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTRC("Save All Scenes"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::S), FILE_SAVE_ALL_SCENES); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTRC("Save Scene"), KeyModifierMask::CMD_OR_CTRL + Key::S), SCENE_SAVE_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTRC("Save Scene As..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::S), SCENE_SAVE_AS_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTRC("Save All Scenes"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::S), SCENE_SAVE_ALL_SCENES); file_menu->add_separator(); - file_menu->add_shortcut(ED_SHORTCUT_ARRAY_AND_COMMAND("editor/quick_open", TTRC("Quick Open..."), { int32_t(KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::O), int32_t(KeyModifierMask::CMD_OR_CTRL + Key::P) }), FILE_QUICK_OPEN); + file_menu->add_shortcut(ED_SHORTCUT_ARRAY_AND_COMMAND("editor/quick_open", TTRC("Quick Open..."), { int32_t(KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::O), int32_t(KeyModifierMask::CMD_OR_CTRL + Key::P) }), SCENE_QUICK_OPEN); ED_SHORTCUT_OVERRIDE_ARRAY("editor/quick_open", "macos", { int32_t(KeyModifierMask::META + KeyModifierMask::CTRL + Key::O), int32_t(KeyModifierMask::CMD_OR_CTRL + Key::P) }); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTRC("Quick Open Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::O), FILE_QUICK_OPEN_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTRC("Quick Open Script..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::O), FILE_QUICK_OPEN_SCRIPT); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTRC("Quick Open Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::O), SCENE_QUICK_OPEN_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTRC("Quick Open Script..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::O), SCENE_QUICK_OPEN_SCRIPT); file_menu->add_separator(); export_as_menu = memnew(PopupMenu); @@ -7688,18 +7685,18 @@ EditorNode::EditorNode() { export_as_menu->connect("index_pressed", callable_mp(this, &EditorNode::_export_as_menu_option)); file_menu->add_separator(); - file_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), FILE_UNDO, false, true); - file_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), FILE_REDO, false, true); + file_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), SCENE_UNDO, false, true); + file_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), SCENE_REDO, false, true); file_menu->add_separator(); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTRC("Reload Saved Scene")), FILE_RELOAD_SAVED_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTRC("Close Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::W), FILE_CLOSE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTRC("Reload Saved Scene")), SCENE_RELOAD_SAVED_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTRC("Close Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::W), SCENE_CLOSE); ED_SHORTCUT_OVERRIDE("editor/close_scene", "macos", KeyModifierMask::CMD_OR_CTRL + Key::W); if (!global_menu || !OS::get_singleton()->has_feature("macos")) { // On macOS "Quit" and "About" options are in the "app" menu. file_menu->add_separator(); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTRC("Quit"), KeyModifierMask::CMD_OR_CTRL + Key::Q), FILE_QUIT, true); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTRC("Quit"), KeyModifierMask::CMD_OR_CTRL + Key::Q), SCENE_QUIT, true); } ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTRC("Editor Settings...")); diff --git a/editor/editor_node.h b/editor/editor_node.h index dc97904e7f..71aa02bc93 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -140,23 +140,23 @@ public: enum MenuOptions { // Scene menu. - FILE_NEW_SCENE, - FILE_NEW_INHERITED_SCENE, - FILE_OPEN_SCENE, - FILE_OPEN_PREV, - FILE_OPEN_RECENT, - FILE_SAVE_SCENE, - FILE_SAVE_AS_SCENE, - FILE_SAVE_ALL_SCENES, - FILE_MULTI_SAVE_AS_SCENE, - FILE_QUICK_OPEN, - FILE_QUICK_OPEN_SCENE, - FILE_QUICK_OPEN_SCRIPT, - FILE_UNDO, - FILE_REDO, - FILE_RELOAD_SAVED_SCENE, - FILE_CLOSE, - FILE_QUIT, + SCENE_NEW_SCENE, + SCENE_NEW_INHERITED_SCENE, + SCENE_OPEN_SCENE, + SCENE_OPEN_PREV, + SCENE_OPEN_RECENT, + SCENE_SAVE_SCENE, + SCENE_SAVE_AS_SCENE, + SCENE_SAVE_ALL_SCENES, + SCENE_MULTI_SAVE_AS_SCENE, + SCENE_QUICK_OPEN, + SCENE_QUICK_OPEN_SCENE, + SCENE_QUICK_OPEN_SCRIPT, + SCENE_UNDO, + SCENE_REDO, + SCENE_RELOAD_SAVED_SCENE, + SCENE_CLOSE, + SCENE_QUIT, FILE_EXPORT_MESH_LIBRARY, @@ -212,8 +212,8 @@ public: // Non-menu options. SCENE_TAB_CLOSE, - FILE_SAVE_AND_RUN, - FILE_SAVE_AND_RUN_MAIN_SCENE, + SAVE_AND_RUN, + SAVE_AND_RUN_MAIN_SCENE, RESOURCE_SAVE, RESOURCE_SAVE_AS, SETTINGS_PICK_MAIN_SCENE, @@ -758,7 +758,7 @@ public: void trigger_menu_option(int p_option, bool p_confirmed); bool has_previous_closed_scenes() const; - void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); } + void new_inherited_scene() { _menu_option_confirm(SCENE_NEW_INHERITED_SCENE, false); } void update_distraction_free_mode(); void set_distraction_free_mode(bool p_enter); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index e8d748f5fb..1507e368a8 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -59,7 +59,7 @@ #include "scene/resources/mesh.h" #include "scene/resources/visual_shader_nodes.h" -///////////////////// Nil ///////////////////////// +///////////////////// NIL ///////////////////////// void EditorPropertyNil::update_property() { } @@ -70,6 +70,91 @@ EditorPropertyNil::EditorPropertyNil() { add_child(prop_label); } +//////////////////// VARIANT /////////////////////// + +void EditorPropertyVariant::_change_type(int p_to_type) { + new_type = Variant::Type(p_to_type); + + Variant zero; + Callable::CallError ce; + Variant::construct(new_type, zero, nullptr, 0, ce); + emit_changed(get_edited_property(), zero); +} + +void EditorPropertyVariant::_set_read_only(bool p_read_only) { + change_type->set_disabled(p_read_only); + if (sub_property) { + sub_property->set_read_only(p_read_only); + } +} + +void EditorPropertyVariant::_notification(int p_what) { + if (p_what == NOTIFICATION_THEME_CHANGED) { + change_type->set_button_icon(get_editor_theme_icon("Edit")); + + PopupMenu *popup = change_type->get_popup(); + for (int i = 0; i < popup->get_item_count(); i++) { + popup->set_item_icon(i, get_editor_theme_icon(Variant::get_type_name(Variant::Type(popup->get_item_id(i))))); + } + } +} + +void EditorPropertyVariant::update_property() { + const Variant &value = get_edited_property_value(); + if (new_type == Variant::VARIANT_MAX) { + new_type = value.get_type(); + } + + if (new_type != current_type) { + current_type = new_type; + + if (sub_property) { + memdelete(sub_property); + sub_property = nullptr; + } + + if (current_type == Variant::OBJECT) { + sub_property = EditorInspector::instantiate_property_editor(nullptr, current_type, "", PROPERTY_HINT_RESOURCE_TYPE, "Resource", PROPERTY_USAGE_NONE); + } else { + sub_property = EditorInspector::instantiate_property_editor(nullptr, current_type, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE); + } + ERR_FAIL_NULL(sub_property); + + sub_property->set_object_and_property(get_edited_object(), get_edited_property()); + sub_property->set_name_split_ratio(0); + sub_property->set_selectable(false); + sub_property->set_use_folding(is_using_folding()); + sub_property->set_read_only(is_read_only()); + sub_property->set_h_size_flags(SIZE_EXPAND_FILL); + sub_property->connect(SNAME("property_changed"), callable_mp((EditorProperty *)this, &EditorProperty::emit_changed)); + content->add_child(sub_property); + content->move_child(sub_property, 0); + sub_property->update_property(); + } else if (sub_property) { + sub_property->update_property(); + } + new_type = Variant::VARIANT_MAX; +} + +EditorPropertyVariant::EditorPropertyVariant() { + content = memnew(HBoxContainer); + add_child(content); + + change_type = memnew(MenuButton); + change_type->set_flat(false); + + PopupMenu *popup = change_type->get_popup(); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + if (i == Variant::CALLABLE || i == Variant::SIGNAL || i == Variant::RID) { + // These types can't be constructed or serialized properly, so skip them. + continue; + } + popup->add_item(Variant::get_type_name(Variant::Type(i)), i); + } + popup->connect(SceneStringName(id_pressed), callable_mp(this, &EditorPropertyVariant::_change_type)); + content->add_child(change_type); +} + ///////////////////// TEXT ///////////////////////// void EditorPropertyText::_set_read_only(bool p_read_only) { @@ -1552,7 +1637,7 @@ void EditorPropertyEasing::_drag_easing(const Ref &p_ev) { float val = get_edited_property_value(); bool sg = val < 0; - val = Math::absf(val); + val = Math::abs(val); val = Math::log(val) / Math::log((float)2.0); // Logarithmic space. @@ -3578,8 +3663,11 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ switch (p_type) { // atomic types case Variant::NIL: { - EditorPropertyNil *editor = memnew(EditorPropertyNil); - return editor; + if (p_usage & PROPERTY_USAGE_NIL_IS_VARIANT) { + return memnew(EditorPropertyVariant); + } else { + return memnew(EditorPropertyNil); + } } break; case Variant::BOOL: { EditorPropertyCheck *editor = memnew(EditorPropertyCheck); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 4f61767dcb..3ae37be141 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -56,6 +56,27 @@ public: EditorPropertyNil(); }; +class EditorPropertyVariant : public EditorProperty { + GDCLASS(EditorPropertyVariant, EditorProperty); + + HBoxContainer *content = nullptr; + EditorProperty *sub_property = nullptr; + MenuButton *change_type = nullptr; + + Variant::Type current_type = Variant::VARIANT_MAX; + Variant::Type new_type = Variant::VARIANT_MAX; + + void _change_type(int p_to_type); + +protected: + virtual void _set_read_only(bool p_read_only) override; + void _notification(int p_what); + +public: + virtual void update_property() override; + EditorPropertyVariant(); +}; + class EditorPropertyText : public EditorProperty { GDCLASS(EditorPropertyText, EditorProperty); LineEdit *text = nullptr; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 8c2ce2d34d..719bcd17bb 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -867,6 +867,14 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint subtype_hint_string = p_hint_string.substr(hint_subtype_separator + 1); subtype = Variant::Type(subtype_string.to_int()); + } else { + subtype = Variant::get_type_by_name(p_hint_string); + + if (subtype == Variant::VARIANT_MAX) { + subtype = Variant::OBJECT; + subtype_hint = PROPERTY_HINT_RESOURCE_TYPE; + subtype_hint_string = p_hint_string; + } } } } @@ -1157,12 +1165,21 @@ void EditorPropertyDictionary::setup(PropertyHint p_hint, const String &p_hint_s key_subtype_hint_string = key.substr(hint_key_subtype_separator + 1); key_subtype = Variant::Type(key_subtype_string.to_int()); + } else { + key_subtype = Variant::get_type_by_name(key); - Variant new_key = object->get_new_item_key(); - VariantInternal::initialize(&new_key, key_subtype); - object->set_new_item_key(new_key); + if (key_subtype == Variant::VARIANT_MAX) { + key_subtype = Variant::OBJECT; + key_subtype_hint = PROPERTY_HINT_RESOURCE_TYPE; + key_subtype_hint_string = key; + } } + + Variant new_key = object->get_new_item_key(); + VariantInternal::initialize(&new_key, key_subtype); + object->set_new_item_key(new_key); } + if (types.size() > 1 && !types[1].is_empty()) { String value = types[1]; int hint_value_subtype_separator = value.find_char(':'); @@ -1176,11 +1193,19 @@ void EditorPropertyDictionary::setup(PropertyHint p_hint, const String &p_hint_s value_subtype_hint_string = value.substr(hint_value_subtype_separator + 1); value_subtype = Variant::Type(value_subtype_string.to_int()); + } else { + value_subtype = Variant::get_type_by_name(value); - Variant new_value = object->get_new_item_value(); - VariantInternal::initialize(&new_value, value_subtype); - object->set_new_item_value(new_value); + if (value_subtype == Variant::VARIANT_MAX) { + value_subtype = Variant::OBJECT; + value_subtype_hint = PROPERTY_HINT_RESOURCE_TYPE; + value_subtype_hint_string = value; + } } + + Variant new_value = object->get_new_item_value(); + VariantInternal::initialize(&new_value, value_subtype); + object->set_new_item_value(new_value); } } diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index bfb8009fe9..c9d1a9ea84 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -75,7 +75,7 @@ public: class EditorResourcePreview : public Node { GDCLASS(EditorResourcePreview, Node); - inline static constexpr int CURRENT_METADATA_VERSION = 1; // Increment this number to invalidate all previews. + static constexpr int CURRENT_METADATA_VERSION = 1; // Increment this number to invalidate all previews. inline static EditorResourcePreview *singleton = nullptr; struct QueueItem { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 063058b848..8d76548130 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1074,8 +1074,7 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { } if (p_extra_config->has_section("presets")) { - List keys; - p_extra_config->get_section_keys("presets", &keys); + Vector keys = p_extra_config->get_section_keys("presets"); for (const String &key : keys) { Variant val = p_extra_config->get_value("presets", key); @@ -1219,6 +1218,7 @@ const String EditorSettings::_get_project_metadata_path() const { #ifndef DISABLE_DEPRECATED void EditorSettings::_remove_deprecated_settings() { + erase("network/connection/engine_version_update_mode"); erase("run/output/always_open_output_on_play"); erase("run/output/always_close_output_on_stop"); } @@ -1662,8 +1662,7 @@ void EditorSettings::load_favorites_and_recent_dirs() { Ref cf; cf.instantiate(); if (cf->load(favorite_properties_file) == OK) { - List secs; - cf->get_sections(&secs); + Vector secs = cf->get_sections(); for (String &E : secs) { PackedStringArray properties = PackedStringArray(cf->get_value(E, "properties")); @@ -1732,8 +1731,7 @@ void EditorSettings::load_text_editor_theme() { return; } - List keys; - cf->get_section_keys("color_theme", &keys); + Vector keys = cf->get_section_keys("color_theme"); for (const String &key : keys) { String val = cf->get_value("color_theme", key); @@ -2152,8 +2150,7 @@ void EditorSettings::get_argument_options(const StringName &p_function, int p_id r_options->push_back(E.key.quote()); } } else if (pf == "get_project_metadata" && project_metadata.is_valid()) { - List sections; - project_metadata->get_sections(§ions); + Vector sections = project_metadata->get_sections(); for (const String §ion : sections) { r_options->push_back(section.quote()); } diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp index ab1419a09c..317e92ce70 100644 --- a/editor/export/editor_export.cpp +++ b/editor/export/editor_export.cpp @@ -332,8 +332,7 @@ void EditorExport::load_config() { String option_section = "preset." + itos(index) + ".options"; - List options; - config->get_section_keys(option_section, &options); + Vector options = config->get_section_keys(option_section); for (const String &E : options) { Variant value = config->get_value(option_section, E); @@ -341,8 +340,7 @@ void EditorExport::load_config() { } if (credentials->has_section(option_section)) { - options.clear(); - credentials->get_section_keys(option_section, &options); + options = credentials->get_section_keys(option_section); for (const String &E : options) { // Drop values for secret properties that no longer exist, or during the next save they would end up in the regular config file. diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index dd7650316c..56990655df 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -1380,8 +1380,7 @@ Error EditorExportPlatform::export_project_files(const Ref & config->set_value("remap", "type", ResourceLoader::get_resource_type(export_path)); // Erase all Paths. - List keys; - config->get_section_keys("remap", &keys); + Vector keys = config->get_section_keys("remap"); for (const String &K : keys) { if (K.begins_with("path")) { config->erase_section_key("remap", K); @@ -1416,9 +1415,7 @@ Error EditorExportPlatform::export_project_files(const Ref & } } else { // File is imported and not customized, replace by what it imports. - List remaps; - config->get_section_keys("remap", &remaps); - + Vector remaps = config->get_section_keys("remap"); HashSet remap_features; for (const String &F : remaps) { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 0d04199247..7522bd7503 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -115,6 +115,12 @@ bool FileSystemList::edit_selected() { switch (get_icon_mode()) { case ItemList::ICON_MODE_LEFT: rect = get_item_rect(s, true); + if (get_v_scroll_bar()->is_visible()) { + rect.position.y -= get_v_scroll_bar()->get_value(); + } + if (get_h_scroll_bar()->is_visible()) { + rect.position.x -= get_h_scroll_bar()->get_value(); + } ofs = Vector2(0, Math::floor((MAX(line_editor->get_minimum_size().height, rect.size.height) - rect.size.height) / 2)); popup_rect.position = get_screen_position() + rect.position - ofs; popup_rect.size = rect.size; @@ -125,6 +131,12 @@ bool FileSystemList::edit_selected() { break; case ItemList::ICON_MODE_TOP: rect = get_item_rect(s, false); + if (get_v_scroll_bar()->is_visible()) { + rect.position.y -= get_v_scroll_bar()->get_value(); + } + if (get_h_scroll_bar()->is_visible()) { + rect.position.x -= get_h_scroll_bar()->get_value(); + } popup_rect.position = get_screen_position() + rect.position; popup_rect.size = rect.size; @@ -2090,14 +2102,14 @@ void FileSystemDock::_tree_rmb_option(int p_option) { // Execute the current option. switch (p_option) { - case FOLDER_EXPAND_ALL: - case FOLDER_COLLAPSE_ALL: { + case FILE_MENU_EXPAND_ALL: + case FILE_MENU_COLLAPSE_ALL: { // Expand or collapse the folder if (selected_strings.size() == 1) { - tree->get_selected()->set_collapsed_recursive(p_option == FOLDER_COLLAPSE_ALL); + tree->get_selected()->set_collapsed_recursive(p_option == FILE_MENU_COLLAPSE_ALL); } } break; - case FILE_RENAME: { + case FILE_MENU_RENAME: { selected_strings = _tree_get_selected(false, true); [[fallthrough]]; } @@ -2130,7 +2142,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected // The first one should be the active item. switch (p_option) { - case FILE_SHOW_IN_EXPLORER: { + case FILE_MENU_SHOW_IN_EXPLORER: { // Show the file/folder in the OS explorer. String fpath = current_path; if (current_path == "Favorites") { @@ -2141,7 +2153,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected OS::get_singleton()->shell_show_in_file_manager(dir, true); } break; - case FILE_OPEN_EXTERNAL: { + case FILE_MENU_OPEN_EXTERNAL: { String fpath = current_path; if (current_path == "Favorites") { fpath = p_selected[0]; @@ -2178,7 +2190,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_OPEN_IN_TERMINAL: { + case FILE_MENU_OPEN_IN_TERMINAL: { String fpath = current_path; if (current_path == "Favorites") { fpath = p_selected[0]; @@ -2313,7 +2325,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_OPEN: { + case FILE_MENU_OPEN: { // Open folders. TreeItem *selected = tree->get_root(); selected = tree->get_next_selected(selected); @@ -2329,14 +2341,14 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_INHERIT: { + case FILE_MENU_INHERIT: { // Create a new scene inherited from the selected one. if (p_selected.size() == 1) { emit_signal(SNAME("inherit"), p_selected[0]); } } break; - case FILE_MAIN_SCENE: { + case FILE_MENU_MAIN_SCENE: { // Set as main scene with selected scene file. if (p_selected.size() == 1) { ProjectSettings::get_singleton()->set("application/run/main_scene", ResourceUID::path_to_uid(p_selected[0])); @@ -2346,7 +2358,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_INSTANTIATE: { + case FILE_MENU_INSTANTIATE: { // Instantiate all selected scenes. Vector paths; for (int i = 0; i < p_selected.size(); i++) { @@ -2360,7 +2372,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_ADD_FAVORITE: { + case FILE_MENU_ADD_FAVORITE: { // Add the files from favorites. Vector favorites_list = EditorSettings::get_singleton()->get_favorites(); for (int i = 0; i < p_selected.size(); i++) { @@ -2372,7 +2384,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected _update_tree(get_uncollapsed_paths()); } break; - case FILE_REMOVE_FAVORITE: { + case FILE_MENU_REMOVE_FAVORITE: { // Remove the files from favorites. Vector favorites_list = EditorSettings::get_singleton()->get_favorites(); for (int i = 0; i < p_selected.size(); i++) { @@ -2385,13 +2397,13 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_SHOW_IN_FILESYSTEM: { + case FILE_MENU_SHOW_IN_FILESYSTEM: { if (!p_selected.is_empty()) { navigate_to_path(p_selected[0]); } } break; - case FILE_DEPENDENCIES: { + case FILE_MENU_DEPENDENCIES: { // Checkout the file dependencies. if (!p_selected.is_empty()) { const String &fpath = p_selected[0]; @@ -2399,7 +2411,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_OWNERS: { + case FILE_MENU_OWNERS: { // Checkout the file owners. if (!p_selected.is_empty()) { const String &fpath = p_selected[0]; @@ -2407,7 +2419,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_MOVE: { + case FILE_MENU_MOVE: { // Move or copy the files to a given location. to_move.clear(); Vector collapsed_paths = _remove_self_included_paths(p_selected); @@ -2423,7 +2435,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_RENAME: { + case FILE_MENU_RENAME: { if (!p_selected.is_empty()) { // Set to_rename variable for callback execution. to_rename.path = p_selected[0]; @@ -2453,7 +2465,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_REMOVE: { + case FILE_MENU_REMOVE: { // Remove the selected files. Vector remove_files; Vector remove_folders; @@ -2475,7 +2487,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_DUPLICATE: { + case FILE_MENU_DUPLICATE: { if (p_selected.size() != 1) { return; } @@ -2494,11 +2506,11 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected make_dir_dialog->popup_centered(); } break; - case FILE_REIMPORT: { + case FILE_MENU_REIMPORT: { ImportDock::get_singleton()->reimport_resources(p_selected); } break; - case FILE_NEW_FOLDER: { + case FILE_MENU_NEW_FOLDER: { String directory = current_path; if (!directory.ends_with("/")) { directory = directory.get_base_dir(); @@ -2508,7 +2520,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected make_dir_dialog->popup_centered(); } break; - case FILE_NEW_SCENE: { + case FILE_MENU_NEW_SCENE: { String directory = current_path; if (!directory.ends_with("/")) { directory = directory.get_base_dir(); @@ -2517,7 +2529,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected make_scene_dialog->popup_centered(); } break; - case FILE_NEW_SCRIPT: { + case FILE_MENU_NEW_SCRIPT: { String fpath = current_path; if (!fpath.ends_with("/")) { fpath = fpath.get_base_dir(); @@ -2526,14 +2538,14 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected make_script_dialog->popup_centered(); } break; - case FILE_COPY_PATH: { + case FILE_MENU_COPY_PATH: { if (!p_selected.is_empty()) { const String &fpath = p_selected[0]; DisplayServer::get_singleton()->clipboard_set(fpath); } } break; - case FILE_COPY_ABSOLUTE_PATH: { + case FILE_MENU_COPY_ABSOLUTE_PATH: { if (!p_selected.is_empty()) { const String &fpath = p_selected[0]; const String absolute_path = ProjectSettings::get_singleton()->globalize_path(fpath); @@ -2541,7 +2553,7 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_COPY_UID: { + case FILE_MENU_COPY_UID: { if (!p_selected.is_empty()) { ResourceUID::ID uid = ResourceLoader::get_resource_uid(p_selected[0]); if (uid != ResourceUID::INVALID_ID) { @@ -2551,10 +2563,10 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } break; - case FILE_NEW_RESOURCE: { + case FILE_MENU_NEW_RESOURCE: { new_resource_dialog->popup_create(true); } break; - case FILE_NEW_TEXTFILE: { + case FILE_MENU_NEW_TEXTFILE: { String fpath = current_path; if (!fpath.ends_with("/")) { fpath = fpath.get_base_dir(); @@ -3201,24 +3213,24 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect if (all_files) { if (all_files_scenes) { if (filenames.size() == 1) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Open Scene"), FILE_OPEN); - p_popup->add_icon_item(get_editor_theme_icon(SNAME("CreateNewSceneFrom")), TTRC("New Inherited Scene"), FILE_INHERIT); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Open Scene"), FILE_MENU_OPEN); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("CreateNewSceneFrom")), TTRC("New Inherited Scene"), FILE_MENU_INHERIT); if (GLOBAL_GET("application/run/main_scene") != filenames[0]) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("PlayScene")), TTRC("Set as Main Scene"), FILE_MAIN_SCENE); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("PlayScene")), TTRC("Set as Main Scene"), FILE_MENU_MAIN_SCENE); } } else { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Open Scenes"), FILE_OPEN); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Open Scenes"), FILE_MENU_OPEN); } - p_popup->add_icon_item(get_editor_theme_icon(SNAME("Instance")), TTRC("Instantiate"), FILE_INSTANTIATE); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("Instance")), TTRC("Instantiate"), FILE_MENU_INSTANTIATE); p_popup->add_separator(); } else if (filenames.size() == 1) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Open"), FILE_OPEN); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Open"), FILE_MENU_OPEN); p_popup->add_separator(); } if (filenames.size() == 1) { - p_popup->add_item(TTRC("Edit Dependencies..."), FILE_DEPENDENCIES); - p_popup->add_item(TTRC("View Owners..."), FILE_OWNERS); + p_popup->add_item(TTRC("Edit Dependencies..."), FILE_MENU_DEPENDENCIES); + p_popup->add_item(TTRC("View Owners..."), FILE_MENU_OWNERS); p_popup->add_separator(); } } @@ -3227,14 +3239,14 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect PopupMenu *new_menu = memnew(PopupMenu); new_menu->connect(SceneStringName(id_pressed), callable_mp(this, &FileSystemDock::_generic_rmb_option_selected)); - p_popup->add_submenu_node_item(TTRC("Create New"), new_menu, FILE_NEW); - p_popup->set_item_icon(p_popup->get_item_index(FILE_NEW), get_editor_theme_icon(SNAME("Add"))); + p_popup->add_submenu_node_item(TTRC("Create New"), new_menu, FILE_MENU_NEW); + p_popup->set_item_icon(p_popup->get_item_index(FILE_MENU_NEW), get_editor_theme_icon(SNAME("Add"))); - new_menu->add_icon_item(get_editor_theme_icon(SNAME("Folder")), TTRC("Folder..."), FILE_NEW_FOLDER); - new_menu->add_icon_item(get_editor_theme_icon(SNAME("PackedScene")), TTRC("Scene..."), FILE_NEW_SCENE); - new_menu->add_icon_item(get_editor_theme_icon(SNAME("Script")), TTRC("Script..."), FILE_NEW_SCRIPT); - new_menu->add_icon_item(get_editor_theme_icon(SNAME("Object")), TTRC("Resource..."), FILE_NEW_RESOURCE); - new_menu->add_icon_item(get_editor_theme_icon(SNAME("TextFile")), TTRC("TextFile..."), FILE_NEW_TEXTFILE); + new_menu->add_icon_item(get_editor_theme_icon(SNAME("Folder")), TTRC("Folder..."), FILE_MENU_NEW_FOLDER); + new_menu->add_icon_item(get_editor_theme_icon(SNAME("PackedScene")), TTRC("Scene..."), FILE_MENU_NEW_SCENE); + new_menu->add_icon_item(get_editor_theme_icon(SNAME("Script")), TTRC("Script..."), FILE_MENU_NEW_SCRIPT); + new_menu->add_icon_item(get_editor_theme_icon(SNAME("Object")), TTRC("Resource..."), FILE_MENU_NEW_RESOURCE); + new_menu->add_icon_item(get_editor_theme_icon(SNAME("TextFile")), TTRC("TextFile..."), FILE_MENU_NEW_TEXTFILE); EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(new_menu, EditorContextMenuPlugin::CONTEXT_SLOT_FILESYSTEM_CREATE, p_paths); p_popup->add_separator(); @@ -3245,11 +3257,11 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect bool root_path_not_selected = p_paths[0] != "res://" && (p_paths.size() <= 1 || p_paths[1] != "res://"); if (all_folders && foldernames.size() > 0) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Expand Folder"), FILE_OPEN); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Expand Folder"), FILE_MENU_OPEN); if (foldernames.size() == 1) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("GuiTreeArrowDown")), TTRC("Expand Hierarchy"), FOLDER_EXPAND_ALL); - p_popup->add_icon_item(get_editor_theme_icon(SNAME("GuiTreeArrowRight")), TTRC("Collapse Hierarchy"), FOLDER_COLLAPSE_ALL); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("GuiTreeArrowDown")), TTRC("Expand Hierarchy"), FILE_MENU_EXPAND_ALL); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("GuiTreeArrowRight")), TTRC("Collapse Hierarchy"), FILE_MENU_COLLAPSE_ALL); } p_popup->add_separator(); @@ -3277,21 +3289,21 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect // Add the options that are only available when a single item is selected. if (p_paths.size() == 1) { - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionCopy")), ED_GET_SHORTCUT("filesystem_dock/copy_path"), FILE_COPY_PATH); - p_popup->add_shortcut(ED_GET_SHORTCUT("filesystem_dock/copy_absolute_path"), FILE_COPY_ABSOLUTE_PATH); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionCopy")), ED_GET_SHORTCUT("filesystem_dock/copy_path"), FILE_MENU_COPY_PATH); + p_popup->add_shortcut(ED_GET_SHORTCUT("filesystem_dock/copy_absolute_path"), FILE_MENU_COPY_ABSOLUTE_PATH); if (ResourceLoader::get_resource_uid(p_paths[0]) != ResourceUID::INVALID_ID) { - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Instance")), ED_GET_SHORTCUT("filesystem_dock/copy_uid"), FILE_COPY_UID); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Instance")), ED_GET_SHORTCUT("filesystem_dock/copy_uid"), FILE_MENU_COPY_UID); } if (root_path_not_selected) { - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Rename")), ED_GET_SHORTCUT("filesystem_dock/rename"), FILE_RENAME); - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Duplicate")), ED_GET_SHORTCUT("filesystem_dock/duplicate"), FILE_DUPLICATE); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Rename")), ED_GET_SHORTCUT("filesystem_dock/rename"), FILE_MENU_RENAME); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Duplicate")), ED_GET_SHORTCUT("filesystem_dock/duplicate"), FILE_MENU_DUPLICATE); } } // Add the options that are only available when the root path is not selected. if (root_path_not_selected) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("MoveUp")), TTRC("Move/Duplicate To..."), FILE_MOVE); - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Remove")), ED_GET_SHORTCUT("filesystem_dock/delete"), FILE_REMOVE); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("MoveUp")), TTRC("Move/Duplicate To..."), FILE_MENU_MOVE); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Remove")), ED_GET_SHORTCUT("filesystem_dock/delete"), FILE_MENU_REMOVE); } // Only add a separator if we have actually placed any options in the menu since the last separator. @@ -3302,10 +3314,10 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect // Add the options that are available when one or more items are selected. if (p_paths.size() >= 1) { if (!all_favorites) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("Favorites")), TTRC("Add to Favorites"), FILE_ADD_FAVORITE); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("Favorites")), TTRC("Add to Favorites"), FILE_MENU_ADD_FAVORITE); } if (!all_not_favorites) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("NonFavorite")), TTRC("Remove from Favorites"), FILE_REMOVE_FAVORITE); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("NonFavorite")), TTRC("Remove from Favorites"), FILE_MENU_REMOVE_FAVORITE); } if (root_path_not_selected) { @@ -3325,7 +3337,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect container_menu = memnew(PopupMenu); container_menu->connect(SceneStringName(id_pressed), callable_mp(this, &FileSystemDock::_generic_rmb_option_selected)); - p_popup->add_submenu_node_item(TTRC("Convert to..."), container_menu, FILE_NEW); + p_popup->add_submenu_node_item(TTRC("Convert to..."), container_menu, FILE_MENU_NEW); conversion_string_template = "%s"; } @@ -3370,7 +3382,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect } if (resource_valid) { - p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Reimport"), FILE_REIMPORT); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTRC("Reimport"), FILE_MENU_REIMPORT); } } } @@ -3395,7 +3407,7 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect if (is_item_in_favorites) { p_popup->add_separator(); added_separator = true; - p_popup->add_icon_item(get_editor_theme_icon(SNAME("ShowInFileSystem")), TTRC("Show in FileSystem"), FILE_SHOW_IN_FILESYSTEM); + p_popup->add_icon_item(get_editor_theme_icon(SNAME("ShowInFileSystem")), TTRC("Show in FileSystem"), FILE_MENU_SHOW_IN_FILESYSTEM); } } @@ -3408,15 +3420,15 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect // Opening the system file manager is not supported on the Android and web editors. const bool is_directory = fpath.ends_with("/"); - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_OPEN_IN_TERMINAL); - p_popup->set_item_text(p_popup->get_item_index(FILE_OPEN_IN_TERMINAL), is_directory ? TTRC("Open in Terminal") : TTRC("Open Folder in Terminal")); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_MENU_OPEN_IN_TERMINAL); + p_popup->set_item_text(p_popup->get_item_index(FILE_MENU_OPEN_IN_TERMINAL), is_directory ? TTRC("Open in Terminal") : TTRC("Open Folder in Terminal")); if (!is_directory) { - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("ExternalLink")), ED_GET_SHORTCUT("filesystem_dock/open_in_external_program"), FILE_OPEN_EXTERNAL); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("ExternalLink")), ED_GET_SHORTCUT("filesystem_dock/open_in_external_program"), FILE_MENU_OPEN_EXTERNAL); } - p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); - p_popup->set_item_text(p_popup->get_item_index(FILE_SHOW_IN_EXPLORER), is_directory ? TTRC("Open in File Manager") : TTRC("Show in File Manager")); + p_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_MENU_SHOW_IN_EXPLORER); + p_popup->set_item_text(p_popup->get_item_index(FILE_MENU_SHOW_IN_EXPLORER), is_directory ? TTRC("Open in File Manager") : TTRC("Show in File Manager")); #endif current_path = fpath; @@ -3453,16 +3465,16 @@ void FileSystemDock::_tree_empty_click(const Vector2 &p_pos, MouseButton p_butto current_path = "res://"; tree_popup->clear(); tree_popup->reset_size(); - tree_popup->add_icon_item(get_editor_theme_icon(SNAME("Folder")), TTRC("New Folder..."), FILE_NEW_FOLDER); - tree_popup->add_icon_item(get_editor_theme_icon(SNAME("PackedScene")), TTRC("New Scene..."), FILE_NEW_SCENE); - tree_popup->add_icon_item(get_editor_theme_icon(SNAME("Script")), TTRC("New Script..."), FILE_NEW_SCRIPT); - tree_popup->add_icon_item(get_editor_theme_icon(SNAME("Object")), TTRC("New Resource..."), FILE_NEW_RESOURCE); - tree_popup->add_icon_item(get_editor_theme_icon(SNAME("TextFile")), TTRC("New TextFile..."), FILE_NEW_TEXTFILE); + tree_popup->add_icon_item(get_editor_theme_icon(SNAME("Folder")), TTRC("New Folder..."), FILE_MENU_NEW_FOLDER); + tree_popup->add_icon_item(get_editor_theme_icon(SNAME("PackedScene")), TTRC("New Scene..."), FILE_MENU_NEW_SCENE); + tree_popup->add_icon_item(get_editor_theme_icon(SNAME("Script")), TTRC("New Script..."), FILE_MENU_NEW_SCRIPT); + tree_popup->add_icon_item(get_editor_theme_icon(SNAME("Object")), TTRC("New Resource..."), FILE_MENU_NEW_RESOURCE); + tree_popup->add_icon_item(get_editor_theme_icon(SNAME("TextFile")), TTRC("New TextFile..."), FILE_MENU_NEW_TEXTFILE); #if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) // Opening the system file manager is not supported on the Android and web editors. tree_popup->add_separator(); - tree_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_OPEN_IN_TERMINAL); - tree_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); + tree_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_MENU_OPEN_IN_TERMINAL); + tree_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_MENU_SHOW_IN_EXPLORER); #endif tree_popup->set_position(tree->get_screen_position() + p_pos); @@ -3523,14 +3535,14 @@ void FileSystemDock::_file_list_empty_clicked(const Vector2 &p_pos, MouseButton file_list_popup->clear(); file_list_popup->reset_size(); - file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("Folder")), TTRC("New Folder..."), FILE_NEW_FOLDER); - file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("PackedScene")), TTRC("New Scene..."), FILE_NEW_SCENE); - file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("Script")), TTRC("New Script..."), FILE_NEW_SCRIPT); - file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("Object")), TTRC("New Resource..."), FILE_NEW_RESOURCE); - file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("TextFile")), TTRC("New TextFile..."), FILE_NEW_TEXTFILE); + file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("Folder")), TTRC("New Folder..."), FILE_MENU_NEW_FOLDER); + file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("PackedScene")), TTRC("New Scene..."), FILE_MENU_NEW_SCENE); + file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("Script")), TTRC("New Script..."), FILE_MENU_NEW_SCRIPT); + file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("Object")), TTRC("New Resource..."), FILE_MENU_NEW_RESOURCE); + file_list_popup->add_icon_item(get_editor_theme_icon(SNAME("TextFile")), TTRC("New TextFile..."), FILE_MENU_NEW_TEXTFILE); file_list_popup->add_separator(); - file_list_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_OPEN_IN_TERMINAL); - file_list_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); + file_list_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Terminal")), ED_GET_SHORTCUT("filesystem_dock/open_in_terminal"), FILE_MENU_OPEN_IN_TERMINAL); + file_list_popup->add_icon_shortcut(get_editor_theme_icon(SNAME("Filesystem")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_MENU_SHOW_IN_EXPLORER); file_list_popup->set_position(files->get_screen_position() + p_pos); file_list_popup->reset_size(); @@ -3631,23 +3643,23 @@ void FileSystemDock::_tree_gui_input(Ref p_event) { if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { - _tree_rmb_option(FILE_DUPLICATE); + _tree_rmb_option(FILE_MENU_DUPLICATE); } else if (ED_IS_SHORTCUT("filesystem_dock/copy_path", p_event)) { - _tree_rmb_option(FILE_COPY_PATH); + _tree_rmb_option(FILE_MENU_COPY_PATH); } else if (ED_IS_SHORTCUT("filesystem_dock/copy_absolute_path", p_event)) { - _tree_rmb_option(FILE_COPY_ABSOLUTE_PATH); + _tree_rmb_option(FILE_MENU_COPY_ABSOLUTE_PATH); } else if (ED_IS_SHORTCUT("filesystem_dock/copy_uid", p_event)) { - _tree_rmb_option(FILE_COPY_UID); + _tree_rmb_option(FILE_MENU_COPY_UID); } else if (ED_IS_SHORTCUT("filesystem_dock/delete", p_event)) { - _tree_rmb_option(FILE_REMOVE); + _tree_rmb_option(FILE_MENU_REMOVE); } else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) { - _tree_rmb_option(FILE_RENAME); + _tree_rmb_option(FILE_MENU_RENAME); } else if (ED_IS_SHORTCUT("filesystem_dock/show_in_explorer", p_event)) { - _tree_rmb_option(FILE_SHOW_IN_EXPLORER); + _tree_rmb_option(FILE_MENU_SHOW_IN_EXPLORER); } else if (ED_IS_SHORTCUT("filesystem_dock/open_in_external_program", p_event)) { - _tree_rmb_option(FILE_OPEN_EXTERNAL); + _tree_rmb_option(FILE_MENU_OPEN_EXTERNAL); } else if (ED_IS_SHORTCUT("filesystem_dock/open_in_terminal", p_event)) { - _tree_rmb_option(FILE_OPEN_IN_TERMINAL); + _tree_rmb_option(FILE_MENU_OPEN_IN_TERMINAL); } else if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) { focus_on_path(); } else if (ED_IS_SHORTCUT("editor/open_search", p_event)) { @@ -3714,19 +3726,19 @@ void FileSystemDock::_file_list_gui_input(Ref p_event) { Ref key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { - _file_list_rmb_option(FILE_DUPLICATE); + _file_list_rmb_option(FILE_MENU_DUPLICATE); } else if (ED_IS_SHORTCUT("filesystem_dock/copy_path", p_event)) { - _file_list_rmb_option(FILE_COPY_PATH); + _file_list_rmb_option(FILE_MENU_COPY_PATH); } else if (ED_IS_SHORTCUT("filesystem_dock/copy_absolute_path", p_event)) { - _file_list_rmb_option(FILE_COPY_ABSOLUTE_PATH); + _file_list_rmb_option(FILE_MENU_COPY_ABSOLUTE_PATH); } else if (ED_IS_SHORTCUT("filesystem_dock/delete", p_event)) { - _file_list_rmb_option(FILE_REMOVE); + _file_list_rmb_option(FILE_MENU_REMOVE); } else if (ED_IS_SHORTCUT("filesystem_dock/rename", p_event)) { - _file_list_rmb_option(FILE_RENAME); + _file_list_rmb_option(FILE_MENU_RENAME); } else if (ED_IS_SHORTCUT("filesystem_dock/show_in_explorer", p_event)) { - _file_list_rmb_option(FILE_SHOW_IN_EXPLORER); + _file_list_rmb_option(FILE_MENU_SHOW_IN_EXPLORER); } else if (ED_IS_SHORTCUT("filesystem_dock/open_in_terminal", p_event)) { - _file_list_rmb_option(FILE_OPEN_IN_TERMINAL); + _file_list_rmb_option(FILE_MENU_OPEN_IN_TERMINAL); } else if (ED_IS_SHORTCUT("editor/open_search", p_event)) { focus_on_filter(); } else { diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 41f8fd507e..51d791a4e6 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -103,34 +103,34 @@ public: private: enum FileMenu { - FILE_OPEN, - FILE_INHERIT, - FILE_MAIN_SCENE, - FILE_INSTANTIATE, - FILE_ADD_FAVORITE, - FILE_REMOVE_FAVORITE, - FILE_SHOW_IN_FILESYSTEM, - FILE_DEPENDENCIES, - FILE_OWNERS, - FILE_MOVE, - FILE_RENAME, - FILE_REMOVE, - FILE_DUPLICATE, - FILE_REIMPORT, - FILE_NEW, - FILE_SHOW_IN_EXPLORER, - FILE_OPEN_EXTERNAL, - FILE_OPEN_IN_TERMINAL, - FILE_COPY_PATH, - FILE_COPY_ABSOLUTE_PATH, - FILE_COPY_UID, - FOLDER_EXPAND_ALL, - FOLDER_COLLAPSE_ALL, - FILE_NEW_RESOURCE, - FILE_NEW_TEXTFILE, - FILE_NEW_FOLDER, - FILE_NEW_SCRIPT, - FILE_NEW_SCENE, + FILE_MENU_OPEN, + FILE_MENU_INHERIT, + FILE_MENU_MAIN_SCENE, + FILE_MENU_INSTANTIATE, + FILE_MENU_ADD_FAVORITE, + FILE_MENU_REMOVE_FAVORITE, + FILE_MENU_SHOW_IN_FILESYSTEM, + FILE_MENU_DEPENDENCIES, + FILE_MENU_OWNERS, + FILE_MENU_MOVE, + FILE_MENU_RENAME, + FILE_MENU_REMOVE, + FILE_MENU_DUPLICATE, + FILE_MENU_REIMPORT, + FILE_MENU_NEW, + FILE_MENU_SHOW_IN_EXPLORER, + FILE_MENU_OPEN_EXTERNAL, + FILE_MENU_OPEN_IN_TERMINAL, + FILE_MENU_COPY_PATH, + FILE_MENU_COPY_ABSOLUTE_PATH, + FILE_MENU_COPY_UID, + FILE_MENU_EXPAND_ALL, + FILE_MENU_COLLAPSE_ALL, + FILE_MENU_NEW_RESOURCE, + FILE_MENU_NEW_TEXTFILE, + FILE_MENU_NEW_FOLDER, + FILE_MENU_NEW_SCRIPT, + FILE_MENU_NEW_SCENE, CONVERT_BASE_ID = 1000, }; diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp index 81e1d2d2e2..c020be9c9a 100644 --- a/editor/gui/editor_file_dialog.cpp +++ b/editor/gui/editor_file_dialog.cpp @@ -53,12 +53,6 @@ #include "scene/gui/texture_rect.h" #include "servers/display_server.h" -EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func = nullptr; -EditorFileDialog::GetIconFunc EditorFileDialog::get_thumbnail_func = nullptr; - -EditorFileDialog::RegisterFunc EditorFileDialog::register_func = nullptr; -EditorFileDialog::RegisterFunc EditorFileDialog::unregister_func = nullptr; - void EditorFileDialog::_native_popup() { // Show native dialog directly. String root; @@ -1985,10 +1979,6 @@ void EditorFileDialog::_go_forward() { dir_next->set_disabled(local_history_pos == local_history.size() - 1); } -bool EditorFileDialog::default_show_hidden_files = false; - -EditorFileDialog::DisplayMode EditorFileDialog::default_display_mode = DISPLAY_THUMBNAILS; - void EditorFileDialog::set_display_mode(DisplayMode p_mode) { if (display_mode == p_mode) { return; diff --git a/editor/gui/editor_file_dialog.h b/editor/gui/editor_file_dialog.h index 9517ae8394..65d3eabb87 100644 --- a/editor/gui/editor_file_dialog.h +++ b/editor/gui/editor_file_dialog.h @@ -74,10 +74,10 @@ public: typedef Ref (*GetIconFunc)(const String &); typedef void (*RegisterFunc)(EditorFileDialog *); - static GetIconFunc get_icon_func; - static GetIconFunc get_thumbnail_func; - static RegisterFunc register_func; - static RegisterFunc unregister_func; + static inline GetIconFunc get_icon_func = nullptr; + static inline GetIconFunc get_thumbnail_func = nullptr; + static inline RegisterFunc register_func = nullptr; + static inline RegisterFunc unregister_func = nullptr; private: enum ItemMenu { @@ -161,8 +161,8 @@ private: int preview_wheel_index = 0; float preview_wheel_timeout = 0.0f; - static bool default_show_hidden_files; - static DisplayMode default_display_mode; + static inline bool default_show_hidden_files = false; + static inline DisplayMode default_display_mode = DISPLAY_THUMBNAILS; bool show_hidden_files; DisplayMode display_mode; diff --git a/editor/gui/editor_quick_open_dialog.cpp b/editor/gui/editor_quick_open_dialog.cpp index 15782266c3..cc589545ad 100644 --- a/editor/gui/editor_quick_open_dialog.cpp +++ b/editor/gui/editor_quick_open_dialog.cpp @@ -350,8 +350,7 @@ void QuickOpenResultContainer::init(const Vector &p_base_types) { file_type_icons.insert(SNAME("__default_icon"), get_editor_theme_icon(SNAME("Object"))); bool history_modified = false; - List history_keys; - history_file->get_section_keys("selected_history", &history_keys); + Vector history_keys = history_file->get_section_keys("selected_history"); for (const String &type : history_keys) { const StringName type_name = type; const PackedStringArray paths = history_file->get_value("selected_history", type); @@ -791,10 +790,10 @@ String QuickOpenResultContainer::get_selected() const { QuickOpenDisplayMode QuickOpenResultContainer::get_adaptive_display_mode(const Vector &p_base_types) { static const Vector grid_preferred_types = { - "Font", - "Texture2D", - "Material", - "Mesh" + StringName("Font", true), + StringName("Texture2D", true), + StringName("Material", true), + StringName("Mesh", true), }; for (const StringName &type : grid_preferred_types) { diff --git a/editor/gui/editor_scene_tabs.cpp b/editor/gui/editor_scene_tabs.cpp index c8873a2685..75bdad23a3 100644 --- a/editor/gui/editor_scene_tabs.cpp +++ b/editor/gui/editor_scene_tabs.cpp @@ -133,7 +133,7 @@ void EditorSceneTabs::_scene_tab_input(const Ref &p_input) { } if ((is_layout_rtl() && mb->get_position().x > tab_buttons) || (!is_layout_rtl() && mb->get_position().x < scene_tabs->get_size().width - tab_buttons)) { - EditorNode::get_singleton()->trigger_menu_option(EditorNode::FILE_NEW_SCENE, true); + EditorNode::get_singleton()->trigger_menu_option(EditorNode::SCENE_NEW_SCENE, true); } } if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { @@ -175,11 +175,11 @@ void EditorSceneTabs::_update_context_menu() { int tab_id = scene_tabs->get_hovered_tab(); bool no_root_node = !EditorNode::get_editor_data().get_edited_scene_root(tab_id); - scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), EditorNode::FILE_NEW_SCENE); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), EditorNode::SCENE_NEW_SCENE); if (tab_id >= 0) { - scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), EditorNode::FILE_SAVE_SCENE); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), EditorNode::SCENE_SAVE_SCENE); DISABLE_LAST_OPTION_IF(no_root_node); - scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), EditorNode::FILE_SAVE_AS_SCENE); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), EditorNode::SCENE_SAVE_AS_SCENE); DISABLE_LAST_OPTION_IF(no_root_node); } @@ -190,7 +190,7 @@ void EditorSceneTabs::_update_context_menu() { break; } } - scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), EditorNode::FILE_SAVE_ALL_SCENES); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), EditorNode::SCENE_SAVE_ALL_SCENES); DISABLE_LAST_OPTION_IF(!can_save_all_scenes); if (tab_id >= 0) { @@ -201,9 +201,9 @@ void EditorSceneTabs::_update_context_menu() { DISABLE_LAST_OPTION_IF(no_root_node); scene_tabs_context_menu->add_separator(); - scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_scene"), EditorNode::FILE_CLOSE); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_scene"), EditorNode::SCENE_CLOSE); scene_tabs_context_menu->set_item_text(-1, TTR("Close Tab")); - scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/reopen_closed_scene"), EditorNode::FILE_OPEN_PREV); + scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/reopen_closed_scene"), EditorNode::SCENE_OPEN_PREV); scene_tabs_context_menu->set_item_text(-1, TTR("Undo Close Tab")); DISABLE_LAST_OPTION_IF(!EditorNode::get_singleton()->has_previous_closed_scenes()); scene_tabs_context_menu->add_item(TTR("Close Other Tabs"), SCENE_CLOSE_OTHERS); @@ -441,7 +441,7 @@ EditorSceneTabs::EditorSceneTabs() { scene_tab_add->set_tooltip_text(TTR("Add a new scene.")); scene_tab_add->set_accessibility_name(TTRC("Add Scene")); scene_tabs->add_child(scene_tab_add); - scene_tab_add->connect(SceneStringName(pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(EditorNode::FILE_NEW_SCENE, false)); + scene_tab_add->connect(SceneStringName(pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(EditorNode::SCENE_NEW_SCENE, false)); scene_tab_add_ph = memnew(Control); scene_tab_add_ph->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); diff --git a/editor/gui/editor_spin_slider.cpp b/editor/gui/editor_spin_slider.cpp index 7fbcbf248d..394fb51bfd 100644 --- a/editor/gui/editor_spin_slider.cpp +++ b/editor/gui/editor_spin_slider.cpp @@ -248,7 +248,7 @@ void EditorSpinSlider::_value_input_gui_input(const Ref &p_event) { if (step < 1) { double divisor = 1.0 / step; - if (trunc(divisor) == divisor) { + if (std::trunc(divisor) == divisor) { step = 1.0; } } diff --git a/editor/import/3d/editor_import_collada.cpp b/editor/import/3d/editor_import_collada.cpp index bd3d09a9cc..ea330f4ebd 100644 --- a/editor/import/3d/editor_import_collada.cpp +++ b/editor/import/3d/editor_import_collada.cpp @@ -1022,7 +1022,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref &p Vector tangents = d[Mesh::ARRAY_TANGENT]; for (int vert = 0; vert < normals.size(); vert++) { Vector3 tan = Vector3(tangents[vert * 4 + 0], tangents[vert * 4 + 1], tangents[vert * 4 + 2]); - if (abs(tan.dot(normals[vert])) > 0.0001) { + if (std::abs(tan.dot(normals[vert])) > 0.0001) { // Tangent is not perpendicular to the normal, so we can't use compression. mesh_flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES; } diff --git a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp index d9ab8c71c0..cc7f712522 100644 --- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp @@ -374,7 +374,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory if (Math::abs(Math::rad_to_deg(src_dir.angle_to(prof_dir))) > float(p_options["retarget/rest_fixer/fix_silhouette/threshold"])) { // Get rotation difference. Vector3 up_vec; // Need to rotate other than roll axis. - switch (Vector3(abs(src_dir.x), abs(src_dir.y), abs(src_dir.z)).min_axis_index()) { + switch (Vector3(std::abs(src_dir.x), std::abs(src_dir.y), std::abs(src_dir.z)).min_axis_index()) { case Vector3::AXIS_X: { up_vec = Vector3(1, 0, 0); } break; @@ -467,7 +467,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory if (bool(p_options["retarget/rest_fixer/normalize_position_tracks"])) { int src_bone_idx = src_skeleton->find_bone(profile->get_scale_base_bone()); if (src_bone_idx >= 0) { - real_t motion_scale = abs(src_skeleton->get_bone_global_rest(src_bone_idx).origin.y); + real_t motion_scale = std::abs(src_skeleton->get_bone_global_rest(src_bone_idx).origin.y); if (motion_scale > 0) { src_skeleton->set_motion_scale(motion_scale); } diff --git a/editor/import/3d/resource_importer_obj.cpp b/editor/import/3d/resource_importer_obj.cpp index 3a092341e1..9e32de00d3 100644 --- a/editor/import/3d/resource_importer_obj.cpp +++ b/editor/import/3d/resource_importer_obj.cpp @@ -434,7 +434,7 @@ static Error _parse_obj(const String &p_path, List> &r_meshes, ERR_FAIL_COND_V(tangents.is_empty(), ERR_FILE_CORRUPT); for (int vert = 0; vert < norms.size(); vert++) { Vector3 tan = Vector3(tangents[vert * 4 + 0], tangents[vert * 4 + 1], tangents[vert * 4 + 2]); - if (abs(tan.dot(norms[vert])) > 0.0001) { + if (std::abs(tan.dot(norms[vert])) > 0.0001) { // Tangent is not perpendicular to the normal, so we can't use compression. mesh_flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES; } diff --git a/editor/import/3d/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp index e444a1fd82..7a9c75d080 100644 --- a/editor/import/3d/scene_import_settings.cpp +++ b/editor/import/3d/scene_import_settings.cpp @@ -757,8 +757,7 @@ void SceneImportSettingsDialog::open_settings(const String &p_path, const String config.instantiate(); Error err = config->load(p_path + ".import"); if (err == OK) { - List keys; - config->get_section_keys("params", &keys); + Vector keys = config->get_section_keys("params"); for (const String &E : keys) { Variant value = config->get_value("params", E); if (E == "_subresources") { diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp index 3b2ac61b77..ac88e2292d 100644 --- a/editor/import/audio_stream_import_settings.cpp +++ b/editor/import/audio_stream_import_settings.cpp @@ -442,8 +442,7 @@ void AudioStreamImportSettingsDialog::edit(const String &p_path, const String &p loop_offset->set_value(config_file->get_value("params", "loop_offset", 0)); bar_beats_edit->set_value(config_file->get_value("params", "bar_beats", 4)); - List keys; - config_file->get_section_keys("params", &keys); + Vector keys = config_file->get_section_keys("params"); for (const String &K : keys) { params[K] = config_file->get_value("params", K); } diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 74ec055c46..be1daa84fb 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -1119,7 +1119,7 @@ void DynamicFontImportSettingsDialog::open_settings(const String &p_path) { for (int i = 0; i < contours.size(); i++) { for (int j = prev_start; j <= contours[i]; j++) { int next_point = (j < contours[i]) ? (j + 1) : prev_start; - if ((points[j].z != TextServer::CONTOUR_CURVE_TAG_ON) || (!Math::is_equal_approx(points[j].x, points[next_point].x) && !Math::is_equal_approx(points[j].y, points[next_point].y))) { + if ((points[j].z != (real_t)TextServer::CONTOUR_CURVE_TAG_ON) || (!Math::is_equal_approx(points[j].x, points[next_point].x) && !Math::is_equal_approx(points[j].y, points[next_point].y))) { is_pixel = false; break; } @@ -1203,8 +1203,7 @@ void DynamicFontImportSettingsDialog::open_settings(const String &p_path) { Error err = config->load(p_path + ".import"); print_verbose("Loading import settings:"); if (err == OK) { - List keys; - config->get_section_keys("params", &keys); + Vector keys = config->get_section_keys("params"); for (const String &key : keys) { print_verbose(String(" ") + key + " == " + String(config->get_value("params", key))); if (key == "preload") { diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index 6f37c3f6dc..f0fbb04974 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -193,7 +193,7 @@ Error ResourceImporterDynamicFont::import(ResourceUID::ID p_source_id, const Str for (int i = 0; i < contours.size(); i++) { for (int j = prev_start; j <= contours[i]; j++) { int next_point = (j < contours[i]) ? (j + 1) : prev_start; - if ((points[j].z != TextServer::CONTOUR_CURVE_TAG_ON) || (!Math::is_equal_approx(points[j].x, points[next_point].x) && !Math::is_equal_approx(points[j].y, points[next_point].y))) { + if ((points[j].z != (real_t)TextServer::CONTOUR_CURVE_TAG_ON) || (!Math::is_equal_approx(points[j].x, points[next_point].x) && !Math::is_equal_approx(points[j].y, points[next_point].y))) { is_pixel = false; break; } diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index cc5986d3b3..08c84b4340 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -192,8 +192,7 @@ void ImportDock::_update_options(const String &p_path, const Ref &p_ HashMap import_options; if (p_config.is_valid() && p_config->has_section("params")) { - List section_keys; - p_config->get_section_keys("params", §ion_keys); + Vector section_keys = p_config->get_section_keys("params"); for (const String §ion_key : section_keys) { import_options[section_key] = p_config->get_value("params", section_key); } @@ -260,8 +259,7 @@ void ImportDock::set_edit_multiple_paths(const Vector &p_paths) { continue; } - List keys; - config->get_section_keys("params", &keys); + Vector keys = config->get_section_keys("params"); for (const String &E : keys) { if (!value_frequency.has(E)) { diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index b78574940c..7198217a16 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -141,8 +141,7 @@ void AnimationNodeBlendTreeEditor::update_graph() { animations.clear(); - List nodes; - blend_tree->get_node_list(&nodes); + LocalVector nodes = blend_tree->get_node_list(); for (const StringName &E : nodes) { GraphNode *node = memnew(GraphNode); @@ -1026,6 +1025,11 @@ void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) { if (updating) { return; } + + if (blend_tree.is_null()) { + return; + } + updating = true; blend_tree->set_graph_offset(p_scroll / EDSCALE); updating = false; diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp index 14f3216713..34ca083341 100644 --- a/editor/plugins/animation_library_editor.cpp +++ b/editor/plugins/animation_library_editor.cpp @@ -891,8 +891,7 @@ Vector AnimationLibraryEditor::_load_mixer_libs_folding() { //The scene/mixer combination is no longer valid and we'll try to recover uint64_t current_mixer_id = uint64_t(mixer->get_instance_id()); String current_mixer_signature = _get_mixer_signature(); - List sections; - config->get_sections(§ions); + Vector sections = config->get_sections(); for (const String §ion : sections) { Variant mixer_id = config->get_value(section, "mixer"); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 235491042d..46d7f32658 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -450,8 +450,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Refget_node_position(selected_node) + drag_ofs / EDSCALE; - List nodes; - state_machine->get_node_list(&nodes); + LocalVector nodes = state_machine->get_node_list(); float best_d_x = 1e20; float best_d_y = 1e20; @@ -663,8 +662,7 @@ void AnimationNodeStateMachineEditor::_open_menu(const Vector2 &p_position) { bool AnimationNodeStateMachineEditor::_create_submenu(PopupMenu *p_menu, Ref p_nodesm, const StringName &p_name, const StringName &p_path) { String prev_path; - List nodes; - p_nodesm->get_node_list(&nodes); + LocalVector nodes = p_nodesm->get_node_list(); PopupMenu *nodes_menu = memnew(PopupMenu); nodes_menu->set_name(p_name); @@ -963,8 +961,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { } int sep = 3 * EDSCALE; - List nodes; - state_machine->get_node_list(&nodes); + LocalVector nodes = state_machine->get_node_list(); node_rects.clear(); Rect2 scroll_range; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 1c789ffa13..7012179702 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -344,7 +344,7 @@ void CanvasItemEditor::_snap_other_nodes( if (ci && !exception) { Transform2D ci_transform = ci->get_screen_transform(); - if (fmod(ci_transform.get_rotation() - p_transform_to_snap.get_rotation(), (real_t)360.0) == 0.0) { + if (std::fmod(ci_transform.get_rotation() - p_transform_to_snap.get_rotation(), (real_t)360.0) == 0.0) { if (ci->_edit_use_rect()) { Point2 begin = ci_transform.xform(ci->_edit_get_rect().get_position()); Point2 end = ci_transform.xform(ci->_edit_get_rect().get_position() + ci->_edit_get_rect().get_size()); @@ -449,7 +449,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig get_tree()->get_edited_scene_root()); } - if (((is_snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, (real_t)360.0) == 0.0) { + if (((is_snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && std::fmod(rotation, (real_t)360.0) == 0.0) { // Guides. if (Node *scene = EditorNode::get_singleton()->get_edited_scene()) { Array vguides = scene->get_meta("_edit_vertical_guides_", Array()); @@ -464,7 +464,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig } } - if (((grid_snap_active && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, (real_t)360.0) == 0.0) { + if (((grid_snap_active && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && std::fmod(rotation, (real_t)360.0) == 0.0) { // Grid Point2 offset = grid_offset; if (snap_relative) { @@ -3163,8 +3163,8 @@ void CanvasItemEditor::_draw_grid() { if (snap_relative && selection.size() > 0) { const Vector2 topleft = _get_encompassing_rect_from_list(selection).position; - real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier)); - real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier)); + real_grid_offset.x = std::fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier)); + real_grid_offset.y = std::fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier)); } else { real_grid_offset = grid_offset; } @@ -3309,8 +3309,8 @@ void CanvasItemEditor::_draw_ruler_tool() { viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); if (draw_secondary_lines) { - const int horizontal_angle = round(180 * horizontal_angle_rad / Math::PI); - const int vertical_angle = round(180 * vertical_angle_rad / Math::PI); + const int horizontal_angle = std::round(180 * horizontal_angle_rad / Math::PI); + const int vertical_angle = std::round(180 * vertical_angle_rad / Math::PI); Point2 text_pos2 = text_pos; text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2); @@ -3358,16 +3358,16 @@ void CanvasItemEditor::_draw_ruler_tool() { Point2 text_pos2 = text_pos; text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2); - viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); - viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); + viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); text_pos2 = text_pos; text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2); - viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); - viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); + viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); } else { - viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); - viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); + viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), std::round((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), std::round((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); } } } else { @@ -3467,7 +3467,7 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) { Vector2 line_starts[4]; Vector2 line_ends[4]; for (int i = 0; i < 4; i++) { - real_t anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i]; + real_t anchor_val = (i >= 2) ? (real_t)ANCHOR_END - anchors_values[i] : anchors_values[i]; line_starts[i] = corners_pos[i].lerp(corners_pos[(i + 1) % 4], anchor_val); line_ends[i] = corners_pos[(i + 3) % 4].lerp(corners_pos[(i + 2) % 4], anchor_val); bool anchor_snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0; @@ -3485,11 +3485,11 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) { _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 3) % 4]) / 2, (Side)(dragged_anchor)); percent_val = anchors_values[(dragged_anchor + 1) % 4]; - percent_val = ((dragged_anchor + 1) % 4 >= 2) ? ANCHOR_END - percent_val : percent_val; + percent_val = ((dragged_anchor + 1) % 4 >= 2) ? (real_t)ANCHOR_END - percent_val : percent_val; _draw_percentage_at_position(percent_val, (line_starts[dragged_anchor] + anchors_pos[dragged_anchor]) / 2, (Side)(dragged_anchor)); percent_val = anchors_values[dragged_anchor]; - percent_val = (dragged_anchor >= 2) ? ANCHOR_END - percent_val : percent_val; + percent_val = (dragged_anchor >= 2) ? (real_t)ANCHOR_END - percent_val : percent_val; _draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Side)((dragged_anchor + 1) % 4)); } diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index d944c56cca..de1eccd16b 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -33,13 +33,17 @@ #include "control_editor_plugin.h" #include "editor/editor_node.h" -#include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/themes/editor_scale.h" +#include "scene/gui/button.h" +#include "scene/gui/check_box.h" #include "scene/gui/check_button.h" #include "scene/gui/grid_container.h" +#include "scene/gui/option_button.h" +#include "scene/gui/panel_container.h" #include "scene/gui/separator.h" +#include "scene/gui/texture_rect.h" // Inspector controls. @@ -162,6 +166,41 @@ void EditorPropertyAnchorsPreset::_set_read_only(bool p_read_only) { options->set_disabled(p_read_only); } +void EditorPropertyAnchorsPreset::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + for (int i = 0; i < options->get_item_count(); i++) { + if (options->is_item_separator(i)) { + continue; + } + int64_t preset = options->get_item_metadata(i); + if (preset < 0 || PRESET_FULL_RECT < preset) { + continue; + } + static const StringName icon_names[] = { + StringName("ControlAlignTopLeft", true), + StringName("ControlAlignTopRight", true), + StringName("ControlAlignBottomLeft", true), + StringName("ControlAlignBottomRight", true), + StringName("ControlAlignCenterLeft", true), + StringName("ControlAlignCenterTop", true), + StringName("ControlAlignCenterRight", true), + StringName("ControlAlignCenterBottom", true), + StringName("ControlAlignCenter", true), + StringName("ControlAlignLeftWide", true), + StringName("ControlAlignTopWide", true), + StringName("ControlAlignRightWide", true), + StringName("ControlAlignBottomWide", true), + StringName("ControlAlignVCenterWide", true), + StringName("ControlAlignHCenterWide", true), + StringName("ControlAlignFullRect", true), + }; + options->set_item_icon(i, get_editor_theme_icon(icon_names[preset])); + } + } break; + } +} + void EditorPropertyAnchorsPreset::_option_selected(int p_which) { int64_t val = options->get_item_metadata(p_which); emit_changed(get_edited_property(), val); @@ -182,30 +221,22 @@ void EditorPropertyAnchorsPreset::update_property() { void EditorPropertyAnchorsPreset::setup(const Vector &p_options) { options->clear(); - Vector split_after; - split_after.append("Custom"); - split_after.append("PresetFullRect"); - split_after.append("PresetBottomLeft"); - split_after.append("PresetCenter"); + const Vector split_after = { + -1, + PRESET_FULL_RECT, + PRESET_BOTTOM_LEFT, + PRESET_CENTER, + }; - for (int i = 0, j = 0; i < p_options.size(); i++, j++) { + for (int i = 0; i < p_options.size(); i++) { Vector text_split = p_options[i].split(":"); int64_t current_val = text_split[1].to_int(); const String &option_name = text_split[0]; - if (option_name.begins_with("Preset")) { - String preset_name = option_name.trim_prefix("Preset"); - String humanized_name = preset_name.capitalize(); - String icon_name = "ControlAlign" + preset_name; - options->add_icon_item(EditorNode::get_singleton()->get_editor_theme()->get_icon(icon_name, EditorStringName(EditorIcons)), humanized_name); - } else { - options->add_item(option_name); - } - - options->set_item_metadata(j, current_val); - if (split_after.has(option_name)) { + options->add_item(option_name); + options->set_item_metadata(-1, current_val); + if (split_after.has(current_val)) { options->add_separator(); - j++; } } } @@ -615,33 +646,33 @@ AnchorPresetPicker::AnchorPresetPicker() { top_row->add_theme_constant_override("separation", grid_separation); main_vb->add_child(top_row); - _add_row_button(top_row, PRESET_TOP_LEFT, TTR("Top Left")); - _add_row_button(top_row, PRESET_CENTER_TOP, TTR("Center Top")); - _add_row_button(top_row, PRESET_TOP_RIGHT, TTR("Top Right")); + _add_row_button(top_row, PRESET_TOP_LEFT, TTRC("Top Left")); + _add_row_button(top_row, PRESET_CENTER_TOP, TTRC("Center Top")); + _add_row_button(top_row, PRESET_TOP_RIGHT, TTRC("Top Right")); _add_separator(top_row, memnew(VSeparator)); - _add_row_button(top_row, PRESET_TOP_WIDE, TTR("Top Wide")); + _add_row_button(top_row, PRESET_TOP_WIDE, TTRC("Top Wide")); HBoxContainer *mid_row = memnew(HBoxContainer); mid_row->set_alignment(BoxContainer::ALIGNMENT_CENTER); mid_row->add_theme_constant_override("separation", grid_separation); main_vb->add_child(mid_row); - _add_row_button(mid_row, PRESET_CENTER_LEFT, TTR("Center Left")); - _add_row_button(mid_row, PRESET_CENTER, TTR("Center")); - _add_row_button(mid_row, PRESET_CENTER_RIGHT, TTR("Center Right")); + _add_row_button(mid_row, PRESET_CENTER_LEFT, TTRC("Center Left")); + _add_row_button(mid_row, PRESET_CENTER, TTRC("Center")); + _add_row_button(mid_row, PRESET_CENTER_RIGHT, TTRC("Center Right")); _add_separator(mid_row, memnew(VSeparator)); - _add_row_button(mid_row, PRESET_HCENTER_WIDE, TTR("HCenter Wide")); + _add_row_button(mid_row, PRESET_HCENTER_WIDE, TTRC("HCenter Wide")); HBoxContainer *bot_row = memnew(HBoxContainer); bot_row->set_alignment(BoxContainer::ALIGNMENT_CENTER); bot_row->add_theme_constant_override("separation", grid_separation); main_vb->add_child(bot_row); - _add_row_button(bot_row, PRESET_BOTTOM_LEFT, TTR("Bottom Left")); - _add_row_button(bot_row, PRESET_CENTER_BOTTOM, TTR("Center Bottom")); - _add_row_button(bot_row, PRESET_BOTTOM_RIGHT, TTR("Bottom Right")); + _add_row_button(bot_row, PRESET_BOTTOM_LEFT, TTRC("Bottom Left")); + _add_row_button(bot_row, PRESET_CENTER_BOTTOM, TTRC("Center Bottom")); + _add_row_button(bot_row, PRESET_BOTTOM_RIGHT, TTRC("Bottom Right")); _add_separator(bot_row, memnew(VSeparator)); - _add_row_button(bot_row, PRESET_BOTTOM_WIDE, TTR("Bottom Wide")); + _add_row_button(bot_row, PRESET_BOTTOM_WIDE, TTRC("Bottom Wide")); _add_separator(main_vb, memnew(HSeparator)); @@ -650,11 +681,11 @@ AnchorPresetPicker::AnchorPresetPicker() { extra_row->add_theme_constant_override("separation", grid_separation); main_vb->add_child(extra_row); - _add_row_button(extra_row, PRESET_LEFT_WIDE, TTR("Left Wide")); - _add_row_button(extra_row, PRESET_VCENTER_WIDE, TTR("VCenter Wide")); - _add_row_button(extra_row, PRESET_RIGHT_WIDE, TTR("Right Wide")); + _add_row_button(extra_row, PRESET_LEFT_WIDE, TTRC("Left Wide")); + _add_row_button(extra_row, PRESET_VCENTER_WIDE, TTRC("VCenter Wide")); + _add_row_button(extra_row, PRESET_RIGHT_WIDE, TTRC("Right Wide")); _add_separator(extra_row, memnew(VSeparator)); - _add_row_button(extra_row, PRESET_FULL_RECT, TTR("Full Rect")); + _add_row_button(extra_row, PRESET_FULL_RECT, TTRC("Full Rect")); } void SizeFlagPresetPicker::_preset_button_pressed(const int p_preset) { diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h index c6f913281c..2d98b84271 100644 --- a/editor/plugins/control_editor_plugin.h +++ b/editor/plugins/control_editor_plugin.h @@ -35,20 +35,17 @@ #include "editor/editor_inspector.h" #include "editor/plugins/editor_plugin.h" #include "scene/gui/box_container.h" -#include "scene/gui/button.h" -#include "scene/gui/check_box.h" -#include "scene/gui/control.h" -#include "scene/gui/label.h" #include "scene/gui/margin_container.h" -#include "scene/gui/option_button.h" -#include "scene/gui/panel_container.h" -#include "scene/gui/popup.h" -#include "scene/gui/separator.h" -#include "scene/gui/texture_rect.h" +class CheckBox; class CheckButton; class EditorSelection; class GridContainer; +class Label; +class OptionButton; +class PanelContainer; +class Separator; +class TextureRect; // Inspector controls. class ControlPositioningWarning : public MarginContainer { @@ -86,6 +83,7 @@ class EditorPropertyAnchorsPreset : public EditorProperty { protected: virtual void _set_read_only(bool p_read_only) override; + void _notification(int p_what); public: void setup(const Vector &p_options); diff --git a/editor/plugins/editor_context_menu_plugin.h b/editor/plugins/editor_context_menu_plugin.h index 8b0da32606..5af6192bce 100644 --- a/editor/plugins/editor_context_menu_plugin.h +++ b/editor/plugins/editor_context_menu_plugin.h @@ -45,7 +45,7 @@ class EditorContextMenuPlugin : public RefCounted { friend class EditorContextMenuPluginManager; - inline static constexpr int MAX_ITEMS = 100; + static constexpr int MAX_ITEMS = 100; public: enum ContextMenuSlot { @@ -57,7 +57,7 @@ public: CONTEXT_SLOT_SCENE_TABS, CONTEXT_SLOT_2D_EDITOR, }; - inline static constexpr int BASE_ID = 2000; + static constexpr int BASE_ID = 2000; private: int slot = -1; diff --git a/editor/plugins/editor_resource_tooltip_plugins.cpp b/editor/plugins/editor_resource_tooltip_plugins.cpp index 7b3ce5737b..21f9845713 100644 --- a/editor/plugins/editor_resource_tooltip_plugins.cpp +++ b/editor/plugins/editor_resource_tooltip_plugins.cpp @@ -140,7 +140,7 @@ Control *EditorAudioStreamTooltipPlugin::make_tooltip_for_path(const String &p_r double length = p_metadata.get("length", 0.0); if (length >= 60.0) { - vb->add_child(memnew(Label(vformat(TTR("Length: %0dm %0ds"), int(length / 60.0), int(fmod(length, 60)))))); + vb->add_child(memnew(Label(vformat(TTR("Length: %0dm %0ds"), int(length / 60.0), int(std::fmod(length, 60)))))); } else if (length >= 1.0) { vb->add_child(memnew(Label(vformat(TTR("Length: %0.1fs"), length)))); } else { diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp index bfc21577fe..e004098d2a 100644 --- a/editor/plugins/game_view_plugin.cpp +++ b/editor/plugins/game_view_plugin.cpp @@ -99,6 +99,12 @@ void GameViewDebugger::_session_started(Ref p_session) { mute_audio_data.append(mute_audio); p_session->send_message("scene:debug_mute_audio", mute_audio_data); + Dictionary shortcut_settings; + shortcut_settings["editor/suspend_resume_embedded_project"] = DebuggerMarshalls::serialize_key_shortcut(ED_GET_SHORTCUT("editor/suspend_resume_embedded_project")); + shortcut_settings["editor/next_frame_embedded_project"] = DebuggerMarshalls::serialize_key_shortcut(ED_GET_SHORTCUT("editor/next_frame_embedded_project")); + + p_session->send_message("scene:setup_embedded_shortcuts", { shortcut_settings }); + emit_signal(SNAME("session_started")); } @@ -421,6 +427,23 @@ void GameView::_update_debugger_buttons() { next_frame_button->set_disabled(!suspend_button->is_pressed()); } +void GameView::_handle_shortcut_requested(int p_embed_action) { + switch (p_embed_action) { + case ScriptEditorDebugger::EMBED_SUSPEND_TOGGLE: { + _toggle_suspend_button(); + } break; + case ScriptEditorDebugger::EMBED_NEXT_FRAME: { + debugger->next_frame(); + } break; + } +} + +void GameView::_toggle_suspend_button() { + const bool new_pressed = !suspend_button->is_pressed(); + suspend_button->set_pressed(new_pressed); + _suspend_button_toggled(new_pressed); +} + void GameView::_suspend_button_toggled(bool p_pressed) { _update_debugger_buttons(); @@ -775,12 +798,14 @@ void GameView::_attach_script_debugger() { if (embedded_script_debugger) { embedded_script_debugger->connect("remote_window_title_changed", callable_mp(this, &GameView::_remote_window_title_changed)); + embedded_script_debugger->connect("embed_shortcut_requested", callable_mp(this, &GameView::_handle_shortcut_requested)); } } void GameView::_detach_script_debugger() { if (embedded_script_debugger) { embedded_script_debugger->disconnect("remote_window_title_changed", callable_mp(this, &GameView::_remote_window_title_changed)); + embedded_script_debugger->disconnect("embed_shortcut_requested", callable_mp(this, &GameView::_handle_shortcut_requested)); embedded_script_debugger = nullptr; } } @@ -932,6 +957,9 @@ GameView::GameView(Ref p_debugger, WindowWrapper *p_wrapper) { suspend_button->connect(SceneStringName(toggled), callable_mp(this, &GameView::_suspend_button_toggled)); suspend_button->set_tooltip_text(TTR("Suspend")); suspend_button->set_accessibility_name(TTRC("Suspend")); + ED_SHORTCUT("editor/suspend_resume_embedded_project", TTRC("Suspend/Resume Embedded Project"), Key::F9); + ED_SHORTCUT_OVERRIDE("editor/suspend_resume_embedded_project", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::B); + suspend_button->set_shortcut(ED_GET_SHORTCUT("editor/suspend_resume_embedded_project")); next_frame_button = memnew(Button); main_menu_hbox->add_child(next_frame_button); @@ -939,6 +967,7 @@ GameView::GameView(Ref p_debugger, WindowWrapper *p_wrapper) { next_frame_button->connect(SceneStringName(pressed), callable_mp(*debugger, &GameViewDebugger::next_frame)); next_frame_button->set_tooltip_text(TTR("Next Frame")); next_frame_button->set_accessibility_name(TTRC("Next Frame")); + next_frame_button->set_shortcut(ED_SHORTCUT("editor/next_frame_embedded_project", TTRC("Next Frame"), Key::F10)); main_menu_hbox->add_child(memnew(VSeparator)); diff --git a/editor/plugins/game_view_plugin.h b/editor/plugins/game_view_plugin.h index f9b2c55c60..419f407365 100644 --- a/editor/plugins/game_view_plugin.h +++ b/editor/plugins/game_view_plugin.h @@ -163,6 +163,8 @@ class GameView : public VBoxContainer { void _update_debugger_buttons(); + void _handle_shortcut_requested(int p_embed_action); + void _toggle_suspend_button(); void _suspend_button_toggled(bool p_pressed); void _node_type_pressed(int p_option); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 9a9ca022b2..2e72bb9742 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2988,10 +2988,11 @@ void Node3DEditorViewport::_notification(int p_what) { if (_camera_moved_externally()) { // If camera moved after this plugin last set it, presumably a tool script has moved it, accept the new camera transform as the cursor position. _apply_camera_transform_to_cursor(); + _update_camera(0); + } else { + _update_camera(delta); } - _update_camera(delta); - const HashMap &selection = editor_selection->get_selection(); bool changed = false; @@ -3496,8 +3497,18 @@ bool Node3DEditorViewport::_camera_moved_externally() { void Node3DEditorViewport::_apply_camera_transform_to_cursor() { // Effectively the reverse of to_camera_transform, use camera transform to set cursor position and rotation. - Transform3D camera_transform = camera->get_camera_transform(); - cursor.pos = camera_transform.origin; + const Transform3D camera_transform = camera->get_camera_transform(); + const Basis basis = camera_transform.basis; + + real_t distance; + if (orthogonal) { + distance = (get_zfar() - get_znear()) / 2.0; + } else { + distance = cursor.distance; + } + + cursor.pos = camera_transform.origin - basis.get_column(2) * distance; + cursor.x_rot = -camera_transform.basis.get_euler().x; cursor.y_rot = -camera_transform.basis.get_euler().y; } diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 9496d16231..c854e457d0 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -183,14 +183,12 @@ class Node3DEditorViewport : public Control { }; public: - enum { - GIZMO_BASE_LAYER = 27, - GIZMO_EDIT_LAYER = 26, - GIZMO_GRID_LAYER = 25, - MISC_TOOL_LAYER = 24, + static constexpr int32_t GIZMO_BASE_LAYER = 27; + static constexpr int32_t GIZMO_EDIT_LAYER = 26; + static constexpr int32_t GIZMO_GRID_LAYER = 25; + static constexpr int32_t MISC_TOOL_LAYER = 24; - FRAME_TIME_HISTORY = 20, - }; + static constexpr int32_t FRAME_TIME_HISTORY = 20; enum NavigationScheme { NAVIGATION_GODOT = 0, diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 2180d0ae06..47dcb2b9b1 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -74,7 +74,7 @@ void ParticlesEditorPlugin::_notification(int p_what) { bool ParticlesEditorPlugin::need_show_lifetime_dialog(SpinBox *p_seconds) { // Add one second to the default generation lifetime, since the progress is updated every second. - p_seconds->set_value(MAX(1.0, trunc(edited_node->get("lifetime").operator double()) + 1.0)); + p_seconds->set_value(MAX(1.0, std::trunc(edited_node->get("lifetime").operator double()) + 1.0)); if (p_seconds->get_value() >= 11.0 + CMP_EPSILON) { // Only pop up the time dialog if the particle's lifetime is long enough to warrant shortening it. diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 85c2d027e5..a723177602 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -475,7 +475,7 @@ void Path3DGizmo::redraw() { const int n = 36; for (int i = 0; i <= n; i++) { const float a = Math::TAU * i / n; - const Vector3 edge = sin(a) * side + cos(a) * up; + const Vector3 edge = std::sin(a) * side + std::cos(a) * up; disk.append(pos + edge * disk_size); } add_vertices(disk, debug_material, Mesh::PRIMITIVE_LINE_STRIP); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index a478ab7005..82ffdaed47 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -332,67 +332,6 @@ void ScriptEditorBase::_bind_methods() { ADD_SIGNAL(MethodInfo("go_to_method", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::STRING, "method"))); } -class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache { - struct Cache { - uint64_t time_loaded = 0; - Ref cache; - }; - - HashMap cached; - -public: - uint64_t max_time_cache = 5 * 60 * 1000; //minutes, five - uint32_t max_cache_size = 128; - - void cleanup() { - List to_clean; - - HashMap::Iterator I = cached.begin(); - while (I) { - if ((OS::get_singleton()->get_ticks_msec() - I->value.time_loaded) > max_time_cache) { - to_clean.push_back(I->key); - } - ++I; - } - - while (to_clean.front()) { - cached.erase(to_clean.front()->get()); - to_clean.pop_front(); - } - } - - virtual Ref get_cached_resource(const String &p_path) { - HashMap::Iterator E = cached.find(p_path); - if (!E) { - Cache c; - c.cache = ResourceLoader::load(p_path); - E = cached.insert(p_path, c); - } - - E->value.time_loaded = OS::get_singleton()->get_ticks_msec(); - - if (cached.size() > max_cache_size) { - uint64_t older; - HashMap::Iterator O = cached.begin(); - older = O->value.time_loaded; - HashMap::Iterator I = O; - while (I) { - if (I->value.time_loaded < older) { - older = I->value.time_loaded; - O = I; - } - ++I; - } - - if (O != E) { //should never happen.. - cached.remove(O); - } - } - - return E->value.cache; - } -}; - void ScriptEditorQuickOpen::popup_dialog(const Vector &p_functions, bool p_dontclear) { popup_centered_ratio(0.6); if (p_dontclear) { @@ -632,8 +571,7 @@ void ScriptEditor::_clear_breakpoints() { } // Clear from closed scripts. - List cached_editors; - script_editor_cache->get_sections(&cached_editors); + Vector cached_editors = script_editor_cache->get_sections(); for (const String &E : cached_editors) { Array breakpoints = _get_cached_breakpoints_for_script(E); for (int breakpoint : breakpoints) { @@ -1019,6 +957,15 @@ void ScriptEditor::_close_other_tabs() { _queue_close_tabs(); } +void ScriptEditor::_close_tabs_below() { + int current_idx = tab_container->get_current_tab(); + for (int i = tab_container->get_tab_count() - 1; i > current_idx; i--) { + script_close_queue.push_back(i); + } + _go_to_tab(current_idx); + _queue_close_tabs(); +} + void ScriptEditor::_close_all_tabs() { for (int i = tab_container->get_tab_count() - 1; i >= 0; i--) { script_close_queue.push_back(i); @@ -1230,7 +1177,7 @@ bool ScriptEditor::_test_script_times_on_disk(Ref p_for_script) { void ScriptEditor::_file_dialog_action(const String &p_file) { switch (file_dialog_option) { - case FILE_NEW_TEXTFILE: { + case FILE_MENU_NEW_TEXTFILE: { Error err; { Ref file = FileAccess::open(p_file, FileAccess::WRITE, &err); @@ -1251,11 +1198,11 @@ void ScriptEditor::_file_dialog_action(const String &p_file) { } [[fallthrough]]; } - case FILE_OPEN: { + case FILE_MENU_OPEN: { open_file(p_file); file_dialog_option = -1; } break; - case FILE_SAVE_AS: { + case FILE_MENU_SAVE_AS: { ScriptEditorBase *current = _get_current_editor(); if (current) { Ref resource = current->get_edited_resource(); @@ -1319,14 +1266,14 @@ bool ScriptEditor::is_files_panel_toggled() { void ScriptEditor::_menu_option(int p_option) { ScriptEditorBase *current = _get_current_editor(); switch (p_option) { - case FILE_NEW: { + case FILE_MENU_NEW: { script_create_dialog->config("Node", "new_script", false, false); script_create_dialog->popup_centered(); } break; - case FILE_NEW_TEXTFILE: { + case FILE_MENU_NEW_TEXTFILE: { file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - file_dialog_option = FILE_NEW_TEXTFILE; + file_dialog_option = FILE_MENU_NEW_TEXTFILE; file_dialog->clear_filters(); for (const String &E : textfile_extensions) { @@ -1336,10 +1283,10 @@ void ScriptEditor::_menu_option(int p_option) { file_dialog->popup_file_dialog(); open_textfile_after_create = true; } break; - case FILE_OPEN: { + case FILE_MENU_OPEN: { file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - file_dialog_option = FILE_OPEN; + file_dialog_option = FILE_MENU_OPEN; List extensions; ResourceLoader::get_recognized_extensions_for_type("Script", &extensions); @@ -1356,7 +1303,7 @@ void ScriptEditor::_menu_option(int p_option) { file_dialog->popup_file_dialog(); return; } break; - case FILE_REOPEN_CLOSED: { + case FILE_MENU_REOPEN_CLOSED: { if (previous_scripts.is_empty()) { return; } @@ -1397,7 +1344,7 @@ void ScriptEditor::_menu_option(int p_option) { } } } break; - case FILE_SAVE_ALL: { + case FILE_MENU_SAVE_ALL: { if (_test_script_times_on_disk()) { return; } @@ -1430,17 +1377,17 @@ void ScriptEditor::_menu_option(int p_option) { OS::get_singleton()->shell_open(REDOT_VERSION_DOCS_URL "/"); } } break; - case WINDOW_NEXT: { + case FILE_MENU_HISTORY_NEXT: { _history_forward(); } break; - case WINDOW_PREV: { + case FILE_MENU_HISTORY_PREV: { _history_back(); } break; - case WINDOW_SORT: { + case FILE_MENU_SORT: { _sort_list_on_update = true; _update_script_names(); } break; - case TOGGLE_FILES_PANEL: { + case FILE_MENU_TOGGLE_FILES_PANEL: { toggle_files_panel(); if (current) { current->update_toggle_files_button(); @@ -1465,10 +1412,10 @@ void ScriptEditor::_menu_option(int p_option) { if (current) { switch (p_option) { - case FILE_SAVE: { + case FILE_MENU_SAVE: { save_current_script(); } break; - case FILE_SAVE_AS: { + case FILE_MENU_SAVE_AS: { if (trim_trailing_whitespace_on_save) { current->trim_trailing_whitespace(); } @@ -1488,7 +1435,7 @@ void ScriptEditor::_menu_option(int p_option) { if (text_file.is_valid()) { file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - file_dialog_option = FILE_SAVE_AS; + file_dialog_option = FILE_MENU_SAVE_AS; List extensions; ResourceLoader::get_recognized_extensions_for_type("Script", &extensions); @@ -1512,7 +1459,7 @@ void ScriptEditor::_menu_option(int p_option) { } } break; - case FILE_TOOL_RELOAD_SOFT: { + case FILE_MENU_SOFT_RELOAD_TOOL: { Ref