diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/compressed_translation.cpp | 2 | ||||
-rw-r--r-- | core/io/image_loader.h | 1 | ||||
-rw-r--r-- | core/io/resource_format_binary.h | 3 | ||||
-rw-r--r-- | core/io/resource_import.h | 2 | ||||
-rw-r--r-- | core/io/resource_loader.cpp | 196 | ||||
-rw-r--r-- | core/io/resource_loader.h | 28 | ||||
-rw-r--r-- | core/io/resource_saver.cpp | 150 | ||||
-rw-r--r-- | core/io/resource_saver.h | 25 | ||||
-rw-r--r-- | core/io/translation_loader_po.h | 1 | ||||
-rw-r--r-- | core/register_core_types.cpp | 53 | ||||
-rw-r--r-- | core/undo_redo.cpp | 19 | ||||
-rw-r--r-- | core/ustring.cpp | 10 | ||||
-rw-r--r-- | core/ustring.h | 35 | ||||
-rw-r--r-- | core/vector.h | 56 |
14 files changed, 499 insertions, 82 deletions
diff --git a/core/compressed_translation.cpp b/core/compressed_translation.cpp index 7dd5308fab..73affd8fe9 100644 --- a/core/compressed_translation.cpp +++ b/core/compressed_translation.cpp @@ -83,7 +83,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { if (ps.orig_len != 0) { CharString dst_s; dst_s.resize(src_s.size()); - int ret = smaz_compress(src_s.get_data(), src_s.size(), &dst_s[0], src_s.size()); + int ret = smaz_compress(src_s.get_data(), src_s.size(), dst_s.ptrw(), src_s.size()); if (ret >= src_s.size()) { //if compressed is larger than original, just use original ps.orig_len = src_s.size(); diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 7a58d46f93..15ee5e9ae1 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -88,6 +88,7 @@ public: }; class ResourceFormatLoaderImage : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderImage, ResourceFormatLoader) public: virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 513252055f..e449ff216b 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -100,6 +100,7 @@ public: }; class ResourceFormatLoaderBinary : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderBinary, ResourceFormatLoader) public: virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; @@ -152,7 +153,7 @@ public: }; class ResourceFormatSaverBinary : public ResourceFormatSaver { - + GDCLASS(ResourceFormatSaverBinary, ResourceFormatSaver) public: static ResourceFormatSaverBinary *singleton; virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); diff --git a/core/io/resource_import.h b/core/io/resource_import.h index 53718bd789..ec66a422a3 100644 --- a/core/io/resource_import.h +++ b/core/io/resource_import.h @@ -37,6 +37,8 @@ class ResourceImporter; class ResourceFormatImporter : public ResourceFormatLoader { + GDCLASS(ResourceFormatImporter, ResourceFormatLoader) + struct PathAndType { String path; String type; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 71b01aa94a..41f3b2935c 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -39,7 +39,7 @@ #include "core/translation.h" #include "core/variant_parser.h" -ResourceFormatLoader *ResourceLoader::loader[MAX_LOADERS]; +Ref<ResourceFormatLoader> ResourceLoader::loader[ResourceLoader::MAX_LOADERS]; int ResourceLoader::loader_count = 0; @@ -73,6 +73,25 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_ return false; } +bool ResourceFormatLoader::handles_type(const String &p_type) const { + + if (get_script_instance() && get_script_instance()->has_method("handles_type")) { + // I guess custom loaders for custom resources should use "Resource" + return get_script_instance()->call("handles_type", p_type); + } + + return false; +} + +String ResourceFormatLoader::get_resource_type(const String &p_path) const { + + if (get_script_instance() && get_script_instance()->has_method("get_resource_type")) { + return get_script_instance()->call("get_resource_type", p_path); + } + + return ""; +} + void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const { if (p_type == "" || handles_type(p_type)) @@ -129,9 +148,37 @@ bool ResourceFormatLoader::exists(const String &p_path) const { return FileAccess::exists(p_path); //by default just check file } +void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) const { + + if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { + PoolStringArray exts = get_script_instance()->call("get_recognized_extensions"); + + { + PoolStringArray::Read r = exts.read(); + for (int i = 0; i < exts.size(); ++i) { + p_extensions->push_back(r[i]); + } + } + } +} + RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error) { - String path = p_path; + if (get_script_instance() && get_script_instance()->has_method("load")) { + Variant res = get_script_instance()->call("load", p_path, p_original_path); + + if (res.get_type() == Variant::INT) { + + if (r_error) + *r_error = (Error)res.operator int64_t(); + + } else { + + if (r_error) + *r_error = OK; + return res; + } + } //or this must be implemented Ref<ResourceInteractiveLoader> ril = load_interactive(p_path, p_original_path, r_error); @@ -160,7 +207,47 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { - //do nothing by default + if (get_script_instance() && get_script_instance()->has_method("get_dependencies")) { + PoolStringArray deps = get_script_instance()->call("get_dependencies", p_path, p_add_types); + + { + PoolStringArray::Read r = deps.read(); + for (int i = 0; i < deps.size(); ++i) { + p_dependencies->push_back(r[i]); + } + } + } +} + +Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { + + if (get_script_instance() && get_script_instance()->has_method("rename_dependencies")) { + + Dictionary deps_dict; + for (Map<String, String>::Element *E = p_map.front(); E; E = E->next()) { + deps_dict[E->key()] = E->value(); + } + + int64_t res = get_script_instance()->call("rename_dependencies", deps_dict); + return (Error)res; + } + + return OK; +} + +void ResourceFormatLoader::_bind_methods() { + + { + MethodInfo info = MethodInfo(Variant::NIL, "load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path")); + info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + ClassDB::add_virtual_method(get_class_static(), info); + } + + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::POOL_STRING_ARRAY, "get_recognized_extensions")); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles_type", PropertyInfo(Variant::STRING, "typename"))); + 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"))); } /////////////////////////////////// @@ -348,9 +435,11 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ return Ref<ResourceInteractiveLoader>(); } -void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_loader, bool p_at_front) { +void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) { + ERR_FAIL_COND(p_format_loader.is_null()); ERR_FAIL_COND(loader_count >= MAX_LOADERS); + if (p_at_front) { for (int i = loader_count; i > 0; i--) { loader[i] = loader[i - 1]; @@ -362,6 +451,27 @@ void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_l } } +void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader) { + + ERR_FAIL_COND(p_format_loader.is_null()); + + // Find loader + int i = 0; + for (; i < loader_count; ++i) { + if (loader[i] == p_format_loader) + break; + } + + ERR_FAIL_COND(i >= loader_count); // Not found + + // Shift next loaders up + for (; i < loader_count - 1; ++i) { + loader[i] = loader[i + 1]; + } + loader[loader_count - 1].unref(); + --loader_count; +} + int ResourceLoader::get_import_order(const String &p_path) { String path = _path_remap(p_path); @@ -645,6 +755,84 @@ void ResourceLoader::set_load_callback(ResourceLoadedCallback p_callback) { ResourceLoadedCallback ResourceLoader::_loaded_callback = NULL; +Ref<ResourceFormatLoader> ResourceLoader::_find_custom_resource_format_loader(String path) { + for (int i = 0; i < loader_count; ++i) { + if (loader[i]->get_script_instance() && loader[i]->get_script_instance()->get_script()->get_path() == path) { + return loader[i]; + } + } + return Ref<ResourceFormatLoader>(); +} + +bool ResourceLoader::add_custom_resource_format_loader(String script_path) { + + if (_find_custom_resource_format_loader(script_path).is_valid()) + return false; + + Ref<Resource> res = ResourceLoader::load(script_path); + ERR_FAIL_COND_V(res.is_null(), false); + ERR_FAIL_COND_V(!res->is_class("Script"), false); + + Ref<Script> s = res; + StringName ibt = s->get_instance_base_type(); + bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatLoader"); + ERR_EXPLAIN("Script does not inherit a CustomResourceLoader: " + script_path); + ERR_FAIL_COND_V(!valid_type, false); + + Object *obj = ClassDB::instance(ibt); + + ERR_EXPLAIN("Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt)); + ERR_FAIL_COND_V(obj == NULL, false); + + ResourceFormatLoader *crl = NULL; + crl = Object::cast_to<ResourceFormatLoader>(obj); + crl->set_script(s.get_ref_ptr()); + ResourceLoader::add_resource_format_loader(crl); + + return true; +} + +void ResourceLoader::remove_custom_resource_format_loader(String script_path) { + + Ref<ResourceFormatLoader> loader = _find_custom_resource_format_loader(script_path); + if (loader.is_valid()) + remove_resource_format_loader(loader); +} + +void ResourceLoader::add_custom_loaders() { + // Custom loaders registration exploits global class names + + String custom_loader_base_class = ResourceFormatLoader::get_class_static(); + + List<StringName> global_classes; + ScriptServer::get_global_class_list(&global_classes); + + for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { + + StringName class_name = E->get(); + StringName base_class = ScriptServer::get_global_class_base(class_name); + + if (base_class == custom_loader_base_class) { + String path = ScriptServer::get_global_class_path(class_name); + add_custom_resource_format_loader(path); + } + } +} + +void ResourceLoader::remove_custom_loaders() { + + Vector<Ref<ResourceFormatLoader> > custom_loaders; + for (int i = 0; i < loader_count; ++i) { + if (loader[i]->get_script_instance()) { + custom_loaders.push_back(loader[i]); + } + } + + for (int i = 0; i < custom_loaders.size(); ++i) { + remove_resource_format_loader(custom_loaders[i]); + } +} + ResourceLoadErrorNotify ResourceLoader::err_notify = NULL; void *ResourceLoader::err_notify_ud = NULL; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index a46a00203f..c411b3c398 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -56,18 +56,24 @@ public: ResourceInteractiveLoader() {} }; -class ResourceFormatLoader { +class ResourceFormatLoader : public Reference { + + GDCLASS(ResourceFormatLoader, Reference) + +protected: + static void _bind_methods(); + public: virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual bool exists(const String &p_path) const; - virtual void get_recognized_extensions(List<String> *p_extensions) const = 0; + 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; - virtual bool handles_type(const String &p_type) const = 0; - virtual String get_resource_type(const String &p_path) const = 0; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); - virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map) { return OK; } + virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); virtual bool is_import_valid(const String &p_path) const { return true; } virtual int get_import_order(const String &p_path) const { return 0; } @@ -86,7 +92,7 @@ class ResourceLoader { MAX_LOADERS = 64 }; - static ResourceFormatLoader *loader[MAX_LOADERS]; + static Ref<ResourceFormatLoader> loader[MAX_LOADERS]; static int loader_count; static bool timestamp_on_load; @@ -109,13 +115,16 @@ class ResourceLoader { static ResourceLoadedCallback _loaded_callback; + static Ref<ResourceFormatLoader> _find_custom_resource_format_loader(String path); + public: static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); 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); - static void add_resource_format_loader(ResourceFormatLoader *p_format_loader, bool p_at_front = false); + static void add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front = false); + static void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader); static String get_resource_type(const String &p_path); static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); @@ -156,6 +165,11 @@ public: static void set_load_callback(ResourceLoadedCallback p_callback); static ResourceLoaderImport import; + + static bool add_custom_resource_format_loader(String script_path); + static void remove_custom_resource_format_loader(String script_path); + static void add_custom_loaders(); + static void remove_custom_loaders(); }; #endif diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 097e81e308..af726d9e2d 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -29,18 +29,62 @@ /*************************************************************************/ #include "resource_saver.h" - #include "core/io/resource_loader.h" #include "core/os/file_access.h" #include "core/project_settings.h" #include "core/script_language.h" -ResourceFormatSaver *ResourceSaver::saver[MAX_SAVERS]; +Ref<ResourceFormatSaver> ResourceSaver::saver[MAX_SAVERS]; int ResourceSaver::saver_count = 0; bool ResourceSaver::timestamp_on_save = false; ResourceSavedCallback ResourceSaver::save_callback = 0; +Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + + if (get_script_instance() && get_script_instance()->has_method("save")) { + return (Error)get_script_instance()->call("save", p_path, p_resource, p_flags).operator int64_t(); + } + + return ERR_METHOD_NOT_FOUND; +} + +bool ResourceFormatSaver::recognize(const RES &p_resource) const { + + if (get_script_instance() && get_script_instance()->has_method("recognize")) { + return get_script_instance()->call("recognize", p_resource); + } + + return false; +} + +void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { + + if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { + PoolStringArray exts = get_script_instance()->call("get_recognized_extensions", p_resource); + + { + PoolStringArray::Read r = exts.read(); + for (int i = 0; i < exts.size(); ++i) { + p_extensions->push_back(r[i]); + } + } + } +} + +void ResourceFormatSaver::_bind_methods() { + + { + PropertyInfo arg0 = PropertyInfo(Variant::STRING, "path"); + PropertyInfo arg1 = PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"); + PropertyInfo arg2 = PropertyInfo(Variant::INT, "flags"); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "save", arg0, arg1, arg2)); + } + + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::POOL_STRING_ARRAY, "get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "recognize", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); +} + Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { String extension = p_path.get_extension(); @@ -113,8 +157,9 @@ void ResourceSaver::get_recognized_extensions(const RES &p_resource, List<String } } -void ResourceSaver::add_resource_format_saver(ResourceFormatSaver *p_format_saver, bool p_at_front) { +void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front) { + ERR_FAIL_COND(p_format_saver.is_null()); ERR_FAIL_COND(saver_count >= MAX_SAVERS); if (p_at_front) { @@ -127,3 +172,102 @@ void ResourceSaver::add_resource_format_saver(ResourceFormatSaver *p_format_save saver[saver_count++] = p_format_saver; } } + +void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver) { + + ERR_FAIL_COND(p_format_saver.is_null()); + + // Find saver + int i = 0; + for (; i < saver_count; ++i) { + if (saver[i] == p_format_saver) + break; + } + + ERR_FAIL_COND(i >= saver_count); // Not found + + // Shift next savers up + for (; i < saver_count - 1; ++i) { + saver[i] = saver[i + 1]; + } + saver[saver_count - 1].unref(); + --saver_count; +} + +Ref<ResourceFormatSaver> ResourceSaver::_find_custom_resource_format_saver(String path) { + for (int i = 0; i < saver_count; ++i) { + if (saver[i]->get_script_instance() && saver[i]->get_script_instance()->get_script()->get_path() == path) { + return saver[i]; + } + } + return Ref<ResourceFormatSaver>(); +} + +bool ResourceSaver::add_custom_resource_format_saver(String script_path) { + + if (_find_custom_resource_format_saver(script_path).is_valid()) + return false; + + Ref<Resource> res = ResourceLoader::load(script_path); + ERR_FAIL_COND_V(res.is_null(), false); + ERR_FAIL_COND_V(!res->is_class("Script"), false); + + Ref<Script> s = res; + StringName ibt = s->get_instance_base_type(); + bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatSaver"); + ERR_EXPLAIN("Script does not inherit a CustomResourceSaver: " + script_path); + ERR_FAIL_COND_V(!valid_type, false); + + Object *obj = ClassDB::instance(ibt); + + ERR_EXPLAIN("Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt)); + ERR_FAIL_COND_V(obj == NULL, false); + + ResourceFormatSaver *crl = NULL; + crl = Object::cast_to<ResourceFormatSaver>(obj); + crl->set_script(s.get_ref_ptr()); + ResourceSaver::add_resource_format_saver(crl); + + return true; +} + +void ResourceSaver::remove_custom_resource_format_saver(String script_path) { + + Ref<ResourceFormatSaver> saver = _find_custom_resource_format_saver(script_path); + if (saver.is_valid()) + remove_resource_format_saver(saver); +} + +void ResourceSaver::add_custom_savers() { + // Custom resource savers exploits global class names + + String custom_saver_base_class = ResourceFormatSaver::get_class_static(); + + List<StringName> global_classes; + ScriptServer::get_global_class_list(&global_classes); + + for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { + + StringName class_name = E->get(); + StringName base_class = ScriptServer::get_global_class_base(class_name); + + if (base_class == custom_saver_base_class) { + String path = ScriptServer::get_global_class_path(class_name); + add_custom_resource_format_saver(path); + } + } +} + +void ResourceSaver::remove_custom_savers() { + + Vector<Ref<ResourceFormatSaver> > custom_savers; + for (int i = 0; i < saver_count; ++i) { + if (saver[i]->get_script_instance()) { + custom_savers.push_back(saver[i]); + } + } + + for (int i = 0; i < custom_savers.size(); ++i) { + remove_resource_format_saver(custom_savers[i]); + } +} diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index cdd43292a2..1a250e84ea 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -37,11 +37,16 @@ @author Juan Linietsky <reduzio@gmail.com> */ -class ResourceFormatSaver { +class ResourceFormatSaver : public Reference { + GDCLASS(ResourceFormatSaver, Reference) + +protected: + static void _bind_methods(); + public: - virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) = 0; - virtual bool recognize(const RES &p_resource) const = 0; - virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const = 0; + virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); + virtual bool recognize(const RES &p_resource) const; + virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; virtual ~ResourceFormatSaver() {} }; @@ -54,11 +59,13 @@ class ResourceSaver { MAX_SAVERS = 64 }; - static ResourceFormatSaver *saver[MAX_SAVERS]; + static Ref<ResourceFormatSaver> saver[MAX_SAVERS]; static int saver_count; static bool timestamp_on_save; static ResourceSavedCallback save_callback; + static Ref<ResourceFormatSaver> _find_custom_resource_format_saver(String path); + public: enum SaverFlags { @@ -73,12 +80,18 @@ public: static Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); static void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions); - static void add_resource_format_saver(ResourceFormatSaver *p_format_saver, bool p_at_front = false); + static void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front = false); + static void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver); static void set_timestamp_on_save(bool p_timestamp) { timestamp_on_save = p_timestamp; } static bool get_timestamp_on_save() { return timestamp_on_save; } static void set_save_callback(ResourceSavedCallback p_callback); + + static bool add_custom_resource_format_saver(String script_path); + static void remove_custom_resource_format_saver(String script_path); + static void add_custom_savers(); + static void remove_custom_savers(); }; #endif diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index 670a9fdd7e..9543307cb5 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -36,6 +36,7 @@ #include "core/translation.h" class TranslationLoaderPO : public ResourceFormatLoader { + GDCLASS(TranslationLoaderPO, ResourceFormatLoader) public: static RES load_translation(FileAccess *f, Error *r_error, const String &p_path = String()); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 6b776cb0b1..61fd3043a5 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -65,11 +65,11 @@ #include "core/translation.h" #include "core/undo_redo.h" -static ResourceFormatSaverBinary *resource_saver_binary = NULL; -static ResourceFormatLoaderBinary *resource_loader_binary = NULL; -static ResourceFormatImporter *resource_format_importer = NULL; +static Ref<ResourceFormatSaverBinary> resource_saver_binary; +static Ref<ResourceFormatLoaderBinary> resource_loader_binary; +static Ref<ResourceFormatImporter> resource_format_importer; -static ResourceFormatLoaderImage *resource_format_image = NULL; +static Ref<ResourceFormatLoaderImage> resource_format_image; static _ResourceLoader *_resource_loader = NULL; static _ResourceSaver *_resource_saver = NULL; @@ -77,7 +77,7 @@ static _OS *_os = NULL; static _Engine *_engine = NULL; static _ClassDB *_classdb = NULL; static _Marshalls *_marshalls = NULL; -static TranslationLoaderPO *resource_format_po = NULL; +static Ref<TranslationLoaderPO> resource_format_po; static _JSON *_json = NULL; static IP *ip = NULL; @@ -106,18 +106,18 @@ void register_core_types() { CoreStringNames::create(); - resource_format_po = memnew(TranslationLoaderPO); + resource_format_po.instance(); ResourceLoader::add_resource_format_loader(resource_format_po); - resource_saver_binary = memnew(ResourceFormatSaverBinary); + resource_saver_binary.instance(); ResourceSaver::add_resource_format_saver(resource_saver_binary); - resource_loader_binary = memnew(ResourceFormatLoaderBinary); + resource_loader_binary.instance(); ResourceLoader::add_resource_format_loader(resource_loader_binary); - resource_format_importer = memnew(ResourceFormatImporter); + resource_format_importer.instance(); ResourceLoader::add_resource_format_loader(resource_format_importer); - resource_format_image = memnew(ResourceFormatLoaderImage); + resource_format_image.instance(); ResourceLoader::add_resource_format_loader(resource_format_image); ClassDB::register_class<Object>(); @@ -165,6 +165,9 @@ void register_core_types() { ClassDB::register_virtual_class<ResourceInteractiveLoader>(); + ClassDB::register_class<ResourceFormatLoader>(); + ClassDB::register_class<ResourceFormatSaver>(); + ClassDB::register_class<_File>(); ClassDB::register_class<_Directory>(); ClassDB::register_class<_Thread>(); @@ -248,16 +251,28 @@ void unregister_core_types() { memdelete(_geometry); - if (resource_format_image) - memdelete(resource_format_image); - if (resource_saver_binary) - memdelete(resource_saver_binary); - if (resource_loader_binary) - memdelete(resource_loader_binary); - if (resource_format_importer) - memdelete(resource_format_importer); + if (resource_format_image.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_format_image); + resource_format_image.unref(); + } + + if (resource_saver_binary.is_valid()) { + ResourceSaver::remove_resource_format_saver(resource_saver_binary); + resource_saver_binary.unref(); + } + + if (resource_loader_binary.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_loader_binary); + resource_loader_binary.unref(); + } + + if (resource_format_importer.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_format_importer); + resource_format_importer.unref(); + } - memdelete(resource_format_po); + ResourceLoader::remove_resource_format_loader(resource_format_po); + resource_format_po.unref(); if (ip) memdelete(ip); diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 3d41c374ea..f2f521c196 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -268,7 +268,24 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) { case Operation::TYPE_METHOD: { - obj->call(op.name, VARIANT_ARGS_FROM_ARRAY(op.args)); + Vector<const Variant *> argptrs; + argptrs.resize(VARIANT_ARG_MAX); + int argc = 0; + + for (int i = 0; i < VARIANT_ARG_MAX; i++) { + if (op.args[i].get_type() == Variant::NIL) { + break; + } + argptrs.write[i] = &op.args[i]; + argc++; + } + argptrs.resize(argc); + + Variant::CallError ce; + obj->call(op.name, (const Variant **)argptrs.ptr(), argc, ce); + if (ce.error != Variant::CallError::CALL_OK) { + ERR_PRINTS("Error calling method from signal '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, (const Variant **)argptrs.ptr(), argc, ce)); + } #ifdef TOOLS_ENABLED Resource *res = Object::cast_to<Resource>(obj); if (res) diff --git a/core/ustring.cpp b/core/ustring.cpp index 3f017fa985..083a1eaed6 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -179,7 +179,7 @@ void String::copy_from_unchecked(const CharType *p_char, const int p_length) { resize(p_length + 1); set(p_length, 0); - CharType *dst = &operator[](0); + CharType *dst = ptrw(); for (int i = 0; i < p_length; i++) { dst[i] = p_char[i]; @@ -250,7 +250,7 @@ String &String::operator+=(const String &p_str) { resize(length() + p_str.size()); const CharType *src = p_str.c_str(); - CharType *dst = &operator[](0); + CharType *dst = ptrw(); set(length(), 0); @@ -289,7 +289,7 @@ String &String::operator+=(const char *p_str) { resize(from + src_len + 1); - CharType *dst = &operator[](0); + CharType *dst = ptrw(); set(length(), 0); @@ -1431,7 +1431,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } resize(str_size + 1); - CharType *dst = &operator[](0); + CharType *dst = ptrw(); dst[str_size] = 0; while (cstr_size) { @@ -3476,7 +3476,7 @@ String String::xml_unescape() const { if (len == 0) return String(); str.resize(len + 1); - _xml_unescape(c_str(), l, &str[0]); + _xml_unescape(c_str(), l, str.ptrw()); str[len] = 0; return str; } diff --git a/core/ustring.h b/core/ustring.h index 8e4dbd8031..e7b13027ea 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -40,6 +40,36 @@ @author Juan Linietsky <reduzio@gmail.com> */ +template <class T> +class CharProxy { + friend class CharString; + friend class String; + + const int _index; + CowData<T> &_cowdata; + + _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &cowdata) : + _index(p_index), + _cowdata(cowdata) {} + +public: + _FORCE_INLINE_ operator T() const { + return _cowdata.get(_index); + } + + _FORCE_INLINE_ const T *operator&() const { + return _cowdata.ptr() + _index; + } + + _FORCE_INLINE_ void operator=(const T &other) const { + _cowdata.set(_index, other); + } + + _FORCE_INLINE_ void operator=(const CharProxy<T> &other) const { + _cowdata.set(_index, other.operator T()); + } +}; + class CharString { CowData<char> _cowdata; @@ -53,8 +83,8 @@ public: _FORCE_INLINE_ char get(int p_index) { return _cowdata.get(p_index); } _FORCE_INLINE_ const char get(int p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ void set(int p_index, const char &p_elem) { _cowdata.set(p_index, p_elem); } - _FORCE_INLINE_ char &operator[](int p_index) { return _cowdata.get_m(p_index); } _FORCE_INLINE_ const char &operator[](int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ CharProxy<char> operator[](int p_index) { return CharProxy<char>(p_index, _cowdata); } _FORCE_INLINE_ CharString() {} _FORCE_INLINE_ CharString(const CharString &p_str) { _cowdata._ref(p_str._cowdata); } @@ -107,8 +137,9 @@ public: _FORCE_INLINE_ void set(int p_index, const CharType &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ int size() const { return _cowdata.size(); } Error resize(int p_size) { return _cowdata.resize(p_size); } - _FORCE_INLINE_ CharType &operator[](int p_index) { return _cowdata.get_m(p_index); } + _FORCE_INLINE_ const CharType &operator[](int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ CharProxy<CharType> operator[](int p_index) { return CharProxy<CharType>(p_index, _cowdata); } bool operator==(const String &p_str) const; bool operator!=(const String &p_str) const; diff --git a/core/vector.h b/core/vector.h index 38a1082407..2fb6f6c1c4 100644 --- a/core/vector.h +++ b/core/vector.h @@ -44,17 +44,11 @@ template <class T> class VectorWriteProxy { - friend class Vector<T>; - CowData<T> *_parent; - - _FORCE_INLINE_ VectorWriteProxy(CowData<T> *parent) : - _parent(parent){}; - public: _FORCE_INLINE_ T &operator[](int p_index) { - CRASH_BAD_INDEX(p_index, _parent->size()); + CRASH_BAD_INDEX(p_index, ((Vector<T> *)(this))->_cowdata.size()); - return _parent->ptrw()[p_index]; + return ((Vector<T> *)(this))->_cowdata.ptrw()[p_index]; } }; @@ -62,39 +56,41 @@ template <class T> class Vector { friend class VectorWriteProxy<T>; - CowData<T> *_cowdata; - public: VectorWriteProxy<T> write; +private: + CowData<T> _cowdata; + +public: bool push_back(const T &p_elem); - void remove(int p_index) { _cowdata->remove(p_index); } + void remove(int p_index) { _cowdata.remove(p_index); } void erase(const T &p_val) { int idx = find(p_val); if (idx >= 0) remove(idx); }; void invert(); - _FORCE_INLINE_ T *ptrw() { return _cowdata->ptrw(); } - _FORCE_INLINE_ const T *ptr() const { return _cowdata->ptr(); } + _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } + _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } _FORCE_INLINE_ void clear() { resize(0); } - _FORCE_INLINE_ bool empty() const { return _cowdata->empty(); } + _FORCE_INLINE_ bool empty() const { return _cowdata.empty(); } - _FORCE_INLINE_ T get(int p_index) { return _cowdata->get(p_index); } - _FORCE_INLINE_ const T get(int p_index) const { return _cowdata->get(p_index); } - _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata->set(p_index, p_elem); } - _FORCE_INLINE_ int size() const { return _cowdata->size(); } - Error resize(int p_size) { return _cowdata->resize(p_size); } - _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata->get(p_index); } - Error insert(int p_pos, const T &p_val) { return _cowdata->insert(p_pos, p_val); } + _FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); } + _FORCE_INLINE_ const T get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } + _FORCE_INLINE_ int size() const { return _cowdata.size(); } + Error resize(int p_size) { return _cowdata.resize(p_size); } + _FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); } + Error insert(int p_pos, const T &p_val) { return _cowdata.insert(p_pos, p_val); } void append_array(const Vector<T> &p_other); template <class C> void sort_custom() { - int len = _cowdata->size(); + int len = _cowdata.size(); if (len == 0) return; @@ -110,7 +106,7 @@ public: void ordered_insert(const T &p_val) { int i; - for (i = 0; i < _cowdata->size(); i++) { + for (i = 0; i < _cowdata.size(); i++) { if (p_val < operator[](i)) { break; @@ -135,20 +131,14 @@ public: return ret; } - _FORCE_INLINE_ Vector() : - _cowdata(new CowData<T>()), - write(VectorWriteProxy<T>(_cowdata)) {} - _FORCE_INLINE_ Vector(const Vector &p_from) : - _cowdata(new CowData<T>()), - write(VectorWriteProxy<T>(_cowdata)) { _cowdata->_ref(p_from._cowdata); } + _FORCE_INLINE_ Vector() {} + _FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } inline Vector &operator=(const Vector &p_from) { - _cowdata->_ref(p_from._cowdata); + _cowdata._ref(p_from._cowdata); return *this; } - _FORCE_INLINE_ ~Vector() { - delete _cowdata; - } + _FORCE_INLINE_ ~Vector() {} }; template <class T> |