From 4906d7185699edd5b15fd59de0ee6c48925d1b39 Mon Sep 17 00:00:00 2001 From: badlogic Date: Fri, 29 Apr 2022 12:43:21 +0200 Subject: [PATCH] [godot] Support per-slot materials via SpineSlotNode. --- .../examples/07-slot-node/slot-node.gd | 4 +- .../examples/07-slot-node/slot-node.tscn | 26 ++++++--- .../08-animation-player/animation-player.tscn | 54 +++++++++--------- .../09-custom-material/custom-material.tscn | 25 +++++++- spine-godot/spine_godot/SpineSlotNode.cpp | 57 ++++++++++++++++++- spine-godot/spine_godot/SpineSlotNode.h | 20 +++++++ spine-godot/spine_godot/SpineSprite.cpp | 22 ++++++- 7 files changed, 166 insertions(+), 42 deletions(-) diff --git a/spine-godot/example/examples/07-slot-node/slot-node.gd b/spine-godot/example/examples/07-slot-node/slot-node.gd index fb039416f..496875d0b 100644 --- a/spine-godot/example/examples/07-slot-node/slot-node.gd +++ b/spine-godot/example/examples/07-slot-node/slot-node.gd @@ -1,8 +1,8 @@ extends Node2D onready var spineboy: SpineSprite = $Spineboy -onready var raptor: SpineSprite = $Spineboy/SlotNodeGun/Raptor -onready var tiny_spineboy: SpineSprite = $Spineboy/SlotNodeFrontFist/TinySpineboy +onready var raptor: SpineSprite = $Spineboy/GunSlot/Raptor +onready var tiny_spineboy: SpineSprite = $Spineboy/FrontFistSlot/TinySpineboy func _ready(): var entry = spineboy.get_animation_state().set_animation("run", true, 0) diff --git a/spine-godot/example/examples/07-slot-node/slot-node.tscn b/spine-godot/example/examples/07-slot-node/slot-node.tscn index 5fae91e55..bbf26cc38 100644 --- a/spine-godot/example/examples/07-slot-node/slot-node.tscn +++ b/spine-godot/example/examples/07-slot-node/slot-node.tscn @@ -1,35 +1,47 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://examples/07-slot-node/slot-node.gd" type="Script" id=1] [ext_resource path="res://assets/spineboy/spinebody-data-res.tres" type="SpineSkeletonDataResource" id=2] [ext_resource path="res://assets/raptor/raprot-data.tres" type="SpineSkeletonDataResource" id=3] +[ext_resource path="res://icon.png" type="Texture" id=4] [node name="Node2D" type="Node2D"] script = ExtResource( 1 ) [node name="Spineboy" type="SpineSprite" parent="."] -position = Vector2( 506, 480 ) +position = Vector2( 474, 506 ) scale = Vector2( 0.560712, 0.560712 ) skeleton_data_res = ExtResource( 2 ) -[node name="SlotNodeGun" type="SpineSlotNode" parent="Spineboy"] -position = Vector2( 40.8752, -276.036 ) +[node name="GunSlot" type="SpineSlotNode" parent="Spineboy"] +position = Vector2( 40.8753, -276.036 ) rotation = 0.837234 scale = Vector2( 1, 1 ) slot_name = "gun" -[node name="Raptor" type="SpineSprite" parent="Spineboy/SlotNodeGun"] +[node name="Raptor" type="SpineSprite" parent="Spineboy/GunSlot"] position = Vector2( 84.6909, -67.9174 ) scale = Vector2( 0.193472, 0.193472 ) skeleton_data_res = ExtResource( 3 ) -[node name="SlotNodeFrontFist" type="SpineSlotNode" parent="Spineboy"] +[node name="EyeSlot" type="SpineSlotNode" parent="Spineboy"] +position = Vector2( -23.4598, -402.301 ) +rotation = -1.71793 +scale = Vector2( 1, 1 ) +slot_name = "eye" + +[node name="Sprite" type="Sprite" parent="Spineboy/EyeSlot"] +position = Vector2( 84.4734, 43.4469 ) +rotation = 1.66344 +texture = ExtResource( 4 ) + +[node name="FrontFistSlot" type="SpineSlotNode" parent="Spineboy"] position = Vector2( -29.0298, -241.577 ) rotation = 0.995187 scale = Vector2( 1, 1 ) slot_name = "front-fist" -[node name="TinySpineboy" type="SpineSprite" parent="Spineboy/SlotNodeFrontFist"] +[node name="TinySpineboy" type="SpineSprite" parent="Spineboy/FrontFistSlot"] position = Vector2( -2.64624, -10.8111 ) scale = Vector2( 0.193389, 0.193389 ) skeleton_data_res = ExtResource( 2 ) diff --git a/spine-godot/example/examples/08-animation-player/animation-player.tscn b/spine-godot/example/examples/08-animation-player/animation-player.tscn index a80618e62..c0e487962 100644 --- a/spine-godot/example/examples/08-animation-player/animation-player.tscn +++ b/spine-godot/example/examples/08-animation-player/animation-player.tscn @@ -36,7 +36,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=85] resource_name = "aim" length = 0.5 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -65,6 +64,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=86] resource_name = "aim_looped" length = 0.5 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -93,7 +93,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=87] resource_name = "death" length = 4.9333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -122,6 +121,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=88] resource_name = "death_looped" length = 4.9333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -149,7 +149,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=89] resource_name = "hoverboard" -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -177,6 +176,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=90] resource_name = "hoverboard_looped" +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -205,7 +205,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=91] resource_name = "idle" length = 1.6667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -234,7 +233,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=92] resource_name = "idle-turn" length = 0.2667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -263,6 +261,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=93] resource_name = "idle-turn_looped" length = 0.2667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -291,6 +290,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=94] resource_name = "idle_looped" length = 1.6667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -319,7 +319,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=95] resource_name = "jump" length = 1.3333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -348,6 +347,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=96] resource_name = "jump_looped" length = 1.3333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -376,7 +376,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=97] resource_name = "portal" length = 3.1667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -405,6 +404,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=98] resource_name = "portal_looped" length = 3.1667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -433,7 +433,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=99] resource_name = "run" length = 0.6667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -462,7 +461,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=100] resource_name = "run-to-idle" length = 0.2667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -491,6 +489,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=101] resource_name = "run-to-idle_looped" length = 0.2667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -519,6 +518,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=102] resource_name = "run_looped" length = 0.6667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -547,7 +547,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=103] resource_name = "shoot" length = 0.6333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -576,6 +575,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=104] resource_name = "shoot_looped" length = 0.6333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -603,7 +603,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=105] resource_name = "walk" -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -631,6 +630,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=106] resource_name = "walk_looped" +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -688,7 +688,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=108] resource_name = "aim" length = 0.5 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -717,6 +716,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=109] resource_name = "aim_looped" length = 0.5 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -745,7 +745,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=110] resource_name = "death" length = 4.9333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -774,6 +773,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=111] resource_name = "death_looped" length = 4.9333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -801,7 +801,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=112] resource_name = "hoverboard" -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -829,6 +828,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=113] resource_name = "hoverboard_looped" +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -857,7 +857,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=114] resource_name = "idle" length = 1.6667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -886,7 +885,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=115] resource_name = "idle-turn" length = 0.2667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -915,6 +913,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=116] resource_name = "idle-turn_looped" length = 0.2667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -943,6 +942,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=117] resource_name = "idle_looped" length = 1.6667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -971,7 +971,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=118] resource_name = "jump" length = 1.3333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1000,6 +999,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=119] resource_name = "jump_looped" length = 1.3333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1028,7 +1028,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=120] resource_name = "portal" length = 3.1667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1057,6 +1056,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=121] resource_name = "portal_looped" length = 3.1667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1085,7 +1085,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=122] resource_name = "run" length = 0.6667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1114,7 +1113,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=123] resource_name = "run-to-idle" length = 0.2667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1143,6 +1141,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=124] resource_name = "run-to-idle_looped" length = 0.2667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1171,6 +1170,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=125] resource_name = "run_looped" length = 0.6667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1199,7 +1199,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=126] resource_name = "shoot" length = 0.6333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1228,6 +1227,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=127] resource_name = "shoot_looped" length = 0.6333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1255,7 +1255,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=128] resource_name = "walk" -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1283,6 +1282,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=129] resource_name = "walk_looped" +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1340,7 +1340,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=131] resource_name = "gun-grab" length = 0.666667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1369,6 +1368,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=132] resource_name = "gun-grab_looped" length = 0.666667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1397,7 +1397,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=133] resource_name = "gun-holster" length = 0.666667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1426,6 +1425,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=134] resource_name = "gun-holster_looped" length = 0.666667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1454,7 +1454,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=135] resource_name = "jump" length = 1.53333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1483,6 +1482,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=136] resource_name = "jump_looped" length = 1.53333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1511,7 +1511,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=137] resource_name = "roar" length = 2.13333 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1540,6 +1539,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=138] resource_name = "roar_looped" length = 2.13333 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1568,7 +1568,6 @@ tracks/1/keys = { [sub_resource type="Animation" id=139] resource_name = "walk" length = 1.26667 -loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 @@ -1597,6 +1596,7 @@ tracks/1/keys = { [sub_resource type="Animation" id=140] resource_name = "walk_looped" length = 1.26667 +loop = true tracks/0/type = "value" tracks/0/path = NodePath(".:animation_name") tracks/0/interp = 1 diff --git a/spine-godot/example/examples/09-custom-material/custom-material.tscn b/spine-godot/example/examples/09-custom-material/custom-material.tscn index 17f6d21c0..27cde2e98 100644 --- a/spine-godot/example/examples/09-custom-material/custom-material.tscn +++ b/spine-godot/example/examples/09-custom-material/custom-material.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=6 format=2] [ext_resource path="res://assets/spineboy/spinebody-data-res.tres" type="SpineSkeletonDataResource" id=1] @@ -6,16 +6,35 @@ code = "shader_type canvas_item; void fragment() { - COLOR = vec4(0.4, 0.6, 0.9, 1.0); + COLOR = texture(TEXTURE, UV); + COLOR.r = 0.0; }" [sub_resource type="ShaderMaterial" id=2] shader = SubResource( 1 ) +[sub_resource type="Shader" id=3] +code = "shader_type canvas_item; + +void fragment() { + COLOR = texture(TEXTURE, UV); + COLOR.b = 0.0; +}" + +[sub_resource type="ShaderMaterial" id=4] +shader = SubResource( 3 ) + [node name="Node2D" type="Node2D"] [node name="SpineSprite" type="SpineSprite" parent="."] -position = Vector2( 471, 482 ) +position = Vector2( 501, 507 ) scale = Vector2( 0.546374, 0.546373 ) skeleton_data_res = ExtResource( 1 ) normal_material = SubResource( 2 ) + +[node name="GunSlot" type="SpineSlotNode" parent="SpineSprite"] +position = Vector2( 40.8752, -276.036 ) +rotation = 0.837234 +scale = Vector2( 1, 1 ) +slot_name = "gun" +normal_material = SubResource( 4 ) diff --git a/spine-godot/spine_godot/SpineSlotNode.cpp b/spine-godot/spine_godot/SpineSlotNode.cpp index 1e13c3562..c3c43911e 100644 --- a/spine-godot/spine_godot/SpineSlotNode.cpp +++ b/spine-godot/spine_godot/SpineSlotNode.cpp @@ -7,6 +7,21 @@ void SpineSlotNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_slot_name"), &SpineSlotNode::set_slot_name); ClassDB::bind_method(D_METHOD("get_slot_name"), &SpineSlotNode::get_slot_name); ClassDB::bind_method(D_METHOD("_on_world_transforms_changed", "spine_sprite"), &SpineSlotNode::on_world_transforms_changed); + + ClassDB::bind_method(D_METHOD("set_normal_material", "material"), &SpineSlotNode::set_normal_material); + ClassDB::bind_method(D_METHOD("get_normal_material"), &SpineSlotNode::get_normal_material); + ClassDB::bind_method(D_METHOD("set_additive_material", "material"), &SpineSlotNode::set_additive_material); + ClassDB::bind_method(D_METHOD("get_additive_material"), &SpineSlotNode::get_additive_material); + ClassDB::bind_method(D_METHOD("set_multiply_material", "material"), &SpineSlotNode::set_multiply_material); + ClassDB::bind_method(D_METHOD("get_multiply_material"), &SpineSlotNode::get_multiply_material); + ClassDB::bind_method(D_METHOD("set_screen_material", "material"), &SpineSlotNode::set_screen_material); + ClassDB::bind_method(D_METHOD("get_screen_material"), &SpineSlotNode::get_screen_material); + + ADD_GROUP("Materials", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_normal_material", "get_normal_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "additive_material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_additive_material", "get_additive_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiply_material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_multiply_material", "get_multiply_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "screen_material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_screen_material", "get_screen_material"); } SpineSlotNode::SpineSlotNode(): slot_index(-1), sprite(nullptr) { @@ -56,13 +71,19 @@ void SpineSlotNode::_get_property_list(List* list) const { Vector slot_names; if (sprite) sprite->get_skeleton_data_res()->get_slot_names(slot_names); else slot_names.push_back(slot_name); + auto element = list->front(); + while (element) { + auto property_info = element->get(); + if (property_info.name == "SpineSlotNode") break; + element = element->next(); + } PropertyInfo slot_name_property; slot_name_property.name = "slot_name"; slot_name_property.type = Variant::STRING; slot_name_property.hint_string = String(",").join(slot_names); slot_name_property.hint = PROPERTY_HINT_ENUM; slot_name_property.usage = PROPERTY_USAGE_DEFAULT; - list->push_back(slot_name_property); + list->insert_after(element, slot_name_property); } bool SpineSlotNode::_get(const StringName& property, Variant& value) const { @@ -117,4 +138,36 @@ void SpineSlotNode::set_slot_name(const String& _slot_name) { String SpineSlotNode::get_slot_name() { return slot_name; -} \ No newline at end of file +} + +Ref SpineSlotNode::get_normal_material() { + return normal_material; +} + +void SpineSlotNode::set_normal_material(Ref material) { + normal_material = material; +} + +Ref SpineSlotNode::get_additive_material() { + return additive_material; +} + +void SpineSlotNode::set_additive_material(Ref material) { + additive_material = material; +} + +Ref SpineSlotNode::get_multiply_material() { + return multiply_material; +} + +void SpineSlotNode::set_multiply_material(Ref material) { + multiply_material = material; +} + +Ref SpineSlotNode::get_screen_material() { + return screen_material; +} + +void SpineSlotNode::set_screen_material(Ref material) { + screen_material = material; +} diff --git a/spine-godot/spine_godot/SpineSlotNode.h b/spine-godot/spine_godot/SpineSlotNode.h index 5344172cf..581c77f99 100644 --- a/spine-godot/spine_godot/SpineSlotNode.h +++ b/spine-godot/spine_godot/SpineSlotNode.h @@ -11,6 +11,10 @@ class SpineSlotNode: public Node2D { protected: String slot_name; int slot_index; + Ref normal_material; + Ref additive_material; + Ref multiply_material; + Ref screen_material; SpineSprite *sprite; static void _bind_methods(); @@ -28,6 +32,22 @@ public: String get_slot_name(); int get_slot_index() { return slot_index; } + + Ref get_normal_material(); + + void set_normal_material(Ref material); + + Ref get_additive_material(); + + void set_additive_material(Ref material); + + Ref get_multiply_material(); + + void set_multiply_material(Ref material); + + Ref get_screen_material(); + + void set_screen_material(Ref material); }; #endif diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index b4f41b648..14bfb3696 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -419,12 +419,32 @@ void SpineSprite::update_meshes(Ref skeleton_ref) { spine::BlendMode blend_mode = slot->getData().getBlendMode(); Ref custom_material; - switch (blend_mode) { + + // See if we have a slot node for this slot with a custom material + auto &nodes = slot_nodes[i]; + if (nodes.size() > 0) { + auto slot_node = nodes[0]; + if (slot_node) { + switch (blend_mode) { + case spine::BlendMode_Normal: custom_material = slot_node->get_normal_material(); break; + case spine::BlendMode_Additive: custom_material = slot_node->get_additive_material(); break; + case spine::BlendMode_Multiply: custom_material = slot_node->get_multiply_material(); break; + case spine::BlendMode_Screen: custom_material = slot_node->get_screen_material(); break; + } + } + } + + // Else, check if we have a material on the sprite itself + if (!custom_material.is_valid()) { + switch (blend_mode) { case spine::BlendMode_Normal: custom_material = normal_material; break; case spine::BlendMode_Additive: custom_material = additive_material; break; case spine::BlendMode_Multiply: custom_material = multiply_material; break; case spine::BlendMode_Screen: custom_material = screen_material; break; + } } + + // Set the custom material, or the default material if (custom_material.is_valid()) mesh_instance->set_material(custom_material); else mesh_instance->set_material(default_materials[slot->getData().getBlendMode()]); }