From b173008c23e2e80ea5f3a0961291b2e2957c0bb8 Mon Sep 17 00:00:00 2001 From: David Hover Date: Sun, 2 Jul 2023 18:38:47 -0400 Subject: [PATCH] Add application/config/enable_uids project setting --- core/config/project_settings.cpp | 1 + core/io/resource_uid.cpp | 70 ++++++++++++++++++++++-- core/io/resource_uid.h | 4 ++ core/register_core_types.cpp | 6 -- doc/classes/ProjectSettings.xml | 7 +++ doc/classes/ResourceUID.xml | 7 +++ editor/editor_file_system.cpp | 16 ++++-- main/main.cpp | 13 +++++ scene/resources/resource_format_text.cpp | 8 ++- 9 files changed, 112 insertions(+), 20 deletions(-) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 1bfb7456627b..607701359bc9 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1289,6 +1289,7 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("application/config/use_custom_user_dir", false); GLOBAL_DEF("application/config/custom_user_dir_name", ""); GLOBAL_DEF("application/config/project_settings_override", ""); + GLOBAL_DEF_RST("application/config/enable_uids", true); GLOBAL_DEF("application/run/main_loop_type", "SceneTree"); GLOBAL_DEF("application/config/auto_accept_quit", true); diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp index 216fc24fffac..8cd22cc16dbb 100644 --- a/core/io/resource_uid.cpp +++ b/core/io/resource_uid.cpp @@ -39,10 +39,18 @@ static constexpr uint32_t char_count = ('z' - 'a'); static constexpr uint32_t base = char_count + ('9' - '0'); String ResourceUID::get_cache_file() { - return ProjectSettings::get_singleton()->get_project_data_path().path_join("uid_cache.bin"); + return ResourceUID::get_singleton()->is_dummy() ? "" : ProjectSettings::get_singleton()->get_project_data_path().path_join("uid_cache.bin"); +} + +bool ResourceUID::is_dummy() const { + return _is_dummy; } String ResourceUID::id_to_text(ID p_id) const { + if (_is_dummy) { + return ""; + } + if (p_id < 0) { return "uid://"; } @@ -62,7 +70,7 @@ String ResourceUID::id_to_text(ID p_id) const { } ResourceUID::ID ResourceUID::text_to_id(const String &p_text) const { - if (!p_text.begins_with("uid://") || p_text == "uid://") { + if (_is_dummy || !p_text.begins_with("uid://") || p_text == "uid://") { return INVALID_ID; } @@ -83,6 +91,10 @@ ResourceUID::ID ResourceUID::text_to_id(const String &p_text) const { } ResourceUID::ID ResourceUID::create_id() { + if (_is_dummy) { + return INVALID_ID; + } + while (true) { ID id = INVALID_ID; MutexLock lock(mutex); @@ -97,10 +109,18 @@ ResourceUID::ID ResourceUID::create_id() { } bool ResourceUID::has_id(ID p_id) const { + if (_is_dummy) { + return false; + } + MutexLock l(mutex); return unique_ids.has(p_id); } void ResourceUID::add_id(ID p_id, const String &p_path) { + if (_is_dummy) { + return; + } + MutexLock l(mutex); ERR_FAIL_COND(unique_ids.has(p_id)); Cache c; @@ -110,6 +130,10 @@ void ResourceUID::add_id(ID p_id, const String &p_path) { } void ResourceUID::set_id(ID p_id, const String &p_path) { + if (_is_dummy) { + return; + } + MutexLock l(mutex); ERR_FAIL_COND(!unique_ids.has(p_id)); CharString cs = p_path.utf8(); @@ -126,18 +150,30 @@ void ResourceUID::set_id(ID p_id, const String &p_path) { } String ResourceUID::get_id_path(ID p_id) const { + if (_is_dummy) { + return ""; + } + MutexLock l(mutex); ERR_FAIL_COND_V(!unique_ids.has(p_id), String()); const CharString &cs = unique_ids[p_id].cs; return String::utf8(cs.ptr()); } void ResourceUID::remove_id(ID p_id) { + if (_is_dummy) { + return; + } + MutexLock l(mutex); ERR_FAIL_COND(!unique_ids.has(p_id)); unique_ids.erase(p_id); } Error ResourceUID::save_to_cache() { + if (_is_dummy) { + return OK; + } + String cache_file = get_cache_file(); if (!FileAccess::exists(cache_file)) { Ref d = DirAccess::create(DirAccess::ACCESS_RESOURCES); @@ -168,6 +204,10 @@ Error ResourceUID::save_to_cache() { } Error ResourceUID::load_from_cache() { + if (_is_dummy) { + return OK; + } + Ref f = FileAccess::open(get_cache_file(), FileAccess::READ); if (f.is_null()) { return ERR_CANT_OPEN; @@ -197,7 +237,7 @@ Error ResourceUID::load_from_cache() { } Error ResourceUID::update_cache() { - if (!changed) { + if (_is_dummy || !changed) { return OK; } @@ -236,11 +276,17 @@ Error ResourceUID::update_cache() { } void ResourceUID::clear() { + if (_is_dummy) { + return; + } + cache_entries = 0; unique_ids.clear(); changed = false; } void ResourceUID::_bind_methods() { + ClassDB::bind_method(D_METHOD("is_dummy"), &ResourceUID::is_dummy); + ClassDB::bind_method(D_METHOD("id_to_text", "id"), &ResourceUID::id_to_text); ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id); @@ -258,9 +304,21 @@ ResourceUID *ResourceUID::singleton = nullptr; ResourceUID::ResourceUID() { ERR_FAIL_COND(singleton != nullptr); singleton = this; - crypto = memnew(CryptoCore::RandomGenerator); - ((CryptoCore::RandomGenerator *)crypto)->init(); + + _is_dummy = !GLOBAL_GET("application/config/enable_uids"); + if (_is_dummy) { + Error err; + Ref uid_cache_dir = DirAccess::open(ProjectSettings::get_singleton()->get_project_data_path(), &err); + if (uid_cache_dir.is_valid()) { + uid_cache_dir->remove("uid_cache.bin"); + } + } else { + crypto = memnew(CryptoCore::RandomGenerator); + ((CryptoCore::RandomGenerator *)crypto)->init(); + } } ResourceUID::~ResourceUID() { - memdelete((CryptoCore::RandomGenerator *)crypto); + if (!_is_dummy) { + memdelete((CryptoCore::RandomGenerator *)crypto); + } } diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h index 22561c5c0325..e0baf403443e 100644 --- a/core/io/resource_uid.h +++ b/core/io/resource_uid.h @@ -46,6 +46,8 @@ class ResourceUID : public Object { static String get_cache_file(); private: + bool _is_dummy = false; + void *crypto = nullptr; // CryptoCore::RandomGenerator (avoid including crypto_core.h) Mutex mutex; struct Cache { @@ -63,6 +65,8 @@ class ResourceUID : public Object { static void _bind_methods(); public: + bool is_dummy() const; + String id_to_text(ID p_id) const; ID text_to_id(const String &p_text) const; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index b4ac53377983..403f44cf9701 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -115,8 +115,6 @@ static GDExtensionManager *gdextension_manager = nullptr; extern void register_global_constants(); extern void unregister_global_constants(); -static ResourceUID *resource_uid = nullptr; - static bool _is_core_extensions_registered = false; void register_core_types() { @@ -270,8 +268,6 @@ void register_core_types() { GDREGISTER_CLASS(EngineProfiler); - resource_uid = memnew(ResourceUID); - gdextension_manager = memnew(GDExtensionManager); resource_loader_gdextension.instantiate(); @@ -382,8 +378,6 @@ void unregister_core_types() { memdelete(gdextension_manager); - memdelete(resource_uid); - if (ip) { memdelete(ip); } diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index d5495ff7dcf2..1b22ed6fe354 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -267,6 +267,13 @@ The project's description, displayed as a tooltip in the Project Manager when hovering the project. + + When enabled, create and use UIDs (unique identifiers) for every scene and resource, as well as cache them in [code].godot/uid_cache.bin[/code]. + UIDs enable the following behaviors: Addons can be installed anywhere. Can move and rename files from a file explorer, version control, or anywhere while the editor is closed. Can open files with the [code]uid://[/code] syntax even if files are moved or renamed. + When disabled, [code].godot/uid_cache.bin[/code] is deleted and UIDs for every scene and resource are cleared only when the scene or resource is resaved. Code that relies on opening files with the [code]uid://[/code] syntax will not work. + [b]Note:[/b] Restart the application after changing this setting. + [b]Note:[/b] Disabling or reenabling UIDs may reimport resources, as well as emit warnings until the scene(s) are saved again. + Icon used for the project, set when project loads. Exporters will also use this icon as a fallback if necessary. diff --git a/doc/classes/ResourceUID.xml b/doc/classes/ResourceUID.xml index 8b990b132aa4..606e31fadcd7 100644 --- a/doc/classes/ResourceUID.xml +++ b/doc/classes/ResourceUID.xml @@ -48,6 +48,13 @@ Converts the given UID to a [code]uid://[/code] string value. + + + + Returns whether ResourceUID is stubbed, where it doesn't create and cache UIDs. + See also [member ProjectSettings.application/config/enable_uids]. + + diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 6f3b6ecdb0e2..6dff7a6be88a 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -441,8 +441,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo return false; //keep mode, do not reimport } - if (!found_uid) { - return true; //UID not found, old format, reimport. + if ((!found_uid && !ResourceUID::get_singleton()->is_dummy()) || (found_uid && ResourceUID::get_singleton()->is_dummy())) { + return true; //UID not found when it should have one, or it is found when it shouldn't have one, reimport } Ref importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); @@ -1832,7 +1832,9 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector uid = ResourceUID::get_singleton()->create_id(); } - f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); // Store in readable format. + if (uid != ResourceUID::INVALID_ID) { + f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); // Store in readable format. + } if (err == OK) { String path = base_path + "." + importer->get_save_extension(); @@ -2066,7 +2068,9 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMapcreate_id(); } - f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format + if (uid != ResourceUID::INVALID_ID) { + f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format + } if (err == OK) { if (importer->get_save_extension().is_empty()) { @@ -2427,8 +2431,8 @@ void EditorFileSystem::move_group_file(const String &p_path, const String &p_new } ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate) { - if (!p_path.is_resource_file() || p_path.begins_with(ProjectSettings::get_singleton()->get_project_data_path())) { - // Saved externally (configuration file) or internal file, do not assign an ID. + if (!p_path.is_resource_file() || p_path.begins_with(ProjectSettings::get_singleton()->get_project_data_path()) || ResourceUID::get_singleton()->is_dummy()) { + // Saved externally (configuration file), internal file, or UIDs are not enabled, do not assign an ID. return ResourceUID::INVALID_ID; } diff --git a/main/main.cpp b/main/main.cpp index 0a9ebd4c6103..b29f5c78644e 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -123,6 +123,7 @@ // Initialized in setup() static Engine *engine = nullptr; static ProjectSettings *globals = nullptr; +static ResourceUID *resource_uid = nullptr; static Input *input = nullptr; static InputMap *input_map = nullptr; static TranslationServer *translation_server = nullptr; @@ -537,6 +538,8 @@ Error Main::test_setup() { register_core_settings(); // Here globals are present. + resource_uid = memnew(ResourceUID); + translation_server = memnew(TranslationServer); tsman = memnew(TextServerManager); @@ -682,6 +685,9 @@ void Main::test_cleanup() { if (engine) { memdelete(engine); } + if (resource_uid) { + memdelete(resource_uid); + } unregister_core_driver_types(); unregister_core_extensions(); @@ -1578,6 +1584,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph initialize_modules(MODULE_INITIALIZATION_LEVEL_CORE); register_core_extensions(); // core extensions must be registered after globals setup and before display + resource_uid = memnew(ResourceUID); ResourceUID::get_singleton()->load_from_cache(); // load UUIDs from cache. if (ProjectSettings::get_singleton()->has_custom_feature("dedicated_server")) { @@ -2110,6 +2117,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (packed_data) { memdelete(packed_data); } + if (resource_uid) { + memdelete(resource_uid); + } unregister_core_driver_types(); unregister_core_extensions(); @@ -3738,6 +3748,9 @@ void Main::cleanup(bool p_force) { if (engine) { memdelete(engine); } + if (resource_uid) { + memdelete(resource_uid); + } if (OS::get_singleton()->is_restart_on_exit_set()) { //attempt to restart with arguments diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index a2c04698e1e4..db9bc6033a2c 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -2333,16 +2333,20 @@ Error ResourceLoaderText::set_uid(Ref p_f, ResourceUID::ID p_uid) { Ref fw; + String uid_as_text = ResourceUID::get_singleton()->id_to_text(p_uid); + if (!uid_as_text.is_empty()) { + uid_as_text = " uid=\"" + uid_as_text + "\""; + } fw = FileAccess::open(local_path + ".uidren", FileAccess::WRITE); if (is_scene) { - fw->store_string("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]"); + fw->store_string("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + uid_as_text + "]"); } else { String script_res_text; if (!script_class.is_empty()) { script_res_text = "script_class=\"" + script_class + "\" "; } - fw->store_string("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]"); + fw->store_string("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + uid_as_text + "]"); } uint8_t c = f->get_8();