|
@@ -30,45 +30,106 @@
|
|
|
#include "SpineAtlasResource.h"
|
|
|
#include "SpineRendererObject.h"
|
|
|
#include "core/io/json.h"
|
|
|
+#include "core/io/image.h"
|
|
|
+#include "scene/resources/image_texture.h"
|
|
|
#include "scene/resources/texture.h"
|
|
|
#include <spine/TextureLoader.h>
|
|
|
|
|
|
+#ifdef TOOLS_ENABLED
|
|
|
+#include "editor/editor_file_system.h"
|
|
|
+#endif
|
|
|
+
|
|
|
class GodotSpineTextureLoader : public spine::TextureLoader {
|
|
|
|
|
|
Array *textures;
|
|
|
Array *normal_maps;
|
|
|
String normal_map_prefix;
|
|
|
+ bool is_importing;
|
|
|
|
|
|
public:
|
|
|
- GodotSpineTextureLoader(Array *_textures, Array *_normal_maps, const String &normal_map_prefix) : textures(_textures), normal_maps(_normal_maps), normal_map_prefix(normal_map_prefix) {
|
|
|
+ GodotSpineTextureLoader(Array *_textures, Array *_normal_maps, const String &normal_map_prefix, bool is_importing) : textures(_textures), normal_maps(_normal_maps), normal_map_prefix(normal_map_prefix), is_importing(is_importing) {
|
|
|
}
|
|
|
|
|
|
- static String fix_path(const String &path) {
|
|
|
- if (path.size() > 5 && path[4] == '/' && path[5] == '/') return path;
|
|
|
+ static bool fix_path(String &path) {
|
|
|
const String prefix = "res:/";
|
|
|
auto i = path.find(prefix);
|
|
|
+ if (i == std::string::npos) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
auto sub_str_pos = i + prefix.size() - 1;
|
|
|
- if (sub_str_pos < 0) return path;
|
|
|
auto res = path.substr(sub_str_pos);
|
|
|
-
|
|
|
if (!EMPTY(res)) {
|
|
|
if (res[0] != '/') {
|
|
|
- return prefix + "/" + res;
|
|
|
+ path = prefix + "/" + res;
|
|
|
} else {
|
|
|
- return prefix + res;
|
|
|
+ path = prefix + res;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+#if VERSION_MAJOR > 3
|
|
|
+ Ref<Texture2D> get_texture_from_image(const String &path, bool is_resource) {
|
|
|
+ Error error = OK;
|
|
|
+ if (is_resource) {
|
|
|
+ return ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error);
|
|
|
+ } else {
|
|
|
+ Ref<Image> img;
|
|
|
+ img.instantiate();
|
|
|
+ img = img->load_from_file(path);
|
|
|
+ return ImageTexture::create_from_image(img);
|
|
|
+ }
|
|
|
+ }
|
|
|
+#else
|
|
|
+ Ref<Texture> get_texture_from_image(const String &path, bool is_resource) {
|
|
|
+ Error error = OK;
|
|
|
+ if (is_resource) {
|
|
|
+ return ResourceLoader::load(path, "", false, &error);
|
|
|
+ } else {
|
|
|
+ Vector<uint8_t> buf = FileAccess::get_file_as_array(path, &error);
|
|
|
+ if (error == OK) {
|
|
|
+ Ref<Image> img;
|
|
|
+ img.instantiate();
|
|
|
+ String filename = path.get_filename().to_lower();
|
|
|
+ if (filename.ends_with(".png")) {
|
|
|
+ img->load_png_from_buffer(buf);
|
|
|
+ } else if (filename_lower.ends_with(".jpg")) {
|
|
|
+ img->load_jpg_from_buffer(buf);
|
|
|
+ }
|
|
|
+ return ImageTexture::create_from_image(img);
|
|
|
}
|
|
|
}
|
|
|
- return path;
|
|
|
+ return Ref<Texture>();
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ void import_image_resource(const String &path) {
|
|
|
+#ifdef VERSION_MAJOR> 4
|
|
|
+#ifdef TOOLS_ENABLED
|
|
|
+ // Required when importing into editor by e.g. drag & drop. The .png files
|
|
|
+ // of the atlas might not have been imported yet.
|
|
|
+ // See https://github.com/EsotericSoftware/spine-runtimes/issues/2385
|
|
|
+ if (is_importing) {
|
|
|
+ HashMap<StringName, Variant> custom_options;
|
|
|
+ Dictionary generator_parameters;
|
|
|
+ EditorFileSystem::get_singleton()->reimport_append(path, custom_options, "", generator_parameters);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
void load(spine::AtlasPage &page, const spine::String &path) override {
|
|
|
Error error = OK;
|
|
|
- auto fixed_path = fix_path(String(path.buffer()));
|
|
|
+ String fixed_path = String(path.buffer());
|
|
|
+ bool is_resource = fix_path(fixed_path);
|
|
|
+
|
|
|
+ import_image_resource(fixed_path);
|
|
|
|
|
|
#if VERSION_MAJOR > 3
|
|
|
- Ref<Texture2D> texture = ResourceLoader::load(fixed_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error);
|
|
|
+ Ref<Texture2D> texture = get_texture_from_image(fixed_path, is_resource);
|
|
|
#else
|
|
|
- Ref<Texture> texture = ResourceLoader::load(fixed_path, "", false, &error);
|
|
|
+ Ref<Texture> texture = get_texture_from_image(fixed_path, is_resource);
|
|
|
#endif
|
|
|
if (error != OK || !texture.is_valid()) {
|
|
|
ERR_PRINT(vformat("Can't load texture: \"%s\"", String(path.buffer())));
|
|
@@ -86,7 +147,8 @@ public:
|
|
|
|
|
|
String new_path = vformat("%s/%s_%s", fixed_path.get_base_dir(), normal_map_prefix, fixed_path.get_file());
|
|
|
if (ResourceLoader::exists(new_path)) {
|
|
|
- Ref<Texture> normal_map = ResourceLoader::load(new_path);
|
|
|
+ import_image_resource(new_path);
|
|
|
+ Ref<Texture> normal_map = get_texture_from_image(new_path, is_resource);
|
|
|
normal_maps->append(normal_map);
|
|
|
renderer_object->normal_map = normal_map;
|
|
|
}
|
|
@@ -156,13 +218,17 @@ String SpineAtlasResource::get_source_path() {
|
|
|
}
|
|
|
|
|
|
Error SpineAtlasResource::load_from_atlas_file(const String &path) {
|
|
|
+ load_from_atlas_file_internal(path, false);
|
|
|
+}
|
|
|
+
|
|
|
+Error SpineAtlasResource::load_from_atlas_file_internal(const String &path, bool is_importing) {
|
|
|
Error err;
|
|
|
source_path = path;
|
|
|
atlas_data = FileAccess::get_file_as_string(path, &err);
|
|
|
if (err != OK) return err;
|
|
|
|
|
|
clear();
|
|
|
- texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, normal_map_prefix);
|
|
|
+ texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, normal_map_prefix, is_importing);
|
|
|
auto atlas_utf8 = atlas_data.utf8();
|
|
|
atlas = new spine::Atlas(atlas_utf8, atlas_utf8.length(), source_path.get_base_dir().utf8(), texture_loader);
|
|
|
if (atlas) return OK;
|
|
@@ -195,7 +261,7 @@ Error SpineAtlasResource::load_from_file(const String &path) {
|
|
|
normal_map_prefix = content["normal_texture_prefix"];
|
|
|
|
|
|
clear();
|
|
|
- texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, normal_map_prefix);
|
|
|
+ texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, normal_map_prefix, false);
|
|
|
auto utf8 = atlas_data.utf8();
|
|
|
atlas = new spine::Atlas(utf8.ptr(), utf8.size(), source_path.get_base_dir().utf8(), texture_loader);
|
|
|
if (atlas) return OK;
|