diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index 1824580110..edbfae32d5 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -179,82 +179,3 @@ void Crypto::_bind_methods() { ClassDB::bind_method(D_METHOD("hmac_digest", "hash_type", "key", "msg"), &Crypto::hmac_digest); ClassDB::bind_method(D_METHOD("constant_time_compare", "trusted", "received"), &Crypto::constant_time_compare); } - -/// Resource loader/saver - -Ref ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - String el = p_path.get_extension().to_lower(); - if (el == "crt") { - X509Certificate *cert = X509Certificate::create(); - if (cert) { - cert->load(p_path); - } - return cert; - } else if (el == "key") { - CryptoKey *key = CryptoKey::create(); - if (key) { - key->load(p_path, false); - } - return key; - } else if (el == "pub") { - CryptoKey *key = CryptoKey::create(); - if (key) { - key->load(p_path, true); - } - return key; - } - return nullptr; -} - -void ResourceFormatLoaderCrypto::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("crt"); - p_extensions->push_back("key"); - p_extensions->push_back("pub"); -} - -bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const { - return p_type == "X509Certificate" || p_type == "CryptoKey"; -} - -String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "crt") { - return "X509Certificate"; - } else if (el == "key" || el == "pub") { - return "CryptoKey"; - } - return ""; -} - -Error ResourceFormatSaverCrypto::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { - Error err; - Ref cert = p_resource; - Ref key = p_resource; - if (cert.is_valid()) { - err = cert->save(p_path); - } else if (key.is_valid()) { - err = key->save(p_path, p_path.has_extension("pub")); - } else { - ERR_FAIL_V(ERR_INVALID_PARAMETER); - } - ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot save Crypto resource to file '%s'.", p_path)); - return OK; -} - -void ResourceFormatSaverCrypto::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { - const X509Certificate *cert = Object::cast_to(*p_resource); - const CryptoKey *key = Object::cast_to(*p_resource); - if (cert) { - p_extensions->push_back("crt"); - } - if (key) { - if (!key->is_public_only()) { - p_extensions->push_back("key"); - } - p_extensions->push_back("pub"); - } -} - -bool ResourceFormatSaverCrypto::recognize(const Ref &p_resource) const { - return Object::cast_to(*p_resource) || Object::cast_to(*p_resource); -} diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index 48bf589abe..5339321965 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -32,8 +32,6 @@ #include "core/crypto/hashing_context.h" #include "core/io/resource.h" -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" #include "core/object/ref_counted.h" class CryptoKey : public Resource { @@ -144,26 +142,3 @@ public: // @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy bool constant_time_compare(const PackedByteArray &p_trusted, const PackedByteArray &p_received); }; - -class ResourceFormatLoaderCrypto : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; - - // Treat certificates as text files, do not generate a `*.{crt,key,pub}.uid` file. - virtual ResourceUID::ID get_resource_uid(const String &p_path) const override { return ResourceUID::INVALID_ID; } - virtual bool has_custom_uid_support() const override { return true; } -}; - -class ResourceFormatSaverCrypto : public ResourceFormatSaver { - GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver); - -public: - virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; - virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; - virtual bool recognize(const Ref &p_resource) const override; -}; diff --git a/core/crypto/crypto_resource_format.cpp b/core/crypto/crypto_resource_format.cpp new file mode 100644 index 0000000000..09fc2bed0c --- /dev/null +++ b/core/crypto/crypto_resource_format.cpp @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* crypto_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "crypto_resource_format.h" + +#include "core/crypto/crypto.h" + +Ref ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + String el = p_path.get_extension().to_lower(); + if (el == "crt") { + X509Certificate *cert = X509Certificate::create(); + if (cert) { + cert->load(p_path); + } + return cert; + } else if (el == "key") { + CryptoKey *key = CryptoKey::create(); + if (key) { + key->load(p_path, false); + } + return key; + } else if (el == "pub") { + CryptoKey *key = CryptoKey::create(); + if (key) { + key->load(p_path, true); + } + return key; + } + return nullptr; +} + +void ResourceFormatLoaderCrypto::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("crt"); + p_extensions->push_back("key"); + p_extensions->push_back("pub"); +} + +bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const { + return p_type == "X509Certificate" || p_type == "CryptoKey"; +} + +String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const { + String el = p_path.get_extension().to_lower(); + if (el == "crt") { + return "X509Certificate"; + } else if (el == "key" || el == "pub") { + return "CryptoKey"; + } + return ""; +} + +Error ResourceFormatSaverCrypto::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { + Error err; + Ref cert = p_resource; + Ref key = p_resource; + if (cert.is_valid()) { + err = cert->save(p_path); + } else if (key.is_valid()) { + err = key->save(p_path, p_path.has_extension("pub")); + } else { + ERR_FAIL_V(ERR_INVALID_PARAMETER); + } + ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot save Crypto resource to file '%s'.", p_path)); + return OK; +} + +void ResourceFormatSaverCrypto::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { + const X509Certificate *cert = Object::cast_to(*p_resource); + const CryptoKey *key = Object::cast_to(*p_resource); + if (cert) { + p_extensions->push_back("crt"); + } + if (key) { + if (!key->is_public_only()) { + p_extensions->push_back("key"); + } + p_extensions->push_back("pub"); + } +} + +bool ResourceFormatSaverCrypto::recognize(const Ref &p_resource) const { + return Object::cast_to(*p_resource) || Object::cast_to(*p_resource); +} diff --git a/core/crypto/crypto_resource_format.h b/core/crypto/crypto_resource_format.h new file mode 100644 index 0000000000..128e975124 --- /dev/null +++ b/core/crypto/crypto_resource_format.h @@ -0,0 +1,58 @@ +/**************************************************************************/ +/* crypto_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/io/resource_uid.h" + +class ResourceFormatLoaderCrypto : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; + + // Treat certificates as text files, do not generate a `*.{crt,key,pub}.uid` file. + virtual ResourceUID::ID get_resource_uid(const String &p_path) const override { return ResourceUID::INVALID_ID; } + virtual bool has_custom_uid_support() const override { return true; } +}; + +class ResourceFormatSaverCrypto : public ResourceFormatSaver { + GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver); + +public: + virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; + virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; + virtual bool recognize(const Ref &p_resource) const override; +}; diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index cc25ff8f1a..7b991b9993 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -33,7 +33,6 @@ #include "core/config/project_settings.h" #include "core/extension/gdextension_library_loader.h" -#include "core/extension/gdextension_manager.h" #include "core/object/callable_mp.h" #include "core/object/class_db.h" #include "core/object/method_bind.h" @@ -845,68 +844,7 @@ void GDExtension::finalize_gdextensions() { gdextension_interface_functions.clear(); } -Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, Ref &p_extension) { - ERR_FAIL_COND_V_MSG(p_extension.is_valid() && p_extension->is_library_open(), ERR_ALREADY_IN_USE, "Cannot load GDExtension resource into already opened library."); - - GDExtensionManager *extension_manager = GDExtensionManager::get_singleton(); - - GDExtensionManager::LoadStatus status = extension_manager->load_extension(p_path); - if (status != GDExtensionManager::LOAD_STATUS_OK && status != GDExtensionManager::LOAD_STATUS_ALREADY_LOADED) { - // Errors already logged in load_extension(). - return FAILED; - } - - p_extension = extension_manager->get_extension(p_path); - return OK; -} - -Ref GDExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - // We can't have two GDExtension resource object representing the same library, because - // loading (or unloading) a GDExtension affects global data. So, we need reuse the same - // object if one has already been loaded (even if caching is disabled at the resource - // loader level). - GDExtensionManager *manager = GDExtensionManager::get_singleton(); - if (manager->is_extension_loaded(p_path)) { - return manager->get_extension(p_path); - } - - Ref lib; - Error err = load_gdextension_resource(p_path, lib); - if (err != OK && r_error) { - // Errors already logged in load_gdextension_resource(). - *r_error = err; - } - return lib; -} - -void GDExtensionResourceLoader::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("gdextension"); -} - -bool GDExtensionResourceLoader::handles_type(const String &p_type) const { - return p_type == "GDExtension"; -} - -String GDExtensionResourceLoader::get_resource_type(const String &p_path) const { - if (p_path.has_extension("gdextension")) { - return "GDExtension"; - } - return ""; -} - #ifdef TOOLS_ENABLED -void GDExtensionResourceLoader::get_classes_used(const String &p_path, HashSet *r_classes) { - Ref gdext = ResourceLoader::load(p_path); - if (gdext.is_null()) { - return; - } - - for (const StringName class_name : gdext->get_classes_used()) { - if (ClassDB::class_exists(class_name)) { - r_classes->insert(class_name); - } - } -} bool GDExtension::has_library_changed() const { return loader->has_library_changed(); diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h index 8bf3ebe6c3..78b30ac999 100644 --- a/core/extension/gdextension.h +++ b/core/extension/gdextension.h @@ -32,8 +32,7 @@ #include "core/extension/gdextension_interface.gen.h" #include "core/extension/gdextension_loader.h" -#include "core/io/resource_loader.h" -#include "core/object/ref_counted.h" +#include "core/io/resource.h" class GDExtensionMethodBind; @@ -181,21 +180,6 @@ public: VARIANT_ENUM_CAST(GDExtension::InitializationLevel) -class GDExtensionResourceLoader : public ResourceFormatLoader { - GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader); - -public: - static Error load_gdextension_resource(const String &p_path, Ref &p_extension); - - virtual Ref load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; -#ifdef TOOLS_ENABLED - virtual void get_classes_used(const String &p_path, HashSet *r_classes) override; -#endif // TOOLS_ENABLED -}; - #ifdef TOOLS_ENABLED class GDExtensionEditorPlugins { private: diff --git a/core/extension/gdextension_resource_format.cpp b/core/extension/gdextension_resource_format.cpp new file mode 100644 index 0000000000..f8b71be17f --- /dev/null +++ b/core/extension/gdextension_resource_format.cpp @@ -0,0 +1,98 @@ +/**************************************************************************/ +/* gdextension_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gdextension_resource_format.h" + +#include "core/extension/gdextension_manager.h" +#include "core/object/class_db.h" + +Ref GDExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + // We can't have two GDExtension resource object representing the same library, because + // loading (or unloading) a GDExtension affects global data. So, we need reuse the same + // object if one has already been loaded (even if caching is disabled at the resource + // loader level). + GDExtensionManager *manager = GDExtensionManager::get_singleton(); + if (manager->is_extension_loaded(p_path)) { + return manager->get_extension(p_path); + } + + Ref lib; + Error err = load_gdextension_resource(p_path, lib); + if (err != OK && r_error) { + // Errors already logged in load_gdextension_resource(). + *r_error = err; + } + return lib; +} + +void GDExtensionResourceLoader::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("gdextension"); +} + +bool GDExtensionResourceLoader::handles_type(const String &p_type) const { + return p_type == "GDExtension"; +} + +String GDExtensionResourceLoader::get_resource_type(const String &p_path) const { + if (p_path.has_extension("gdextension")) { + return "GDExtension"; + } + return ""; +} + +Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, Ref &p_extension) { + ERR_FAIL_COND_V_MSG(p_extension.is_valid() && p_extension->is_library_open(), ERR_ALREADY_IN_USE, "Cannot load GDExtension resource into already opened library."); + + GDExtensionManager *extension_manager = GDExtensionManager::get_singleton(); + + GDExtensionManager::LoadStatus status = extension_manager->load_extension(p_path); + if (status != GDExtensionManager::LOAD_STATUS_OK && status != GDExtensionManager::LOAD_STATUS_ALREADY_LOADED) { + // Errors already logged in load_extension(). + return FAILED; + } + + p_extension = extension_manager->get_extension(p_path); + return OK; +} + +#ifdef TOOLS_ENABLED +void GDExtensionResourceLoader::get_classes_used(const String &p_path, HashSet *r_classes) { + Ref gdext = ResourceLoader::load(p_path); + if (gdext.is_null()) { + return; + } + + for (const StringName class_name : gdext->get_classes_used()) { + if (ClassDB::class_exists(class_name)) { + r_classes->insert(class_name); + } + } +} +#endif // TOOLS_ENABLED diff --git a/core/extension/gdextension_resource_format.h b/core/extension/gdextension_resource_format.h new file mode 100644 index 0000000000..1bd867fd09 --- /dev/null +++ b/core/extension/gdextension_resource_format.h @@ -0,0 +1,49 @@ +/**************************************************************************/ +/* gdextension_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/extension/gdextension.h" +#include "core/io/resource_loader.h" + +class GDExtensionResourceLoader : public ResourceFormatLoader { + GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader); + +public: + static Error load_gdextension_resource(const String &p_path, Ref &p_extension); + + virtual Ref load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; +#ifdef TOOLS_ENABLED + virtual void get_classes_used(const String &p_path, HashSet *r_classes) override; +#endif // TOOLS_ENABLED +}; diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index c8e909e281..83298371f3 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -139,74 +139,3 @@ void ImageLoader::cleanup() { remove_image_format_loader(loader[0]); } } - -///////////////// - -Ref ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref f = FileAccess::open(p_path, FileAccess::READ); - if (f.is_null()) { - if (r_error) { - *r_error = ERR_CANT_OPEN; - } - return Ref(); - } - - uint8_t header[4] = { 0, 0, 0, 0 }; - f->get_buffer(header, 4); - - bool unrecognized = header[0] != 'G' || header[1] != 'D' || header[2] != 'I' || header[3] != 'M'; - if (unrecognized) { - if (r_error) { - *r_error = ERR_FILE_UNRECOGNIZED; - } - ERR_FAIL_V(Ref()); - } - - String extension = f->get_pascal_string(); - - int idx = -1; - - for (int i = 0; i < ImageLoader::loader.size(); i++) { - if (ImageLoader::loader[i]->recognize(extension)) { - idx = i; - break; - } - } - - if (idx == -1) { - if (r_error) { - *r_error = ERR_FILE_UNRECOGNIZED; - } - ERR_FAIL_V(Ref()); - } - - Ref image; - image.instantiate(); - - Error err = ImageLoader::loader.write[idx]->load_image(image, f); - - if (err != OK) { - if (r_error) { - *r_error = err; - } - return Ref(); - } - - if (r_error) { - *r_error = OK; - } - - return image; -} - -void ResourceFormatLoaderImage::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("image"); -} - -bool ResourceFormatLoaderImage::handles_type(const String &p_type) const { - return p_type == "Image"; -} - -String ResourceFormatLoaderImage::get_resource_type(const String &p_path) const { - return p_path.get_extension().to_lower() == "image" ? "Image" : String(); -} diff --git a/core/io/image_loader.h b/core/io/image_loader.h index e8fbbc5110..12441cca7a 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -32,7 +32,6 @@ #include "core/io/file_access.h" #include "core/io/image.h" -#include "core/io/resource_loader.h" #include "core/object/gdvirtual.gen.h" #include "core/string/ustring.h" #include "core/templates/list.h" @@ -98,13 +97,3 @@ public: static void cleanup(); }; - -class ResourceFormatLoaderImage : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderImage, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; -}; diff --git a/core/io/image_resource_format.cpp b/core/io/image_resource_format.cpp new file mode 100644 index 0000000000..244350f619 --- /dev/null +++ b/core/io/image_resource_format.cpp @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* image_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "image_resource_format.h" + +Ref ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref f = FileAccess::open(p_path, FileAccess::READ); + if (f.is_null()) { + if (r_error) { + *r_error = ERR_CANT_OPEN; + } + return Ref(); + } + + uint8_t header[4] = { 0, 0, 0, 0 }; + f->get_buffer(header, 4); + + bool unrecognized = header[0] != 'G' || header[1] != 'D' || header[2] != 'I' || header[3] != 'M'; + if (unrecognized) { + if (r_error) { + *r_error = ERR_FILE_UNRECOGNIZED; + } + ERR_FAIL_V(Ref()); + } + + String extension = f->get_pascal_string(); + + int idx = -1; + + for (int i = 0; i < ImageLoader::loader.size(); i++) { + if (ImageLoader::loader[i]->recognize(extension)) { + idx = i; + break; + } + } + + if (idx == -1) { + if (r_error) { + *r_error = ERR_FILE_UNRECOGNIZED; + } + ERR_FAIL_V(Ref()); + } + + Ref image; + image.instantiate(); + + Error err = ImageLoader::loader.write[idx]->load_image(image, f); + + if (err != OK) { + if (r_error) { + *r_error = err; + } + return Ref(); + } + + if (r_error) { + *r_error = OK; + } + + return image; +} + +void ResourceFormatLoaderImage::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("image"); +} + +bool ResourceFormatLoaderImage::handles_type(const String &p_type) const { + return p_type == "Image"; +} + +String ResourceFormatLoaderImage::get_resource_type(const String &p_path) const { + return p_path.get_extension().to_lower() == "image" ? "Image" : String(); +} diff --git a/core/io/image_resource_format.h b/core/io/image_resource_format.h new file mode 100644 index 0000000000..7d76de0a5c --- /dev/null +++ b/core/io/image_resource_format.h @@ -0,0 +1,44 @@ +/**************************************************************************/ +/* image_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/image_loader.h" +#include "core/io/resource_loader.h" + +class ResourceFormatLoaderImage : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderImage, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; +}; diff --git a/core/io/json.cpp b/core/io/json.cpp index dd91816155..e055346c43 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -30,8 +30,7 @@ #include "json.h" -#include "core/config/engine.h" -#include "core/io/file_access.h" +#include "core/io/resource_loader.h" #include "core/object/class_db.h" #include "core/object/script_language.h" #include "core/variant/container_type_validate.h" @@ -1551,88 +1550,3 @@ Variant JSON::_to_native(const Variant &p_json, bool p_allow_objects, int p_dept #undef VALUE_TYPE #undef ARGS #undef PROPS - -//////////// - -Ref ResourceFormatLoaderJSON::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - if (r_error) { - *r_error = ERR_FILE_CANT_OPEN; - } - - if (!FileAccess::exists(p_path)) { - if (r_error) { - *r_error = ERR_FILE_NOT_FOUND; - } - return Ref(); - } - - Ref json; - json.instantiate(); - - Error err = json->parse(FileAccess::get_file_as_string(p_path), Engine::get_singleton()->is_editor_hint()); - if (err != OK) { - String err_text = "Error parsing JSON file at '" + p_path + "', on line " + itos(json->get_error_line()) + ": " + json->get_error_message(); - - if (Engine::get_singleton()->is_editor_hint()) { - // If running on editor, still allow opening the JSON so the code editor can edit it. - WARN_PRINT(err_text); - } else { - if (r_error) { - *r_error = err; - } - ERR_PRINT(err_text); - return Ref(); - } - } - - if (r_error) { - *r_error = OK; - } - - return json; -} - -void ResourceFormatLoaderJSON::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("json"); -} - -bool ResourceFormatLoaderJSON::handles_type(const String &p_type) const { - return (p_type == "JSON"); -} - -String ResourceFormatLoaderJSON::get_resource_type(const String &p_path) const { - if (p_path.has_extension("json")) { - return "JSON"; - } - return ""; -} - -Error ResourceFormatSaverJSON::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { - Ref json = p_resource; - ERR_FAIL_COND_V(json.is_null(), ERR_INVALID_PARAMETER); - - String source = json->get_parsed_text().is_empty() ? JSON::stringify(json->get_data(), "\t", false, true) : json->get_parsed_text(); - - Error err; - Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); - - ERR_FAIL_COND_V_MSG(err, err, vformat("Cannot save json '%s'.", p_path)); - - file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; - } - - return OK; -} - -void ResourceFormatSaverJSON::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { - Ref json = p_resource; - if (json.is_valid()) { - p_extensions->push_back("json"); - } -} - -bool ResourceFormatSaverJSON::recognize(const Ref &p_resource) const { - return p_resource->get_class_name() == "JSON"; //only json, not inherited -} diff --git a/core/io/json.h b/core/io/json.h index 34a27f3061..9346a75bd3 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -31,8 +31,6 @@ #pragma once #include "core/io/resource.h" -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" #include "core/variant/variant.h" class JSON : public Resource { @@ -105,26 +103,3 @@ public: _FORCE_INLINE_ int get_error_line() const { return err_line; } _FORCE_INLINE_ String get_error_message() const { return err_str; } }; - -class ResourceFormatLoaderJSON : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderJSON, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; - - // Treat JSON as a text file, do not generate a `*.json.uid` file. - virtual ResourceUID::ID get_resource_uid(const String &p_path) const override { return ResourceUID::INVALID_ID; } - virtual bool has_custom_uid_support() const override { return true; } -}; - -class ResourceFormatSaverJSON : public ResourceFormatSaver { - GDSOFTCLASS(ResourceFormatSaverJSON, ResourceFormatSaver); - -public: - virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; - virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; - virtual bool recognize(const Ref &p_resource) const override; -}; diff --git a/core/io/json_resource_format.cpp b/core/io/json_resource_format.cpp new file mode 100644 index 0000000000..7955fbf971 --- /dev/null +++ b/core/io/json_resource_format.cpp @@ -0,0 +1,118 @@ +/**************************************************************************/ +/* json_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "json_resource_format.h" + +#include "core/config/engine.h" +#include "core/io/file_access.h" +#include "core/io/json.h" + +Ref ResourceFormatLoaderJSON::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + if (r_error) { + *r_error = ERR_FILE_CANT_OPEN; + } + + if (!FileAccess::exists(p_path)) { + if (r_error) { + *r_error = ERR_FILE_NOT_FOUND; + } + return Ref(); + } + + Ref json; + json.instantiate(); + + Error err = json->parse(FileAccess::get_file_as_string(p_path), Engine::get_singleton()->is_editor_hint()); + if (err != OK) { + String err_text = "Error parsing JSON file at '" + p_path + "', on line " + itos(json->get_error_line()) + ": " + json->get_error_message(); + + if (Engine::get_singleton()->is_editor_hint()) { + // If running on editor, still allow opening the JSON so the code editor can edit it. + WARN_PRINT(err_text); + } else { + if (r_error) { + *r_error = err; + } + ERR_PRINT(err_text); + return Ref(); + } + } + + if (r_error) { + *r_error = OK; + } + + return json; +} + +void ResourceFormatLoaderJSON::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("json"); +} + +bool ResourceFormatLoaderJSON::handles_type(const String &p_type) const { + return (p_type == "JSON"); +} + +String ResourceFormatLoaderJSON::get_resource_type(const String &p_path) const { + if (p_path.has_extension("json")) { + return "JSON"; + } + return ""; +} + +Error ResourceFormatSaverJSON::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { + Ref json = p_resource; + ERR_FAIL_COND_V(json.is_null(), ERR_INVALID_PARAMETER); + + String source = json->get_parsed_text().is_empty() ? JSON::stringify(json->get_data(), "\t", false, true) : json->get_parsed_text(); + + Error err; + Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); + + ERR_FAIL_COND_V_MSG(err, err, vformat("Cannot save json '%s'.", p_path)); + + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } + + return OK; +} + +void ResourceFormatSaverJSON::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { + Ref json = p_resource; + if (json.is_valid()) { + p_extensions->push_back("json"); + } +} + +bool ResourceFormatSaverJSON::recognize(const Ref &p_resource) const { + return p_resource->get_class_name() == "JSON"; //only json, not inherited +} diff --git a/core/io/json_resource_format.h b/core/io/json_resource_format.h new file mode 100644 index 0000000000..3867a92b5e --- /dev/null +++ b/core/io/json_resource_format.h @@ -0,0 +1,58 @@ +/**************************************************************************/ +/* json_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/io/resource_uid.h" + +class ResourceFormatLoaderJSON : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderJSON, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; + + // Treat JSON as a text file, do not generate a `*.json.uid` file. + virtual ResourceUID::ID get_resource_uid(const String &p_path) const override { return ResourceUID::INVALID_ID; } + virtual bool has_custom_uid_support() const override { return true; } +}; + +class ResourceFormatSaverJSON : public ResourceFormatSaver { + GDSOFTCLASS(ResourceFormatSaverJSON, ResourceFormatSaver); + +public: + virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; + virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; + virtual bool recognize(const Ref &p_resource) const override; +}; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 4138c7482d..80696814aa 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -35,10 +35,12 @@ #include "core/core_bind.h" #include "core/crypto/aes_context.h" #include "core/crypto/crypto.h" +#include "core/crypto/crypto_resource_format.h" #include "core/crypto/hashing_context.h" #include "core/debugger/engine_profiler.h" #include "core/extension/gdextension.h" #include "core/extension/gdextension_manager.h" +#include "core/extension/gdextension_resource_format.h" #include "core/extension/godot_instance.h" #include "core/input/input.h" #include "core/input/input_map.h" @@ -49,7 +51,9 @@ #include "core/io/file_access_encrypted.h" #include "core/io/http_client.h" #include "core/io/image_loader.h" +#include "core/io/image_resource_format.h" #include "core/io/json.h" +#include "core/io/json_resource_format.h" #include "core/io/marshalls.h" #include "core/io/missing_resource.h" #include "core/io/packet_peer.h" diff --git a/editor/scene/2d/tiles/tiles_editor_plugin.h b/editor/scene/2d/tiles/tiles_editor_plugin.h index 53ffd07839..61aa41c555 100644 --- a/editor/scene/2d/tiles/tiles_editor_plugin.h +++ b/editor/scene/2d/tiles/tiles_editor_plugin.h @@ -30,6 +30,7 @@ #pragma once +#include "core/os/semaphore.h" #include "editor/plugins/editor_plugin.h" #include "editor/scene/2d/tiles/tile_map_layer_editor.h" #include "editor/scene/2d/tiles/tile_set_editor.h" diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index a05b46c4df..96e4dad0d8 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -38,6 +38,7 @@ #include "gdscript_tokenizer_buffer.h" #include "gdscript_warning.h" +#include "core/io/resource_loader.h" #include "core/object/callable_mp.h" #include "core/object/class_db.h" @@ -2885,150 +2886,3 @@ Ref GDScriptLanguage::get_orphan_subclass(const String &p_qualified_na } return Ref(Object::cast_to(obj)); } - -/*************** RESOURCE ***************/ - -Ref ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Error err; - bool ignoring = p_cache_mode == CACHE_MODE_IGNORE || p_cache_mode == CACHE_MODE_IGNORE_DEEP; - Ref scr = GDScriptCache::get_full_script(p_original_path, err, "", ignoring); - - if (err && scr.is_valid()) { - // If !scr.is_valid(), the error was likely from scr->load_source_code(), which already generates an error. - ERR_PRINT_ED(vformat(R"(Failed to load script "%s" with error "%s".)", p_original_path, error_names[err])); - } - - if (r_error) { - // Don't fail loading because of parsing error. - *r_error = scr.is_valid() ? OK : err; - } - - return scr; -} - -void ResourceFormatLoaderGDScript::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("gd"); - p_extensions->push_back("gdc"); -} - -bool ResourceFormatLoaderGDScript::handles_type(const String &p_type) const { - return (p_type == "Script" || p_type == "GDScript"); -} - -String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "gd" || el == "gdc") { - return "GDScript"; - } - return ""; -} - -void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List *p_dependencies, bool p_add_types) { - Ref file = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'."); - - String source = file->get_as_utf8_string(); - if (source.is_empty()) { - return; - } - - GDScriptParser parser; - if (OK != parser.parse(source, p_path, false)) { - return; - } - - for (const String &E : parser.get_dependencies()) { - p_dependencies->push_back(E); - } -} - -void ResourceFormatLoaderGDScript::get_classes_used(const String &p_path, HashSet *r_classes) { - Ref scr = ResourceLoader::load(p_path); - if (scr.is_null()) { - return; - } - - const String source = scr->get_source_code(); - GDScriptTokenizerText tokenizer; - tokenizer.set_source_code(source); - GDScriptTokenizer::Token current = tokenizer.scan(); - while (current.type != GDScriptTokenizer::Token::TK_EOF) { - if (!current.is_identifier()) { - current = tokenizer.scan(); - continue; - } - - int insert_idx = 0; - for (int i = 0; i < current.start_line - 1; i++) { - insert_idx = source.find("\n", insert_idx) + 1; - } - // Insert the "cursor" character, needed for the lookup to work. - const String source_with_cursor = source.insert(insert_idx + current.start_column, String::chr(0xFFFF)); - - ScriptLanguage::LookupResult result; - if (scr->get_language()->lookup_code(source_with_cursor, current.get_identifier(), p_path, nullptr, result) == OK) { - if (!result.class_name.is_empty() && ClassDB::class_exists(result.class_name)) { - r_classes->insert(result.class_name); - } - - if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_PROPERTY) { - PropertyInfo prop; - if (ClassDB::get_property_info(result.class_name, result.class_member, &prop)) { - if (!prop.class_name.is_empty() && ClassDB::class_exists(prop.class_name)) { - r_classes->insert(prop.class_name); - } - if (!prop.hint_string.is_empty() && ClassDB::class_exists(prop.hint_string)) { - r_classes->insert(prop.hint_string); - } - } - } else if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_METHOD) { - MethodInfo met; - if (ClassDB::get_method_info(result.class_name, result.class_member, &met)) { - if (!met.return_val.class_name.is_empty() && ClassDB::class_exists(met.return_val.class_name)) { - r_classes->insert(met.return_val.class_name); - } - if (!met.return_val.hint_string.is_empty() && ClassDB::class_exists(met.return_val.hint_string)) { - r_classes->insert(met.return_val.hint_string); - } - } - } - } - - current = tokenizer.scan(); - } -} - -Error ResourceFormatSaverGDScript::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { - Ref sqscr = p_resource; - ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); - - String source = sqscr->get_source_code(); - - { - Error err; - Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); - - ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'."); - - file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; - } - } - - if (ScriptServer::is_reload_scripts_on_save_enabled()) { - GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, true); - } - - return OK; -} - -void ResourceFormatSaverGDScript::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { - if (Object::cast_to(*p_resource)) { - p_extensions->push_back("gd"); - } -} - -bool ResourceFormatSaverGDScript::recognize(const Ref &p_resource) const { - return Object::cast_to(*p_resource) != nullptr; -} diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 8662a77b1c..ed6eabd675 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -35,8 +35,6 @@ #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" #include "core/doc_data.h" -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" #include "core/object/script_language.h" #include "core/templates/rb_set.h" @@ -659,24 +657,3 @@ public: GDScriptLanguage(); ~GDScriptLanguage(); }; - -class ResourceFormatLoaderGDScript : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderGDScript, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; - virtual void get_dependencies(const String &p_path, List *p_dependencies, bool p_add_types = false) override; - virtual void get_classes_used(const String &p_path, HashSet *r_classes) override; -}; - -class ResourceFormatSaverGDScript : public ResourceFormatSaver { - GDSOFTCLASS(ResourceFormatSaverGDScript, ResourceFormatSaver); - -public: - virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; - virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; - virtual bool recognize(const Ref &p_resource) const override; -}; diff --git a/modules/gdscript/gdscript_resource_format.cpp b/modules/gdscript/gdscript_resource_format.cpp new file mode 100644 index 0000000000..2d6582f311 --- /dev/null +++ b/modules/gdscript/gdscript_resource_format.cpp @@ -0,0 +1,182 @@ +/**************************************************************************/ +/* gdscript_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gdscript_resource_format.h" + +#include "gdscript_cache.h" +#include "gdscript_parser.h" + +#include "core/io/file_access.h" +#include "core/object/class_db.h" + +Ref ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Error err; + bool ignoring = p_cache_mode == CACHE_MODE_IGNORE || p_cache_mode == CACHE_MODE_IGNORE_DEEP; + Ref scr = GDScriptCache::get_full_script(p_original_path, err, "", ignoring); + + if (err && scr.is_valid()) { + // If !scr.is_valid(), the error was likely from scr->load_source_code(), which already generates an error. + ERR_PRINT_ED(vformat(R"(Failed to load script "%s" with error "%s".)", p_original_path, error_names[err])); + } + + if (r_error) { + // Don't fail loading because of parsing error. + *r_error = scr.is_valid() ? OK : err; + } + + return scr; +} + +void ResourceFormatLoaderGDScript::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("gd"); + p_extensions->push_back("gdc"); +} + +bool ResourceFormatLoaderGDScript::handles_type(const String &p_type) const { + return (p_type == "Script" || p_type == "GDScript"); +} + +String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const { + String el = p_path.get_extension().to_lower(); + if (el == "gd" || el == "gdc") { + return "GDScript"; + } + return ""; +} + +void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List *p_dependencies, bool p_add_types) { + Ref file = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'."); + + String source = file->get_as_utf8_string(); + if (source.is_empty()) { + return; + } + + GDScriptParser parser; + if (OK != parser.parse(source, p_path, false)) { + return; + } + + for (const String &E : parser.get_dependencies()) { + p_dependencies->push_back(E); + } +} + +void ResourceFormatLoaderGDScript::get_classes_used(const String &p_path, HashSet *r_classes) { + Ref scr = ResourceLoader::load(p_path); + if (scr.is_null()) { + return; + } + + const String source = scr->get_source_code(); + GDScriptTokenizerText tokenizer; + tokenizer.set_source_code(source); + GDScriptTokenizer::Token current = tokenizer.scan(); + while (current.type != GDScriptTokenizer::Token::TK_EOF) { + if (!current.is_identifier()) { + current = tokenizer.scan(); + continue; + } + + int insert_idx = 0; + for (int i = 0; i < current.start_line - 1; i++) { + insert_idx = source.find("\n", insert_idx) + 1; + } + // Insert the "cursor" character, needed for the lookup to work. + const String source_with_cursor = source.insert(insert_idx + current.start_column, String::chr(0xFFFF)); + + ScriptLanguage::LookupResult result; + if (scr->get_language()->lookup_code(source_with_cursor, current.get_identifier(), p_path, nullptr, result) == OK) { + if (!result.class_name.is_empty() && ClassDB::class_exists(result.class_name)) { + r_classes->insert(result.class_name); + } + + if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_PROPERTY) { + PropertyInfo prop; + if (ClassDB::get_property_info(result.class_name, result.class_member, &prop)) { + if (!prop.class_name.is_empty() && ClassDB::class_exists(prop.class_name)) { + r_classes->insert(prop.class_name); + } + if (!prop.hint_string.is_empty() && ClassDB::class_exists(prop.hint_string)) { + r_classes->insert(prop.hint_string); + } + } + } else if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_METHOD) { + MethodInfo met; + if (ClassDB::get_method_info(result.class_name, result.class_member, &met)) { + if (!met.return_val.class_name.is_empty() && ClassDB::class_exists(met.return_val.class_name)) { + r_classes->insert(met.return_val.class_name); + } + if (!met.return_val.hint_string.is_empty() && ClassDB::class_exists(met.return_val.hint_string)) { + r_classes->insert(met.return_val.hint_string); + } + } + } + } + + current = tokenizer.scan(); + } +} + +Error ResourceFormatSaverGDScript::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { + Ref sqscr = p_resource; + ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); + + String source = sqscr->get_source_code(); + + { + Error err; + Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); + + ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'."); + + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } + } + + if (ScriptServer::is_reload_scripts_on_save_enabled()) { + GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, true); + } + + return OK; +} + +void ResourceFormatSaverGDScript::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { + if (Object::cast_to(*p_resource)) { + p_extensions->push_back("gd"); + } +} + +bool ResourceFormatSaverGDScript::recognize(const Ref &p_resource) const { + return Object::cast_to(*p_resource) != nullptr; +} diff --git a/modules/gdscript/gdscript_resource_format.h b/modules/gdscript/gdscript_resource_format.h new file mode 100644 index 0000000000..8fdc1136ef --- /dev/null +++ b/modules/gdscript/gdscript_resource_format.h @@ -0,0 +1,55 @@ +/**************************************************************************/ +/* gdscript_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" + +class ResourceFormatLoaderGDScript : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderGDScript, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; + virtual void get_dependencies(const String &p_path, List *p_dependencies, bool p_add_types = false) override; + virtual void get_classes_used(const String &p_path, HashSet *r_classes) override; +}; + +class ResourceFormatSaverGDScript : public ResourceFormatSaver { + GDSOFTCLASS(ResourceFormatSaverGDScript, ResourceFormatSaver); + +public: + virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; + virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; + virtual bool recognize(const Ref &p_resource) const override; +}; diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 7adc4eb20c..a7b342723e 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -33,6 +33,7 @@ #include "gdscript.h" #include "gdscript_cache.h" #include "gdscript_parser.h" +#include "gdscript_resource_format.h" #include "gdscript_tokenizer_buffer.h" #include "gdscript_utility_functions.h" diff --git a/modules/gltf/tests/test_gltf.h b/modules/gltf/tests/test_gltf.h index 9b28f9f30e..d346fb89ae 100644 --- a/modules/gltf/tests/test_gltf.h +++ b/modules/gltf/tests/test_gltf.h @@ -44,6 +44,7 @@ #include "editor/import/3d/resource_importer_scene.h" #include "editor/import/resource_importer_texture.h" #include "scene/resources/compressed_texture.h" +#include "scene/resources/compressed_texture_resource_format.h" #include "scene/resources/packed_scene.h" #include "tests/test_utils.h" diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index e4dad17f6b..b3be32af3d 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -79,13 +79,6 @@ // This must be a superset of `ignored_types` in bindings_generator.cpp. const Vector ignored_types = {}; -#ifdef TOOLS_ENABLED -static bool _create_project_solution_if_needed() { - CRASH_COND(CSharpLanguage::get_singleton()->get_godotsharp_editor() == nullptr); - return CSharpLanguage::get_singleton()->get_godotsharp_editor()->call("CreateProjectSolutionIfNeeded"); -} -#endif - CSharpLanguage *CSharpLanguage::singleton = nullptr; GDExtensionInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = { @@ -2826,123 +2819,3 @@ void CSharpScript::get_members(HashSet *p_members) { } #endif // DEBUG_ENABLED } - -/*************** RESOURCE ***************/ - -Ref ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - if (r_error) { - *r_error = ERR_FILE_CANT_OPEN; - } - - // TODO ignore anything inside bin/ and obj/ in tools builds? - - String real_path = p_path; - if (p_path.begins_with("csharp://")) { - // This is a virtual path used by generic types, extract the real path. - real_path = "res://" + p_path.trim_prefix("csharp://"); - real_path = real_path.substr(0, real_path.rfind_char(':')); - } - - Ref scr; - - if (GDMonoCache::godot_api_cache_updated) { - GDMonoCache::managed_callbacks.ScriptManagerBridge_GetOrCreateScriptBridgeForPath(&p_path, &scr); - ERR_FAIL_COND_V_MSG(scr.is_null(), Ref(), "Could not create C# script '" + real_path + "'."); - } else { - scr.instantiate(); - } - -#ifdef DEBUG_ENABLED - Error err = scr->load_source_code(real_path); - ERR_FAIL_COND_V_MSG(err != OK, Ref(), "Cannot load C# script file '" + real_path + "'."); -#endif // DEBUG_ENABLED - - // Only one instance of a C# script is allowed to exist. - ERR_FAIL_COND_V_MSG(!scr->get_path().is_empty() && scr->get_path() != p_original_path, Ref(), - "The C# script path is different from the path it was registered in the C# dictionary."); - - Ref existing = ResourceCache::get_ref(p_path); - switch (p_cache_mode) { - case ResourceFormatLoader::CACHE_MODE_IGNORE: - case ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP: - break; - case ResourceFormatLoader::CACHE_MODE_REUSE: - if (existing.is_null()) { - scr->set_path(p_original_path); - } else { - scr = existing; - } - break; - case ResourceFormatLoader::CACHE_MODE_REPLACE: - case ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP: - scr->set_path(p_original_path, true); - break; - } - - scr->reload(); - - if (r_error) { - *r_error = OK; - } - - return scr; -} - -void ResourceFormatLoaderCSharpScript::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("cs"); -} - -bool ResourceFormatLoaderCSharpScript::handles_type(const String &p_type) const { - return p_type == "Script" || p_type == CSharpLanguage::get_singleton()->get_type(); -} - -String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path) const { - return p_path.has_extension("cs") ? CSharpLanguage::get_singleton()->get_type() : ""; -} - -Error ResourceFormatSaverCSharpScript::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { - Ref sqscr = p_resource; - ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); - - String source = sqscr->get_source_code(); - -#ifdef TOOLS_ENABLED - if (!FileAccess::exists(p_path)) { - // The file does not yet exist, let's assume the user just created this script. In such - // cases we need to check whether the solution and csproj were already created or not. - if (!_create_project_solution_if_needed()) { - ERR_PRINT("C# project could not be created; cannot add file: '" + p_path + "'."); - } - } -#endif - - { - Error err; - Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'."); - - file->store_string(source); - - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; - } - } - -#ifdef TOOLS_ENABLED - if (ScriptServer::is_reload_scripts_on_save_enabled()) { - CSharpLanguage::get_singleton()->reload_tool_script(p_resource, false); - } -#endif - - return OK; -} - -void ResourceFormatSaverCSharpScript::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { - if (Object::cast_to(p_resource.ptr())) { - p_extensions->push_back("cs"); - } -} - -bool ResourceFormatSaverCSharpScript::recognize(const Ref &p_resource) const { - return Object::cast_to(p_resource.ptr()) != nullptr; -} diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index edfe090862..366f2be7b8 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -34,8 +34,6 @@ #include "mono_gd/gd_mono.h" #include "core/doc_data.h" -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" #include "core/object/script_language.h" #include "core/templates/rb_map.h" #include "core/templates/self_list.h" @@ -584,22 +582,3 @@ public: CSharpLanguage(); ~CSharpLanguage(); }; - -class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderCSharpScript, ResourceFormatLoader); - -public: - Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - void get_recognized_extensions(List *p_extensions) const override; - bool handles_type(const String &p_type) const override; - String get_resource_type(const String &p_path) const override; -}; - -class ResourceFormatSaverCSharpScript : public ResourceFormatSaver { - GDSOFTCLASS(ResourceFormatSaverCSharpScript, ResourceFormatSaver); - -public: - Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; - void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; - bool recognize(const Ref &p_resource) const override; -}; diff --git a/modules/mono/csharp_script_resource_format.cpp b/modules/mono/csharp_script_resource_format.cpp new file mode 100644 index 0000000000..61f6772b70 --- /dev/null +++ b/modules/mono/csharp_script_resource_format.cpp @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* csharp_script_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "csharp_script_resource_format.h" + +#include "mono_gd/gd_mono_cache.h" + +#include "core/io/file_access.h" + +#ifdef TOOLS_ENABLED +static bool _create_project_solution_if_needed() { + CRASH_COND(CSharpLanguage::get_singleton()->get_godotsharp_editor() == nullptr); + return CSharpLanguage::get_singleton()->get_godotsharp_editor()->call("CreateProjectSolutionIfNeeded"); +} +#endif + +Ref ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + if (r_error) { + *r_error = ERR_FILE_CANT_OPEN; + } + + // TODO ignore anything inside bin/ and obj/ in tools builds? + + String real_path = p_path; + if (p_path.begins_with("csharp://")) { + // This is a virtual path used by generic types, extract the real path. + real_path = "res://" + p_path.trim_prefix("csharp://"); + real_path = real_path.substr(0, real_path.rfind_char(':')); + } + + Ref scr; + + if (GDMonoCache::godot_api_cache_updated) { + GDMonoCache::managed_callbacks.ScriptManagerBridge_GetOrCreateScriptBridgeForPath(&p_path, &scr); + ERR_FAIL_COND_V_MSG(scr.is_null(), Ref(), "Could not create C# script '" + real_path + "'."); + } else { + scr.instantiate(); + } + +#ifdef DEBUG_ENABLED + Error err = scr->load_source_code(real_path); + ERR_FAIL_COND_V_MSG(err != OK, Ref(), "Cannot load C# script file '" + real_path + "'."); +#endif // DEBUG_ENABLED + + // Only one instance of a C# script is allowed to exist. + ERR_FAIL_COND_V_MSG(!scr->get_path().is_empty() && scr->get_path() != p_original_path, Ref(), + "The C# script path is different from the path it was registered in the C# dictionary."); + + Ref existing = ResourceCache::get_ref(p_path); + switch (p_cache_mode) { + case ResourceFormatLoader::CACHE_MODE_IGNORE: + case ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP: + break; + case ResourceFormatLoader::CACHE_MODE_REUSE: + if (existing.is_null()) { + scr->set_path(p_original_path); + } else { + scr = existing; + } + break; + case ResourceFormatLoader::CACHE_MODE_REPLACE: + case ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP: + scr->set_path(p_original_path, true); + break; + } + + scr->reload(); + + if (r_error) { + *r_error = OK; + } + + return scr; +} + +void ResourceFormatLoaderCSharpScript::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("cs"); +} + +bool ResourceFormatLoaderCSharpScript::handles_type(const String &p_type) const { + return p_type == "Script" || p_type == CSharpLanguage::get_singleton()->get_type(); +} + +String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path) const { + return p_path.has_extension("cs") ? CSharpLanguage::get_singleton()->get_type() : ""; +} + +Error ResourceFormatSaverCSharpScript::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { + Ref sqscr = p_resource; + ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); + + String source = sqscr->get_source_code(); + +#ifdef TOOLS_ENABLED + if (!FileAccess::exists(p_path)) { + // The file does not yet exist, let's assume the user just created this script. In such + // cases we need to check whether the solution and csproj were already created or not. + if (!_create_project_solution_if_needed()) { + ERR_PRINT("C# project could not be created; cannot add file: '" + p_path + "'."); + } + } +#endif + + { + Error err; + Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'."); + + file->store_string(source); + + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } + } + +#ifdef TOOLS_ENABLED + if (ScriptServer::is_reload_scripts_on_save_enabled()) { + CSharpLanguage::get_singleton()->reload_tool_script(p_resource, false); + } +#endif + + return OK; +} + +void ResourceFormatSaverCSharpScript::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { + if (Object::cast_to(p_resource.ptr())) { + p_extensions->push_back("cs"); + } +} + +bool ResourceFormatSaverCSharpScript::recognize(const Ref &p_resource) const { + return Object::cast_to(p_resource.ptr()) != nullptr; +} diff --git a/modules/mono/csharp_script_resource_format.h b/modules/mono/csharp_script_resource_format.h new file mode 100644 index 0000000000..a01c750f6e --- /dev/null +++ b/modules/mono/csharp_script_resource_format.h @@ -0,0 +1,53 @@ +/**************************************************************************/ +/* csharp_script_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" + +class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderCSharpScript, ResourceFormatLoader); + +public: + Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + void get_recognized_extensions(List *p_extensions) const override; + bool handles_type(const String &p_type) const override; + String get_resource_type(const String &p_path) const override; +}; + +class ResourceFormatSaverCSharpScript : public ResourceFormatSaver { + GDSOFTCLASS(ResourceFormatSaverCSharpScript, ResourceFormatSaver); + +public: + Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; + void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; + bool recognize(const Ref &p_resource) const override; +}; diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp index be0ce02cef..b259117c1a 100644 --- a/modules/mono/register_types.cpp +++ b/modules/mono/register_types.cpp @@ -31,6 +31,7 @@ #include "register_types.h" #include "csharp_script.h" +#include "csharp_script_resource_format.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" diff --git a/modules/navigation_2d/nav_region_2d.h b/modules/navigation_2d/nav_region_2d.h index 88a93a3754..7dd4191092 100644 --- a/modules/navigation_2d/nav_region_2d.h +++ b/modules/navigation_2d/nav_region_2d.h @@ -34,6 +34,7 @@ #include "nav_base_2d.h" #include "nav_utils_2d.h" +#include "core/object/worker_thread_pool.h" #include "core/os/rw_lock.h" #include "scene/resources/2d/navigation_polygon.h" diff --git a/modules/navigation_3d/nav_region_3d.h b/modules/navigation_3d/nav_region_3d.h index 1490f30230..a9da756cd9 100644 --- a/modules/navigation_3d/nav_region_3d.h +++ b/modules/navigation_3d/nav_region_3d.h @@ -34,6 +34,7 @@ #include "nav_base_3d.h" #include "nav_utils_3d.h" +#include "core/object/worker_thread_pool.h" #include "core/os/rw_lock.h" #include "scene/resources/navigation_mesh.h" diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 60ca72be51..9d3424e885 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -124,6 +124,7 @@ #include "scene/resources/color_palette.h" #include "scene/resources/compositor.h" #include "scene/resources/compressed_texture.h" +#include "scene/resources/compressed_texture_resource_format.h" #include "scene/resources/curve_texture.h" #include "scene/resources/drawable_texture_2d.h" #include "scene/resources/environment.h" @@ -148,6 +149,8 @@ #include "scene/resources/portable_compressed_texture.h" #include "scene/resources/resource_format_text.h" #include "scene/resources/shader_include.h" +#include "scene/resources/shader_include_resource_format.h" +#include "scene/resources/shader_resource_format.h" #include "scene/resources/skeleton_profile.h" #include "scene/resources/sky.h" #include "scene/resources/style_box.h" diff --git a/scene/resources/compressed_texture.cpp b/scene/resources/compressed_texture.cpp index 2ea03b3599..22d12c2f56 100644 --- a/scene/resources/compressed_texture.cpp +++ b/scene/resources/compressed_texture.cpp @@ -31,6 +31,7 @@ #include "compressed_texture.h" #include "core/io/file_access.h" +#include "core/io/resource_loader.h" #include "core/object/class_db.h" #include "scene/resources/bit_map.h" #include "servers/rendering/rendering_server.h" @@ -465,35 +466,6 @@ CompressedTexture2D::~CompressedTexture2D() { } } -Ref ResourceFormatLoaderCompressedTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref st; - st.instantiate(); - Error err = st->load(p_path); - if (r_error) { - *r_error = err; - } - if (err != OK) { - return Ref(); - } - - return st; -} - -void ResourceFormatLoaderCompressedTexture2D::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("ctex"); -} - -bool ResourceFormatLoaderCompressedTexture2D::handles_type(const String &p_type) const { - return p_type == "CompressedTexture2D"; -} - -String ResourceFormatLoaderCompressedTexture2D::get_resource_type(const String &p_path) const { - if (p_path.has_extension("ctex")) { - return "CompressedTexture2D"; - } - return ""; -} - void CompressedTexture3D::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); @@ -649,35 +621,6 @@ CompressedTexture3D::~CompressedTexture3D() { } } -Ref ResourceFormatLoaderCompressedTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref st; - st.instantiate(); - Error err = st->load(p_path); - if (r_error) { - *r_error = err; - } - if (err != OK) { - return Ref(); - } - - return st; -} - -void ResourceFormatLoaderCompressedTexture3D::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("ctex3d"); -} - -bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) const { - return p_type == "CompressedTexture3D"; -} - -String ResourceFormatLoaderCompressedTexture3D::get_resource_type(const String &p_path) const { - if (p_path.has_extension("ctex3d")) { - return "CompressedTexture3D"; - } - return ""; -} - void CompressedTextureLayered::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { RenderingServer::get_singleton()->texture_set_path(texture, p_path); @@ -841,59 +784,3 @@ CompressedTextureLayered::~CompressedTextureLayered() { RS::get_singleton()->free_rid(texture); } } - -///////////////////////////////////////////////// - -Ref ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref ct; - if (p_path.has_extension("ctexarray")) { - Ref c; - c.instantiate(); - ct = c; - } else if (p_path.has_extension("ccube")) { - Ref c; - c.instantiate(); - ct = c; - } else if (p_path.has_extension("ccubearray")) { - Ref c; - c.instantiate(); - ct = c; - } else { - if (r_error) { - *r_error = ERR_FILE_UNRECOGNIZED; - } - return Ref(); - } - Error err = ct->load(p_path); - if (r_error) { - *r_error = err; - } - if (err != OK) { - return Ref(); - } - - return ct; -} - -void ResourceFormatLoaderCompressedTextureLayered::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("ctexarray"); - p_extensions->push_back("ccube"); - p_extensions->push_back("ccubearray"); -} - -bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_type) const { - return p_type == "CompressedTexture2DArray" || p_type == "CompressedCubemap" || p_type == "CompressedCubemapArray"; -} - -String ResourceFormatLoaderCompressedTextureLayered::get_resource_type(const String &p_path) const { - if (p_path.has_extension("ctexarray")) { - return "CompressedTexture2DArray"; - } - if (p_path.has_extension("ccube")) { - return "CompressedCubemap"; - } - if (p_path.has_extension("ccubearray")) { - return "CompressedCubemapArray"; - } - return ""; -} diff --git a/scene/resources/compressed_texture.h b/scene/resources/compressed_texture.h index 35f3677dcb..d0b7937272 100644 --- a/scene/resources/compressed_texture.h +++ b/scene/resources/compressed_texture.h @@ -30,7 +30,6 @@ #pragma once -#include "core/io/resource_loader.h" #include "scene/resources/texture.h" #include "servers/rendering/rendering_server_enums.h" @@ -110,16 +109,6 @@ public: ~CompressedTexture2D(); }; -class ResourceFormatLoaderCompressedTexture2D : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderCompressedTexture2D, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; -}; - class CompressedTextureLayered : public TextureLayered { GDCLASS(CompressedTextureLayered, TextureLayered); @@ -176,16 +165,6 @@ public: ~CompressedTextureLayered(); }; -class ResourceFormatLoaderCompressedTextureLayered : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderCompressedTextureLayered, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; -}; - class CompressedTexture2DArray : public CompressedTextureLayered { GDCLASS(CompressedTexture2DArray, CompressedTextureLayered) public: @@ -261,13 +240,3 @@ public: ~CompressedTexture3D(); }; - -class ResourceFormatLoaderCompressedTexture3D : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderCompressedTexture3D, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; -}; diff --git a/scene/resources/compressed_texture_resource_format.cpp b/scene/resources/compressed_texture_resource_format.cpp new file mode 100644 index 0000000000..0958dbb905 --- /dev/null +++ b/scene/resources/compressed_texture_resource_format.cpp @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* compressed_texture_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "compressed_texture_resource_format.h" + +#include "scene/resources/compressed_texture.h" + +Ref ResourceFormatLoaderCompressedTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref st; + st.instantiate(); + Error err = st->load(p_path); + if (r_error) { + *r_error = err; + } + if (err != OK) { + return Ref(); + } + + return st; +} + +void ResourceFormatLoaderCompressedTexture2D::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("ctex"); +} + +bool ResourceFormatLoaderCompressedTexture2D::handles_type(const String &p_type) const { + return p_type == "CompressedTexture2D"; +} + +String ResourceFormatLoaderCompressedTexture2D::get_resource_type(const String &p_path) const { + if (p_path.has_extension("ctex")) { + return "CompressedTexture2D"; + } + return ""; +} + +Ref ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref ct; + if (p_path.has_extension("ctexarray")) { + Ref c; + c.instantiate(); + ct = c; + } else if (p_path.has_extension("ccube")) { + Ref c; + c.instantiate(); + ct = c; + } else if (p_path.has_extension("ccubearray")) { + Ref c; + c.instantiate(); + ct = c; + } else { + if (r_error) { + *r_error = ERR_FILE_UNRECOGNIZED; + } + return Ref(); + } + Error err = ct->load(p_path); + if (r_error) { + *r_error = err; + } + if (err != OK) { + return Ref(); + } + + return ct; +} + +void ResourceFormatLoaderCompressedTextureLayered::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("ctexarray"); + p_extensions->push_back("ccube"); + p_extensions->push_back("ccubearray"); +} + +bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_type) const { + return p_type == "CompressedTexture2DArray" || p_type == "CompressedCubemap" || p_type == "CompressedCubemapArray"; +} + +String ResourceFormatLoaderCompressedTextureLayered::get_resource_type(const String &p_path) const { + if (p_path.has_extension("ctexarray")) { + return "CompressedTexture2DArray"; + } + if (p_path.has_extension("ccube")) { + return "CompressedCubemap"; + } + if (p_path.has_extension("ccubearray")) { + return "CompressedCubemapArray"; + } + return ""; +} + +Ref ResourceFormatLoaderCompressedTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref st; + st.instantiate(); + Error err = st->load(p_path); + if (r_error) { + *r_error = err; + } + if (err != OK) { + return Ref(); + } + + return st; +} + +void ResourceFormatLoaderCompressedTexture3D::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("ctex3d"); +} + +bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) const { + return p_type == "CompressedTexture3D"; +} + +String ResourceFormatLoaderCompressedTexture3D::get_resource_type(const String &p_path) const { + if (p_path.has_extension("ctex3d")) { + return "CompressedTexture3D"; + } + return ""; +} diff --git a/scene/resources/compressed_texture_resource_format.h b/scene/resources/compressed_texture_resource_format.h new file mode 100644 index 0000000000..7003553843 --- /dev/null +++ b/scene/resources/compressed_texture_resource_format.h @@ -0,0 +1,63 @@ +/**************************************************************************/ +/* compressed_texture_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/resource_loader.h" + +class ResourceFormatLoaderCompressedTexture2D : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderCompressedTexture2D, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; +}; + +class ResourceFormatLoaderCompressedTextureLayered : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderCompressedTextureLayered, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; +}; + +class ResourceFormatLoaderCompressedTexture3D : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderCompressedTexture3D, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; +}; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 01a7a85a1f..2b8c1300ce 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -32,7 +32,6 @@ #include "shader.compat.inc" #include "core/config/engine.h" -#include "core/io/file_access.h" #include "core/object/callable_mp.h" #include "core/object/class_db.h" #include "scene/main/scene_tree.h" @@ -308,79 +307,3 @@ Shader::~Shader() { RenderingServer::get_singleton()->free_rid(shader_rid); } } - -//////////// - -Ref ResourceFormatLoaderShader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - if (r_error) { - *r_error = ERR_FILE_CANT_OPEN; - } - - Error error = OK; - Vector buffer = FileAccess::get_file_as_bytes(p_path, &error); - ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot load shader: " + p_path); - - String str; - if (buffer.size() > 0) { - error = str.append_utf8((const char *)buffer.ptr(), buffer.size()); - ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot parse shader: " + p_path); - } - - Ref shader; - shader.instantiate(); - - shader->set_include_path(p_path); - shader->set_code(str); - - if (r_error) { - *r_error = OK; - } - - return shader; -} - -void ResourceFormatLoaderShader::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("gdshader"); -} - -bool ResourceFormatLoaderShader::handles_type(const String &p_type) const { - return (p_type == "Shader"); -} - -String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const { - if (p_path.has_extension("gdshader")) { - return "Shader"; - } - return ""; -} - -Error ResourceFormatSaverShader::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { - Ref shader = p_resource; - ERR_FAIL_COND_V(shader.is_null(), ERR_INVALID_PARAMETER); - - String source = shader->get_code(); - - Error err; - Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); - - ERR_FAIL_COND_V_MSG(err, err, "Cannot save shader '" + p_path + "'."); - - file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; - } - - return OK; -} - -void ResourceFormatSaverShader::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { - if (const Shader *shader = Object::cast_to(*p_resource)) { - if (shader->is_text_shader()) { - p_extensions->push_back("gdshader"); - } - } -} - -bool ResourceFormatSaverShader::recognize(const Ref &p_resource) const { - return p_resource->get_class_name() == "Shader"; //only shader, not inherited -} diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 7863003b77..6fb7865659 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -106,22 +106,3 @@ public: }; VARIANT_ENUM_CAST(Shader::Mode); - -class ResourceFormatLoaderShader : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderShader, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; -}; - -class ResourceFormatSaverShader : public ResourceFormatSaver { - GDSOFTCLASS(ResourceFormatSaverShader, ResourceFormatSaver); - -public: - virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; - virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; - virtual bool recognize(const Ref &p_resource) const override; -}; diff --git a/scene/resources/shader_include.cpp b/scene/resources/shader_include.cpp index d30c668e0e..9476fd0cfa 100644 --- a/scene/resources/shader_include.cpp +++ b/scene/resources/shader_include.cpp @@ -30,7 +30,6 @@ #include "shader_include.h" -#include "core/io/file_access.h" #include "core/object/callable_mp.h" #include "core/object/class_db.h" #include "servers/rendering/shader_preprocessor.h" @@ -83,80 +82,3 @@ void ShaderInclude::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code"); } - -// ResourceFormatLoaderShaderInclude - -Ref ResourceFormatLoaderShaderInclude::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - if (r_error) { - *r_error = ERR_FILE_CANT_OPEN; - } - - Error error = OK; - Vector buffer = FileAccess::get_file_as_bytes(p_path, &error); - ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot load shader include: " + p_path); - - String str; - if (buffer.size() > 0) { - error = str.append_utf8((const char *)buffer.ptr(), buffer.size()); - ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot parse shader include: " + p_path); - } - - Ref shader_inc; - shader_inc.instantiate(); - - shader_inc->set_include_path(p_path); - shader_inc->set_code(str); - - if (r_error) { - *r_error = OK; - } - - return shader_inc; -} - -void ResourceFormatLoaderShaderInclude::get_recognized_extensions(List *p_extensions) const { - p_extensions->push_back("gdshaderinc"); -} - -bool ResourceFormatLoaderShaderInclude::handles_type(const String &p_type) const { - return (p_type == "ShaderInclude"); -} - -String ResourceFormatLoaderShaderInclude::get_resource_type(const String &p_path) const { - if (p_path.has_extension("gdshaderinc")) { - return "ShaderInclude"; - } - return ""; -} - -// ResourceFormatSaverShaderInclude - -Error ResourceFormatSaverShaderInclude::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { - Ref shader_inc = p_resource; - ERR_FAIL_COND_V(shader_inc.is_null(), ERR_INVALID_PARAMETER); - - String source = shader_inc->get_code(); - - Error error; - Ref file = FileAccess::open(p_path, FileAccess::WRITE, &error); - - ERR_FAIL_COND_V_MSG(error, error, "Cannot save shader include '" + p_path + "'."); - - file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; - } - - return OK; -} - -void ResourceFormatSaverShaderInclude::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { - const ShaderInclude *shader_inc = Object::cast_to(*p_resource); - if (shader_inc != nullptr) { - p_extensions->push_back("gdshaderinc"); - } -} - -bool ResourceFormatSaverShaderInclude::recognize(const Ref &p_resource) const { - return p_resource->get_class_name() == "ShaderInclude"; //only shader, not inherited -} diff --git a/scene/resources/shader_include.h b/scene/resources/shader_include.h index 0930f5b475..f4ceb8ba31 100644 --- a/scene/resources/shader_include.h +++ b/scene/resources/shader_include.h @@ -31,8 +31,6 @@ #pragma once #include "core/io/resource.h" -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" #include "core/templates/hash_set.h" class ShaderInclude : public Resource { @@ -54,22 +52,3 @@ public: void set_include_path(const String &p_path); }; - -class ResourceFormatLoaderShaderInclude : public ResourceFormatLoader { - GDSOFTCLASS(ResourceFormatLoaderShaderInclude, ResourceFormatLoader); - -public: - virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; - virtual void get_recognized_extensions(List *p_extensions) const override; - virtual bool handles_type(const String &p_type) const override; - virtual String get_resource_type(const String &p_path) const override; -}; - -class ResourceFormatSaverShaderInclude : public ResourceFormatSaver { - GDSOFTCLASS(ResourceFormatSaverShaderInclude, ResourceFormatSaver); - -public: - virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; - virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; - virtual bool recognize(const Ref &p_resource) const override; -}; diff --git a/scene/resources/shader_include_resource_format.cpp b/scene/resources/shader_include_resource_format.cpp new file mode 100644 index 0000000000..a74e0106aa --- /dev/null +++ b/scene/resources/shader_include_resource_format.cpp @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* shader_include_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "shader_include_resource_format.h" + +#include "core/io/file_access.h" +#include "scene/resources/shader_include.h" + +// ResourceFormatLoaderShaderInclude + +Ref ResourceFormatLoaderShaderInclude::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + if (r_error) { + *r_error = ERR_FILE_CANT_OPEN; + } + + Error error = OK; + Vector buffer = FileAccess::get_file_as_bytes(p_path, &error); + ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot load shader include: " + p_path); + + String str; + if (buffer.size() > 0) { + error = str.append_utf8((const char *)buffer.ptr(), buffer.size()); + ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot parse shader include: " + p_path); + } + + Ref shader_inc; + shader_inc.instantiate(); + + shader_inc->set_include_path(p_path); + shader_inc->set_code(str); + + if (r_error) { + *r_error = OK; + } + + return shader_inc; +} + +void ResourceFormatLoaderShaderInclude::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("gdshaderinc"); +} + +bool ResourceFormatLoaderShaderInclude::handles_type(const String &p_type) const { + return (p_type == "ShaderInclude"); +} + +String ResourceFormatLoaderShaderInclude::get_resource_type(const String &p_path) const { + if (p_path.has_extension("gdshaderinc")) { + return "ShaderInclude"; + } + return ""; +} + +// ResourceFormatSaverShaderInclude + +Error ResourceFormatSaverShaderInclude::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { + Ref shader_inc = p_resource; + ERR_FAIL_COND_V(shader_inc.is_null(), ERR_INVALID_PARAMETER); + + String source = shader_inc->get_code(); + + Error error; + Ref file = FileAccess::open(p_path, FileAccess::WRITE, &error); + + ERR_FAIL_COND_V_MSG(error, error, "Cannot save shader include '" + p_path + "'."); + + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } + + return OK; +} + +void ResourceFormatSaverShaderInclude::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { + const ShaderInclude *shader_inc = Object::cast_to(*p_resource); + if (shader_inc != nullptr) { + p_extensions->push_back("gdshaderinc"); + } +} + +bool ResourceFormatSaverShaderInclude::recognize(const Ref &p_resource) const { + return p_resource->get_class_name() == "ShaderInclude"; //only shader, not inherited +} diff --git a/scene/resources/shader_include_resource_format.h b/scene/resources/shader_include_resource_format.h new file mode 100644 index 0000000000..080049e133 --- /dev/null +++ b/scene/resources/shader_include_resource_format.h @@ -0,0 +1,53 @@ +/**************************************************************************/ +/* shader_include_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" + +class ResourceFormatLoaderShaderInclude : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderShaderInclude, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; +}; + +class ResourceFormatSaverShaderInclude : public ResourceFormatSaver { + GDSOFTCLASS(ResourceFormatSaverShaderInclude, ResourceFormatSaver); + +public: + virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; + virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; + virtual bool recognize(const Ref &p_resource) const override; +}; diff --git a/scene/resources/shader_resource_format.cpp b/scene/resources/shader_resource_format.cpp new file mode 100644 index 0000000000..9f2510bb38 --- /dev/null +++ b/scene/resources/shader_resource_format.cpp @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* shader_resource_format.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "shader_resource_format.h" + +#include "core/io/file_access.h" +#include "scene/resources/shader.h" + +Ref ResourceFormatLoaderShader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + if (r_error) { + *r_error = ERR_FILE_CANT_OPEN; + } + + Error error = OK; + Vector buffer = FileAccess::get_file_as_bytes(p_path, &error); + ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot load shader: " + p_path); + + String str; + if (buffer.size() > 0) { + error = str.append_utf8((const char *)buffer.ptr(), buffer.size()); + ERR_FAIL_COND_V_MSG(error, nullptr, "Cannot parse shader: " + p_path); + } + + Ref shader; + shader.instantiate(); + + shader->set_include_path(p_path); + shader->set_code(str); + + if (r_error) { + *r_error = OK; + } + + return shader; +} + +void ResourceFormatLoaderShader::get_recognized_extensions(List *p_extensions) const { + p_extensions->push_back("gdshader"); +} + +bool ResourceFormatLoaderShader::handles_type(const String &p_type) const { + return (p_type == "Shader"); +} + +String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const { + if (p_path.has_extension("gdshader")) { + return "Shader"; + } + return ""; +} + +Error ResourceFormatSaverShader::save(const Ref &p_resource, const String &p_path, uint32_t p_flags) { + Ref shader = p_resource; + ERR_FAIL_COND_V(shader.is_null(), ERR_INVALID_PARAMETER); + + String source = shader->get_code(); + + Error err; + Ref file = FileAccess::open(p_path, FileAccess::WRITE, &err); + + ERR_FAIL_COND_V_MSG(err, err, "Cannot save shader '" + p_path + "'."); + + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } + + return OK; +} + +void ResourceFormatSaverShader::get_recognized_extensions(const Ref &p_resource, List *p_extensions) const { + if (const Shader *shader = Object::cast_to(*p_resource)) { + if (shader->is_text_shader()) { + p_extensions->push_back("gdshader"); + } + } +} + +bool ResourceFormatSaverShader::recognize(const Ref &p_resource) const { + return p_resource->get_class_name() == "Shader"; //only shader, not inherited +} diff --git a/scene/resources/shader_resource_format.h b/scene/resources/shader_resource_format.h new file mode 100644 index 0000000000..b6fea34daa --- /dev/null +++ b/scene/resources/shader_resource_format.h @@ -0,0 +1,53 @@ +/**************************************************************************/ +/* shader_resource_format.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" + +class ResourceFormatLoaderShader : public ResourceFormatLoader { + GDSOFTCLASS(ResourceFormatLoaderShader, ResourceFormatLoader); + +public: + virtual Ref load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override; + virtual void get_recognized_extensions(List *p_extensions) const override; + virtual bool handles_type(const String &p_type) const override; + virtual String get_resource_type(const String &p_path) const override; +}; + +class ResourceFormatSaverShader : public ResourceFormatSaver { + GDSOFTCLASS(ResourceFormatSaverShader, ResourceFormatSaver); + +public: + virtual Error save(const Ref &p_resource, const String &p_path, uint32_t p_flags = 0) override; + virtual void get_recognized_extensions(const Ref &p_resource, List *p_extensions) const override; + virtual bool recognize(const Ref &p_resource) const override; +};