diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/io/resource_format_binary.cpp | 68 | ||||
-rw-r--r-- | core/io/resource_loader.cpp | 36 | ||||
-rw-r--r-- | core/io/resource_loader.h | 4 |
3 files changed, 79 insertions, 29 deletions
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index ab460c5f4c..f71257fa76 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -749,44 +749,54 @@ Error ResourceLoaderBinary::load() { String t = get_unicode_string(); Ref<Resource> res; + Resource *r = nullptr; - if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) { - //use the existing one - Ref<Resource> cached = ResourceCache::get_ref(path); - if (cached->get_class() == t) { - cached->reset_state(); - res = cached; - } + MissingResource *missing_resource = nullptr; + + if (main) { + res = ResourceLoader::get_resource_ref_override(local_path); + r = res.ptr(); } + if (!r) { + if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) { + //use the existing one + Ref<Resource> cached = ResourceCache::get_ref(path); + if (cached->get_class() == t) { + cached->reset_state(); + res = cached; + } + } - MissingResource *missing_resource = nullptr; + if (res.is_null()) { + //did not replace + + Object *obj = ClassDB::instantiate(t); + if (!obj) { + if (ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) { + //create a missing resource + missing_resource = memnew(MissingResource); + missing_resource->set_original_class(t); + missing_resource->set_recording_properties(true); + obj = missing_resource; + } else { + error = ERR_FILE_CORRUPT; + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + "."); + } + } - if (res.is_null()) { - //did not replace - - Object *obj = ClassDB::instantiate(t); - if (!obj) { - if (ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) { - //create a missing resource - missing_resource = memnew(MissingResource); - missing_resource->set_original_class(t); - missing_resource->set_recording_properties(true); - obj = missing_resource; - } else { + r = Object::cast_to<Resource>(obj); + if (!r) { + String obj_class = obj->get_class(); error = ERR_FILE_CORRUPT; - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + "."); + memdelete(obj); //bye + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + "."); } - } - Resource *r = Object::cast_to<Resource>(obj); - if (!r) { - String obj_class = obj->get_class(); - error = ERR_FILE_CORRUPT; - memdelete(obj); //bye - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + "."); + res = Ref<Resource>(r); } + } - res = Ref<Resource>(r); + if (r) { if (!path.is_empty()) { if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { r->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); // If got here because the resource with same path has different type, replace it. diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index eb3b117297..ed5e482296 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -272,6 +272,7 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin } load_paths_stack->resize(load_paths_stack->size() - 1); + res_ref_overrides.erase(load_nesting); load_nesting--; if (!res.is_null()) { @@ -730,6 +731,40 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro } } +Ref<Resource> ResourceLoader::ensure_resource_ref_override_for_outer_load(const String &p_path, const String &p_res_type) { + ERR_FAIL_COND_V(load_nesting == 0, Ref<Resource>()); // It makes no sense to use this from nesting level 0. + const String &local_path = _validate_local_path(p_path); + HashMap<String, Ref<Resource>> &overrides = res_ref_overrides[load_nesting - 1]; + HashMap<String, Ref<Resource>>::Iterator E = overrides.find(local_path); + if (E) { + return E->value; + } else { + Object *obj = ClassDB::instantiate(p_res_type); + ERR_FAIL_NULL_V(obj, Ref<Resource>()); + Ref<Resource> res(obj); + if (!res.is_valid()) { + memdelete(obj); + ERR_FAIL_V(Ref<Resource>()); + } + overrides[local_path] = res; + return res; + } +} + +Ref<Resource> ResourceLoader::get_resource_ref_override(const String &p_path) { + DEV_ASSERT(p_path == _validate_local_path(p_path)); + HashMap<int, HashMap<String, Ref<Resource>>>::Iterator E = res_ref_overrides.find(load_nesting); + if (!E) { + return nullptr; + } + HashMap<String, Ref<Resource>>::Iterator F = E->value.find(p_path); + if (!F) { + return nullptr; + } + + return F->value; +} + bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) { String local_path = _validate_local_path(p_path); @@ -1222,6 +1257,7 @@ bool ResourceLoader::timestamp_on_load = false; thread_local int ResourceLoader::load_nesting = 0; thread_local WorkerThreadPool::TaskID ResourceLoader::caller_task_id = 0; thread_local Vector<String> *ResourceLoader::load_paths_stack; +thread_local HashMap<int, HashMap<String, Ref<Resource>>> ResourceLoader::res_ref_overrides; template <> thread_local uint32_t SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG>::count = 0; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 11abb4dc18..c48f39b5cc 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -187,6 +187,7 @@ private: static thread_local int load_nesting; static thread_local WorkerThreadPool::TaskID caller_task_id; + static thread_local HashMap<int, HashMap<String, Ref<Resource>>> res_ref_overrides; // Outermost key is nesting level. static thread_local Vector<String> *load_paths_stack; // A pointer to avoid broken TLS implementations from double-running the destructor. static SafeBinaryMutex<BINARY_MUTEX_TAG> thread_load_mutex; static HashMap<String, ThreadLoadTask> thread_load_tasks; @@ -272,6 +273,9 @@ public: static void set_create_missing_resources_if_class_unavailable(bool p_enable); _FORCE_INLINE_ static bool is_creating_missing_resources_if_class_unavailable_enabled() { return create_missing_resources_if_class_unavailable; } + static Ref<Resource> ensure_resource_ref_override_for_outer_load(const String &p_path, const String &p_res_type); + static Ref<Resource> get_resource_ref_override(const String &p_path); + static bool is_cleaning_tasks(); static void initialize(); |