diff options
author | Marc Gilleron <marc.gilleron@gmail.com> | 2018-06-11 02:59:53 +0200 |
---|---|---|
committer | Marc Gilleron <marc.gilleron@gmail.com> | 2018-12-15 05:34:53 +0000 |
commit | 065e2670af53ae2f71b78d57f8a217b4539cbbe2 (patch) | |
tree | a6b802b74f6f7ebd2018b5a3d35061bdcb91eb9d | |
parent | ca28c455bfdc8408485c217c17f07011c0b43f64 (diff) |
Added basic support for custom resource savers and loaders
77 files changed, 1102 insertions, 145 deletions
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 7ade4a2dfc..5e1ecfd230 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); @@ -155,6 +164,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 6134d9db57..38b59bdb53 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,10 +80,16 @@ 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 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/doc/classes/ResourceFormatDDS.xml b/doc/classes/ResourceFormatDDS.xml new file mode 100644 index 0000000000..e237dfc6a5 --- /dev/null +++ b/doc/classes/ResourceFormatDDS.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatDDS" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatImporter.xml b/doc/classes/ResourceFormatImporter.xml new file mode 100644 index 0000000000..fa5b44fa18 --- /dev/null +++ b/doc/classes/ResourceFormatImporter.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatImporter" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml new file mode 100644 index 0000000000..f03f0bbf54 --- /dev/null +++ b/doc/classes/ResourceFormatLoader.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoader" inherits="Reference" category="Core" version="3.1"> + <brief_description> + Loads a specific resource type from a file. + </brief_description> + <description> + Godot loads resources in the editor or in exported games using ResourceFormatLoaders. They get queried when you call `load`, or when a resource with internal dependencies is loaded. Each file type may load as a different resource type, so multiple ResourceFormatLoader are registered in the engine. + Extending this class allows you to define your own. You should give it a global class name with `class_name` for it to be registered. You may as well implement a [ResourceFormatSaver]. + Note: you can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends if the format is suitable or not for the final exported game. Example: it's better to import .PNG textures as .STEX first, so they can be loaded with better efficiency on the graphics card. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="get_dependencies" qualifiers="virtual"> + <return type="void"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="add_types" type="String"> + </argument> + <description> + If implemented, gets the dependencies of a given resource. If add_types is true, paths should be appended "::TypeName", where `TypeName` is the class name of the dependency. Note that custom resource types defined by scripts aren't known by the [ClassDB], so you might just return "Resource" for them. + </description> + </method> + <method name="get_recognized_extensions" qualifiers="virtual"> + <return type="PoolStringArray"> + </return> + <description> + Gets the list of extensions for files this loader is able to read. + </description> + </method> + <method name="get_resource_type" qualifiers="virtual"> + <return type="String"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + Gets the class name of the resource associated with the given path. If the loader cannot handle it, it should return "". Note that custom resource types defined by scripts aren't known by the [ClassDB], so you might just return "Resource" for them. + </description> + </method> + <method name="handles_type" qualifiers="virtual"> + <return type="bool"> + </return> + <argument index="0" name="typename" type="String"> + </argument> + <description> + Tells which resource class this loader can load. Note that custom resource types defined by scripts aren't known by the [ClassDB], so you might just return "Resource" for them. + </description> + </method> + <method name="load" qualifiers="virtual"> + <return type="Variant"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="original_path" type="String"> + </argument> + <description> + Loads a resource when the engine finds this loader to be compatible. original_path: If the loaded resource is the result of an import, original_path will target the source file. Returns a resource object if succeeded, or an ERR_* constant listed in [@GlobalScope] if it failed. + </description> + </method> + <method name="rename_dependencies" qualifiers="virtual"> + <return type="int"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="renames" type="String"> + </argument> + <description> + If implemented, renames dependencies within the given resource and saves it. renames is a dictionary { String => String } mapping old dependency paths to new paths. Returns OK on success, or an ERR_* constant listed in [@GlobalScope] in case of failure. + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderBMFont.xml b/doc/classes/ResourceFormatLoaderBMFont.xml new file mode 100644 index 0000000000..1e999353f8 --- /dev/null +++ b/doc/classes/ResourceFormatLoaderBMFont.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderBMFont" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderBinary.xml b/doc/classes/ResourceFormatLoaderBinary.xml new file mode 100644 index 0000000000..3c768851e2 --- /dev/null +++ b/doc/classes/ResourceFormatLoaderBinary.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderBinary" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderDynamicFont.xml b/doc/classes/ResourceFormatLoaderDynamicFont.xml new file mode 100644 index 0000000000..4cd5c9b2a6 --- /dev/null +++ b/doc/classes/ResourceFormatLoaderDynamicFont.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderDynamicFont" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderGDScript.xml b/doc/classes/ResourceFormatLoaderGDScript.xml new file mode 100644 index 0000000000..b661e4746a --- /dev/null +++ b/doc/classes/ResourceFormatLoaderGDScript.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderGDScript" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderImage.xml b/doc/classes/ResourceFormatLoaderImage.xml new file mode 100644 index 0000000000..5f7e55af28 --- /dev/null +++ b/doc/classes/ResourceFormatLoaderImage.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderImage" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderNativeScript.xml b/doc/classes/ResourceFormatLoaderNativeScript.xml new file mode 100644 index 0000000000..496602e7dd --- /dev/null +++ b/doc/classes/ResourceFormatLoaderNativeScript.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderNativeScript" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderShader.xml b/doc/classes/ResourceFormatLoaderShader.xml new file mode 100644 index 0000000000..0948810532 --- /dev/null +++ b/doc/classes/ResourceFormatLoaderShader.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderShader" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderStreamTexture.xml b/doc/classes/ResourceFormatLoaderStreamTexture.xml new file mode 100644 index 0000000000..34843f9e1a --- /dev/null +++ b/doc/classes/ResourceFormatLoaderStreamTexture.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderStreamTexture" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderText.xml b/doc/classes/ResourceFormatLoaderText.xml new file mode 100644 index 0000000000..db3b28f233 --- /dev/null +++ b/doc/classes/ResourceFormatLoaderText.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderText" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderTextureLayered.xml b/doc/classes/ResourceFormatLoaderTextureLayered.xml new file mode 100644 index 0000000000..cd31f35e49 --- /dev/null +++ b/doc/classes/ResourceFormatLoaderTextureLayered.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderTextureLayered" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderTheora.xml b/doc/classes/ResourceFormatLoaderTheora.xml new file mode 100644 index 0000000000..dff7e2f3dc --- /dev/null +++ b/doc/classes/ResourceFormatLoaderTheora.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderTheora" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatLoaderWebm.xml b/doc/classes/ResourceFormatLoaderWebm.xml new file mode 100644 index 0000000000..f2b403161e --- /dev/null +++ b/doc/classes/ResourceFormatLoaderWebm.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatLoaderWebm" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatPKM.xml b/doc/classes/ResourceFormatPKM.xml new file mode 100644 index 0000000000..aa511823d3 --- /dev/null +++ b/doc/classes/ResourceFormatPKM.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatPKM" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatPVR.xml b/doc/classes/ResourceFormatPVR.xml new file mode 100644 index 0000000000..4f3b4f670f --- /dev/null +++ b/doc/classes/ResourceFormatPVR.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatPVR" inherits="ResourceFormatLoader" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatSaver.xml b/doc/classes/ResourceFormatSaver.xml new file mode 100644 index 0000000000..d15d97fc84 --- /dev/null +++ b/doc/classes/ResourceFormatSaver.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatSaver" inherits="Reference" category="Core" version="3.1"> + <brief_description> + Saves a specific resource type to a file. + </brief_description> + <description> + The engine can save resources when you do it from the editor, or when you call `ResourceSaver.save(resource)`. This is accomplished with multiple `ResourceFormatSavers`, each handling its own format. + By default, Godot saves resources as `.tres`, `.res` or another built-in format, but you can choose to create your own format by extending this class. You should give it a global class name with `class_name` for it to be registered. You may as well implement a [ResourceFormatLoader]. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="get_recognized_extensions" qualifiers="virtual"> + <return type="PoolStringArray"> + </return> + <argument index="0" name="resource" type="Resource"> + </argument> + <description> + Gets the list of extensions for files this saver is able to write. + </description> + </method> + <method name="recognize" qualifiers="virtual"> + <return type="bool"> + </return> + <argument index="0" name="resource" type="Resource"> + </argument> + <description> + Returns true if the given resource object can be saved by this saver. + </description> + </method> + <method name="save" qualifiers="virtual"> + <return type="int"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="resource" type="Resource"> + </argument> + <argument index="2" name="flags" type="int"> + </argument> + <description> + Saves the given resource object to a file. flags is a bitmask composed with FLAG_* constants defined in [ResourceSaver]. Returns OK on success, or an ERR_* constant listed in [@GlobalScope] if it failed. + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatSaverBinary.xml b/doc/classes/ResourceFormatSaverBinary.xml new file mode 100644 index 0000000000..7afec9ba23 --- /dev/null +++ b/doc/classes/ResourceFormatSaverBinary.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatSaverBinary" inherits="ResourceFormatSaver" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatSaverGDScript.xml b/doc/classes/ResourceFormatSaverGDScript.xml new file mode 100644 index 0000000000..27964c7c9b --- /dev/null +++ b/doc/classes/ResourceFormatSaverGDScript.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatSaverGDScript" inherits="ResourceFormatSaver" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatSaverNativeScript.xml b/doc/classes/ResourceFormatSaverNativeScript.xml new file mode 100644 index 0000000000..9f8c0ccc78 --- /dev/null +++ b/doc/classes/ResourceFormatSaverNativeScript.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatSaverNativeScript" inherits="ResourceFormatSaver" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatSaverShader.xml b/doc/classes/ResourceFormatSaverShader.xml new file mode 100644 index 0000000000..cdc512dfea --- /dev/null +++ b/doc/classes/ResourceFormatSaverShader.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatSaverShader" inherits="ResourceFormatSaver" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceFormatSaverText.xml b/doc/classes/ResourceFormatSaverText.xml new file mode 100644 index 0000000000..6ae4ff4a2c --- /dev/null +++ b/doc/classes/ResourceFormatSaverText.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceFormatSaverText" inherits="ResourceFormatSaver" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/ResourceSaverPNG.xml b/doc/classes/ResourceSaverPNG.xml new file mode 100644 index 0000000000..a161a4de5f --- /dev/null +++ b/doc/classes/ResourceSaverPNG.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ResourceSaverPNG" inherits="ResourceFormatSaver" category="Core" version="3.1"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/drivers/dummy/texture_loader_dummy.h b/drivers/dummy/texture_loader_dummy.h index f0a355ec12..6809e76331 100644 --- a/drivers/dummy/texture_loader_dummy.h +++ b/drivers/dummy/texture_loader_dummy.h @@ -35,6 +35,7 @@ #include "scene/resources/texture.h" class ResourceFormatDummyTexture : public ResourceFormatLoader { + GDCLASS(ResourceFormatDummyTexture, 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/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index 34950f6723..2d5fd0882c 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -35,6 +35,7 @@ #include "core/io/resource_saver.h" class ResourceSaverPNG : public ResourceFormatSaver { + GDCLASS(ResourceSaverPNG, ResourceFormatSaver) public: static Error save_image(const String &p_path, const Ref<Image> &p_img); diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp index 9f5d9c1abf..9a6e0f45fc 100644 --- a/drivers/register_driver_types.cpp +++ b/drivers/register_driver_types.cpp @@ -42,15 +42,15 @@ #include "platform/windows/export/export.h" #endif -static ImageLoaderPNG *image_loader_png = NULL; -static ResourceSaverPNG *resource_saver_png = NULL; +static ImageLoaderPNG *image_loader_png; +static Ref<ResourceSaverPNG> resource_saver_png; void register_core_driver_types() { image_loader_png = memnew(ImageLoaderPNG); ImageLoader::add_image_format_loader(image_loader_png); - resource_saver_png = memnew(ResourceSaverPNG); + resource_saver_png.instance(); ResourceSaver::add_resource_format_saver(resource_saver_png); } @@ -58,8 +58,11 @@ void unregister_core_driver_types() { if (image_loader_png) memdelete(image_loader_png); - if (resource_saver_png) - memdelete(resource_saver_png); + + if (resource_saver_png.is_valid()) { + ResourceSaver::remove_resource_format_saver(resource_saver_png); + resource_saver_png.unref(); + } } void register_driver_types() { diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 94eb1a3399..37e2079b64 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1401,6 +1401,14 @@ void EditorFileSystem::update_script_classes() { ScriptServer::save_global_classes(); EditorNode::get_editor_data().script_class_save_icon_paths(); + + // Rescan custom loaders and savers. + // Doing the following here because the `filesystem_changed` signal fires multiple times and isn't always followed by script classes update. + // So I thought it's better to do this when script classes really get updated + ResourceLoader::remove_custom_loaders(); + ResourceLoader::add_custom_loaders(); + ResourceSaver::remove_custom_savers(); + ResourceSaver::add_custom_savers(); } void EditorFileSystem::_queue_update_script_classes() { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d009ed61b5..0ca134646a 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2471,7 +2471,7 @@ void EditorNode::_editor_select(int p_which) { } } -void EditorNode::add_editor_plugin(EditorPlugin *p_editor) { +void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) { if (p_editor->has_main_screen()) { @@ -2496,9 +2496,11 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor) { } singleton->editor_data.add_editor_plugin(p_editor); singleton->add_child(p_editor); + if (p_config_changed) + p_editor->enable_plugin(); } -void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) { +void EditorNode::remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) { if (p_editor->has_main_screen()) { @@ -2521,6 +2523,8 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) { } p_editor->make_visible(false); p_editor->clear(); + if (p_config_changed) + p_editor->disable_plugin(); singleton->editor_plugins_over->get_plugins_list().erase(p_editor); singleton->remove_child(p_editor); singleton->editor_data.remove_editor_plugin(p_editor); @@ -2546,7 +2550,7 @@ void EditorNode::_update_addon_config() { project_settings->queue_save(); } -void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled) { +void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed) { ERR_FAIL_COND(p_enabled && plugin_addons.has(p_addon)); ERR_FAIL_COND(!p_enabled && !plugin_addons.has(p_addon)); @@ -2554,7 +2558,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled) if (!p_enabled) { EditorPlugin *addon = plugin_addons[p_addon]; - remove_editor_plugin(addon); + remove_editor_plugin(addon, p_config_changed); memdelete(addon); //bye plugin_addons.erase(p_addon); _update_addon_config(); @@ -2606,7 +2610,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled) ep->set_script(script.get_ref_ptr()); ep->set_dir_cache(p_addon); plugin_addons[p_addon] = ep; - add_editor_plugin(ep); + add_editor_plugin(ep, p_config_changed); _update_addon_config(); } diff --git a/editor/editor_node.h b/editor/editor_node.h index 4d89d1f956..bc0710a3ee 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -639,8 +639,8 @@ public: ProjectSettingsEditor *get_project_settings() { return project_settings; } - static void add_editor_plugin(EditorPlugin *p_editor); - static void remove_editor_plugin(EditorPlugin *p_editor); + static void add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); + static void remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); } @@ -653,7 +653,7 @@ public: void add_control_to_dock(DockSlot p_slot, Control *p_control); void remove_control_from_dock(Control *p_control); - void set_addon_plugin_enabled(const String &p_addon, bool p_enabled); + void set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed = false); bool is_addon_plugin_enabled(const String &p_addon) const; void edit_node(Node *p_node); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 86b2db877e..0d4574e097 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -698,6 +698,34 @@ void EditorPlugin::remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_ ResourceImporterScene::get_singleton()->remove_importer(p_importer); } +int find(const PoolStringArray &a, const String &v) { + PoolStringArray::Read r = a.read(); + for (int j = 0; j < a.size(); ++j) { + if (r[j] == v) { + return j; + } + } + return -1; +} + +void EditorPlugin::enable_plugin() { + // Called when the plugin gets enabled in project settings, after it's added to the tree. + // You can implement it to register autoloads. + + if (get_script_instance() && get_script_instance()->has_method("enable_plugin")) { + get_script_instance()->call("enable_plugin"); + } +} + +void EditorPlugin::disable_plugin() { + // Last function called when the plugin gets disabled in project settings. + // Implement it to cleanup things from the project, such as unregister autoloads. + + if (get_script_instance() && get_script_instance()->has_method("disable_plugin")) { + get_script_instance()->call("disable_plugin"); + } +} + void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) { if (get_script_instance() && get_script_instance()->has_method("set_window_layout")) { @@ -801,6 +829,8 @@ void EditorPlugin::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo("set_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "build")); + ClassDB::add_virtual_method(get_class_static(), MethodInfo("enable_plugin")); + ClassDB::add_virtual_method(get_class_static(), MethodInfo("disable_plugin")); ADD_SIGNAL(MethodInfo("scene_changed", PropertyInfo(Variant::OBJECT, "scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("scene_closed", PropertyInfo(Variant::STRING, "filepath"))); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index e03aeb5d30..5f060a4e96 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -232,6 +232,9 @@ public: String get_dir_cache() { return _dir_cache; } Ref<ConfigFile> get_config(); + void enable_plugin(); + void disable_plugin(); + EditorPlugin(); virtual ~EditorPlugin(); }; diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 30027c0c34..a4d543c567 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -152,7 +152,7 @@ void EditorPluginSettings::_plugin_activity_changed() { bool active = ti->get_range(3); String name = ti->get_metadata(0); - EditorNode::get_singleton()->set_addon_plugin_enabled(name, active); + EditorNode::get_singleton()->set_addon_plugin_enabled(name, active, true); bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(name); diff --git a/main/main.cpp b/main/main.cpp index db23a6c214..fd9054bf93 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1230,6 +1230,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { register_driver_types(); + // This loads global classes, so it must happen before custom loaders and savers are registered ScriptServer::init_languages(); MAIN_PRINT("Main: Load Translations"); @@ -1489,6 +1490,9 @@ bool Main::start() { } #endif + ResourceLoader::add_custom_loaders(); + ResourceSaver::add_custom_savers(); + if (!project_manager && !editor) { // game if (game_path != "" || script != "") { //autoload @@ -1956,11 +1960,13 @@ void Main::force_redraw() { * so that the engine closes cleanly without leaking memory or crashing. * The order matters as some of those steps are linked with each other. */ - void Main::cleanup() { ERR_FAIL_COND(!_start_success); + ResourceLoader::remove_custom_loaders(); + ResourceSaver::remove_custom_savers(); + message_queue->flush(); memdelete(message_queue); diff --git a/modules/dds/register_types.cpp b/modules/dds/register_types.cpp index d6351fb6fe..94f0ebfd5f 100644 --- a/modules/dds/register_types.cpp +++ b/modules/dds/register_types.cpp @@ -32,15 +32,16 @@ #include "texture_loader_dds.h" -static ResourceFormatDDS *resource_loader_dds = NULL; +static Ref<ResourceFormatDDS> resource_loader_dds; void register_dds_types() { - resource_loader_dds = memnew(ResourceFormatDDS); + resource_loader_dds.instance(); ResourceLoader::add_resource_format_loader(resource_loader_dds); } void unregister_dds_types() { - memdelete(resource_loader_dds); + ResourceLoader::remove_resource_format_loader(resource_loader_dds); + resource_loader_dds.unref(); } diff --git a/modules/dds/texture_loader_dds.h b/modules/dds/texture_loader_dds.h index 4e2593c744..abd747f63e 100644 --- a/modules/dds/texture_loader_dds.h +++ b/modules/dds/texture_loader_dds.h @@ -35,6 +35,7 @@ #include "scene/resources/texture.h" class ResourceFormatDDS : public ResourceFormatLoader { + GDCLASS(ResourceFormatDDS, 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/modules/etc/register_types.cpp b/modules/etc/register_types.cpp index 1d1f0e1b77..301193874d 100644 --- a/modules/etc/register_types.cpp +++ b/modules/etc/register_types.cpp @@ -33,11 +33,11 @@ #include "image_etc.h" #include "texture_loader_pkm.h" -static ResourceFormatPKM *resource_loader_pkm = NULL; +static Ref<ResourceFormatPKM> resource_loader_pkm; void register_etc_types() { - resource_loader_pkm = memnew(ResourceFormatPKM); + resource_loader_pkm.instance(); ResourceLoader::add_resource_format_loader(resource_loader_pkm); _register_etc_compress_func(); @@ -45,5 +45,6 @@ void register_etc_types() { void unregister_etc_types() { - memdelete(resource_loader_pkm); + ResourceLoader::remove_resource_format_loader(resource_loader_pkm); + resource_loader_pkm.unref(); } diff --git a/modules/etc/texture_loader_pkm.h b/modules/etc/texture_loader_pkm.h index b5a95767c7..8308b84109 100644 --- a/modules/etc/texture_loader_pkm.h +++ b/modules/etc/texture_loader_pkm.h @@ -35,6 +35,7 @@ #include "scene/resources/texture.h" class ResourceFormatPKM : public ResourceFormatLoader { + GDCLASS(ResourceFormatPKM, 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/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index c5364a72ac..528344a814 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -161,6 +161,7 @@ public: }; class GDNativeLibraryResourceLoader : public ResourceFormatLoader { + GDCLASS(GDNativeLibraryResourceLoader, ResourceFormatLoader) public: virtual RES load(const String &p_path, const String &p_original_path, Error *r_error); virtual void get_recognized_extensions(List<String> *p_extensions) const; @@ -169,6 +170,7 @@ public: }; class GDNativeLibraryResourceSaver : public ResourceFormatSaver { + GDCLASS(GDNativeLibraryResourceSaver, ResourceFormatSaver) public: virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags); virtual bool recognize(const RES &p_resource) const; diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index e6f3c06ee5..67fb54387d 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -380,6 +380,7 @@ public: }; class ResourceFormatLoaderNativeScript : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderNativeScript, 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; @@ -388,6 +389,7 @@ public: }; class ResourceFormatSaverNativeScript : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverNativeScript, ResourceFormatSaver) 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; diff --git a/modules/gdnative/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp index 4433c0a638..1e0c3d9fd8 100644 --- a/modules/gdnative/nativescript/register_types.cpp +++ b/modules/gdnative/nativescript/register_types.cpp @@ -39,8 +39,8 @@ NativeScriptLanguage *native_script_language; -ResourceFormatLoaderNativeScript *resource_loader_gdns = NULL; -ResourceFormatSaverNativeScript *resource_saver_gdns = NULL; +Ref<ResourceFormatLoaderNativeScript> resource_loader_gdns; +Ref<ResourceFormatSaverNativeScript> resource_saver_gdns; void register_nativescript_types() { native_script_language = memnew(NativeScriptLanguage); @@ -50,18 +50,20 @@ void register_nativescript_types() { native_script_language->set_language_index(ScriptServer::get_language_count()); ScriptServer::register_language(native_script_language); - resource_saver_gdns = memnew(ResourceFormatSaverNativeScript); + resource_saver_gdns.instance(); ResourceSaver::add_resource_format_saver(resource_saver_gdns); - resource_loader_gdns = memnew(ResourceFormatLoaderNativeScript); + resource_loader_gdns.instance(); ResourceLoader::add_resource_format_loader(resource_loader_gdns); } void unregister_nativescript_types() { - memdelete(resource_loader_gdns); + ResourceLoader::remove_resource_format_loader(resource_loader_gdns); + resource_loader_gdns.unref(); - memdelete(resource_saver_gdns); + ResourceSaver::remove_resource_format_saver(resource_saver_gdns); + resource_saver_gdns.unref(); if (native_script_language) { ScriptServer::unregister_language(native_script_language); diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp index 2b538c4a36..0cda8859dd 100644 --- a/modules/gdnative/pluginscript/pluginscript_language.cpp +++ b/modules/gdnative/pluginscript/pluginscript_language.cpp @@ -417,8 +417,8 @@ void PluginScriptLanguage::unlock() { PluginScriptLanguage::PluginScriptLanguage(const godot_pluginscript_language_desc *desc) : _desc(*desc) { - _resource_loader = memnew(ResourceFormatLoaderPluginScript(this)); - _resource_saver = memnew(ResourceFormatSaverPluginScript(this)); + _resource_loader = Ref<ResourceFormatLoaderPluginScript>(memnew(ResourceFormatLoaderPluginScript(this))); + _resource_saver = Ref<ResourceFormatSaverPluginScript>(memnew(ResourceFormatSaverPluginScript(this))); // TODO: totally remove _lock attribute if NO_THREADS is set #ifdef NO_THREADS @@ -429,8 +429,6 @@ PluginScriptLanguage::PluginScriptLanguage(const godot_pluginscript_language_des } PluginScriptLanguage::~PluginScriptLanguage() { - memdelete(_resource_loader); - memdelete(_resource_saver); #ifndef NO_THREADS if (_lock) { memdelete(_lock); diff --git a/modules/gdnative/pluginscript/pluginscript_language.h b/modules/gdnative/pluginscript/pluginscript_language.h index c4df6f3a33..f749e900f5 100644 --- a/modules/gdnative/pluginscript/pluginscript_language.h +++ b/modules/gdnative/pluginscript/pluginscript_language.h @@ -48,8 +48,8 @@ class PluginScriptLanguage : public ScriptLanguage { friend class PluginScript; friend class PluginScriptInstance; - ResourceFormatLoaderPluginScript *_resource_loader; - ResourceFormatSaverPluginScript *_resource_saver; + Ref<ResourceFormatLoaderPluginScript> _resource_loader; + Ref<ResourceFormatSaverPluginScript> _resource_saver; const godot_pluginscript_language_desc _desc; godot_pluginscript_language_data *_data; @@ -59,8 +59,8 @@ class PluginScriptLanguage : public ScriptLanguage { public: virtual String get_name() const; - _FORCE_INLINE_ ResourceFormatLoaderPluginScript *get_resource_loader() { return _resource_loader; }; - _FORCE_INLINE_ ResourceFormatSaverPluginScript *get_resource_saver() { return _resource_saver; }; + _FORCE_INLINE_ Ref<ResourceFormatLoaderPluginScript> get_resource_loader() { return _resource_loader; } + _FORCE_INLINE_ Ref<ResourceFormatSaverPluginScript> get_resource_saver() { return _resource_saver; } /* LANGUAGE FUNCTIONS */ virtual void init(); diff --git a/modules/gdnative/pluginscript/pluginscript_loader.h b/modules/gdnative/pluginscript/pluginscript_loader.h index 5c17bb932e..ee9869be84 100644 --- a/modules/gdnative/pluginscript/pluginscript_loader.h +++ b/modules/gdnative/pluginscript/pluginscript_loader.h @@ -39,6 +39,9 @@ class PluginScriptLanguage; class ResourceFormatLoaderPluginScript : public ResourceFormatLoader { + + GDCLASS(ResourceFormatLoaderPluginScript, ResourceFormatLoader) + PluginScriptLanguage *_language; public: @@ -50,6 +53,9 @@ public: }; class ResourceFormatSaverPluginScript : public ResourceFormatSaver { + + GDCLASS(ResourceFormatSaverPluginScript, ResourceFormatSaver) + PluginScriptLanguage *_language; public: diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 62e87c3651..51f0b9afcc 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -299,8 +299,8 @@ GDNativeCallRegistry *GDNativeCallRegistry::singleton; Vector<Ref<GDNative> > singleton_gdnatives; -GDNativeLibraryResourceLoader *resource_loader_gdnlib = NULL; -GDNativeLibraryResourceSaver *resource_saver_gdnlib = NULL; +Ref<GDNativeLibraryResourceLoader> resource_loader_gdnlib; +Ref<GDNativeLibraryResourceSaver> resource_saver_gdnlib; void register_gdnative_types() { @@ -312,8 +312,8 @@ void register_gdnative_types() { ClassDB::register_class<GDNativeLibrary>(); ClassDB::register_class<GDNative>(); - resource_loader_gdnlib = memnew(GDNativeLibraryResourceLoader); - resource_saver_gdnlib = memnew(GDNativeLibraryResourceSaver); + resource_loader_gdnlib.instance(); + resource_saver_gdnlib.instance(); ResourceLoader::add_resource_format_loader(resource_loader_gdnlib); ResourceSaver::add_resource_format_saver(resource_saver_gdnlib); @@ -391,8 +391,11 @@ void unregister_gdnative_types() { } #endif - memdelete(resource_loader_gdnlib); - memdelete(resource_saver_gdnlib); + ResourceLoader::remove_resource_format_loader(resource_loader_gdnlib); + ResourceSaver::remove_resource_format_saver(resource_saver_gdnlib); + + resource_loader_gdnlib.unref(); + resource_saver_gdnlib.unref(); // This is for printing out the sizes of the core types diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 752d660ffb..3e7cb076aa 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -500,6 +500,7 @@ public: }; class ResourceFormatLoaderGDScript : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderGDScript, 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; @@ -508,6 +509,7 @@ public: }; class ResourceFormatSaverGDScript : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverGDScript, ResourceFormatSaver) public: virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 26dcbdcf89..9c4dc0c926 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -38,8 +38,8 @@ #include "gdscript_tokenizer.h" GDScriptLanguage *script_language_gd = NULL; -ResourceFormatLoaderGDScript *resource_loader_gd = NULL; -ResourceFormatSaverGDScript *resource_saver_gd = NULL; +Ref<ResourceFormatLoaderGDScript> resource_loader_gd; +Ref<ResourceFormatSaverGDScript> resource_saver_gd; #ifdef TOOLS_ENABLED @@ -87,9 +87,11 @@ void register_gdscript_types() { script_language_gd = memnew(GDScriptLanguage); ScriptServer::register_language(script_language_gd); - resource_loader_gd = memnew(ResourceFormatLoaderGDScript); + + resource_loader_gd.instance(); ResourceLoader::add_resource_format_loader(resource_loader_gd); - resource_saver_gd = memnew(ResourceFormatSaverGDScript); + + resource_saver_gd.instance(); ResourceSaver::add_resource_format_saver(resource_saver_gd); #ifdef TOOLS_ENABLED @@ -104,8 +106,14 @@ void unregister_gdscript_types() { if (script_language_gd) memdelete(script_language_gd); - if (resource_loader_gd) - memdelete(resource_loader_gd); - if (resource_saver_gd) - memdelete(resource_saver_gd); + + if (resource_loader_gd.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_loader_gd); + resource_loader_gd.unref(); + } + + if (resource_saver_gd.is_valid()) { + ResourceSaver::remove_resource_format_saver(resource_saver_gd); + resource_saver_gd.unref(); + } } diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 501e0d9d6d..e62cd49172 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -398,6 +398,7 @@ public: }; class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderCSharpScript, 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; @@ -406,6 +407,7 @@ public: }; class ResourceFormatSaverCSharpScript : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverCSharpScript, ResourceFormatSaver) public: virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp index f6cb143e8e..9ee7a0b5c4 100644 --- a/modules/mono/register_types.cpp +++ b/modules/mono/register_types.cpp @@ -35,8 +35,8 @@ #include "csharp_script.h" CSharpLanguage *script_language_cs = NULL; -ResourceFormatLoaderCSharpScript *resource_loader_cs = NULL; -ResourceFormatSaverCSharpScript *resource_saver_cs = NULL; +Ref<ResourceFormatLoaderCSharpScript> resource_loader_cs; +Ref<ResourceFormatSaverCSharpScript> resource_saver_cs; _GodotSharp *_godotsharp = NULL; @@ -52,9 +52,10 @@ void register_mono_types() { script_language_cs->set_language_index(ScriptServer::get_language_count()); ScriptServer::register_language(script_language_cs); - resource_loader_cs = memnew(ResourceFormatLoaderCSharpScript); + resource_loader_cs.instance(); ResourceLoader::add_resource_format_loader(resource_loader_cs); - resource_saver_cs = memnew(ResourceFormatSaverCSharpScript); + + resource_saver_cs.instance(); ResourceSaver::add_resource_format_saver(resource_saver_cs); } @@ -63,10 +64,16 @@ void unregister_mono_types() { if (script_language_cs) memdelete(script_language_cs); - if (resource_loader_cs) - memdelete(resource_loader_cs); - if (resource_saver_cs) - memdelete(resource_saver_cs); + + if (resource_loader_cs.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_loader_cs); + resource_loader_cs.unref(); + } + + if (resource_saver_cs.is_valid()) { + ResourceSaver::remove_resource_format_saver(resource_saver_cs); + resource_saver_cs.unref(); + } if (_godotsharp) memdelete(_godotsharp); diff --git a/modules/opus/audio_stream_opus.h b/modules/opus/audio_stream_opus.h index c004adeb77..c962936238 100644 --- a/modules/opus/audio_stream_opus.h +++ b/modules/opus/audio_stream_opus.h @@ -132,6 +132,7 @@ public: }; class ResourceFormatLoaderAudioStreamOpus : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderAudioStreamOpus, 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/modules/opus/register_types.cpp b/modules/opus/register_types.cpp index f34555841e..3367fc1090 100644 --- a/modules/opus/register_types.cpp +++ b/modules/opus/register_types.cpp @@ -32,7 +32,7 @@ #include "audio_stream_opus.h" -static ResourceFormatLoaderAudioStreamOpus *opus_stream_loader = NULL; +static Ref<ResourceFormatLoaderAudioStreamOpus> opus_stream_loader; void register_opus_types() { // Sorry guys, do not enable this unless you can figure out a way diff --git a/modules/pvr/register_types.cpp b/modules/pvr/register_types.cpp index 0991828ef2..cf5bdabf3f 100644 --- a/modules/pvr/register_types.cpp +++ b/modules/pvr/register_types.cpp @@ -32,15 +32,16 @@ #include "texture_loader_pvr.h" -static ResourceFormatPVR *resource_loader_pvr = NULL; +static Ref<ResourceFormatPVR> resource_loader_pvr; void register_pvr_types() { - resource_loader_pvr = memnew(ResourceFormatPVR); + resource_loader_pvr.instance(); ResourceLoader::add_resource_format_loader(resource_loader_pvr); } void unregister_pvr_types() { - memdelete(resource_loader_pvr); + ResourceLoader::remove_resource_format_loader(resource_loader_pvr); + resource_loader_pvr.unref(); } diff --git a/modules/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h index c859a4cdda..530b6948f0 100644 --- a/modules/pvr/texture_loader_pvr.h +++ b/modules/pvr/texture_loader_pvr.h @@ -35,6 +35,7 @@ #include "scene/resources/texture.h" class ResourceFormatPVR : public ResourceFormatLoader { + GDCLASS(ResourceFormatPVR, 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/modules/theora/register_types.cpp b/modules/theora/register_types.cpp index 971fe39c44..3da721c6a0 100644 --- a/modules/theora/register_types.cpp +++ b/modules/theora/register_types.cpp @@ -32,11 +32,11 @@ #include "video_stream_theora.h" -static ResourceFormatLoaderTheora *resource_loader_theora = NULL; +static Ref<ResourceFormatLoaderTheora> resource_loader_theora; void register_theora_types() { - resource_loader_theora = memnew(ResourceFormatLoaderTheora); + resource_loader_theora.instance(); ResourceLoader::add_resource_format_loader(resource_loader_theora, true); ClassDB::register_class<VideoStreamTheora>(); @@ -44,7 +44,9 @@ void register_theora_types() { void unregister_theora_types() { - if (resource_loader_theora) { - memdelete(resource_loader_theora); + ResourceLoader::remove_resource_format_loader(resource_loader_theora); + + if (resource_loader_theora.is_valid()) { + resource_loader_theora.unref(); } } diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index 4be723f85b..c9629fbf9f 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -186,6 +186,7 @@ public: }; class ResourceFormatLoaderTheora : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderTheora, 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/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h index 73c4b5f3f4..7683f38991 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.h +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -127,6 +127,7 @@ public: }; class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderAudioStreamOGGVorbis, 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/modules/vorbis/register_types.cpp b/modules/vorbis/register_types.cpp index 0ea1fbe8b2..8219e9e7ba 100644 --- a/modules/vorbis/register_types.cpp +++ b/modules/vorbis/register_types.cpp @@ -32,16 +32,17 @@ #include "audio_stream_ogg_vorbis.h" -static ResourceFormatLoaderAudioStreamOGGVorbis *vorbis_stream_loader = NULL; +static Ref<ResourceFormatLoaderAudioStreamOGGVorbis> vorbis_stream_loader; void register_vorbis_types() { - vorbis_stream_loader = memnew(ResourceFormatLoaderAudioStreamOGGVorbis); + vorbis_stream_loader.instance(); ResourceLoader::add_resource_format_loader(vorbis_stream_loader); ClassDB::register_class<AudioStreamOGGVorbis>(); } void unregister_vorbis_types() { - memdelete(vorbis_stream_loader); + ResourceLoader::remove_resource_format_loader(vorbis_stream_loader); + vorbis_stream_loader.unref(); } diff --git a/modules/webm/register_types.cpp b/modules/webm/register_types.cpp index 121b528d5b..dfa2dcf21c 100644 --- a/modules/webm/register_types.cpp +++ b/modules/webm/register_types.cpp @@ -32,11 +32,11 @@ #include "video_stream_webm.h" -static ResourceFormatLoaderWebm *resource_loader_webm = NULL; +static Ref<ResourceFormatLoaderWebm> resource_loader_webm; void register_webm_types() { - resource_loader_webm = memnew(ResourceFormatLoaderWebm); + resource_loader_webm.instance(); ResourceLoader::add_resource_format_loader(resource_loader_webm, true); ClassDB::register_class<VideoStreamWebm>(); @@ -44,7 +44,9 @@ void register_webm_types() { void unregister_webm_types() { - if (resource_loader_webm) { - memdelete(resource_loader_webm); + ResourceLoader::remove_resource_format_loader(resource_loader_webm); + + if (resource_loader_webm.is_valid()) { + resource_loader_webm.unref(); } } diff --git a/modules/webm/video_stream_webm.h b/modules/webm/video_stream_webm.h index 3739a73114..9501f513a0 100644 --- a/modules/webm/video_stream_webm.h +++ b/modules/webm/video_stream_webm.h @@ -127,6 +127,7 @@ public: }; class ResourceFormatLoaderWebm : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderWebm, 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/platform/server/os_server.cpp b/platform/server/os_server.cpp index 60f20d6009..5d67e2113f 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -99,7 +99,7 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int _ensure_user_data_dir(); - resource_loader_dummy = memnew(ResourceFormatDummyTexture); + resource_loader_dummy.instance(); ResourceLoader::add_resource_format_loader(resource_loader_dummy); return OK; @@ -118,7 +118,8 @@ void OS_Server::finalize() { memdelete(power_manager); - memdelete(resource_loader_dummy); + ResourceLoader::remove_resource_format_loader(resource_loader_dummy); + resource_loader_dummy.unref(); args.clear(); } diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 0367ec3db9..b5dc7900e6 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -77,7 +77,7 @@ class OS_Server : public OS_Unix { int video_driver_index; - ResourceFormatDummyTexture *resource_loader_dummy; + Ref<ResourceFormatDummyTexture> resource_loader_dummy; protected: virtual int get_video_driver_count() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index d7750c91ef..ae6211a3df 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -210,18 +210,18 @@ #include "scene/resources/physics_material.h" #endif -static ResourceFormatSaverText *resource_saver_text = NULL; -static ResourceFormatLoaderText *resource_loader_text = NULL; +static Ref<ResourceFormatSaverText> resource_saver_text; +static Ref<ResourceFormatLoaderText> resource_loader_text; -static ResourceFormatLoaderDynamicFont *resource_loader_dynamic_font = NULL; +static Ref<ResourceFormatLoaderDynamicFont> resource_loader_dynamic_font; -static ResourceFormatLoaderStreamTexture *resource_loader_stream_texture = NULL; -static ResourceFormatLoaderTextureLayered *resource_loader_texture_layered = NULL; +static Ref<ResourceFormatLoaderStreamTexture> resource_loader_stream_texture; +static Ref<ResourceFormatLoaderTextureLayered> resource_loader_texture_layered; -static ResourceFormatLoaderBMFont *resource_loader_bmfont = NULL; +static Ref<ResourceFormatLoaderBMFont> resource_loader_bmfont; -static ResourceFormatSaverShader *resource_saver_shader = NULL; -static ResourceFormatLoaderShader *resource_loader_shader = NULL; +static Ref<ResourceFormatSaverShader> resource_saver_shader; +static Ref<ResourceFormatLoaderShader> resource_loader_shader; void register_scene_types() { @@ -231,28 +231,28 @@ void register_scene_types() { Node::init_node_hrcr(); - resource_loader_dynamic_font = memnew(ResourceFormatLoaderDynamicFont); + resource_loader_dynamic_font.instance(); ResourceLoader::add_resource_format_loader(resource_loader_dynamic_font); - resource_loader_stream_texture = memnew(ResourceFormatLoaderStreamTexture); + resource_loader_stream_texture.instance(); ResourceLoader::add_resource_format_loader(resource_loader_stream_texture); - resource_loader_texture_layered = memnew(ResourceFormatLoaderTextureLayered); + resource_loader_texture_layered.instance(); ResourceLoader::add_resource_format_loader(resource_loader_texture_layered); - resource_saver_text = memnew(ResourceFormatSaverText); + resource_saver_text.instance(); ResourceSaver::add_resource_format_saver(resource_saver_text, true); - resource_loader_text = memnew(ResourceFormatLoaderText); + resource_loader_text.instance(); ResourceLoader::add_resource_format_loader(resource_loader_text, true); - resource_saver_shader = memnew(ResourceFormatSaverShader); + resource_saver_shader.instance(); ResourceSaver::add_resource_format_saver(resource_saver_shader, true); - resource_loader_shader = memnew(ResourceFormatLoaderShader); + resource_loader_shader.instance(); ResourceLoader::add_resource_format_loader(resource_loader_shader, true); - resource_loader_bmfont = memnew(ResourceFormatLoaderBMFont); + resource_loader_bmfont.instance(); ResourceLoader::add_resource_format_loader(resource_loader_bmfont, true); OS::get_singleton()->yield(); //may take time to init @@ -735,27 +735,37 @@ void unregister_scene_types() { clear_default_theme(); - memdelete(resource_loader_dynamic_font); - memdelete(resource_loader_stream_texture); - memdelete(resource_loader_texture_layered); + ResourceLoader::remove_resource_format_loader(resource_loader_dynamic_font); + resource_loader_dynamic_font.unref(); + + ResourceLoader::remove_resource_format_loader(resource_loader_texture_layered); + resource_loader_texture_layered.unref(); + + ResourceLoader::remove_resource_format_loader(resource_loader_stream_texture); + resource_loader_stream_texture.unref(); DynamicFont::finish_dynamic_fonts(); - if (resource_saver_text) { - memdelete(resource_saver_text); + if (resource_saver_text.is_valid()) { + ResourceSaver::remove_resource_format_saver(resource_saver_text); + resource_saver_text.unref(); } - if (resource_loader_text) { - memdelete(resource_loader_text); + if (resource_loader_text.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_loader_text); + resource_loader_text.unref(); } - if (resource_saver_shader) { - memdelete(resource_saver_shader); + if (resource_saver_shader.is_valid()) { + ResourceSaver::remove_resource_format_saver(resource_saver_shader); + resource_saver_shader.unref(); } - if (resource_loader_shader) { - memdelete(resource_loader_shader); + if (resource_loader_shader.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_loader_shader); + resource_loader_shader.unref(); } - if (resource_loader_bmfont) { - memdelete(resource_loader_bmfont); + if (resource_loader_bmfont.is_valid()) { + ResourceLoader::remove_resource_format_loader(resource_loader_bmfont); + resource_loader_bmfont.unref(); } SpatialMaterial::finish_shaders(); diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 96437e8982..9c41c948bd 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -303,6 +303,7 @@ VARIANT_ENUM_CAST(DynamicFont::SpacingType); ///////////// class ResourceFormatLoaderDynamicFont : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderDynamicFont, 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/scene/resources/dynamic_font_stb.h b/scene/resources/dynamic_font_stb.h index e1ef72ea4f..c83cc1b01f 100644 --- a/scene/resources/dynamic_font_stb.h +++ b/scene/resources/dynamic_font_stb.h @@ -180,6 +180,7 @@ public: ///////////// class ResourceFormatLoaderDynamicFont : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderDynamicFont, 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/scene/resources/font.h b/scene/resources/font.h index 39e66a822d..3c5e650758 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -201,6 +201,7 @@ public: }; class ResourceFormatLoaderBMFont : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderBMFont, 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/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index 8d1af2bbb2..e5ee6ae760 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -128,7 +128,7 @@ public: }; class ResourceFormatLoaderText : public ResourceFormatLoader { - + GDCLASS(ResourceFormatLoaderText, ResourceFormatLoader) public: static ResourceFormatLoaderText *singleton; virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); @@ -170,6 +170,7 @@ public: }; class ResourceFormatSaverText : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverText, ResourceFormatSaver) public: static ResourceFormatSaverText *singleton; virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); diff --git a/scene/resources/shader.h b/scene/resources/shader.h index c2c205237f..6804832fb9 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -100,6 +100,7 @@ public: VARIANT_ENUM_CAST(Shader::Mode); class ResourceFormatLoaderShader : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderShader, 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; @@ -108,6 +109,7 @@ public: }; class ResourceFormatSaverShader : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverShader, ResourceFormatSaver) public: virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; diff --git a/scene/resources/texture.h b/scene/resources/texture.h index e9b69e9cb1..845a075015 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -236,6 +236,7 @@ public: }; class ResourceFormatLoaderStreamTexture : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderStreamTexture, 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; @@ -489,6 +490,7 @@ public: }; class ResourceFormatLoaderTextureLayered : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderTextureLayered, ResourceFormatLoader) public: enum Compression { COMPRESSION_LOSSLESS, |