Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add application/config/enable_uids project setting #81122

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
70 changes: 64 additions & 6 deletions core/io/resource_uid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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://<invalid>";
}
Expand All @@ -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://<invalid>") {
if (_is_dummy || !p_text.begins_with("uid://") || p_text == "uid://<invalid>") {
return INVALID_ID;
}

Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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();
Expand All @@ -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<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
Expand Down Expand Up @@ -168,6 +204,10 @@ Error ResourceUID::save_to_cache() {
}

Error ResourceUID::load_from_cache() {
if (_is_dummy) {
return OK;
}

Ref<FileAccess> f = FileAccess::open(get_cache_file(), FileAccess::READ);
if (f.is_null()) {
return ERR_CANT_OPEN;
Expand Down Expand Up @@ -197,7 +237,7 @@ Error ResourceUID::load_from_cache() {
}

Error ResourceUID::update_cache() {
if (!changed) {
if (_is_dummy || !changed) {
return OK;
}

Expand Down Expand Up @@ -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);

Expand All @@ -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<DirAccess> 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);
}
}
4 changes: 4 additions & 0 deletions core/io/resource_uid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;

Expand Down
6 changes: 0 additions & 6 deletions core/register_core_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -270,8 +268,6 @@ void register_core_types() {

GDREGISTER_CLASS(EngineProfiler);

resource_uid = memnew(ResourceUID);

gdextension_manager = memnew(GDExtensionManager);

resource_loader_gdextension.instantiate();
Expand Down Expand Up @@ -382,8 +378,6 @@ void unregister_core_types() {

memdelete(gdextension_manager);

memdelete(resource_uid);

if (ip) {
memdelete(ip);
}
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,13 @@
<member name="application/config/description" type="String" setter="" getter="" default="&quot;&quot;">
The project's description, displayed as a tooltip in the Project Manager when hovering the project.
</member>
<member name="application/config/enable_uids" type="bool" setter="" getter="" default="true">
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.
</member>
<member name="application/config/icon" type="String" setter="" getter="" default="&quot;&quot;">
Icon used for the project, set when project loads. Exporters will also use this icon as a fallback if necessary.
</member>
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/ResourceUID.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@
Converts the given UID to a [code]uid://[/code] string value.
</description>
</method>
<method name="is_dummy" qualifiers="const">
<return type="bool" />
<description>
Returns whether ResourceUID is stubbed, where it doesn't create and cache UIDs.
See also [member ProjectSettings.application/config/enable_uids].
</description>
</method>
<method name="remove_id">
<return type="void" />
<param index="0" name="id" type="int" />
Expand Down
16 changes: 10 additions & 6 deletions editor/editor_file_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -2066,7 +2068,9 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin
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) {
if (importer->get_save_extension().is_empty()) {
Expand Down Expand Up @@ -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;
}

Expand Down
13 changes: 13 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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")) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions scene/resources/resource_format_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2333,16 +2333,20 @@ Error ResourceLoaderText::set_uid(Ref<FileAccess> p_f, ResourceUID::ID p_uid) {

Ref<FileAccess> 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();
Expand Down
Loading