From 88038fa9069fb6c27b6712d07450fb05130dfbac Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 8 Apr 2022 23:04:23 +0200 Subject: [PATCH] [godot] New SpineSprite implementation with more coherent resource management. --- .../spineboy/spinebody-data-new-res.tres | 10 + spine-godot/example/spineboy.tscn | 7 +- .../spine_godot/SpineNewAnimationState.cpp | 171 ++++++++++++++++++ .../spine_godot/SpineNewAnimationState.h | 82 +++++++++ .../modules/spine_godot/SpineNewBone.cpp | 27 +-- .../godot/modules/spine_godot/SpineNewBone.h | 6 +- .../modules/spine_godot/SpineNewSkeleton.cpp | 22 +-- .../modules/spine_godot/SpineNewSkeleton.h | 6 +- .../SpineNewSkeletonDataResource.cpp | 22 ++- .../modules/spine_godot/SpineNewSprite.cpp | 76 ++++---- .../modules/spine_godot/SpineNewSprite.h | 16 +- .../modules/spine_godot/register_types.cpp | 6 + 12 files changed, 364 insertions(+), 87 deletions(-) create mode 100644 spine-godot/example/assets/spineboy/spinebody-data-new-res.tres create mode 100644 spine-godot/godot/modules/spine_godot/SpineNewAnimationState.cpp create mode 100644 spine-godot/godot/modules/spine_godot/SpineNewAnimationState.h diff --git a/spine-godot/example/assets/spineboy/spinebody-data-new-res.tres b/spine-godot/example/assets/spineboy/spinebody-data-new-res.tres new file mode 100644 index 000000000..73189d31a --- /dev/null +++ b/spine-godot/example/assets/spineboy/spinebody-data-new-res.tres @@ -0,0 +1,10 @@ +[gd_resource type="SpineNewSkeletonDataResource" load_steps=3 format=2] + +[ext_resource path="res://assets/spineboy/spineboy.atlas" type="SpineAtlasResource" id=1] +[ext_resource path="res://assets/spineboy/spineboy-pro.skel" type="SpineSkeletonFileResource" id=2] + +[resource] +atlas_res = ExtResource( 1 ) +skeleton_file_res = ExtResource( 2 ) +animations = null +skins = null diff --git a/spine-godot/example/spineboy.tscn b/spine-godot/example/spineboy.tscn index e0628758b..540068f6b 100644 --- a/spine-godot/example/spineboy.tscn +++ b/spine-godot/example/spineboy.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=9 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://Spineboy.gd" type="Script" id=1] [ext_resource path="res://assets/spineboy/spineboy-data.tres" type="SpineSkeletonDataResource" id=2] [ext_resource path="res://assets/mix-and-match/mix-and-match-data.tres" type="SpineSkeletonDataResource" id=3] +[ext_resource path="res://assets/spineboy/spinebody-data-new-res.tres" type="SpineNewSkeletonDataResource" id=4] [ext_resource path="res://mix-and-match.gd" type="Script" id=5] [ext_resource path="res://assets/raptor/raprot-data.tres" type="SpineSkeletonDataResource" id=6] @@ -33,3 +34,7 @@ script = ExtResource( 5 ) position = Vector2( 261.223, 541.504 ) scale = Vector2( 0.5, 0.5 ) animation_state_data_res = SubResource( 5 ) + +[node name="SpineNewSprite" type="SpineNewSprite" parent="."] +position = Vector2( 631.194, 1005.65 ) +skeleton_data_res = ExtResource( 4 ) diff --git a/spine-godot/godot/modules/spine_godot/SpineNewAnimationState.cpp b/spine-godot/godot/modules/spine_godot/SpineNewAnimationState.cpp new file mode 100644 index 000000000..b20a40552 --- /dev/null +++ b/spine-godot/godot/modules/spine_godot/SpineNewAnimationState.cpp @@ -0,0 +1,171 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "SpineNewAnimationState.h" + +void SpineNewAnimationState::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_animation", "anim_name", "loop", "track_id"), &SpineNewAnimationState::set_animation, DEFVAL(true), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("update", "delta"), &SpineNewAnimationState::update, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("apply", "skeleton"), &SpineNewAnimationState::apply); + ClassDB::bind_method(D_METHOD("clear_tracks"), &SpineNewAnimationState::clear_tracks); + ClassDB::bind_method(D_METHOD("clear_track"), &SpineNewAnimationState::clear_track); + ClassDB::bind_method(D_METHOD("add_animation", "anim_name", "delay", "loop", "track_id"), &SpineNewAnimationState::add_animation, DEFVAL(0), DEFVAL(true), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("set_empty_animation", "track_id", "mix_duration"), &SpineNewAnimationState::set_empty_animation); + ClassDB::bind_method(D_METHOD("add_empty_animation", "track_id", "mix_duration", "delay"), &SpineNewAnimationState::add_empty_animation); + ClassDB::bind_method(D_METHOD("set_empty_animations", "mix_duration"), &SpineNewAnimationState::set_empty_animations); + ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineNewAnimationState::get_time_scale); + ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &SpineNewAnimationState::set_time_scale); + ClassDB::bind_method(D_METHOD("disable_queue"), &SpineNewAnimationState::disable_queue); + ClassDB::bind_method(D_METHOD("enable_queue"), &SpineNewAnimationState::enable_queue); + ClassDB::bind_method(D_METHOD("get_current", "track_id"), &SpineNewAnimationState::get_current); +} + +SpineNewAnimationState::SpineNewAnimationState() : animation_state(nullptr), skeleton_data_res(nullptr) { +} + +SpineNewAnimationState::~SpineNewAnimationState() { + delete animation_state; +} + +void SpineNewAnimationState::set_skeleton_data_res(Ref data_res) { + delete animation_state; + animation_state = nullptr; + skeleton_data_res = data_res; + if (!skeleton_data_res.is_valid() || !skeleton_data_res->is_skeleton_data_loaded()) return; + animation_state = new spine::AnimationState(skeleton_data_res->get_animation_state_data()); +} + +Ref SpineNewAnimationState::get_skeleton_data_res() const { + return skeleton_data_res; +} + +#define CHECK_V \ + if (!animation_state) { \ + ERR_PRINT("The animation state is not loaded yet!"); \ + return; \ + } +#define CHECK_X(x) \ + if (!animation_state) { \ + ERR_PRINT("The animation state is not loaded yet!"); \ + return x; \ + } +#define S_T(x) (spine::String(x.utf8())) +Ref SpineNewAnimationState::set_animation(const String &anim_name, bool loop, uint64_t track) { + CHECK_X(nullptr); + auto skeleton_data = animation_state->getData()->getSkeletonData(); + auto anim = skeleton_data->findAnimation(anim_name.utf8().ptr()); + if (!anim) { + ERR_PRINT(String("Can not find animation: ") + anim_name); + return nullptr; + } + auto entry = animation_state->setAnimation(track, anim, loop); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineNewAnimationState::add_animation(const String &anim_name, float delay, bool loop, uint64_t track) { + CHECK_X(nullptr); + auto skeleton_data = animation_state->getData()->getSkeletonData(); + auto anim = skeleton_data->findAnimation(anim_name.utf8().ptr()); + if (!anim) { + ERR_PRINT(String("Can not find animation: ") + anim_name); + return nullptr; + } + auto entry = animation_state->addAnimation(track, anim, loop, delay); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} + +Ref SpineNewAnimationState::set_empty_animation(uint64_t track_id, float mix_duration) { + CHECK_X(nullptr); + auto entry = animation_state->setEmptyAnimation(track_id, mix_duration); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +Ref SpineNewAnimationState::add_empty_animation(uint64_t track_id, float mix_duration, float delay) { + CHECK_X(nullptr); + auto entry = animation_state->addEmptyAnimation(track_id, mix_duration, delay); + Ref gd_entry(memnew(SpineTrackEntry)); + gd_entry->set_spine_object(entry); + return gd_entry; +} +void SpineNewAnimationState::set_empty_animations(float mix_duration) { + CHECK_V; + animation_state->setEmptyAnimations(mix_duration); +} + +void SpineNewAnimationState::update(float delta) { + CHECK_V; + animation_state->update(delta); +} +bool SpineNewAnimationState::apply(Ref skeleton) { + CHECK_X(false); + return animation_state->apply(*(skeleton->get_spine_object())); +} + +void SpineNewAnimationState::clear_tracks() { + CHECK_V; + animation_state->clearTracks(); +} +void SpineNewAnimationState::clear_track(uint64_t track_id) { + CHECK_V; + animation_state->clearTrack(track_id); +} + +float SpineNewAnimationState::get_time_scale() { + CHECK_X(0); + return animation_state->getTimeScale(); +} +void SpineNewAnimationState::set_time_scale(float time_scale) { + CHECK_V; + animation_state->setTimeScale(time_scale); +} + +void SpineNewAnimationState::disable_queue() { + CHECK_V; + animation_state->disableQueue(); +} +void SpineNewAnimationState::enable_queue() { + CHECK_V; + animation_state->enableQueue(); +} + +Ref SpineNewAnimationState::get_current(uint64_t track_index) { + CHECK_X(nullptr); + Ref gd_entry(memnew(SpineTrackEntry)); + auto entry = animation_state->getCurrent(track_index); + if (entry == nullptr) return nullptr; + gd_entry->set_spine_object(entry); + return gd_entry; +} + +#undef CHECK_V +#undef CHECK_X diff --git a/spine-godot/godot/modules/spine_godot/SpineNewAnimationState.h b/spine-godot/godot/modules/spine_godot/SpineNewAnimationState.h new file mode 100644 index 000000000..119537550 --- /dev/null +++ b/spine-godot/godot/modules/spine_godot/SpineNewAnimationState.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef GODOT_SPINENEWANIMATIONSTATE_H +#define GODOT_SPINENEWANIMATIONSTATE_H + +#include "SpineNewSkeleton.h" +#include "SpineTrackEntry.h" + +class SpineNewAnimationState : public Reference { + GDCLASS(SpineNewAnimationState, Reference); + +protected: + static void _bind_methods(); + +private: + spine::AnimationState *animation_state; + Ref skeleton_data_res; + +public: + SpineNewAnimationState(); + ~SpineNewAnimationState(); + + void set_skeleton_data_res(Ref skeleton_data_res); + Ref get_skeleton_data_res() const; + + inline void set_spine_object(spine::AnimationState *animation_state) { this->animation_state = animation_state; } + inline spine::AnimationState *get_spine_object() { return animation_state; } + + Ref set_animation(const String &anim_name, bool loop, uint64_t track_id); + + Ref add_animation(const String &anim_name, float delay, bool loop, uint64_t track_id); + + Ref set_empty_animation(uint64_t track_id, float mix_duration); + + Ref add_empty_animation(uint64_t track_id, float mix_duration, float delay); + void set_empty_animations(float mix_duration); + + float get_time_scale(); + void set_time_scale(float time_scale); + + void disable_queue(); + void enable_queue(); + + void update(float delta); + + bool apply(Ref skeleton); + + void clear_tracks(); + + void clear_track(uint64_t track_id); + + Ref get_current(uint64_t track_index); +}; + +#endif//GODOT_SPINENEWANIMATIONSTATE_H diff --git a/spine-godot/godot/modules/spine_godot/SpineNewBone.cpp b/spine-godot/godot/modules/spine_godot/SpineNewBone.cpp index 591728d57..f1dbfbff2 100644 --- a/spine-godot/godot/modules/spine_godot/SpineNewBone.cpp +++ b/spine-godot/godot/modules/spine_godot/SpineNewBone.cpp @@ -98,9 +98,14 @@ void SpineNewBone::_bind_methods() { ClassDB::bind_method(D_METHOD("apply_world_transform_2d", "node2d"), &SpineNewBone::apply_world_transform_2d); } -SpineNewBone::SpineNewBone() : bone(NULL), the_sprite(nullptr) {} +SpineNewBone::SpineNewBone() : bone(nullptr), sprite(nullptr) {} + SpineNewBone::~SpineNewBone() {} +void SpineNewBone::set_spine_sprite(SpineNewSprite* sprite) { + this->sprite = sprite; +} + void SpineNewBone::update_world_transform() { bone->updateWorldTransform(); } @@ -151,7 +156,7 @@ Ref SpineNewBone::get_skeleton() { auto &s = bone->getSkeleton(); Ref gd_s(memnew(SpineNewSkeleton)); gd_s->set_spine_object(&s); - gd_s->set_spine_sprite(the_sprite); + gd_s->set_spine_sprite(sprite); return gd_s; } @@ -160,7 +165,7 @@ Ref SpineNewBone::get_parent() { if (b == NULL) return NULL; Ref gd_b(memnew(SpineNewBone)); gd_b->set_spine_object(b); - gd_b->set_spine_sprite(the_sprite); + gd_b->set_spine_sprite(sprite); return gd_b; } @@ -173,7 +178,7 @@ Array SpineNewBone::get_children() { if (b == NULL) gd_bs[i] = Ref(NULL); Ref gd_b(memnew(SpineNewBone)); gd_b->set_spine_object(b); - gd_b->set_spine_sprite(the_sprite); + gd_b->set_spine_sprite(sprite); gd_bs[i] = gd_b; } return gd_bs; @@ -390,13 +395,13 @@ void SpineNewBone::set_godot_transform(Transform2D trans) { Transform2D SpineNewBone::get_godot_global_transform() { if (get_spine_object() == nullptr) return Transform2D(); - if (the_sprite == nullptr) + if (sprite == nullptr) return get_godot_transform(); - Transform2D res = the_sprite->get_transform(); + Transform2D res = sprite->get_transform(); res.translate(get_world_x(), -get_world_y()); res.rotate(Math::deg2rad(-get_world_rotation_x())); res.scale(Vector2(get_world_scale_x(), get_world_scale_y())); - auto p = the_sprite->get_parent() ? Object::cast_to(the_sprite->get_parent()) : nullptr; + auto p = sprite->get_parent() ? Object::cast_to(sprite->get_parent()) : nullptr; if (p) { return p->get_global_transform() * res; } @@ -406,9 +411,9 @@ Transform2D SpineNewBone::get_godot_global_transform() { void SpineNewBone::set_godot_global_transform(Transform2D transform) { if (get_spine_object() == nullptr) return; - if (the_sprite == nullptr) + if (sprite == nullptr) set_godot_transform(transform); - transform = the_sprite->get_global_transform().affine_inverse() * transform; + transform = sprite->get_global_transform().affine_inverse() * transform; Vector2 position = transform.get_origin(); real_t rotation = transform.get_rotation(); Vector2 scale = transform.get_scale(); @@ -433,7 +438,3 @@ void SpineNewBone::set_godot_global_transform(Transform2D transform) { set_scale_x(scale.x); set_scale_y(scale.y); } - -void SpineNewBone::set_spine_sprite(SpineNewSprite *s) { - the_sprite = s; -} diff --git a/spine-godot/godot/modules/spine_godot/SpineNewBone.h b/spine-godot/godot/modules/spine_godot/SpineNewBone.h index b3df4c334..37ab9bb23 100644 --- a/spine-godot/godot/modules/spine_godot/SpineNewBone.h +++ b/spine-godot/godot/modules/spine_godot/SpineNewBone.h @@ -46,8 +46,7 @@ protected: private: spine::Bone *bone; - - SpineNewSprite *the_sprite; + SpineNewSprite* sprite; public: SpineNewBone(); @@ -56,11 +55,12 @@ public: inline void set_spine_object(spine::Bone *b) { bone = b; } + inline spine::Bone *get_spine_object() { return bone; } - void set_spine_sprite(SpineNewSprite *s); + void set_spine_sprite(SpineNewSprite* sprite); void update_world_transform(); diff --git a/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.cpp b/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.cpp index 7048314fa..8e374d85e 100644 --- a/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.cpp +++ b/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.cpp @@ -46,7 +46,7 @@ void SpineNewSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("find_path_constraint", "constraint_name"), &SpineNewSkeleton::find_path_constraint); ClassDB::bind_method(D_METHOD("get_bounds"), &SpineNewSkeleton::get_bounds); ClassDB::bind_method(D_METHOD("get_root_bone"), &SpineNewSkeleton::get_root_bone); - ClassDB::bind_method(D_METHOD("get_data"), &SpineNewSkeleton::get_data); + ClassDB::bind_method(D_METHOD("get_data"), &SpineNewSkeleton::get_skeleton_data_res); ClassDB::bind_method(D_METHOD("get_bones"), &SpineNewSkeleton::get_bones); ClassDB::bind_method(D_METHOD("get_slots"), &SpineNewSkeleton::get_slots); ClassDB::bind_method(D_METHOD("get_draw_orders"), &SpineNewSkeleton::get_draw_orders); @@ -77,9 +77,17 @@ SpineNewSkeleton::~SpineNewSkeleton() { void SpineNewSkeleton::set_skeleton_data_res(Ref data_res) { delete skeleton; skeleton = nullptr; - if (!data_res.is_valid()) return; - skeleton = new spine::Skeleton(data_res->get_skeleton_data()); skeleton_data_res = data_res; + if (!data_res.is_valid() || !data_res->is_skeleton_data_loaded()) return; + skeleton = new spine::Skeleton(data_res->get_skeleton_data()); +} + +Ref SpineNewSkeleton::get_skeleton_data_res() const { + return skeleton_data_res; +} + +void SpineNewSkeleton::set_spine_sprite(SpineNewSprite* sprite) { + this->sprite = sprite; } #define S_T(x) (spine::String((x).utf8())) @@ -205,10 +213,6 @@ Ref SpineNewSkeleton::get_root_bone() { return gd_b; } -Ref SpineNewSkeleton::get_data() const { - return skeleton_data_res; -} - Array SpineNewSkeleton::get_bones() { auto &as = skeleton->getBones(); Array gd_as; @@ -337,7 +341,3 @@ float SpineNewSkeleton::get_scale_y() { void SpineNewSkeleton::set_scale_y(float v) { skeleton->setScaleY(v); } - -void SpineNewSkeleton::set_spine_sprite(SpineNewSprite *s) { - sprite = s; -} diff --git a/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.h b/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.h index a1d3d9cad..aaff11eb3 100644 --- a/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.h +++ b/spine-godot/godot/modules/spine_godot/SpineNewSkeleton.h @@ -56,6 +56,7 @@ public: ~SpineNewSkeleton(); void set_skeleton_data_res(Ref data_res); + Ref get_skeleton_data_res() const; inline void set_spine_object(spine::Skeleton *s) { skeleton = s; @@ -64,8 +65,7 @@ public: return skeleton; } - void set_spine_sprite(SpineNewSprite *s); - + void set_spine_sprite(SpineNewSprite *sprite); void update_world_transform(); @@ -95,8 +95,6 @@ public: Ref get_root_bone(); - Ref get_data() const; - Array get_bones(); Array get_slots(); Array get_draw_orders(); diff --git a/spine-godot/godot/modules/spine_godot/SpineNewSkeletonDataResource.cpp b/spine-godot/godot/modules/spine_godot/SpineNewSkeletonDataResource.cpp index 05d9364f2..2232e0911 100644 --- a/spine-godot/godot/modules/spine_godot/SpineNewSkeletonDataResource.cpp +++ b/spine-godot/godot/modules/spine_godot/SpineNewSkeletonDataResource.cpp @@ -29,6 +29,11 @@ #include "SpineNewSkeletonDataResource.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#include "editor/editor_inspector.h" +#endif + void SpineNewSkeletonDataResource::_bind_methods() { ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"), &SpineNewSkeletonDataResource::is_skeleton_data_loaded); ClassDB::bind_method(D_METHOD("set_atlas_res", "atlas_res"), &SpineNewSkeletonDataResource::set_atlas_res); @@ -81,13 +86,6 @@ SpineNewSkeletonDataResource::~SpineNewSkeletonDataResource() { } void SpineNewSkeletonDataResource::update_skeleton_data() { - if (atlas_res.is_valid() && skeleton_file_res.is_valid()) { - load_res(atlas_res->get_spine_atlas(), skeleton_file_res->get_json(), skeleton_file_res->get_binary()); - emit_signal("skeleton_data_changed"); - } -} - -void SpineNewSkeletonDataResource::load_res(spine::Atlas *atlas, const String &json, const Vector &binary) { if (skeleton_data) { delete skeleton_data; skeleton_data = nullptr; @@ -97,6 +95,16 @@ void SpineNewSkeletonDataResource::load_res(spine::Atlas *atlas, const String &j animation_state_data = nullptr; } + if (atlas_res.is_valid() && skeleton_file_res.is_valid()) { + load_res(atlas_res->get_spine_atlas(), skeleton_file_res->get_json(), skeleton_file_res->get_binary()); + } + emit_signal("skeleton_data_changed"); +#ifdef TOOLS_ENABLED + property_list_changed_notify(); +#endif +} + +void SpineNewSkeletonDataResource::load_res(spine::Atlas *atlas, const String &json, const Vector &binary) { if ((json.empty() && binary.empty()) || atlas == nullptr) return; spine::SkeletonData *data; diff --git a/spine-godot/godot/modules/spine_godot/SpineNewSprite.cpp b/spine-godot/godot/modules/spine_godot/SpineNewSprite.cpp index 20b11be3c..ccefade7a 100644 --- a/spine-godot/godot/modules/spine_godot/SpineNewSprite.cpp +++ b/spine-godot/godot/modules/spine_godot/SpineNewSprite.cpp @@ -36,10 +36,9 @@ void SpineNewSprite::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skeleton_data_res", "skeleton_data_res"), &SpineNewSprite::set_skeleton_data_res); ClassDB::bind_method(D_METHOD("get_skeleton_data_res"), &SpineNewSprite::get_skeleton_data_res); - ClassDB::bind_method(D_METHOD("_on_animation_data_created"), &SpineNewSprite::_on_animation_data_created); ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineNewSprite::get_skeleton); ClassDB::bind_method(D_METHOD("get_animation_state"), &SpineNewSprite::get_animation_state); - ClassDB::bind_method(D_METHOD("_on_animation_data_changed"), &SpineNewSprite::_on_animation_data_changed); + ClassDB::bind_method(D_METHOD("_on_skeleton_data_changed"), &SpineNewSprite::_on_skeleton_data_changed); ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineNewSprite::get_bind_slot_nodes); ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineNewSprite::set_bind_slot_nodes); @@ -73,11 +72,10 @@ void SpineNewSprite::_bind_methods() { BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual); } -SpineNewSprite::SpineNewSprite() : overlap(false), - skeleton_clipper(nullptr), - process_mode(ProcessMode_Process) { +SpineNewSprite::SpineNewSprite() : overlap(false), process_mode(ProcessMode_Process), skeleton_clipper(nullptr) { skeleton_clipper = new spine::SkeletonClipping(); } + SpineNewSprite::~SpineNewSprite() { delete skeleton_clipper; } @@ -161,9 +159,11 @@ void SpineNewSprite::update_bind_slot_nodes() { } } } + void SpineNewSprite::update_bind_slot_node_transform(Ref bone, Node2D *node2d) { bone->apply_world_transform_2d(node2d); } + void SpineNewSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d) { auto mesh_ins = find_node(slot_name); if (mesh_ins) { @@ -184,55 +184,53 @@ Node *SpineNewSprite::find_child_node_by_node(Node *node) { void SpineNewSprite::set_skeleton_data_res(const Ref &s) { skeleton_data_res = s; - _on_animation_data_changed(); + _on_skeleton_data_changed(); } Ref SpineNewSprite::get_skeleton_data_res() { return skeleton_data_res; } -void SpineNewSprite::_on_animation_data_created() { - skeleton = Ref(memnew(SpineNewSkeleton)); - skeleton->set_skeleton_data_res(skeleton_data_res); - skeleton->set_spine_sprite(this); - - animation_state = Ref(memnew(SpineAnimationState)); - animation_state->create_animation_state(skeleton_data_res->get_animation_state_data()); - animation_state->get_spine_object()->setListener(this); - - animation_state->update(0); - animation_state->apply(skeleton); - skeleton->update_world_transform(); - gen_mesh_from_skeleton(skeleton); - - if (process_mode == ProcessMode_Process) { - _notification(NOTIFICATION_INTERNAL_PROCESS); - } else if (process_mode == ProcessMode_Physics) { - _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); - } -} - -void SpineNewSprite::_on_animation_data_changed() { +void SpineNewSprite::_on_skeleton_data_changed() { remove_mesh_instances(); skeleton.unref(); animation_state.unref(); - if (skeleton_data_res.is_valid()) { - if (!skeleton_data_res->is_connected("skeleton_data_changed", this, "_on_animation_data_created")) - skeleton_data_res->connect("skeleton_data_changed", this, "_on_animation_data_created"); - if (skeleton_data_res->is_skeleton_data_loaded()) { - _on_animation_data_created(); + if (skeleton_data_res.is_valid()) { + 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_valid() && skeleton_data_res->is_skeleton_data_loaded()) { + skeleton = Ref(memnew(SpineNewSkeleton)); + skeleton->set_skeleton_data_res(skeleton_data_res); + skeleton->set_spine_sprite(this); + + animation_state = Ref(memnew(SpineNewAnimationState)); + animation_state->set_skeleton_data_res(skeleton_data_res); + if (animation_state->get_spine_object()) animation_state->get_spine_object()->setListener(this); + + animation_state->update(0); + animation_state->apply(skeleton); + skeleton->update_world_transform(); + gen_mesh_from_skeleton(skeleton); + + if (process_mode == ProcessMode_Process) { + _notification(NOTIFICATION_INTERNAL_PROCESS); + } else if (process_mode == ProcessMode_Physics) { + _notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); } } } -Ref SpineNewSprite::get_skeleton() { +Ref SpineNewSprite::get_skeleton() { return skeleton; } -Ref SpineNewSprite::get_animation_state() { + +Ref SpineNewSprite::get_animation_state() { return animation_state; } -void SpineNewSprite::gen_mesh_from_skeleton(Ref s) { +void SpineNewSprite::gen_mesh_from_skeleton(Ref s) { auto sk = s->get_spine_object(); for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) { auto mesh_ins = memnew(SpineSpriteMeshInstance2D); @@ -305,7 +303,7 @@ void SpineNewSprite::remove_redundant_mesh_instances() { } \ } while (false); -void SpineNewSprite::update_mesh_from_skeleton(Ref s) { +void SpineNewSprite::update_mesh_from_skeleton(Ref s) { static const unsigned short VERTEX_STRIDE = 2; static unsigned short quad_indices[] = {0, 1, 2, 2, 3, 0}; @@ -606,7 +604,7 @@ bool SpineNewSprite::_set(const StringName &p_property, const Variant &p_value) if (animation_state.is_valid() && skeleton.is_valid()) { auto animName = p_value.operator String(); skeleton->set_to_setup_pose(); - if (skeleton->get_data()->find_animation(animName).is_valid()) { + if (skeleton->get_skeleton_data_res()->find_animation(animName).is_valid()) { animation_state->set_animation(animName, true, 0); } else { animation_state->clear_tracks(); @@ -617,7 +615,7 @@ bool SpineNewSprite::_set(const StringName &p_property, const Variant &p_value) if (p_property == "Preview skin") { if (animation_state.is_valid() && skeleton.is_valid()) { auto skinName = p_value.operator String(); - if (skeleton->get_data()->find_skin(skinName).is_valid()) { + if (skeleton->get_skeleton_data_res()->find_skin(skinName).is_valid()) { skeleton->set_skin_by_name(skinName); } else { skeleton->set_skin(nullptr); diff --git a/spine-godot/godot/modules/spine_godot/SpineNewSprite.h b/spine-godot/godot/modules/spine_godot/SpineNewSprite.h index 3dfd45830..d47ae7af0 100644 --- a/spine-godot/godot/modules/spine_godot/SpineNewSprite.h +++ b/spine-godot/godot/modules/spine_godot/SpineNewSprite.h @@ -32,9 +32,8 @@ #include -#include "SpineAnimationState.h" -#include "SpineAnimationStateDataResource.h" #include "SpineNewSkeleton.h" +#include "SpineNewAnimationState.h" #include "SpineSpriteMeshInstance2D.h" class SpineNewSprite : public Node2D, public spine::AnimationStateListenerObject { @@ -62,7 +61,7 @@ private: Ref skeleton_data_res; Ref skeleton; - Ref animation_state; + Ref animation_state; String preview_animation; Array bind_slot_nodes; @@ -80,14 +79,14 @@ public: void set_skeleton_data_res(const Ref &a); Ref get_skeleton_data_res(); - Ref get_skeleton(); - Ref get_animation_state(); + Ref get_skeleton(); + Ref get_animation_state(); - void gen_mesh_from_skeleton(Ref s); + void gen_mesh_from_skeleton(Ref s); void remove_mesh_instances(); void remove_redundant_mesh_instances(); - void update_mesh_from_skeleton(Ref s); + void update_mesh_from_skeleton(Ref s); void update_bind_slot_nodes(); void update_bind_slot_node_transform(Ref bone, Node2D *node2d); @@ -96,8 +95,7 @@ public: virtual void callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event); - void _on_animation_data_created(); - void _on_animation_data_changed(); + void _on_skeleton_data_changed(); void _update_all(float delta); diff --git a/spine-godot/godot/modules/spine_godot/register_types.cpp b/spine-godot/godot/modules/spine_godot/register_types.cpp index 62110ec28..7e5afe135 100644 --- a/spine-godot/godot/modules/spine_godot/register_types.cpp +++ b/spine-godot/godot/modules/spine_godot/register_types.cpp @@ -62,6 +62,8 @@ static Ref skeleton_file_saver; #include "editor/editor_export.h" #include "editor/editor_node.h" #include "SpineRuntimeEditorPlugin.h" +#include "SpineNewSkeletonDataResource.h" +#include "SpineNewSprite.h" static void editor_init_callback() { EditorNode::get_singleton()->add_editor_plugin(memnew(SpineRuntimeEditorPlugin(EditorNode::get_singleton()))); @@ -77,9 +79,12 @@ void register_spine_godot_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -96,6 +101,7 @@ void register_spine_godot_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class();