diff options
Diffstat (limited to 'core/io')
-rw-r--r-- | core/io/image.cpp | 22 | ||||
-rw-r--r-- | core/io/image.h | 2 | ||||
-rw-r--r-- | core/io/image_loader.cpp | 2 | ||||
-rw-r--r-- | core/io/image_loader.h | 2 | ||||
-rw-r--r-- | core/io/ip.cpp | 24 | ||||
-rw-r--r-- | core/io/logger.cpp | 4 | ||||
-rw-r--r-- | core/io/resource.cpp | 37 | ||||
-rw-r--r-- | core/io/resource.h | 2 | ||||
-rw-r--r-- | core/io/resource_format_binary.cpp | 69 | ||||
-rw-r--r-- | core/io/resource_format_binary.h | 4 | ||||
-rw-r--r-- | core/io/resource_importer.cpp | 4 | ||||
-rw-r--r-- | core/io/resource_importer.h | 2 | ||||
-rw-r--r-- | core/io/resource_loader.cpp | 30 | ||||
-rw-r--r-- | core/io/resource_loader.h | 18 | ||||
-rw-r--r-- | core/io/translation_loader_po.cpp | 2 | ||||
-rw-r--r-- | core/io/translation_loader_po.h | 2 | ||||
-rw-r--r-- | core/io/xml_parser.cpp | 66 | ||||
-rw-r--r-- | core/io/xml_parser.h | 2 |
18 files changed, 146 insertions, 148 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp index 986c29b539..5d46d75efe 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -2985,6 +2985,26 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { _set_color_at_ofs(data.ptrw(), ofs, p_color); } +void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation) { + uint8_t *w = data.ptrw(); + uint32_t pixel_size = get_format_pixel_size(format); + uint32_t pixel_count = data.size() / pixel_size; + + for (uint32_t i = 0; i < pixel_count; i++) { + Color c = _get_color_at_ofs(w, i); + Vector3 rgb(c.r, c.g, c.b); + + rgb *= p_brightness; + rgb = Vector3(0.5, 0.5, 0.5).lerp(rgb, p_contrast); + float center = (rgb.x + rgb.y + rgb.z) / 3.0; + rgb = Vector3(center, center, center).lerp(rgb, p_saturation); + c.r = rgb.x; + c.g = rgb.y; + c.b = rgb.z; + _set_color_at_ofs(w, i, c); + } +} + Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA); ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA); @@ -3132,6 +3152,8 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pixelv", "point", "color"), &Image::set_pixelv); ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel); + ClassDB::bind_method(D_METHOD("adjust_bcs", "brightness", "contrast", "saturation"), &Image::adjust_bcs); + ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer); ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer); ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer); diff --git a/core/io/image.h b/core/io/image.h index b894be7df4..df8f9b35a1 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -390,6 +390,8 @@ public: void set_pixelv(const Point2i &p_point, const Color &p_color); void set_pixel(int p_x, int p_y, const Color &p_color); + void adjust_bcs(float p_brightness, float p_contrast, float p_saturation); + void set_as_black(); void copy_internals_from(const Ref<Image> &p_image) { diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 8ca1cb3beb..7de038e6fe 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -122,7 +122,7 @@ void ImageLoader::cleanup() { ///////////////// -RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { if (r_error) { diff --git a/core/io/image_loader.h b/core/io/image_loader.h index bf67e1486f..a5d588e0b5 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -72,7 +72,7 @@ public: class ResourceFormatLoaderImage : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index df95785000..e1d9c19f10 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -40,13 +40,13 @@ VARIANT_ENUM_CAST(IP::ResolverStatus); struct _IP_ResolverPrivate { struct QueueItem { - volatile IP::ResolverStatus status; + SafeNumeric<IP::ResolverStatus> status; IP_Address response; String hostname; IP::Type type; void clear() { - status = IP::RESOLVER_STATUS_NONE; + status.set(IP::RESOLVER_STATUS_NONE); response = IP_Address(); type = IP::TYPE_NONE; hostname = ""; @@ -61,7 +61,7 @@ struct _IP_ResolverPrivate { IP::ResolverID find_empty_id() const { for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) { - if (queue[i].status == IP::RESOLVER_STATUS_NONE) { + if (queue[i].status.get() == IP::RESOLVER_STATUS_NONE) { return i; } } @@ -77,15 +77,15 @@ struct _IP_ResolverPrivate { void resolve_queues() { for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) { - if (queue[i].status != IP::RESOLVER_STATUS_WAITING) { + if (queue[i].status.get() != IP::RESOLVER_STATUS_WAITING) { continue; } queue[i].response = IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type); if (!queue[i].response.is_valid()) { - queue[i].status = IP::RESOLVER_STATUS_ERROR; + queue[i].status.set(IP::RESOLVER_STATUS_ERROR); } else { - queue[i].status = IP::RESOLVER_STATUS_DONE; + queue[i].status.set(IP::RESOLVER_STATUS_DONE); } } } @@ -137,10 +137,10 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ resolver->queue[id].type = p_type; if (resolver->cache.has(key) && resolver->cache[key].is_valid()) { resolver->queue[id].response = resolver->cache[key]; - resolver->queue[id].status = IP::RESOLVER_STATUS_DONE; + resolver->queue[id].status.set(IP::RESOLVER_STATUS_DONE); } else { resolver->queue[id].response = IP_Address(); - resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING; + resolver->queue[id].status.set(IP::RESOLVER_STATUS_WAITING); if (resolver->thread.is_started()) { resolver->sem.post(); } else { @@ -156,12 +156,12 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const { MutexLock lock(resolver->mutex); - if (resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE) { + if (resolver->queue[p_id].status.get() == IP::RESOLVER_STATUS_NONE) { ERR_PRINT("Condition status == IP::RESOLVER_STATUS_NONE"); resolver->mutex.unlock(); return IP::RESOLVER_STATUS_NONE; } - return resolver->queue[p_id].status; + return resolver->queue[p_id].status.get(); } IP_Address IP::get_resolve_item_address(ResolverID p_id) const { @@ -169,7 +169,7 @@ IP_Address IP::get_resolve_item_address(ResolverID p_id) const { MutexLock lock(resolver->mutex); - if (resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE) { + if (resolver->queue[p_id].status.get() != IP::RESOLVER_STATUS_DONE) { ERR_PRINT("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet."); resolver->mutex.unlock(); return IP_Address(); @@ -183,7 +183,7 @@ void IP::erase_resolve_item(ResolverID p_id) { MutexLock lock(resolver->mutex); - resolver->queue[p_id].status = IP::RESOLVER_STATUS_NONE; + resolver->queue[p_id].status.set(IP::RESOLVER_STATUS_NONE); } void IP::clear_cache(const String &p_hostname) { diff --git a/core/io/logger.cpp b/core/io/logger.cpp index da200f5717..bd0285a7a9 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -207,7 +207,7 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) { Memory::free_static(buf); } - if (p_err || GLOBAL_GET("application/run/flush_stdout_on_print")) { + if (p_err || !ProjectSettings::get_singleton() || GLOBAL_GET("application/run/flush_stdout_on_print")) { // Don't always flush when printing stdout to avoid performance // issues when `print()` is spammed in release builds. file->flush(); @@ -228,7 +228,7 @@ void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) { vfprintf(stderr, p_format, p_list); } else { vprintf(p_format, p_list); - if (GLOBAL_GET("application/run/flush_stdout_on_print")) { + if (!ProjectSettings::get_singleton() || GLOBAL_GET("application/run/flush_stdout_on_print")) { // Don't always flush when printing stdout to avoid performance // issues when `print()` is spammed in release builds. fflush(stdout); diff --git a/core/io/resource.cpp b/core/io/resource.cpp index db79998a90..8560e2abc7 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -87,7 +87,6 @@ void Resource::set_path(const String &p_path, bool p_take_over) { ResourceCache::lock.write_unlock(); } - _change_notify("resource_path"); _resource_path_changed(); } @@ -105,7 +104,6 @@ int Resource::get_subindex() const { void Resource::set_name(const String &p_name) { name = p_name; - _change_notify("resource_name"); } String Resource::get_name() const { @@ -116,20 +114,18 @@ bool Resource::editor_can_reload_from_file() { return true; //by default yes } -void Resource::reload_from_file() { - String path = get_path(); - if (!path.is_resource_file()) { - return; +void Resource::reset_state() { +} +Error Resource::copy_from(const Ref<Resource> &p_resource) { + ERR_FAIL_COND_V(p_resource.is_null(), ERR_INVALID_PARAMETER); + if (get_class() != p_resource->get_class()) { + return ERR_INVALID_PARAMETER; } - Ref<Resource> s = ResourceLoader::load(ResourceLoader::path_remap(path), get_class(), true); - - if (!s.is_valid()) { - return; - } + reset_state(); //may want to reset state List<PropertyInfo> pi; - s->get_property_list(&pi); + p_resource->get_property_list(&pi); for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) { if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { @@ -139,8 +135,23 @@ void Resource::reload_from_file() { continue; //do not change path } - set(E->get().name, s->get(E->get().name)); + set(E->get().name, p_resource->get(E->get().name)); } + return OK; +} +void Resource::reload_from_file() { + String path = get_path(); + if (!path.is_resource_file()) { + return; + } + + Ref<Resource> s = ResourceLoader::load(ResourceLoader::path_remap(path), get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE); + + if (!s.is_valid()) { + return; + } + + copy_from(s); } Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) { diff --git a/core/io/resource.h b/core/io/resource.h index d0cd6ea3ac..ae18ac0c8a 100644 --- a/core/io/resource.h +++ b/core/io/resource.h @@ -90,6 +90,8 @@ public: static Node *(*_get_local_scene_func)(); //used by editor virtual bool editor_can_reload_from_file(); + virtual void reset_state(); //for resources that use variable amount of properties, either via _validate_property or _get_property_list, this function needs to be implemented to correctly clear state + virtual Error copy_from(const Ref<Resource> &p_resource); virtual void reload_from_file(); void register_owner(Object *p_owner); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index fad58d65fd..fb6ad7d65e 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -313,17 +313,12 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { uint32_t index = f->get_32(); String path = res_path + "::" + itos(index); - if (use_nocache) { - if (!internal_index_cache.has(path)) { - WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data()); - } - r_v = internal_index_cache[path]; + //always use internal cache for loading internal resources + if (!internal_index_cache.has(path)) { + WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data()); + r_v = Variant(); } else { - RES res = ResourceLoader::load(path); - if (res.is_null()) { - WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); - } - r_v = res; + r_v = internal_index_cache[path]; } } break; @@ -645,7 +640,7 @@ Error ResourceLoaderBinary::load() { } } else { - Error err = ResourceLoader::load_threaded_request(path, external_resources[i].type, use_sub_threads, local_path); + Error err = ResourceLoader::load_threaded_request(path, external_resources[i].type, use_sub_threads, ResourceFormatLoader::CACHE_MODE_REUSE, local_path); if (err != OK) { if (!ResourceLoader::get_abort_on_missing_resources()) { ResourceLoader::notify_dependency_error(local_path, path, external_resources[i].type); @@ -675,7 +670,7 @@ Error ResourceLoaderBinary::load() { path = res_path + "::" + path; } - if (!use_nocache) { + if (cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE) { if (ResourceCache::has(path)) { //already loaded, don't do anything stage++; @@ -684,7 +679,7 @@ Error ResourceLoaderBinary::load() { } } } else { - if (!use_nocache && !ResourceCache::has(res_path)) { + if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE && !ResourceCache::has(res_path)) { path = res_path; } } @@ -695,26 +690,40 @@ Error ResourceLoaderBinary::load() { String t = get_unicode_string(); - Object *obj = ClassDB::instance(t); - if (!obj) { - error = ERR_FILE_CORRUPT; - ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + "."); - } + RES res; - 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 + "."); + if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) { + //use the existing one + Resource *r = ResourceCache::get(path); + if (r->get_class() == t) { + r->reset_state(); + res = Ref<Resource>(r); + } } - RES res = RES(r); + if (res.is_null()) { + //did not replace - if (path != String()) { - r->set_path(path); + Object *obj = ClassDB::instance(t); + if (!obj) { + error = ERR_FILE_CORRUPT; + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + "."); + } + + 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 = RES(r); + if (path != String() && 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 + } + r->set_subindex(subindex); } - r->set_subindex(subindex); if (!main) { internal_index_cache[path] = res; @@ -961,7 +970,7 @@ ResourceLoaderBinary::~ResourceLoaderBinary() { } } -RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { if (r_error) { *r_error = ERR_FILE_CANT_OPEN; } @@ -972,7 +981,7 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'."); ResourceLoaderBinary loader; - loader.use_nocache = p_no_cache; + loader.cache_mode = p_cache_mode; loader.use_sub_threads = p_use_sub_threads; loader.progress = r_progress; String path = p_original_path != "" ? p_original_path : p_path; diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 428725f1d2..3592bbdbc4 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -78,7 +78,7 @@ class ResourceLoaderBinary { Map<String, String> remaps; Error error = OK; - bool use_nocache = false; + ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE; friend class ResourceFormatLoaderBinary; @@ -103,7 +103,7 @@ public: class ResourceFormatLoaderBinary : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index d86877ee14..3e460726f6 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -116,7 +116,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy return OK; } -RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { PathAndType pat; Error err = _get_path_and_type(p_path, pat); @@ -128,7 +128,7 @@ RES ResourceFormatImporter::load(const String &p_path, const String &p_original_ return RES(); } - RES res = ResourceLoader::_load(pat.path, p_path, pat.type, p_no_cache, r_error, p_use_sub_threads, r_progress); + RES res = ResourceLoader::_load(pat.path, p_path, pat.type, p_cache_mode, r_error, p_use_sub_threads, r_progress); #ifdef TOOLS_ENABLED if (res.is_valid()) { diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index d31273e3cb..bda8b74b73 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -57,7 +57,7 @@ class ResourceFormatImporter : public ResourceFormatLoader { public: static ResourceFormatImporter *get_singleton() { return singleton; } - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index d66511a39f..cba9a47187 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -113,9 +113,9 @@ void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) } } -RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { if (get_script_instance() && get_script_instance()->has_method("load")) { - Variant res = get_script_instance()->call("load", p_path, p_original_path, p_use_sub_threads); + Variant res = get_script_instance()->call("load", p_path, p_original_path, p_use_sub_threads, p_cache_mode); if (res.get_type() == Variant::INT) { if (r_error) { @@ -164,7 +164,7 @@ Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map< void ResourceFormatLoader::_bind_methods() { { - MethodInfo info = MethodInfo(Variant::NIL, "load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path")); + MethodInfo info = MethodInfo(Variant::NIL, "load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path"), PropertyInfo(Variant::BOOL, "use_sub_threads"), PropertyInfo(Variant::INT, "cache_mode")); info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; ClassDB::add_virtual_method(get_class_static(), info); } @@ -174,11 +174,15 @@ void ResourceFormatLoader::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type", PropertyInfo(Variant::STRING, "path"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "rename_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "renames"))); + + BIND_ENUM_CONSTANT(CACHE_MODE_IGNORE); + BIND_ENUM_CONSTANT(CACHE_MODE_REUSE); + BIND_ENUM_CONSTANT(CACHE_MODE_REPLACE); } /////////////////////////////////// -RES ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error, bool p_use_sub_threads, float *r_progress) { +RES ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) { bool found = false; // Try all loaders and pick the first match for the type hint @@ -187,7 +191,7 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c continue; } found = true; - RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_no_cache); + RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode); if (res.is_null()) { continue; } @@ -214,7 +218,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { //this is an actual thread, so wait for Ok fom semaphore thread_load_semaphore->wait(); //wait until its ok to start loading } - load_task.resource = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, false, &load_task.error, load_task.use_sub_threads, &load_task.progress); + load_task.resource = _load(load_task.remapped_path, load_task.remapped_path != load_task.local_path ? load_task.local_path : String(), load_task.type_hint, load_task.cache_mode, &load_task.error, load_task.use_sub_threads, &load_task.progress); load_task.progress = 1.0; //it was fully loaded at this point, so force progress to 1.0 @@ -267,7 +271,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { thread_load_mutex->unlock(); } -Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, const String &p_source_resource) { +Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, ResourceFormatLoader::CacheMode p_cache_mode, const String &p_source_resource) { String local_path; if (p_path.is_rel_path()) { local_path = "res://" + p_path; @@ -314,6 +318,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String & load_task.remapped_path = _path_remap(local_path, &load_task.xl_remapped); load_task.local_path = local_path; load_task.type_hint = p_type_hint; + load_task.cache_mode = p_cache_mode; load_task.use_sub_threads = p_use_sub_threads; { //must check if resource is already loaded before attempting to load it in a thread @@ -501,7 +506,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) { return resource; } -RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { +RES ResourceLoader::load(const String &p_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error) { if (r_error) { *r_error = ERR_CANT_OPEN; } @@ -513,7 +518,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p local_path = ProjectSettings::get_singleton()->localize_path(p_path); } - if (!p_no_cache) { + if (p_cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE) { thread_load_mutex->lock(); //Is it already being loaded? poll until done @@ -561,6 +566,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p load_task.local_path = local_path; load_task.remapped_path = _path_remap(local_path, &load_task.xl_remapped); load_task.type_hint = p_type_hint; + load_task.cache_mode = p_cache_mode; //ignore load_task.loader_id = Thread::get_caller_id(); thread_load_tasks[local_path] = load_task; @@ -581,7 +587,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p print_verbose("Loading resource: " + path); float p; - RES res = _load(path, local_path, p_type_hint, p_no_cache, r_error, false, &p); + RES res = _load(path, local_path, p_type_hint, p_cache_mode, r_error, false, &p); if (res.is_null()) { print_verbose("Failed loading resource: " + path); @@ -966,11 +972,11 @@ void ResourceLoader::reload_translation_remaps() { } void ResourceLoader::load_translation_remaps() { - if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) { + if (!ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) { return; } - Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps"); + Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"); List<Variant> keys; remaps.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index dbf6be46c5..914d988caa 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -38,11 +38,18 @@ class ResourceFormatLoader : public Reference { GDCLASS(ResourceFormatLoader, Reference); +public: + enum CacheMode { + CACHE_MODE_IGNORE, //resource and subresources do not use path cache, no path is set into resource. + CACHE_MODE_REUSE, //resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available + CACHE_MODE_REPLACE, //resource and and subresource use path cache, but replace existing loaded resources when available with information from disk + }; + protected: static void _bind_methods(); public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual bool exists(const String &p_path) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; @@ -59,6 +66,8 @@ public: virtual ~ResourceFormatLoader() {} }; +VARIANT_ENUM_CAST(ResourceFormatLoader::CacheMode) + typedef void (*ResourceLoadErrorNotify)(void *p_ud, const String &p_text); typedef void (*DependencyErrorNotify)(void *p_ud, const String &p_loading, const String &p_which, const String &p_type); @@ -99,7 +108,7 @@ private: friend class ResourceFormatImporter; friend class ResourceInteractiveLoader; //internal load function - static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error, bool p_use_sub_threads, float *r_progress); + static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress); static ResourceLoadedCallback _loaded_callback; @@ -114,6 +123,7 @@ private: String type_hint; float progress = 0.0; ThreadLoadStatus status = THREAD_LOAD_IN_PROGRESS; + ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE; Error error = OK; RES resource; bool xl_remapped = false; @@ -136,11 +146,11 @@ private: static float _dependency_get_progress(const String &p_path); public: - static Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, const String &p_source_resource = String()); + static Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, const String &p_source_resource = String()); static ThreadLoadStatus load_threaded_get_status(const String &p_path, float *r_progress = nullptr); static RES load_threaded_get(const String &p_path, Error *r_error = nullptr); - static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = nullptr); + static RES load(const String &p_path, const String &p_type_hint = "", ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, Error *r_error = nullptr); static bool exists(const String &p_path, const String &p_type_hint = ""); static void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions); diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index ce2c3eb1cd..0e11ff514a 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -277,7 +277,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { return translation; } -RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { if (r_error) { *r_error = ERR_CANT_OPEN; } diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index a524972588..36d33fcac3 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -38,7 +38,7 @@ class TranslationLoaderPO : public ResourceFormatLoader { public: static RES load_translation(FileAccess *f, Error *r_error = nullptr); - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 905be6089d..1574634aad 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -36,63 +36,6 @@ VARIANT_ENUM_CAST(XMLParser::NodeType); -static bool _equalsn(const char32_t *str1, const char32_t *str2, int len) { - int i; - for (i = 0; i < len && str1[i] && str2[i]; ++i) { - if (str1[i] != str2[i]) { - return false; - } - } - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same length - return (i == len) || (str1[i] == 0 && str2[i] == 0); -} - -String XMLParser::_replace_special_characters(const String &origstr) { - int pos = origstr.find("&"); - int oldPos = 0; - - if (pos == -1) { - return origstr; - } - - String newstr; - - while (pos != -1 && pos < origstr.length() - 2) { - // check if it is one of the special characters - - int specialChar = -1; - for (int i = 0; i < (int)special_characters.size(); ++i) { - const char32_t *p = &origstr[pos] + 1; - - if (_equalsn(&special_characters[i][1], p, special_characters[i].length() - 1)) { - specialChar = i; - break; - } - } - - if (specialChar != -1) { - newstr += (origstr.substr(oldPos, pos - oldPos)); - newstr += (special_characters[specialChar][0]); - pos += special_characters[specialChar].length(); - } else { - newstr += (origstr.substr(oldPos, pos - oldPos + 1)); - pos += 1; - } - - // find next & - oldPos = pos; - pos = origstr.find("&", pos); - } - - if (oldPos < origstr.length() - 1) { - newstr += (origstr.substr(oldPos, origstr.length() - oldPos)); - } - - return newstr; -} - static inline bool _is_white_space(char c) { return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); } @@ -116,7 +59,7 @@ bool XMLParser::_set_text(char *start, char *end) { // set current text to the parsed text, and replace xml special characters String s = String::utf8(start, (int)(end - start)); - node_name = _replace_special_characters(s); + node_name = s.xml_unescape(); // current XML node type is text node_type = NODE_TEXT; @@ -292,7 +235,7 @@ void XMLParser::_parse_opening_xml_element() { String s = String::utf8(attributeValueBegin, (int)(attributeValueEnd - attributeValueBegin)); - attr.value = _replace_special_characters(s); + attr.value = s.xml_unescape(); attributes.push_back(attr); } else { // tag is closed directly @@ -555,11 +498,6 @@ int XMLParser::get_current_line() const { } XMLParser::XMLParser() { - special_characters.push_back("&"); - special_characters.push_back("<lt;"); - special_characters.push_back(">gt;"); - special_characters.push_back("\"quot;"); - special_characters.push_back("'apos;"); } XMLParser::~XMLParser() { diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h index 01af6a90ad..847edf958d 100644 --- a/core/io/xml_parser.h +++ b/core/io/xml_parser.h @@ -68,8 +68,6 @@ private: char *data = nullptr; char *P = nullptr; uint64_t length = 0; - void unescape(String &p_str); - Vector<String> special_characters; String node_name; bool node_empty = false; NodeType node_type = NODE_NONE; |