summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorMarc Gilleron <marc.gilleron@gmail.com>2018-06-11 02:59:53 +0200
committerMarc Gilleron <marc.gilleron@gmail.com>2018-12-15 05:34:53 +0000
commit065e2670af53ae2f71b78d57f8a217b4539cbbe2 (patch)
treea6b802b74f6f7ebd2018b5a3d35061bdcb91eb9d /core
parentca28c455bfdc8408485c217c17f07011c0b43f64 (diff)
Added basic support for custom resource savers and loaders
Diffstat (limited to 'core')
-rw-r--r--core/io/image_loader.h1
-rw-r--r--core/io/resource_format_binary.h3
-rw-r--r--core/io/resource_import.h2
-rw-r--r--core/io/resource_loader.cpp196
-rw-r--r--core/io/resource_loader.h28
-rw-r--r--core/io/resource_saver.cpp150
-rw-r--r--core/io/resource_saver.h25
-rw-r--r--core/io/translation_loader_po.h1
-rw-r--r--core/register_core_types.cpp53
9 files changed, 419 insertions, 40 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);