Skip to content

Commit

Permalink
Add application/config/enable_uids project setting
Browse files Browse the repository at this point in the history
  • Loading branch information
dhoverml committed Aug 29, 2023
1 parent 247c354 commit b173008
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 20 deletions.
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

0 comments on commit b173008

Please sign in to comment.