From 065e2670af53ae2f71b78d57f8a217b4539cbbe2 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Mon, 11 Jun 2018 02:59:53 +0200 Subject: Added basic support for custom resource savers and loaders --- core/io/image_loader.h | 1 + core/io/resource_format_binary.h | 3 +- core/io/resource_import.h | 2 + core/io/resource_loader.cpp | 196 ++++++++++++++++++++- core/io/resource_loader.h | 28 ++- core/io/resource_saver.cpp | 150 +++++++++++++++- core/io/resource_saver.h | 25 ++- core/io/translation_loader_po.h | 1 + core/register_core_types.cpp | 53 ++++-- doc/classes/ResourceFormatDDS.xml | 15 ++ doc/classes/ResourceFormatImporter.xml | 15 ++ doc/classes/ResourceFormatLoader.xml | 77 ++++++++ doc/classes/ResourceFormatLoaderBMFont.xml | 15 ++ doc/classes/ResourceFormatLoaderBinary.xml | 15 ++ doc/classes/ResourceFormatLoaderDynamicFont.xml | 15 ++ doc/classes/ResourceFormatLoaderGDScript.xml | 15 ++ doc/classes/ResourceFormatLoaderImage.xml | 15 ++ doc/classes/ResourceFormatLoaderNativeScript.xml | 15 ++ doc/classes/ResourceFormatLoaderShader.xml | 15 ++ doc/classes/ResourceFormatLoaderStreamTexture.xml | 15 ++ doc/classes/ResourceFormatLoaderText.xml | 15 ++ doc/classes/ResourceFormatLoaderTextureLayered.xml | 15 ++ doc/classes/ResourceFormatLoaderTheora.xml | 15 ++ doc/classes/ResourceFormatLoaderWebm.xml | 15 ++ doc/classes/ResourceFormatPKM.xml | 15 ++ doc/classes/ResourceFormatPVR.xml | 15 ++ doc/classes/ResourceFormatSaver.xml | 49 ++++++ doc/classes/ResourceFormatSaverBinary.xml | 15 ++ doc/classes/ResourceFormatSaverGDScript.xml | 15 ++ doc/classes/ResourceFormatSaverNativeScript.xml | 15 ++ doc/classes/ResourceFormatSaverShader.xml | 15 ++ doc/classes/ResourceFormatSaverText.xml | 15 ++ doc/classes/ResourceSaverPNG.xml | 15 ++ drivers/dummy/texture_loader_dummy.h | 1 + drivers/png/resource_saver_png.h | 1 + drivers/register_driver_types.cpp | 13 +- editor/editor_file_system.cpp | 8 + editor/editor_node.cpp | 14 +- editor/editor_node.h | 6 +- editor/editor_plugin.cpp | 30 ++++ editor/editor_plugin.h | 3 + editor/editor_plugin_settings.cpp | 2 +- main/main.cpp | 8 +- modules/dds/register_types.cpp | 7 +- modules/dds/texture_loader_dds.h | 1 + modules/etc/register_types.cpp | 7 +- modules/etc/texture_loader_pkm.h | 1 + modules/gdnative/gdnative.h | 2 + modules/gdnative/nativescript/nativescript.h | 2 + modules/gdnative/nativescript/register_types.cpp | 14 +- .../pluginscript/pluginscript_language.cpp | 6 +- .../gdnative/pluginscript/pluginscript_language.h | 8 +- .../gdnative/pluginscript/pluginscript_loader.h | 6 + modules/gdnative/register_types.cpp | 15 +- modules/gdscript/gdscript.h | 2 + modules/gdscript/register_types.cpp | 24 ++- modules/mono/csharp_script.h | 2 + modules/mono/register_types.cpp | 23 ++- modules/opus/audio_stream_opus.h | 1 + modules/opus/register_types.cpp | 2 +- modules/pvr/register_types.cpp | 7 +- modules/pvr/texture_loader_pvr.h | 1 + modules/theora/register_types.cpp | 10 +- modules/theora/video_stream_theora.h | 1 + modules/vorbis/audio_stream_ogg_vorbis.h | 1 + modules/vorbis/register_types.cpp | 7 +- modules/webm/register_types.cpp | 10 +- modules/webm/video_stream_webm.h | 1 + platform/server/os_server.cpp | 5 +- platform/server/os_server.h | 2 +- scene/register_scene_types.cpp | 68 ++++--- scene/resources/dynamic_font.h | 1 + scene/resources/dynamic_font_stb.h | 1 + scene/resources/font.h | 1 + scene/resources/scene_format_text.h | 3 +- scene/resources/shader.h | 2 + scene/resources/texture.h | 2 + 77 files changed, 1102 insertions(+), 145 deletions(-) create mode 100644 doc/classes/ResourceFormatDDS.xml create mode 100644 doc/classes/ResourceFormatImporter.xml create mode 100644 doc/classes/ResourceFormatLoader.xml create mode 100644 doc/classes/ResourceFormatLoaderBMFont.xml create mode 100644 doc/classes/ResourceFormatLoaderBinary.xml create mode 100644 doc/classes/ResourceFormatLoaderDynamicFont.xml create mode 100644 doc/classes/ResourceFormatLoaderGDScript.xml create mode 100644 doc/classes/ResourceFormatLoaderImage.xml create mode 100644 doc/classes/ResourceFormatLoaderNativeScript.xml create mode 100644 doc/classes/ResourceFormatLoaderShader.xml create mode 100644 doc/classes/ResourceFormatLoaderStreamTexture.xml create mode 100644 doc/classes/ResourceFormatLoaderText.xml create mode 100644 doc/classes/ResourceFormatLoaderTextureLayered.xml create mode 100644 doc/classes/ResourceFormatLoaderTheora.xml create mode 100644 doc/classes/ResourceFormatLoaderWebm.xml create mode 100644 doc/classes/ResourceFormatPKM.xml create mode 100644 doc/classes/ResourceFormatPVR.xml create mode 100644 doc/classes/ResourceFormatSaver.xml create mode 100644 doc/classes/ResourceFormatSaverBinary.xml create mode 100644 doc/classes/ResourceFormatSaverGDScript.xml create mode 100644 doc/classes/ResourceFormatSaverNativeScript.xml create mode 100644 doc/classes/ResourceFormatSaverShader.xml create mode 100644 doc/classes/ResourceFormatSaverText.xml create mode 100644 doc/classes/ResourceSaverPNG.xml 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 *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 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 *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 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 *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 *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 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 *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 &p_map) { + + if (get_script_instance() && get_script_instance()->has_method("rename_dependencies")) { + + Dictionary deps_dict; + for (Map::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 ResourceLoader::load_interactive(const String &p_ return Ref(); } -void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_loader, bool p_at_front) { +void ResourceLoader::add_resource_format_loader(Ref 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 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 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(); +} + +bool ResourceLoader::add_custom_resource_format_loader(String script_path) { + + if (_find_custom_resource_format_loader(script_path).is_valid()) + return false; + + Ref res = ResourceLoader::load(script_path); + ERR_FAIL_COND_V(res.is_null(), false); + ERR_FAIL_COND_V(!res->is_class("Script"), false); + + Ref