diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index a63dc2cac..1d5e381ec 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -33,7 +33,7 @@ #include "SpineSkeleton.h" #include "SpineRendererObject.h" -Ref SpineSprite::materials[4] = {}; +Ref SpineSprite::default_materials[4] = {}; static int sprite_count = 0; void SpineSprite::_bind_methods() { @@ -41,18 +41,17 @@ void SpineSprite::_bind_methods() { ClassDB::bind_method(D_METHOD("get_skeleton_data_res"), &SpineSprite::get_skeleton_data_res); ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSprite::get_skeleton); ClassDB::bind_method(D_METHOD("get_animation_state"), &SpineSprite::get_animation_state); - ClassDB::bind_method(D_METHOD("_on_skeleton_data_changed"), &SpineSprite::_on_skeleton_data_changed); - + ClassDB::bind_method(D_METHOD("on_skeleton_data_changed"), &SpineSprite::on_skeleton_data_changed); ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineSprite::get_bind_slot_nodes); ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes); - ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform); - ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform); + ClassDB::bind_method(D_METHOD("get_global_bone_transform", "bone_name"), &SpineSprite::get_global_bone_transform); + ClassDB::bind_method(D_METHOD("set_global_bone_transform", "bone_name", "global_transform"), &SpineSprite::set_global_bone_transform); ClassDB::bind_method(D_METHOD("set_update_mode", "v"), &SpineSprite::set_update_mode); ClassDB::bind_method(D_METHOD("get_update_mode"), &SpineSprite::get_update_mode); - ClassDB::bind_method(D_METHOD("update_all", "delta"), &SpineSprite::_update_all); + ClassDB::bind_method(D_METHOD("update_skeleton", "delta"), &SpineSprite::update_skeleton); ADD_SIGNAL(MethodInfo("animation_start", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); ADD_SIGNAL(MethodInfo("animation_interrupt", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); @@ -60,37 +59,37 @@ void SpineSprite::_bind_methods() { ADD_SIGNAL(MethodInfo("animation_complete", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); ADD_SIGNAL(MethodInfo("animation_dispose", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); ADD_SIGNAL(MethodInfo("animation_event", PropertyInfo(Variant::OBJECT, "animation_state", PROPERTY_HINT_TYPE_STRING, "SpineAnimationState"), PropertyInfo(Variant::OBJECT, "track_entry", PROPERTY_HINT_TYPE_STRING, "SpineTrackEntry"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_TYPE_STRING, "SpineEvent"))); + ADD_SIGNAL(MethodInfo("world_transforms_changed")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonDataResource"), "set_skeleton_data_res", "get_skeleton_data_res"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manual"), "set_update_mode", "get_update_mode"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes"); BIND_ENUM_CONSTANT(UpdateMode::UpdateMode_Process) BIND_ENUM_CONSTANT(UpdateMode::UpdateMode_Physics) BIND_ENUM_CONSTANT(UpdateMode::UpdateMode_Manual) } -SpineSprite::SpineSprite() : overlap(false), update_mode(UpdateMode_Process), skeleton_clipper(nullptr) { +SpineSprite::SpineSprite() : update_mode(UpdateMode_Process), skeleton_clipper(nullptr) { skeleton_clipper = new spine::SkeletonClipping(); // One material per blend mode, shared across all sprites. - if (!materials[0].is_valid()) { + if (!default_materials[0].is_valid()) { Ref material_normal(memnew(CanvasItemMaterial)); material_normal->set_blend_mode(CanvasItemMaterial::BLEND_MODE_MIX); - materials[spine::BlendMode_Normal] = material_normal; + default_materials[spine::BlendMode_Normal] = material_normal; Ref material_additive(memnew(CanvasItemMaterial)); material_additive->set_blend_mode(CanvasItemMaterial::BLEND_MODE_ADD); - materials[spine::BlendMode_Additive] = material_additive; + default_materials[spine::BlendMode_Additive] = material_additive; Ref material_multiply(memnew(CanvasItemMaterial)); material_multiply->set_blend_mode(CanvasItemMaterial::BLEND_MODE_MUL); - materials[spine::BlendMode_Multiply] = material_multiply; + default_materials[spine::BlendMode_Multiply] = material_multiply; Ref material_screen(memnew(CanvasItemMaterial)); material_screen->set_blend_mode(CanvasItemMaterial::BLEND_MODE_MIX); - materials[spine::BlendMode_Screen] = material_screen; + default_materials[spine::BlendMode_Screen] = material_screen; } sprite_count++; } @@ -99,30 +98,31 @@ SpineSprite::~SpineSprite() { delete skeleton_clipper; sprite_count--; if (!sprite_count) { - for (int i = 0; i < 4; i++) materials[i].unref(); + for (int i = 0; i < 4; i++) + default_materials[i].unref(); } } void SpineSprite::set_skeleton_data_res(const Ref &s) { skeleton_data_res = s; - _on_skeleton_data_changed(); + on_skeleton_data_changed(); } Ref SpineSprite::get_skeleton_data_res() { return skeleton_data_res; } -void SpineSprite::_on_skeleton_data_changed() { +void SpineSprite::on_skeleton_data_changed() { remove_meshes(); skeleton.unref(); animation_state.unref(); if (skeleton_data_res.is_valid()) { #if VERSION_MAJOR > 3 - if (!skeleton_data_res->is_connected("skeleton_data_changed", callable_mp(this, &SpineSprite::_on_skeleton_data_changed))) - skeleton_data_res->connect("skeleton_data_changed", callable_mp(this, &SpineSprite::_on_skeleton_data_changed)); + if (!skeleton_data_res->is_connected("skeleton_data_changed", callable_mp(this, &SpineSprite::on_skeleton_data_changed))) + skeleton_data_res->connect("skeleton_data_changed", callable_mp(this, &SpineSprite::on_skeleton_data_changed)); #else - if (!skeleton_data_res->is_connected("skeleton_data_changed", this, "_on_skeleton_data_changed")) - skeleton_data_res->connect("skeleton_data_changed", this, "_on_skeleton_data_changed"); + if (!skeleton_data_res->is_connected("skeleton_data_changed", this, "on_skeleton_data_changed")) + skeleton_data_res->connect("skeleton_data_changed", this, "on_skeleton_data_changed"); #endif } @@ -150,6 +150,28 @@ void SpineSprite::_on_skeleton_data_changed() { NOTIFY_PROPERTY_LIST_CHANGED(); } +void SpineSprite::generate_meshes_for_slots(Ref skeleton_ref) { + auto skeleton = skeleton_ref->get_spine_object(); + for (int i = 0, n = skeleton->getSlots().size(); i < n; i++) { + + auto mesh_instance = memnew(MeshInstance2D); + mesh_instance->set_position(Vector2(0, 0)); + mesh_instance->set_material(default_materials[spine::BlendMode_Normal]); + + add_child(mesh_instance); + mesh_instance->set_owner(this); + mesh_instances.push_back(mesh_instance); + } +} + +void SpineSprite::remove_meshes() { + for (size_t i = 0; i < mesh_instances.size(); ++i) { + remove_child(mesh_instances[i]); + memdelete(mesh_instances[i]); + } + mesh_instances.clear(); +} + Ref SpineSprite::get_skeleton() { return skeleton; } @@ -158,8 +180,8 @@ Ref SpineSprite::get_animation_state() { return animation_state; } -void SpineSprite::_notification(int p_what) { - switch (p_what) { +void SpineSprite::_notification(int what) { + switch (what) { case NOTIFICATION_READY: { set_process_internal(update_mode == UpdateMode_Process); set_physics_process_internal(update_mode == UpdateMode_Physics); @@ -167,12 +189,12 @@ void SpineSprite::_notification(int p_what) { } case NOTIFICATION_INTERNAL_PROCESS: { if (update_mode == UpdateMode_Process) - _update_all(get_process_delta_time()); + update_skeleton(get_process_delta_time()); break; } case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (update_mode == UpdateMode_Physics) - _update_all(get_physics_process_delta_time()); + update_skeleton(get_physics_process_delta_time()); break; } default: @@ -180,7 +202,7 @@ void SpineSprite::_notification(int p_what) { } } -void SpineSprite::_update_all(float delta) { +void SpineSprite::update_skeleton(float delta) { if (!(skeleton.is_valid() && animation_state.is_valid()) || EMPTY(mesh_instances)) return; @@ -190,6 +212,7 @@ void SpineSprite::_update_all(float delta) { animation_state->apply(skeleton); skeleton->update_world_transform(); + emit_signal("world_transforms_changed"); update_meshes(skeleton); update(); update_bind_slot_nodes(); @@ -276,28 +299,6 @@ Node *SpineSprite::find_child_node_by_node(Node *node) { return node; } -void SpineSprite::generate_meshes_for_slots(Ref skeleton_ref) { - auto skeleton = skeleton_ref->get_spine_object(); - for (int i = 0, n = skeleton->getSlots().size(); i < n; i++) { - - auto mesh_instance = memnew(MeshInstance2D); - mesh_instance->set_position(Vector2(0, 0)); - mesh_instance->set_material(materials[spine::BlendMode_Normal]); - - add_child(mesh_instance); - mesh_instance->set_owner(this); - mesh_instances.push_back(mesh_instance); - } -} - -void SpineSprite::remove_meshes() { - for (size_t i = 0; i < mesh_instances.size(); ++i) { - remove_child(mesh_instances[i]); - memdelete(mesh_instances[i]); - } - mesh_instances.clear(); -} - #define TEMP_COPY(t, get_res) \ do { \ auto &temp_uvs = get_res; \ @@ -307,11 +308,11 @@ void SpineSprite::remove_meshes() { } \ } while (false); -void SpineSprite::update_meshes(Ref s) { +void SpineSprite::update_meshes(Ref skeleton) { static const unsigned short VERTEX_STRIDE = 2; static unsigned short quad_indices[] = {0, 1, 2, 2, 3, 0}; - auto sk = s->get_spine_object(); + auto sk = skeleton->get_spine_object(); for (int i = 0, n = sk->getSlots().size(); i < n; ++i) { spine::Vector vertices; spine::Vector uvs; @@ -322,7 +323,6 @@ void SpineSprite::update_meshes(Ref s) { spine::Attachment *attachment = slot->getAttachment(); if (!attachment) { mesh_instances[i]->set_visible(false); - skeleton_clipper->clipEnd(*slot); continue; } @@ -494,43 +494,40 @@ void SpineSprite::update_meshes(Ref s) { skeleton_clipper->clipEnd(*slot); if (mesh_ins->get_material()->is_class("CanvasItemMaterial")) { - mesh_ins->set_material(materials[slot->getData().getBlendMode()]); + mesh_ins->set_material(default_materials[slot->getData().getBlendMode()]); } } skeleton_clipper->clipEnd(); } void SpineSprite::callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event) { - Ref gd_entry(nullptr); - Ref gd_event(nullptr); - - if (entry) { - gd_entry = Ref(memnew(SpineTrackEntry)); - gd_entry->set_spine_object(entry); - } + Ref entry_ref = Ref(memnew(SpineTrackEntry)); + entry_ref->set_spine_object(entry); + + Ref event_ref(nullptr); if (event) { - gd_event = Ref(memnew(SpineEvent)); - gd_event->set_spine_object(event); + event_ref = Ref(memnew(SpineEvent)); + event_ref->set_spine_object(event); } switch (type) { case spine::EventType_Start: { - emit_signal("animation_start", animation_state, gd_entry, gd_event); + emit_signal("animation_start", animation_state, entry_ref, event_ref); } break; case spine::EventType_Interrupt: { - emit_signal("animation_interrupt", animation_state, gd_entry, gd_event); + emit_signal("animation_interrupt", animation_state, entry_ref, event_ref); } break; case spine::EventType_End: { - emit_signal("animation_end", animation_state, gd_entry, gd_event); + emit_signal("animation_end", animation_state, entry_ref, event_ref); } break; case spine::EventType_Complete: { - emit_signal("animation_complete", animation_state, gd_entry, gd_event); + emit_signal("animation_complete", animation_state, entry_ref, event_ref); } break; case spine::EventType_Dispose: { - emit_signal("animation_dispose", animation_state, gd_entry, gd_event); + emit_signal("animation_dispose", animation_state, entry_ref, event_ref); } break; case spine::EventType_Event: { - emit_signal("animation_event", animation_state, gd_entry, gd_event); + emit_signal("animation_event", animation_state, entry_ref, event_ref); } break; } } @@ -543,7 +540,7 @@ void SpineSprite::set_bind_slot_nodes(Array v) { bind_slot_nodes = v; } -Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) { +Transform2D SpineSprite::get_global_bone_transform(const String &bone_name) { if (!animation_state.is_valid() && !skeleton.is_valid()) { return get_global_transform(); } @@ -555,7 +552,7 @@ Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) { return bone->get_godot_global_transform(); } -void SpineSprite::bone_set_global_transform(const String &bone_name, Transform2D transform) { +void SpineSprite::set_global_bone_transform(const String &bone_name, Transform2D transform) { if (!animation_state.is_valid() && !skeleton.is_valid()) { return; } @@ -576,63 +573,6 @@ void SpineSprite::set_update_mode(SpineSprite::UpdateMode v) { set_physics_process_internal(update_mode == UpdateMode_Physics); } -void SpineSprite::_get_property_list(List *p_list) const { - Vector animations; - Vector skins; - if (skeleton_data_res.is_valid()) { - skeleton_data_res->get_animation_names(animations); - skeleton_data_res->get_skin_names(skins); - } - animations.insert(0, "- None -"); - - PropertyInfo animationListProperty; - animationListProperty.name = "Preview animation"; - animationListProperty.type = Variant::STRING; - animationListProperty.hint_string = String(",").join(animations); - animationListProperty.hint = PROPERTY_HINT_ENUM; - animationListProperty.usage = PROPERTY_USAGE_EDITOR; - p_list->push_back(animationListProperty); - - PropertyInfo skinListProperty; - skinListProperty.name = "Preview skin"; - skinListProperty.type = Variant::STRING; - skinListProperty.hint_string = String(",").join(skins); - skinListProperty.hint = PROPERTY_HINT_ENUM; - skinListProperty.usage = PROPERTY_USAGE_EDITOR; - p_list->push_back(skinListProperty); -} - -bool SpineSprite::_get(const StringName &p_property, Variant &r_value) const { - return false; -} - -bool SpineSprite::_set(const StringName &p_property, const Variant &p_value) { - if (p_property == "Preview animation") { - if (animation_state.is_valid() && skeleton.is_valid()) { - auto animName = p_value.operator String(); - skeleton->set_to_setup_pose(); - if (skeleton->get_skeleton_data_res()->find_animation(animName).is_valid()) { - animation_state->set_animation(animName, true, 0); - } else { - animation_state->clear_tracks(); - } - } - } - - if (p_property == "Preview skin") { - if (animation_state.is_valid() && skeleton.is_valid()) { - auto skinName = p_value.operator String(); - if (skeleton->get_skeleton_data_res()->find_skin(skinName).is_valid()) { - skeleton->set_skin_by_name(skinName); - } else { - skeleton->set_skin(nullptr); - } - skeleton->set_to_setup_pose(); - } - } - return false; -} - #ifdef TOOLS_ENABLED Rect2 SpineSprite::_edit_get_rect() const { if (skeleton_data_res.is_valid() && skeleton_data_res->is_skeleton_data_loaded()) { diff --git a/spine-godot/spine_godot/SpineSprite.h b/spine-godot/spine_godot/SpineSprite.h index fbf56c92a..32f59fa56 100644 --- a/spine-godot/spine_godot/SpineSprite.h +++ b/spine-godot/spine_godot/SpineSprite.h @@ -37,18 +37,7 @@ #include "scene/resources/texture.h" class SpineSprite : public Node2D, public spine::AnimationStateListenerObject { - GDCLASS(SpineSprite, Node2D); - -protected: - static void _bind_methods(); - - void _notification(int p_what); - - void _get_property_list(List *p_list) const; - bool _get(const StringName &p_property, Variant &r_value) const; - bool _set(const StringName &p_property, const Variant &p_value); - - void _validate_and_play_current_animations(); + GDCLASS(SpineSprite, Node2D) public: enum UpdateMode { @@ -56,56 +45,55 @@ public: UpdateMode_Physics, UpdateMode_Manual }; - -private: + +protected: Ref skeleton_data_res; - Ref skeleton; Ref animation_state; - - String preview_animation; Array bind_slot_nodes; - bool overlap; - UpdateMode update_mode; Vector mesh_instances; spine::SkeletonClipping *skeleton_clipper; - static Ref materials[4]; - -public: - SpineSprite(); - ~SpineSprite(); - - void set_skeleton_data_res(const Ref &a); - Ref get_skeleton_data_res(); - - Ref get_skeleton(); - Ref get_animation_state(); + static Ref default_materials[4]; + + static void _bind_methods(); + void _notification(int what); void generate_meshes_for_slots(Ref skeleton_ref); void remove_meshes(); - - void update_meshes(Ref s); + void update_meshes(Ref skeleton); void update_bind_slot_nodes(); void update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d); Node *find_child_node_by_node(Node *node); - virtual void callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event); + void callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event); - void _on_skeleton_data_changed(); +public: + SpineSprite(); + ~SpineSprite(); - void _update_all(float delta); + void set_skeleton_data_res(const Ref &_spine_skeleton_data_resource); + + Ref get_skeleton_data_res(); + + Ref get_skeleton(); + + Ref get_animation_state(); + + void on_skeleton_data_changed(); + + void update_skeleton(float delta); Array get_bind_slot_nodes(); void set_bind_slot_nodes(Array v); - Transform2D bone_get_global_transform(const String &bone_name); - - void bone_set_global_transform(const String &bone_name, Transform2D transform); + Transform2D get_global_bone_transform(const String &bone_name); + void set_global_bone_transform(const String &bone_name, Transform2D transform); + UpdateMode get_update_mode(); void set_update_mode(UpdateMode v);