[godot] Adds specular map support (#2850)

This commit is contained in:
Luke Ingram 2025-05-16 03:28:21 -04:00 committed by GitHub
parent 6f94019aa3
commit 6a08383460
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 80 additions and 18 deletions

View File

@ -61,10 +61,12 @@ class GodotSpineTextureLoader : public spine::TextureLoader {
Array *textures;
Array *normal_maps;
Array *specular_maps;
String normal_map_prefix;
String specular_map_prefix;
public:
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) {
GodotSpineTextureLoader(Array *_textures, Array *_normal_maps, Array *_specular_maps, const String &normal_map_prefix, const String &specular_map_prefix, bool is_importing) : textures(_textures), normal_maps(_normal_maps), specular_maps(_specular_maps), normal_map_prefix(normal_map_prefix), specular_map_prefix(specular_map_prefix) {
}
static bool fix_path(String &path) {
@ -156,6 +158,7 @@ public:
auto renderer_object = memnew(SpineRendererObject);
renderer_object->texture = Ref<Texture>(nullptr);
renderer_object->normal_map = Ref<Texture>(nullptr);
renderer_object->specular_map = Ref<Texture>(nullptr);
page.texture = (void *) renderer_object;
return;
}
@ -164,9 +167,12 @@ public:
auto renderer_object = memnew(SpineRendererObject);
renderer_object->texture = texture;
renderer_object->normal_map = Ref<Texture>(nullptr);
renderer_object->specular_map = Ref<Texture>(nullptr);
String normal_map_path = vformat("%s/%s_%s", fixed_path.get_base_dir(), normal_map_prefix, fixed_path.get_file());
String specular_map_path = vformat("%s/%s_%s", fixed_path.get_base_dir(), specular_map_prefix, fixed_path.get_file());
is_resource = fix_path(normal_map_path);
is_resource = fix_path(specular_map_path);
#if SPINE_GODOT_EXTENSION
if (ResourceLoader::get_singleton()->exists(normal_map_path)) {
import_image_resource(normal_map_path);
@ -174,6 +180,13 @@ public:
normal_maps->append(normal_map);
renderer_object->normal_map = normal_map;
}
if (ResourceLoader::get_singleton()->exists(specular_map_path)) {
import_image_resource(specular_map_path);
Ref<Texture> specular_map = get_texture_from_image(specular_map_path, is_resource);
specular_maps->append(specular_map);
renderer_object->specular_map = specular_map;
}
#else
if (ResourceLoader::exists(normal_map_path)) {
import_image_resource(normal_map_path);
@ -181,12 +194,20 @@ public:
normal_maps->append(normal_map);
renderer_object->normal_map = normal_map;
}
if (ResourceLoader::exists(specular_map_path)) {
import_image_resource(specular_map_path);
Ref<Texture> specular_map = get_texture_from_image(specular_map_path, is_resource);
specular_maps->append(specular_map);
renderer_object->specular_map = specular_map;
}
#endif
#if VERSION_MAJOR > 3
renderer_object->canvas_texture.instantiate();
renderer_object->canvas_texture->set_diffuse_texture(renderer_object->texture);
renderer_object->canvas_texture->set_normal_texture(renderer_object->normal_map);
renderer_object->canvas_texture->set_specular_texture(renderer_object->specular_map);
#endif
page.texture = (void *) renderer_object;
@ -198,6 +219,7 @@ public:
auto renderer_object = (SpineRendererObject *) data;
if (renderer_object->texture.is_valid()) renderer_object->texture.unref();
if (renderer_object->normal_map.is_valid()) renderer_object->normal_map.unref();
if (renderer_object->specular_map.is_valid()) renderer_object->specular_map.unref();
#if VERSION_MAJOR > 3
if (renderer_object->canvas_texture.is_valid()) renderer_object->canvas_texture.unref();
#endif
@ -210,13 +232,15 @@ void SpineAtlasResource::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_source_path"), &SpineAtlasResource::get_source_path);
ClassDB::bind_method(D_METHOD("get_textures"), &SpineAtlasResource::get_textures);
ClassDB::bind_method(D_METHOD("get_normal_maps"), &SpineAtlasResource::get_normal_maps);
ClassDB::bind_method(D_METHOD("get_specular_maps"), &SpineAtlasResource::get_specular_maps);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_path"), "", "get_source_path");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures"), "", "get_textures");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "normal_maps"), "", "get_normal_maps");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "specular_maps"), "", "get_specular_maps");
}
SpineAtlasResource::SpineAtlasResource() : atlas(nullptr), texture_loader(nullptr), normal_map_prefix("n") {
SpineAtlasResource::SpineAtlasResource() : atlas(nullptr), texture_loader(nullptr), normal_map_prefix("n"), specular_map_prefix("s") {
}
SpineAtlasResource::~SpineAtlasResource() {
@ -231,6 +255,7 @@ void SpineAtlasResource::clear() {
texture_loader = nullptr;
textures.clear();
normal_maps.clear();
specular_maps.clear();
}
Array SpineAtlasResource::get_textures() {
@ -241,6 +266,10 @@ Array SpineAtlasResource::get_normal_maps() {
return normal_maps;
}
Array SpineAtlasResource::get_specular_maps() {
return specular_maps;
}
String SpineAtlasResource::get_source_path() {
return source_path;
}
@ -261,7 +290,7 @@ Error SpineAtlasResource::load_from_atlas_file_internal(const String &path, bool
#endif
clear();
texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, normal_map_prefix, is_importing);
texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, &specular_maps, normal_map_prefix, specular_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;
@ -301,9 +330,10 @@ Error SpineAtlasResource::load_from_file(const String &path) {
source_path = content["source_path"];
atlas_data = content["atlas_data"];
normal_map_prefix = content["normal_texture_prefix"];
specular_map_prefix = content["specular_texture_prefix"];
clear();
texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, normal_map_prefix, false);
texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, &specular_maps, normal_map_prefix, specular_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;
@ -334,6 +364,7 @@ Error SpineAtlasResource::save_to_file(const String &path) {
content["source_path"] = source_path;
content["atlas_data"] = atlas_data;
content["normal_texture_prefix"] = normal_map_prefix;
content["specular_texture_prefix"] = specular_map_prefix;
#if VERSION_MAJOR > 3
JSON *json = memnew(JSON);
file->store_string(json->stringify(content));
@ -361,8 +392,10 @@ Error SpineAtlasResource::copy_from(const Ref<Resource> &p_resource) {
this->source_path = spineAtlas->source_path;
this->atlas_data = spineAtlas->atlas_data;
this->normal_map_prefix = spineAtlas->normal_map_prefix;
this->specular_map_prefix = spineAtlas->specular_map_prefix;
this->textures = spineAtlas->textures;
this->normal_maps = spineAtlas->normal_maps;
this->specular_maps = spineAtlas->specular_maps;
emit_signal(SNAME("skeleton_file_changed"));
return OK;

View File

@ -60,9 +60,11 @@ protected:
String source_path;
String atlas_data;
String normal_map_prefix;
String specular_map_prefix;
Array textures;
Array normal_maps;
Array specular_maps;
public:
SpineAtlasResource();
@ -72,6 +74,8 @@ public:
void set_normal_texture_prefix(const String &prefix) { normal_map_prefix = prefix; }
void set_specular_texture_prefix(const String &prefix) { specular_map_prefix = prefix; }
Error load_from_atlas_file(const String &path);// .atlas
Error load_from_atlas_file_internal(const String &path, bool is_importing);// .atlas
@ -92,6 +96,8 @@ public:
Array get_normal_maps();
Array get_specular_maps();
void clear_native_data() const {
this->atlas = nullptr;
this->texture_loader = nullptr;

View File

@ -54,6 +54,7 @@ Error SpineAtlasResourceImportPlugin::import(const String &source_file, const St
#endif
Ref<SpineAtlasResource> atlas(memnew(SpineAtlasResource));
atlas->set_normal_texture_prefix(options["normal_map_prefix"]);
atlas->set_specular_texture_prefix(options["specular_map_prefix"]);
atlas->load_from_atlas_file_internal(source_file, true);
#if VERSION_MAJOR > 3
@ -74,12 +75,21 @@ Error SpineAtlasResourceImportPlugin::import(const String &source_file, const St
#ifdef SPINE_GODOT_EXTENSION
TypedArray<Dictionary> SpineAtlasResourceImportPlugin::_get_import_options(const String &p_path, int32_t p_preset_index) const {
TypedArray<Dictionary> options;
Dictionary dictionary;
dictionary["name"] = "normal_map_prefix";
dictionary["type"] = Variant::STRING;
dictionary["hint_string"] = "String";
dictionary["default_value"] = String("n");
options.push_back(dictionary);
Dictionary normal_map_dictionary;
normal_map_dictionary["name"] = "normal_map_prefix";
normal_map_dictionary["type"] = Variant::STRING;
normal_map_dictionary["hint_string"] = "String";
normal_map_dictionary["default_value"] = String("n");
options.push_back(normal_map_dictionary);
Dictionary specular_map_dictionary;
specular_map_dictionary["name"] = "specular_map_prefix";
specular_map_dictionary["type"] = Variant::STRING;
specular_map_dictionary["hint_string"] = "String";
specular_map_dictionary["default_value"] = String("s");
options.push_back(specular_map_dictionary);
return options;
}
#else
@ -89,12 +99,19 @@ void SpineAtlasResourceImportPlugin::get_import_options(const String &path, List
void SpineAtlasResourceImportPlugin::get_import_options(List<ImportOption> *options, int preset) const {
#endif
if (preset == 0) {
ImportOption op;
op.option.name = "normal_map_prefix";
op.option.type = Variant::STRING;
op.option.hint_string = "String";
op.default_value = String("n");
options->push_back(op);
ImportOption normal_map_op;
normal_map_op.option.name = "normal_map_prefix";
normal_map_op.option.type = Variant::STRING;
normal_map_op.option.hint_string = "String";
normal_map_op.default_value = String("n");
options->push_back(normal_map_op);
ImportOption specular_map_op;
specular_map_op.option.name = "specular_map_prefix";
specular_map_op.option.type = Variant::STRING;
specular_map_op.option.hint_string = "String";
specular_map_op.default_value = String("s");
options->push_back(specular_map_op);
}
}
#endif

View File

@ -46,6 +46,7 @@
struct SpineRendererObject {
Ref<Texture> texture;
Ref<Texture> normal_map;
Ref<Texture> specular_map;
#if VERSION_MAJOR > 3
Ref<CanvasTexture> canvas_texture;
#endif

View File

@ -179,6 +179,7 @@ static void add_triangles(SpineMesh2D *mesh_instance,
#else
auto texture = renderer_object->texture;
auto normal_map = renderer_object->normal_map;
auto specular_map = renderer_object->specular_map;
VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_instance->get_canvas_item(),
indices,
vertices,
@ -188,7 +189,8 @@ static void add_triangles(SpineMesh2D *mesh_instance,
Vector<float>(),
texture.is_null() ? RID() : texture->get_rid(),
-1,
normal_map.is_null() ? RID() : normal_map->get_rid());
normal_map.is_null() ? RID() : normal_map->get_rid(),
specular_map.is_null() ? RID() : specular_map->get_rid());
#endif
#endif
}
@ -403,7 +405,8 @@ void SpineMesh2D::update_mesh(const Vector<Point2> &vertices,
Transform2D(),
Color(1, 1, 1, 1),
renderer_object->texture.is_null() ? RID() : renderer_object->texture->get_rid(),
renderer_object->normal_map.is_null() ? RID() : renderer_object->normal_map->get_rid());
renderer_object->normal_map.is_null() ? RID() : renderer_object->normal_map->get_rid(),
renderer_object->specular_map.is_null() ? RID() : renderer_object->specular_map->get_rid());
#endif
}
#endif

View File

@ -19,6 +19,8 @@
<members>
<member name="normal_maps" type="Array" setter="" getter="get_normal_maps" default="[ ]">
</member>
<member name="specular_maps" type="Array" setter="" getter="get_specular_maps" default="[ ]">
</member>
<member name="source_path" type="String" setter="" getter="get_source_path" default="&quot;&quot;">
</member>
<member name="textures" type="Array" setter="" getter="get_textures" default="[ ]">