[godot] Break everything so we it can be rebuild.

This commit is contained in:
Mario Zechner 2022-04-08 21:30:41 +02:00
parent 991b0a73fa
commit 702c685b32
12 changed files with 2208 additions and 405 deletions

View File

@ -2,6 +2,6 @@ Import('env')
env_spine_runtime = env.Clone()
env_spine_runtime.Prepend(CPPPATH=["spine-cpp/include"])
env_spine_runtime.Prepend(CPPPATH=["spine-cpp/include", "modules/spine_godot/spine-cpp/include"])
env_spine_runtime.add_source_files(env.modules_sources, "spine-cpp/src/spine/*.cpp")
env_spine_runtime.add_source_files(env.modules_sources, "*.cpp")

View File

@ -39,7 +39,6 @@ void SpineAnimationState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_empty_animation", "track_id", "mix_duration"), &SpineAnimationState::set_empty_animation);
ClassDB::bind_method(D_METHOD("add_empty_animation", "track_id", "mix_duration", "delay"), &SpineAnimationState::add_empty_animation);
ClassDB::bind_method(D_METHOD("set_empty_animations", "mix_duration"), &SpineAnimationState::set_empty_animations);
ClassDB::bind_method(D_METHOD("get_data"), &SpineAnimationState::get_data);
ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineAnimationState::get_time_scale);
ClassDB::bind_method(D_METHOD("set_time_scale", "time_scale"), &SpineAnimationState::set_time_scale);
ClassDB::bind_method(D_METHOD("disable_queue"), &SpineAnimationState::disable_queue);
@ -57,13 +56,12 @@ SpineAnimationState::~SpineAnimationState() {
}
}
void SpineAnimationState::load_animation_state(Ref<SpineAnimationStateDataResource> animation_state_data) {
void SpineAnimationState::create_animation_state(spine::AnimationStateData *animation_state_data) {
if (animation_state) {
delete animation_state;
animation_state = NULL;
}
animation_state = new spine::AnimationState(animation_state_data->get_animation_state_data());
anim_state_data_res = animation_state_data;
animation_state = new spine::AnimationState(animation_state_data);
}
#define CHECK_V \
@ -79,26 +77,26 @@ void SpineAnimationState::load_animation_state(Ref<SpineAnimationStateDataResour
#define S_T(x) (spine::String(x.utf8()))
Ref<SpineTrackEntry> SpineAnimationState::set_animation(const String &anim_name, bool loop, uint64_t track) {
CHECK_X(NULL);
auto skeleton_data = anim_state_data_res->get_skeleton();
auto anim = skeleton_data->find_animation(anim_name);
if (!anim.is_valid() || anim->get_spine_object() == NULL) {
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 NULL;
}
auto entry = animation_state->setAnimation(track, anim->get_spine_object(), loop);
auto entry = animation_state->setAnimation(track, anim, loop);
Ref<SpineTrackEntry> gd_entry(memnew(SpineTrackEntry));
gd_entry->set_spine_object(entry);
return gd_entry;
}
Ref<SpineTrackEntry> SpineAnimationState::add_animation(const String &anim_name, float delay, bool loop, uint64_t track) {
CHECK_X(NULL);
auto skeleton_data = anim_state_data_res->get_skeleton();
auto anim = skeleton_data->find_animation(anim_name);
if (!anim.is_valid() || anim->get_spine_object() == NULL) {
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 NULL;
}
auto entry = animation_state->addAnimation(track, anim->get_spine_object(), loop, delay);
auto entry = animation_state->addAnimation(track, anim, loop, delay);
Ref<SpineTrackEntry> gd_entry(memnew(SpineTrackEntry));
gd_entry->set_spine_object(entry);
return gd_entry;
@ -142,11 +140,6 @@ void SpineAnimationState::clear_track(uint64_t track_id) {
animation_state->clearTrack(track_id);
}
Ref<SpineAnimationStateDataResource> SpineAnimationState::get_data() {
CHECK_X(NULL);
return anim_state_data_res;
}
float SpineAnimationState::get_time_scale() {
CHECK_X(0);
return animation_state->getTimeScale();

View File

@ -43,13 +43,11 @@ protected:
private:
spine::AnimationState *animation_state;
Ref<SpineAnimationStateDataResource> anim_state_data_res;
public:
SpineAnimationState();
~SpineAnimationState();
void load_animation_state(Ref<SpineAnimationStateDataResource> animation_state_data);
void create_animation_state(spine::AnimationStateData *animation_state_data);
inline void set_spine_object(spine::AnimationState *animation_state) { this->animation_state = animation_state; }
inline spine::AnimationState *get_spine_object() { return animation_state; }

View File

@ -0,0 +1,439 @@
/******************************************************************************
* 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 "SpineNewBone.h"
#include "SpineNewSprite.h"
#include "SpineNewSkeleton.h"
void SpineNewBone::_bind_methods() {
ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineNewBone::update_world_transform);
ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineNewBone::set_to_setup_pose);
ClassDB::bind_method(D_METHOD("world_to_local", "world_position"), &SpineNewBone::world_to_local);
ClassDB::bind_method(D_METHOD("local_to_world", "local_position"), &SpineNewBone::local_to_world);
ClassDB::bind_method(D_METHOD("world_to_local_rotation", "world_rotation"), &SpineNewBone::world_to_local_rotation);
ClassDB::bind_method(D_METHOD("local_to_world_rotation", "local_rotation"), &SpineNewBone::local_to_world_rotation);
ClassDB::bind_method(D_METHOD("rotate_world"), &SpineNewBone::rotate_world);
ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_x"), &SpineNewBone::get_world_to_local_rotation_x);
ClassDB::bind_method(D_METHOD("get_world_to_local_rotation_y"), &SpineNewBone::get_world_to_local_rotation_y);
ClassDB::bind_method(D_METHOD("get_data"), &SpineNewBone::get_data);
ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineNewBone::get_skeleton);
ClassDB::bind_method(D_METHOD("get_parent"), &SpineNewBone::get_parent);
ClassDB::bind_method(D_METHOD("get_children"), &SpineNewBone::get_children);
ClassDB::bind_method(D_METHOD("get_x"), &SpineNewBone::get_x);
ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineNewBone::set_x);
ClassDB::bind_method(D_METHOD("get_y"), &SpineNewBone::get_y);
ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineNewBone::set_y);
ClassDB::bind_method(D_METHOD("get_rotation"), &SpineNewBone::get_rotation);
ClassDB::bind_method(D_METHOD("set_rotation", "v"), &SpineNewBone::set_rotation);
ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineNewBone::get_scale_x);
ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineNewBone::set_scale_x);
ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineNewBone::get_scale_y);
ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineNewBone::set_scale_y);
ClassDB::bind_method(D_METHOD("get_shear_x"), &SpineNewBone::get_shear_x);
ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineNewBone::set_shear_x);
ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineNewBone::get_shear_y);
ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineNewBone::set_shear_y);
ClassDB::bind_method(D_METHOD("get_applied_rotation"), &SpineNewBone::get_applied_rotation);
ClassDB::bind_method(D_METHOD("set_applied_rotation", "v"), &SpineNewBone::set_applied_rotation);
ClassDB::bind_method(D_METHOD("get_a_x"), &SpineNewBone::get_a_x);
ClassDB::bind_method(D_METHOD("set_a_x", "v"), &SpineNewBone::set_a_x);
ClassDB::bind_method(D_METHOD("get_a_y"), &SpineNewBone::get_a_y);
ClassDB::bind_method(D_METHOD("set_a_y", "v"), &SpineNewBone::set_a_y);
ClassDB::bind_method(D_METHOD("get_a_scale_x"), &SpineNewBone::get_a_scale_x);
ClassDB::bind_method(D_METHOD("set_a_scale_x", "v"), &SpineNewBone::set_a_scale_x);
ClassDB::bind_method(D_METHOD("get_a_scale_y"), &SpineNewBone::get_a_scale_y);
ClassDB::bind_method(D_METHOD("set_a_scale_y", "v"), &SpineNewBone::set_a_scale_y);
ClassDB::bind_method(D_METHOD("get_a_shear_x"), &SpineNewBone::get_a_shear_x);
ClassDB::bind_method(D_METHOD("set_a_shear_x", "v"), &SpineNewBone::set_a_shear_x);
ClassDB::bind_method(D_METHOD("get_a_shear_y"), &SpineNewBone::get_a_shear_y);
ClassDB::bind_method(D_METHOD("set_a_shear_y", "v"), &SpineNewBone::set_a_shear_y);
ClassDB::bind_method(D_METHOD("get_a"), &SpineNewBone::get_a);
ClassDB::bind_method(D_METHOD("set_a", "v"), &SpineNewBone::set_a);
ClassDB::bind_method(D_METHOD("get_b"), &SpineNewBone::get_b);
ClassDB::bind_method(D_METHOD("set_b", "v"), &SpineNewBone::set_b);
ClassDB::bind_method(D_METHOD("get_c"), &SpineNewBone::get_c);
ClassDB::bind_method(D_METHOD("set_c", "v"), &SpineNewBone::set_c);
ClassDB::bind_method(D_METHOD("get_d"), &SpineNewBone::get_d);
ClassDB::bind_method(D_METHOD("set_d", "v"), &SpineNewBone::set_d);
ClassDB::bind_method(D_METHOD("get_world_x"), &SpineNewBone::get_world_x);
ClassDB::bind_method(D_METHOD("set_world_x", "v"), &SpineNewBone::set_world_x);
ClassDB::bind_method(D_METHOD("get_world_y"), &SpineNewBone::get_world_y);
ClassDB::bind_method(D_METHOD("set_world_y", "v"), &SpineNewBone::set_world_y);
ClassDB::bind_method(D_METHOD("get_world_rotation_x"), &SpineNewBone::get_world_rotation_x);
ClassDB::bind_method(D_METHOD("get_world_rotation_y"), &SpineNewBone::get_world_rotation_y);
ClassDB::bind_method(D_METHOD("get_world_scale_x"), &SpineNewBone::get_world_scale_x);
ClassDB::bind_method(D_METHOD("get_world_scale_y"), &SpineNewBone::get_world_scale_y);
ClassDB::bind_method(D_METHOD("is_active"), &SpineNewBone::is_active);
ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineNewBone::set_active);
ClassDB::bind_method(D_METHOD("get_godot_transform"), &SpineNewBone::get_godot_transform);
ClassDB::bind_method(D_METHOD("set_godot_transform", "local_transform"), &SpineNewBone::set_godot_transform);
ClassDB::bind_method(D_METHOD("get_godot_global_transform"), &SpineNewBone::get_godot_global_transform);
ClassDB::bind_method(D_METHOD("set_godot_global_transform", "global_transform"), &SpineNewBone::set_godot_global_transform);
ClassDB::bind_method(D_METHOD("apply_world_transform_2d", "node2d"), &SpineNewBone::apply_world_transform_2d);
}
SpineNewBone::SpineNewBone() : bone(NULL), the_sprite(nullptr) {}
SpineNewBone::~SpineNewBone() {}
void SpineNewBone::update_world_transform() {
bone->updateWorldTransform();
}
void SpineNewBone::set_to_setup_pose() {
bone->setToSetupPose();
}
Vector2 SpineNewBone::world_to_local(Vector2 world_position) {
float x, y;
bone->worldToLocal(world_position.x, world_position.y, x, y);
return Vector2(x, y);
}
Vector2 SpineNewBone::local_to_world(Vector2 local_position) {
float x, y;
bone->localToWorld(local_position.x, local_position.y, x, y);
return Vector2(x, y);
}
float SpineNewBone::world_to_local_rotation(float world_rotation) {
return bone->worldToLocalRotation(world_rotation);
}
float SpineNewBone::local_to_world_rotation(float local_rotation) {
return bone->localToWorldRotation(local_rotation);
}
void SpineNewBone::rotate_world(float degrees) {
bone->rotateWorld(degrees);
}
float SpineNewBone::get_world_to_local_rotation_x() {
return bone->getWorldToLocalRotationX();
}
float SpineNewBone::get_world_to_local_rotation_y() {
return bone->getWorldToLocalRotationY();
}
Ref<SpineBoneData> SpineNewBone::get_data() {
auto &bd = bone->getData();
Ref<SpineBoneData> gd_bd(memnew(SpineBoneData));
gd_bd->set_spine_object(&bd);
return gd_bd;
}
Ref<SpineNewSkeleton> SpineNewBone::get_skeleton() {
auto &s = bone->getSkeleton();
Ref<SpineNewSkeleton> gd_s(memnew(SpineNewSkeleton));
gd_s->set_spine_object(&s);
gd_s->set_spine_sprite(the_sprite);
return gd_s;
}
Ref<SpineNewBone> SpineNewBone::get_parent() {
auto b = bone->getParent();
if (b == NULL) return NULL;
Ref<SpineNewBone> gd_b(memnew(SpineNewBone));
gd_b->set_spine_object(b);
gd_b->set_spine_sprite(the_sprite);
return gd_b;
}
Array SpineNewBone::get_children() {
auto bs = bone->getChildren();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
auto b = bs[i];
if (b == NULL) gd_bs[i] = Ref<SpineNewBone>(NULL);
Ref<SpineNewBone> gd_b(memnew(SpineNewBone));
gd_b->set_spine_object(b);
gd_b->set_spine_sprite(the_sprite);
gd_bs[i] = gd_b;
}
return gd_bs;
}
float SpineNewBone::get_x() {
return bone->getX();
}
void SpineNewBone::set_x(float v) {
bone->setX(v);
}
float SpineNewBone::get_y() {
return bone->getY();
}
void SpineNewBone::set_y(float v) {
bone->setY(v);
}
float SpineNewBone::get_rotation() {
return bone->getRotation();
}
void SpineNewBone::set_rotation(float v) {
bone->setRotation(v);
}
float SpineNewBone::get_scale_x() {
return bone->getScaleX();
}
void SpineNewBone::set_scale_x(float v) {
bone->setScaleX(v);
}
float SpineNewBone::get_scale_y() {
return bone->getScaleY();
}
void SpineNewBone::set_scale_y(float v) {
bone->setScaleY(v);
}
float SpineNewBone::get_shear_x() {
return bone->getShearX();
}
void SpineNewBone::set_shear_x(float v) {
bone->setShearX(v);
}
float SpineNewBone::get_shear_y() {
return bone->getShearY();
}
void SpineNewBone::set_shear_y(float v) {
bone->setShearY(v);
}
float SpineNewBone::get_applied_rotation() {
return bone->getAppliedRotation();
}
void SpineNewBone::set_applied_rotation(float v) {
bone->setAppliedRotation(v);
}
float SpineNewBone::get_a_x() {
return bone->getAX();
}
void SpineNewBone::set_a_x(float v) {
bone->setAX(v);
}
float SpineNewBone::get_a_y() {
return bone->getAY();
}
void SpineNewBone::set_a_y(float v) {
bone->setAY(v);
}
float SpineNewBone::get_a_scale_x() {
return bone->getAScaleX();
}
void SpineNewBone::set_a_scale_x(float v) {
bone->setAScaleX(v);
}
float SpineNewBone::get_a_scale_y() {
return bone->getAScaleY();
}
void SpineNewBone::set_a_scale_y(float v) {
bone->setAScaleY(v);
}
float SpineNewBone::get_a_shear_x() {
return bone->getAShearX();
}
void SpineNewBone::set_a_shear_x(float v) {
bone->setAShearX(v);
}
float SpineNewBone::get_a_shear_y() {
return bone->getAShearY();
}
void SpineNewBone::set_a_shear_y(float v) {
bone->setAShearY(v);
}
float SpineNewBone::get_a() {
return bone->getA();
}
void SpineNewBone::set_a(float v) {
bone->setA(v);
}
float SpineNewBone::get_b() {
return bone->getB();
}
void SpineNewBone::set_b(float v) {
bone->setB(v);
}
float SpineNewBone::get_c() {
return bone->getC();
}
void SpineNewBone::set_c(float v) {
bone->setC(v);
}
float SpineNewBone::get_d() {
return bone->getD();
}
void SpineNewBone::set_d(float v) {
bone->setD(v);
}
float SpineNewBone::get_world_x() {
return bone->getWorldX();
}
void SpineNewBone::set_world_x(float v) {
bone->setWorldX(v);
}
float SpineNewBone::get_world_y() {
return bone->getWorldY();
}
void SpineNewBone::set_world_y(float v) {
bone->setWorldY(v);
}
float SpineNewBone::get_world_rotation_x() {
return bone->getWorldRotationX();
}
float SpineNewBone::get_world_rotation_y() {
return bone->getWorldRotationY();
}
float SpineNewBone::get_world_scale_x() {
return bone->getWorldScaleX();
}
float SpineNewBone::get_world_scale_y() {
return bone->getWorldScaleY();
}
bool SpineNewBone::is_active() {
return bone->isActive();
}
void SpineNewBone::set_active(bool v) {
bone->setActive(v);
}
// External feature functions
void SpineNewBone::apply_world_transform_2d(Variant o) {
if (o.get_type() == Variant::OBJECT) {
auto node = (Node *) o;
if (node->is_class("Node2D")) {
auto node2d = (Node2D *) node;
// In godot the y-axis is nag to spine
node2d->set_transform(Transform2D(
get_a(), get_c(),
get_b(), get_d(),
get_world_x(), -get_world_y()));
// Fix the rotation
auto pos = node2d->get_position();
node2d->translate(-pos);
node2d->set_rotation(-node2d->get_rotation());
node2d->translate(pos);
}
}
}
Transform2D SpineNewBone::get_godot_transform() {
if (get_spine_object() == nullptr)
return Transform2D();
Transform2D trans;
trans.translate(get_x(), -get_y());
// It seems that spine uses degree for rotation
trans.rotate(Math::deg2rad(-get_rotation()));
trans.scale(Size2(get_scale_x(), get_scale_y()));
return trans;
}
void SpineNewBone::set_godot_transform(Transform2D trans) {
if (get_spine_object() == nullptr)
return;
Vector2 position = trans.get_origin();
position.y *= -1;
real_t rotation = trans.get_rotation();
rotation = Math::rad2deg(-rotation);
Vector2 scale = trans.get_scale();
set_x(position.x);
set_y(position.y);
set_rotation(rotation);
set_scale_x(scale.x);
set_scale_y(scale.y);
}
Transform2D SpineNewBone::get_godot_global_transform() {
if (get_spine_object() == nullptr)
return Transform2D();
if (the_sprite == nullptr)
return get_godot_transform();
Transform2D res = the_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<CanvasItem>(the_sprite->get_parent()) : nullptr;
if (p) {
return p->get_global_transform() * res;
}
return res;
}
void SpineNewBone::set_godot_global_transform(Transform2D transform) {
if (get_spine_object() == nullptr)
return;
if (the_sprite == nullptr)
set_godot_transform(transform);
transform = the_sprite->get_global_transform().affine_inverse() * transform;
Vector2 position = transform.get_origin();
real_t rotation = transform.get_rotation();
Vector2 scale = transform.get_scale();
position.y *= -1;
auto parent = get_parent();
if (parent.is_valid()) {
position = parent->world_to_local(position);
if (parent->get_world_scale_x() != 0)
scale.x /= parent->get_world_scale_x();
else
print_error("The parent scale.x is zero.");
if (parent->get_world_scale_y() != 0)
scale.y /= parent->get_world_scale_y();
else
print_error("The parent scale.y is zero.");
}
rotation = world_to_local_rotation(Math::rad2deg(-rotation));
set_x(position.x);
set_y(position.y);
set_rotation(rotation);
set_scale_x(scale.x);
set_scale_y(scale.y);
}
void SpineNewBone::set_spine_sprite(SpineNewSprite *s) {
the_sprite = s;
}

View File

@ -0,0 +1,169 @@
/******************************************************************************
* 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_SPINENEWBONE_H
#define GODOT_SPINENEWBONE_H
#include <scene/2d/node_2d.h>
#include <spine/spine.h>
#include "SpineBoneData.h"
class SpineNewSkeleton;
class SpineNewSprite;
class SpineNewBone : public Reference {
GDCLASS(SpineNewBone, Reference);
protected:
static void _bind_methods();
private:
spine::Bone *bone;
SpineNewSprite *the_sprite;
public:
SpineNewBone();
~SpineNewBone();
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 update_world_transform();
void set_to_setup_pose();
Vector2 world_to_local(Vector2 world_position);
Vector2 local_to_world(Vector2 local_position);
float world_to_local_rotation(float world_rotation);
float local_to_world_rotation(float local_rotation);
void rotate_world(float degrees);
float get_world_to_local_rotation_x();
float get_world_to_local_rotation_y();
Ref<SpineBoneData> get_data();
Ref<SpineNewSkeleton> get_skeleton();
Ref<SpineNewBone> get_parent();
Array get_children();
float get_x();
void set_x(float v);
float get_y();
void set_y(float v);
float get_rotation();
void set_rotation(float v);
float get_scale_x();
void set_scale_x(float v);
float get_scale_y();
void set_scale_y(float v);
float get_shear_x();
void set_shear_x(float v);
float get_shear_y();
void set_shear_y(float v);
float get_applied_rotation();
void set_applied_rotation(float v);
float get_a_x();
void set_a_x(float v);
float get_a_y();
void set_a_y(float v);
float get_a_scale_x();
void set_a_scale_x(float v);
float get_a_scale_y();
void set_a_scale_y(float v);
float get_a_shear_x();
void set_a_shear_x(float v);
float get_a_shear_y();
void set_a_shear_y(float v);
float get_a();
void set_a(float v);
float get_b();
void set_b(float v);
float get_c();
void set_c(float v);
float get_d();
void set_d(float v);
float get_world_x();
void set_world_x(float v);
float get_world_y();
void set_world_y(float v);
float get_world_rotation_x();
float get_world_rotation_y();
float get_world_scale_x();
float get_world_scale_y();
bool is_active();
void set_active(bool v);
// External feature functions
void apply_world_transform_2d(Variant o);
Transform2D get_godot_transform();
void set_godot_transform(Transform2D trans);
Transform2D get_godot_global_transform();
void set_godot_global_transform(Transform2D trans);
};
#endif//GODOT_SPINEBONE_H

View File

@ -0,0 +1,343 @@
/******************************************************************************
* 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 "SpineNewSkeleton.h"
void SpineNewSkeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineNewSkeleton::update_world_transform);
ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineNewSkeleton::set_to_setup_pose);
ClassDB::bind_method(D_METHOD("set_bones_to_setup_pose"), &SpineNewSkeleton::set_bones_to_setup_pose);
ClassDB::bind_method(D_METHOD("set_slots_to_setup_pose"), &SpineNewSkeleton::set_slots_to_setup_pose);
ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineNewSkeleton::find_bone);
ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineNewSkeleton::find_slot);
ClassDB::bind_method(D_METHOD("set_skin_by_name", "skin_name"), &SpineNewSkeleton::set_skin_by_name);
ClassDB::bind_method(D_METHOD("set_skin", "new_skin"), &SpineNewSkeleton::set_skin);
ClassDB::bind_method(D_METHOD("get_attachment_by_slot_name", "slot_name", "attachment_name"), &SpineNewSkeleton::get_attachment_by_slot_name);
ClassDB::bind_method(D_METHOD("get_attachment_by_slot_index", "slot_index", "attachment_name"), &SpineNewSkeleton::get_attachment_by_slot_index);
ClassDB::bind_method(D_METHOD("set_attachment", "slot_name", "attachment_name"), &SpineNewSkeleton::set_attachment);
ClassDB::bind_method(D_METHOD("find_ik_constraint", "constraint_name"), &SpineNewSkeleton::find_ik_constraint);
ClassDB::bind_method(D_METHOD("find_transform_constraint", "constraint_name"), &SpineNewSkeleton::find_transform_constraint);
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_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);
ClassDB::bind_method(D_METHOD("get_ik_constraints"), &SpineNewSkeleton::get_ik_constraints);
ClassDB::bind_method(D_METHOD("get_path_constraints"), &SpineNewSkeleton::get_path_constraints);
ClassDB::bind_method(D_METHOD("get_transform_constraints"), &SpineNewSkeleton::get_transform_constraints);
ClassDB::bind_method(D_METHOD("get_skin"), &SpineNewSkeleton::get_skin);
ClassDB::bind_method(D_METHOD("get_color"), &SpineNewSkeleton::get_color);
ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineNewSkeleton::set_color);
ClassDB::bind_method(D_METHOD("set_position", "pos"), &SpineNewSkeleton::set_position);
ClassDB::bind_method(D_METHOD("get_x"), &SpineNewSkeleton::get_x);
ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineNewSkeleton::set_x);
ClassDB::bind_method(D_METHOD("get_y"), &SpineNewSkeleton::get_y);
ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineNewSkeleton::set_y);
ClassDB::bind_method(D_METHOD("get_scale_x"), &SpineNewSkeleton::get_scale_x);
ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineNewSkeleton::set_scale_x);
ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineNewSkeleton::get_scale_y);
ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineNewSkeleton::set_scale_y);
}
SpineNewSkeleton::SpineNewSkeleton() : skeleton(nullptr), sprite(nullptr), skeleton_data_res(nullptr) {
}
SpineNewSkeleton::~SpineNewSkeleton() {
delete skeleton;
}
void SpineNewSkeleton::set_skeleton_data_res(Ref<SpineNewSkeletonDataResource> 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;
}
#define S_T(x) (spine::String((x).utf8()))
void SpineNewSkeleton::update_world_transform() {
skeleton->updateWorldTransform();
}
void SpineNewSkeleton::set_to_setup_pose() {
skeleton->setToSetupPose();
}
void SpineNewSkeleton::set_bones_to_setup_pose() {
skeleton->setBonesToSetupPose();
}
void SpineNewSkeleton::set_slots_to_setup_pose() {
skeleton->setSlotsToSetupPose();
}
Ref<SpineNewBone> SpineNewSkeleton::find_bone(const String &name) {
if (name.empty()) return nullptr;
auto bone = skeleton->findBone(S_T(name));
if (!bone) return nullptr;
Ref<SpineNewBone> bone_ref(memnew(SpineNewBone));
bone_ref->set_spine_object(bone);
bone_ref->set_spine_sprite(sprite);
return bone_ref;
}
Ref<SpineSlot> SpineNewSkeleton::find_slot(const String &name) {
if (name.empty()) return nullptr;
auto slot = skeleton->findSlot(S_T(name));
if (!slot) return nullptr;
Ref<SpineSlot> slot_ref(memnew(SpineSlot));
slot_ref->set_spine_object(slot);
return slot_ref;
}
void SpineNewSkeleton::set_skin_by_name(const String &skin_name) {
skeleton->setSkin(S_T(skin_name));
}
void SpineNewSkeleton::set_skin(Ref<SpineSkin> new_skin) {
if (new_skin.is_valid())
skeleton->setSkin(new_skin->get_spine_object());
else
skeleton->setSkin(nullptr);
}
Ref<SpineAttachment> SpineNewSkeleton::get_attachment_by_slot_name(const String &slot_name, const String &attachment_name) {
auto a = skeleton->getAttachment(S_T(slot_name), S_T(attachment_name));
if (a == nullptr) return nullptr;
Ref<SpineAttachment> gd_a(memnew(SpineAttachment));
gd_a->set_spine_object(a);
return gd_a;
}
Ref<SpineAttachment> SpineNewSkeleton::get_attachment_by_slot_index(int slot_index, const String &attachment_name) {
auto a = skeleton->getAttachment(slot_index, S_T(attachment_name));
if (a == nullptr) return nullptr;
Ref<SpineAttachment> gd_a(memnew(SpineAttachment));
gd_a->set_spine_object(a);
return gd_a;
}
void SpineNewSkeleton::set_attachment(const String &slot_name, const String &attachment_name) {
ERR_FAIL_COND(slot_name.empty());
ERR_FAIL_COND(get_attachment_by_slot_name(slot_name, attachment_name) == nullptr);
skeleton->setAttachment(S_T(slot_name), S_T(attachment_name));
}
Ref<SpineIkConstraint> SpineNewSkeleton::find_ik_constraint(const String &constraint_name) {
if (constraint_name.empty()) return nullptr;
auto c = skeleton->findIkConstraint(S_T(constraint_name));
if (c == nullptr) return nullptr;
Ref<SpineIkConstraint> gd_c(memnew(SpineIkConstraint));
gd_c->set_spine_object(c);
return gd_c;
}
Ref<SpineTransformConstraint> SpineNewSkeleton::find_transform_constraint(const String &constraint_name) {
if (constraint_name.empty()) return nullptr;
auto c = skeleton->findTransformConstraint(S_T(constraint_name));
if (c == nullptr) return nullptr;
Ref<SpineTransformConstraint> gd_c(memnew(SpineTransformConstraint));
gd_c->set_spine_object(c);
return gd_c;
}
Ref<SpinePathConstraint> SpineNewSkeleton::find_path_constraint(const String &constraint_name) {
if (constraint_name.empty()) return nullptr;
auto c = skeleton->findPathConstraint(S_T(constraint_name));
if (c == nullptr) return nullptr;
Ref<SpinePathConstraint> gd_c(memnew(SpinePathConstraint));
gd_c->set_spine_object(c);
return gd_c;
}
Dictionary SpineNewSkeleton::get_bounds() {
float x, y, w, h;
spine::Vector<float> vertex_buffer;
skeleton->getBounds(x, y, w, h, vertex_buffer);
Dictionary res;
res["x"] = x;
res["y"] = y;
res["w"] = w;
res["h"] = h;
Array gd_a;
gd_a.resize(vertex_buffer.size());
for (size_t i = 0; i < gd_a.size(); ++i) {
gd_a[i] = vertex_buffer[i];
}
res["vertex_buffer"] = gd_a;
return res;
}
Ref<SpineNewBone> SpineNewSkeleton::get_root_bone() {
auto b = skeleton->getRootBone();
if (b == nullptr) return nullptr;
Ref<SpineNewBone> gd_b(memnew(SpineNewBone));
gd_b->set_spine_object(b);
gd_b->set_spine_sprite(sprite);
return gd_b;
}
Ref<SpineNewSkeletonDataResource> SpineNewSkeleton::get_data() const {
return skeleton_data_res;
}
Array SpineNewSkeleton::get_bones() {
auto &as = skeleton->getBones();
Array gd_as;
gd_as.resize(as.size());
for (size_t i = 0; i < gd_as.size(); ++i) {
auto b = as[i];
if (b == nullptr) gd_as[i] = Ref<SpineNewBone>(nullptr);
Ref<SpineNewBone> gd_a(memnew(SpineNewBone));
gd_a->set_spine_object(b);
gd_a->set_spine_sprite(sprite);
gd_as[i] = gd_a;
}
return gd_as;
}
Array SpineNewSkeleton::get_slots() {
auto &as = skeleton->getSlots();
Array gd_as;
gd_as.resize(as.size());
for (size_t i = 0; i < gd_as.size(); ++i) {
auto b = as[i];
if (b == nullptr) gd_as[i] = Ref<SpineSlot>(nullptr);
Ref<SpineSlot> gd_a(memnew(SpineSlot));
gd_a->set_spine_object(b);
gd_as[i] = gd_a;
}
return gd_as;
}
Array SpineNewSkeleton::get_draw_orders() {
auto &as = skeleton->getDrawOrder();
Array gd_as;
gd_as.resize(as.size());
for (size_t i = 0; i < gd_as.size(); ++i) {
auto b = as[i];
if (b == nullptr) gd_as[i] = Ref<SpineSlot>(nullptr);
Ref<SpineSlot> gd_a(memnew(SpineSlot));
gd_a->set_spine_object(b);
gd_as[i] = gd_a;
}
return gd_as;
}
Array SpineNewSkeleton::get_ik_constraints() {
auto &as = skeleton->getIkConstraints();
Array gd_as;
gd_as.resize(as.size());
for (size_t i = 0; i < gd_as.size(); ++i) {
auto b = as[i];
if (b == nullptr) gd_as[i] = Ref<SpineIkConstraint>(nullptr);
Ref<SpineIkConstraint> gd_a(memnew(SpineIkConstraint));
gd_a->set_spine_object(b);
gd_as[i] = gd_a;
}
return gd_as;
}
Array SpineNewSkeleton::get_path_constraints() {
auto &as = skeleton->getPathConstraints();
Array gd_as;
gd_as.resize(as.size());
for (size_t i = 0; i < gd_as.size(); ++i) {
auto b = as[i];
if (b == nullptr) gd_as[i] = Ref<SpinePathConstraint>(nullptr);
Ref<SpinePathConstraint> gd_a(memnew(SpinePathConstraint));
gd_a->set_spine_object(b);
gd_as[i] = gd_a;
}
return gd_as;
}
Array SpineNewSkeleton::get_transform_constraints() {
auto &as = skeleton->getTransformConstraints();
Array gd_as;
gd_as.resize(as.size());
for (size_t i = 0; i < gd_as.size(); ++i) {
auto b = as[i];
if (b == nullptr) gd_as[i] = Ref<SpineTransformConstraint>(nullptr);
Ref<SpineTransformConstraint> gd_a(memnew(SpineTransformConstraint));
gd_a->set_spine_object(b);
gd_as[i] = gd_a;
}
return gd_as;
}
Ref<SpineSkin> SpineNewSkeleton::get_skin() {
auto s = skeleton->getSkin();
if (s == nullptr) return nullptr;
Ref<SpineSkin> gd_s(memnew(SpineSkin));
gd_s->set_spine_object(s);
return gd_s;
}
Color SpineNewSkeleton::get_color() {
auto &c = skeleton->getColor();
return Color(c.r, c.g, c.b, c.a);
}
void SpineNewSkeleton::set_color(Color v) {
auto &c = skeleton->getColor();
c.set(v.r, v.g, v.b, v.a);
}
void SpineNewSkeleton::set_position(Vector2 pos) {
skeleton->setPosition(pos.x, pos.y);
}
float SpineNewSkeleton::get_x() {
return skeleton->getX();
}
void SpineNewSkeleton::set_x(float v) {
skeleton->setX(v);
}
float SpineNewSkeleton::get_y() {
return skeleton->getY();
}
void SpineNewSkeleton::set_y(float v) {
skeleton->setY(v);
}
float SpineNewSkeleton::get_scale_x() {
return skeleton->getScaleX();
}
void SpineNewSkeleton::set_scale_x(float v) {
skeleton->setScaleX(v);
}
float SpineNewSkeleton::get_scale_y() {
return skeleton->getScaleY();
}
void SpineNewSkeleton::set_scale_y(float v) {
skeleton->setScaleY(v);
}
void SpineNewSkeleton::set_spine_sprite(SpineNewSprite *s) {
sprite = s;
}

View File

@ -0,0 +1,127 @@
/******************************************************************************
* 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_SPINENEWSKELETON_H
#define GODOT_SPINENEWSKELETON_H
#include <spine/spine.h>
#include "SpineNewSkeletonDataResource.h"
#include "SpineNewBone.h"
#include "SpineSlot.h"
#include "SpineIkConstraint.h"
#include "SpineTransformConstraint.h"
class SpineNewSprite;
class SpineNewSkeleton : public Reference {
GDCLASS(SpineNewSkeleton, Reference);
protected:
static void _bind_methods();
private:
spine::Skeleton *skeleton;
SpineNewSprite *sprite;
Ref<SpineNewSkeletonDataResource> skeleton_data_res;
public:
SpineNewSkeleton();
~SpineNewSkeleton();
void set_skeleton_data_res(Ref<SpineNewSkeletonDataResource> data_res);
inline void set_spine_object(spine::Skeleton *s) {
skeleton = s;
}
inline spine::Skeleton *get_spine_object() {
return skeleton;
}
void set_spine_sprite(SpineNewSprite *s);
void update_world_transform();
void set_to_setup_pose();
void set_bones_to_setup_pose();
void set_slots_to_setup_pose();
Ref<SpineNewBone> find_bone(const String &name);
Ref<SpineSlot> find_slot(const String &name);
void set_skin_by_name(const String &skin_name);
void set_skin(Ref<SpineSkin> new_skin);
Ref<SpineAttachment> get_attachment_by_slot_name(const String &slot_name, const String &attachment_name);
Ref<SpineAttachment> get_attachment_by_slot_index(int slot_index, const String &attachment_name);
void set_attachment(const String &slot_name, const String &attachment_name);
Ref<SpineIkConstraint> find_ik_constraint(const String &constraint_name);
Ref<SpineTransformConstraint> find_transform_constraint(const String &constraint_name);
Ref<SpinePathConstraint> find_path_constraint(const String &constraint_name);
Dictionary get_bounds();
Ref<SpineNewBone> get_root_bone();
Ref<SpineNewSkeletonDataResource> get_data() const;
Array get_bones();
Array get_slots();
Array get_draw_orders();
Array get_ik_constraints();
Array get_path_constraints();
Array get_transform_constraints();
Ref<SpineSkin> get_skin();
Color get_color();
void set_color(Color v);
void set_position(Vector2 pos);
float get_x();
void set_x(float v);
float get_y();
void set_y(float v);
float get_scale_x();
void set_scale_x(float v);
float get_scale_y();
void set_scale_y(float v);
};
#endif//GODOT_SPINENEWSKELETON_H

View File

@ -30,428 +30,409 @@
#include "SpineNewSkeletonDataResource.h"
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);
ClassDB::bind_method(D_METHOD("get_atlas_res"), &SpineNewSkeletonDataResource::get_atlas_res);
ClassDB::bind_method(D_METHOD("set_skeleton_file_res", "skeleton_file_res"), &SpineNewSkeletonDataResource::set_skeleton_file_res);
ClassDB::bind_method(D_METHOD("get_skeleton_file_res"), &SpineNewSkeletonDataResource::get_skeleton_file_res);
ClassDB::bind_method(D_METHOD("is_skeleton_data_loaded"), &SpineNewSkeletonDataResource::is_skeleton_data_loaded);
ClassDB::bind_method(D_METHOD("find_animation", "animation_name"), &SpineNewSkeletonDataResource::find_animation);
ClassDB::bind_method(D_METHOD("get_skeleton_name"), &SpineNewSkeletonDataResource::get_skeleton_name);
ClassDB::bind_method(D_METHOD("set_skeleton_name", "skeleton_name"), &SpineNewSkeletonDataResource::set_skeleton_name);
ClassDB::bind_method(D_METHOD("get_x"), &SpineNewSkeletonDataResource::get_x);
ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineNewSkeletonDataResource::set_x);
ClassDB::bind_method(D_METHOD("get_y"), &SpineNewSkeletonDataResource::get_y);
ClassDB::bind_method(D_METHOD("set_y", "v"), &SpineNewSkeletonDataResource::set_y);
ClassDB::bind_method(D_METHOD("get_width"), &SpineNewSkeletonDataResource::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &SpineNewSkeletonDataResource::get_height);
ClassDB::bind_method(D_METHOD("get_version"), &SpineNewSkeletonDataResource::get_version);
ClassDB::bind_method(D_METHOD("get_fps"), &SpineNewSkeletonDataResource::get_fps);
ClassDB::bind_method(D_METHOD("set_fps", "v"), &SpineNewSkeletonDataResource::set_fps);
// Spine API
ClassDB::bind_method(D_METHOD("find_bone", "bone_name"), &SpineNewSkeletonDataResource::find_bone);
ClassDB::bind_method(D_METHOD("find_slot", "slot_name"), &SpineNewSkeletonDataResource::find_slot);
ClassDB::bind_method(D_METHOD("find_skin", "skin_name"), &SpineNewSkeletonDataResource::find_skin);
ClassDB::bind_method(D_METHOD("find_event", "event_data_name"), &SpineNewSkeletonDataResource::find_event);
ClassDB::bind_method(D_METHOD("find_animation", "animation_name"), &SpineNewSkeletonDataResource::find_animation);
ClassDB::bind_method(D_METHOD("find_ik_constraint_data", "constraint_name"), &SpineNewSkeletonDataResource::find_ik_constraint);
ClassDB::bind_method(D_METHOD("find_transform_constraint_data", "constraint_name"), &SpineNewSkeletonDataResource::find_transform_constraint);
ClassDB::bind_method(D_METHOD("find_path_constraint_data", "constraint_name"), &SpineNewSkeletonDataResource::find_path_constraint);
ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineNewSkeletonDataResource::get_bones);
ClassDB::bind_method(D_METHOD("get_all_slot_data"), &SpineNewSkeletonDataResource::get_slots);
ClassDB::bind_method(D_METHOD("get_skeleton_name"), &SpineNewSkeletonDataResource::get_skeleton_name);
ClassDB::bind_method(D_METHOD("get_bones"), &SpineNewSkeletonDataResource::get_bones);
ClassDB::bind_method(D_METHOD("get_slots"), &SpineNewSkeletonDataResource::get_slots);
ClassDB::bind_method(D_METHOD("get_skins"), &SpineNewSkeletonDataResource::get_skins);
ClassDB::bind_method(D_METHOD("get_default_skin"), &SpineNewSkeletonDataResource::get_default_skin);
ClassDB::bind_method(D_METHOD("set_default_skin", "v"), &SpineNewSkeletonDataResource::set_default_skin);
ClassDB::bind_method(D_METHOD("get_all_event_data"), &SpineNewSkeletonDataResource::get_events);
ClassDB::bind_method(D_METHOD("set_default_skin", "skin"), &SpineNewSkeletonDataResource::set_default_skin);
ClassDB::bind_method(D_METHOD("get_events"), &SpineNewSkeletonDataResource::get_events);
ClassDB::bind_method(D_METHOD("get_animations"), &SpineNewSkeletonDataResource::get_animations);
ClassDB::bind_method(D_METHOD("get_all_ik_constraint_data"), &SpineNewSkeletonDataResource::get_ik_constraints);
ClassDB::bind_method(D_METHOD("get_all_transform_constraint_data"), &SpineNewSkeletonDataResource::get_transform_constraints);
ClassDB::bind_method(D_METHOD("get_all_path_constraint_data"), &SpineNewSkeletonDataResource::get_path_constraints);
ClassDB::bind_method(D_METHOD("get_ik_constraints"), &SpineNewSkeletonDataResource::get_ik_constraints);
ClassDB::bind_method(D_METHOD("get_transform_constraints"), &SpineNewSkeletonDataResource::get_transform_constraints);
ClassDB::bind_method(D_METHOD("get_path_constraints"), &SpineNewSkeletonDataResource::get_path_constraints);
ClassDB::bind_method(D_METHOD("get_x"), &SpineNewSkeletonDataResource::get_x);
ClassDB::bind_method(D_METHOD("get_y"), &SpineNewSkeletonDataResource::get_y);
ClassDB::bind_method(D_METHOD("get_width"), &SpineNewSkeletonDataResource::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &SpineNewSkeletonDataResource::get_height);
ClassDB::bind_method(D_METHOD("get_version"), &SpineNewSkeletonDataResource::get_version);
ClassDB::bind_method(D_METHOD("get_hash"), &SpineNewSkeletonDataResource::get_hash);
ClassDB::bind_method(D_METHOD("get_images_path"), &SpineNewSkeletonDataResource::get_images_path);
ClassDB::bind_method(D_METHOD("get_audio_path"), &SpineNewSkeletonDataResource::get_audio_path);
ClassDB::bind_method(D_METHOD("get_fps"), &SpineNewSkeletonDataResource::get_fps);
ADD_SIGNAL(MethodInfo("skeleton_data_loaded"));
ADD_SIGNAL(MethodInfo("atlas_res_changed"));
ADD_SIGNAL(MethodInfo("skeleton_file_res_changed"));
ADD_SIGNAL(MethodInfo("skeleton_data_changed"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineAtlasResource"), "set_atlas_res", "get_atlas_res");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_file_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineSkeletonFileResource"), "set_skeleton_file_res", "get_skeleton_file_res");
}
SpineNewSkeletonDataResource::SpineNewSkeletonDataResource() : valid(false), spine_object(false), skeleton_data(NULL) {
SpineNewSkeletonDataResource::SpineNewSkeletonDataResource() : skeleton_data(nullptr), animation_state_data(nullptr) {
}
SpineNewSkeletonDataResource::~SpineNewSkeletonDataResource() {
if (skeleton_data && !spine_object) {
delete skeleton_data;
skeleton_data = NULL;
}
delete skeleton_data;
delete animation_state_data;
}
bool SpineNewSkeletonDataResource::is_skeleton_data_loaded() const {
return valid || spine_object;
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<uint8_t> &binary) {
valid = false;
if (skeleton_data) {
delete skeleton_data;
skeleton_data = NULL;
skeleton_data = nullptr;
}
if (animation_state_data) {
delete animation_state_data;
animation_state_data = nullptr;
}
if ((json.empty() && binary.empty()) || atlas == NULL) return;
if ((json.empty() && binary.empty()) || atlas == nullptr) return;
spine::SkeletonData *skeletonData = NULL;
spine::SkeletonData *data;
if (!json.empty()) {
spine::SkeletonJson skeletonJson(atlas);
skeletonData = skeletonJson.readSkeletonData(json.utf8());
if (!skeletonData) {
data = skeletonJson.readSkeletonData(json.utf8());
if (!data) {
print_error(String("Error while loading skeleton data: ") + get_path());
print_error(String("Error message: ") + skeletonJson.getError().buffer());
return;
}
} else {
spine::SkeletonBinary skeletonBinary(atlas);
skeletonData = skeletonBinary.readSkeletonData(binary.ptr(), binary.size());
if (!skeletonData) {
data = skeletonBinary.readSkeletonData(binary.ptr(), binary.size());
if (!data) {
print_error(String("Error while loading skeleton data: ") + get_path());
print_error(String("Error message: ") + skeletonBinary.getError().buffer());
return;
}
}
skeleton_data = skeletonData;
valid = true;
skeleton_data = data;
animation_state_data = new spine::AnimationStateData(data);
}
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());
if (valid) {
emit_signal("skeleton_data_loaded");
}
}
bool SpineNewSkeletonDataResource::is_skeleton_data_loaded() const {
return skeleton_data != nullptr;
}
void SpineNewSkeletonDataResource::set_atlas_res(const Ref<SpineAtlasResource> &a) {
atlas_res = a;
valid = false;
emit_signal("atlas_res_changed");
void SpineNewSkeletonDataResource::set_atlas_res(const Ref<SpineAtlasResource> &atlas) {
atlas_res = atlas;
update_skeleton_data();
}
Ref<SpineAtlasResource> SpineNewSkeletonDataResource::get_atlas_res() {
return atlas_res;
}
void SpineNewSkeletonDataResource::set_skeleton_file_res(const Ref<SpineSkeletonFileResource> &s) {
skeleton_file_res = s;
valid = false;
emit_signal("skeleton_file_res_changed");
void SpineNewSkeletonDataResource::set_skeleton_file_res(const Ref<SpineSkeletonFileResource> &skeleton_file) {
skeleton_file_res = skeleton_file;
update_skeleton_data();
}
Ref<SpineSkeletonFileResource> SpineNewSkeletonDataResource::get_skeleton_file_res() {
return skeleton_file_res;
}
void SpineNewSkeletonDataResource::get_animation_names(Vector<String> &animation_names) const {
animation_names.clear();
if (!is_skeleton_data_loaded()) return;
auto animations = skeleton_data->getAnimations();
for (size_t i = 0; i < animations.size(); ++i) {
auto animation = animations[i];
animation_names.push_back(animation->getName().buffer());
}
}
void SpineNewSkeletonDataResource::get_skin_names(Vector<String> &skin_names) const {
skin_names.clear();
if (!is_skeleton_data_loaded()) return;
auto skins = skeleton_data->getSkins();
for (size_t i = 0; i < skins.size(); ++i) {
auto skin = skins[i];
skin_names.push_back(skin->getName().buffer());
}
}
void SpineNewSkeletonDataResource::_get_property_list(List<PropertyInfo> *p_list) const {
PropertyInfo property;
Vector<String> animation_names;
property.name = "animations";
property.type = Variant::STRING;
get_animation_names(animation_names);
property.hint_string = String(",").join(animation_names);
property.hint = PROPERTY_HINT_ENUM;
p_list->push_back(property);
property.name = "skins";
property.type = Variant::STRING;
get_skin_names(animation_names);
property.hint_string = String(",").join(animation_names);
property.hint = PROPERTY_HINT_ENUM;
p_list->push_back(property);
}
#define CHECK(x) \
if (!is_skeleton_data_loaded()) { \
ERR_PRINT("skeleton data has not loaded yet!"); \
return x; \
}
#define S_T(x) (spine::String(x.utf8()))
Ref<SpineAnimation> SpineNewSkeletonDataResource::find_animation(const String &animation_name) {
CHECK(NULL);
if (animation_name.empty()) {
return NULL;
}
auto a = skeleton_data->findAnimation(S_T(animation_name));
if (!a) return NULL;
Ref<SpineAnimation> sa(memnew(SpineAnimation));
sa->set_spine_object(a);
return sa;
#define S_T(x) (spine::String((x).utf8()))
Ref<SpineAnimation> SpineNewSkeletonDataResource::find_animation(const String &animation_name) const {
CHECK(nullptr)
if (animation_name.empty()) return nullptr;
auto animation = skeleton_data->findAnimation(S_T(animation_name));
if (!animation) return nullptr;
Ref<SpineAnimation> animation_ref(memnew(SpineAnimation));
animation_ref->set_spine_object(animation);
return animation_ref;
}
String SpineNewSkeletonDataResource::get_skeleton_name() {
CHECK("");
Ref<SpineBoneData> SpineNewSkeletonDataResource::find_bone(const String &bone_name) const {
CHECK(nullptr)
if (bone_name.empty()) return nullptr;
auto bone = skeleton_data->findBone(S_T(bone_name));
if (bone == nullptr) return nullptr;
Ref<SpineBoneData> bone_ref(memnew(SpineBoneData));
bone_ref->set_spine_object(bone);
return bone_ref;
}
Ref<SpineSlotData> SpineNewSkeletonDataResource::find_slot(const String &slot_name) const {
CHECK(nullptr)
if (slot_name.empty()) return nullptr;
auto slot = skeleton_data->findSlot(S_T(slot_name));
if (slot == nullptr) return nullptr;
Ref<SpineSlotData> slot_ref(memnew(SpineSlotData));
slot_ref->set_spine_object(slot);
return slot_ref;
}
Ref<SpineSkin> SpineNewSkeletonDataResource::find_skin(const String &skin_name) const {
CHECK(nullptr)
if (skin_name.empty()) return nullptr;
auto skin = skeleton_data->findSkin(S_T(skin_name));
if (skin == nullptr) return nullptr;
Ref<SpineSkin> skin_ref(memnew(SpineSkin));
skin_ref->set_spine_object(skin);
return skin_ref;
}
Ref<SpineEventData> SpineNewSkeletonDataResource::find_event(const String &event_data_name) const {
CHECK(nullptr)
if (event_data_name.empty()) return nullptr;
auto event = skeleton_data->findEvent(S_T(event_data_name));
if (event == nullptr) return nullptr;
Ref<SpineEventData> event_ref(memnew(SpineEventData));
event_ref->set_spine_object(event);
return event_ref;
}
Ref<SpineIkConstraintData> SpineNewSkeletonDataResource::find_ik_constraint(const String &constraint_name) const {
CHECK(nullptr)
if (constraint_name.empty()) return nullptr;
auto constraint = skeleton_data->findIkConstraint(S_T(constraint_name));
if (constraint == nullptr) return nullptr;
Ref<SpineIkConstraintData> constraint_ref(memnew(SpineIkConstraintData));
constraint_ref->set_spine_object(constraint);
return constraint_ref;
}
Ref<SpineTransformConstraintData> SpineNewSkeletonDataResource::find_transform_constraint(const String &constraint_name) const {
CHECK(nullptr)
if (constraint_name.empty()) return nullptr;
auto constraint = skeleton_data->findTransformConstraint(S_T(constraint_name));
if (constraint == nullptr) return nullptr;
Ref<SpineTransformConstraintData> constraint_ref(memnew(SpineTransformConstraintData));
constraint_ref->set_spine_object(constraint);
return constraint_ref;
}
Ref<SpinePathConstraintData> SpineNewSkeletonDataResource::find_path_constraint(const String &constraint_name) const {
CHECK(nullptr)
if (constraint_name.empty()) return nullptr;
auto constraint = skeleton_data->findPathConstraint(S_T(constraint_name));
if (constraint == nullptr) return nullptr;
Ref<SpinePathConstraintData> constraint_ref(memnew(SpinePathConstraintData));
constraint_ref->set_spine_object(constraint);
return constraint_ref;
}
String SpineNewSkeletonDataResource::get_skeleton_name() const{
CHECK("")
return skeleton_data->getName().buffer();
}
void SpineNewSkeletonDataResource::set_skeleton_name(const String &v) {
CHECK();
skeleton_data->setName(S_T(v));
Array SpineNewSkeletonDataResource::get_bones() const {
Array bone_refs;
CHECK(bone_refs)
auto bones = skeleton_data->getBones();
bone_refs.resize((int)bones.size());
for (int i = 0; i < bones.size(); ++i) {
Ref<SpineBoneData> bone_ref(memnew(SpineBoneData));
bone_ref->set_spine_object(bones[i]);
bone_refs[i] = bone_ref;
}
return bone_refs;
}
float SpineNewSkeletonDataResource::get_x() {
CHECK(0);
Array SpineNewSkeletonDataResource::get_slots() const {
Array slot_refs;
CHECK(slot_refs)
auto slots = skeleton_data->getSlots();
slot_refs.resize((int)slots.size());
for (int i = 0; i < slots.size(); ++i) {
Ref<SpineSlotData> slot_ref(memnew(SpineSlotData));
slot_ref->set_spine_object(slots[i]);
slot_refs[i] = slot_ref;
}
return slot_refs;
}
Array SpineNewSkeletonDataResource::get_skins() const {
Array skin_refs;
CHECK(skin_refs)
auto skins = skeleton_data->getSkins();
skin_refs.resize((int)skins.size());
for (int i = 0; i < skins.size(); ++i) {
Ref<SpineSkin> skin_ref(memnew(SpineSkin));
skin_ref->set_spine_object(skins[i]);
skin_refs[i] = skin_ref;
}
return skin_refs;
}
Ref<SpineSkin> SpineNewSkeletonDataResource::get_default_skin() const {
CHECK(nullptr)
auto skin = skeleton_data->getDefaultSkin();
if (skin == nullptr) return nullptr;
Ref<SpineSkin> skin_ref(memnew(SpineSkin));
skin_ref->set_spine_object(skin);
return skin_ref;
}
void SpineNewSkeletonDataResource::set_default_skin(Ref<SpineSkin> skin) {
CHECK()
if (skin.is_valid())
skeleton_data->setDefaultSkin(skin->get_spine_object());
else
skeleton_data->setDefaultSkin(nullptr);
}
Array SpineNewSkeletonDataResource::get_events() const {
Array event_refs;
CHECK(event_refs)
auto events = skeleton_data->getEvents();
event_refs.resize((int)events.size());
for (int i = 0; i < events.size(); ++i) {
Ref<SpineEventData> event_ref(memnew(SpineEventData));
event_ref->set_spine_object(events[i]);
event_refs[i] = event_ref;
}
return event_refs;
}
Array SpineNewSkeletonDataResource::get_animations() const {
Array animation_refs;
CHECK(animation_refs)
auto animations = skeleton_data->getAnimations();
animation_refs.resize((int)animations.size());
for (int i = 0; i < animations.size(); ++i) {
Ref<SpineAnimation> animation_ref(memnew(SpineAnimation));
animation_ref->set_spine_object(animations[i]);
animation_refs[i] = animation_ref;
}
return animation_refs;
}
Array SpineNewSkeletonDataResource::get_ik_constraints() const {
Array constraint_refs;
CHECK(constraint_refs)
auto constraints = skeleton_data->getIkConstraints();
constraint_refs.resize((int)constraints.size());
for (int i = 0; i < constraints.size(); ++i) {
Ref<SpineIkConstraintData> constraint_ref(memnew(SpineIkConstraintData));
constraint_ref->set_spine_object(constraints[i]);
constraint_refs[i] = constraint_ref;
}
return constraint_refs;
}
Array SpineNewSkeletonDataResource::get_transform_constraints() const {
Array constraint_refs;
CHECK(constraint_refs)
auto constraints = skeleton_data->getTransformConstraints();
constraint_refs.resize((int)constraints.size());
for (int i = 0; i < constraints.size(); ++i) {
Ref<SpineTransformConstraintData> constraint_ref(memnew(SpineTransformConstraintData));
constraint_ref->set_spine_object(constraints[i]);
constraint_refs[i] = constraint_ref;
}
return constraint_refs;
}
Array SpineNewSkeletonDataResource::get_path_constraints() const {
Array constraint_refs;
CHECK(constraint_refs)
auto constraints = skeleton_data->getPathConstraints();
constraint_refs.resize((int)constraints.size());
for (int i = 0; i < constraints.size(); ++i) {
Ref<SpinePathConstraintData> constraint_ref(memnew(SpinePathConstraintData));
constraint_ref->set_spine_object(constraints[i]);
constraint_refs[i] = constraint_ref;
}
return constraint_refs;
}
float SpineNewSkeletonDataResource::get_x() const{
CHECK(0)
return skeleton_data->getX();
}
void SpineNewSkeletonDataResource::set_x(float v) {
CHECK();
skeleton_data->setX(v);
}
float SpineNewSkeletonDataResource::get_y() {
CHECK(0);
float SpineNewSkeletonDataResource::get_y() const {
CHECK(0)
return skeleton_data->getY();
}
void SpineNewSkeletonDataResource::set_y(float v) {
CHECK();
skeleton_data->setY(v);
}
float SpineNewSkeletonDataResource::get_width() {
CHECK(0);
float SpineNewSkeletonDataResource::get_width() const{
CHECK(0)
return skeleton_data->getWidth();
}
float SpineNewSkeletonDataResource::get_height() {
CHECK(0);
float SpineNewSkeletonDataResource::get_height() const {
CHECK(0)
return skeleton_data->getHeight();
}
String SpineNewSkeletonDataResource::get_version() {
CHECK("error");
String SpineNewSkeletonDataResource::get_version() const {
CHECK("")
return skeleton_data->getVersion().buffer();
}
float SpineNewSkeletonDataResource::get_fps() {
CHECK(0);
String SpineNewSkeletonDataResource::get_hash() const {
CHECK("")
return skeleton_data->getHash().buffer();
}
String SpineNewSkeletonDataResource::get_images_path() const {
CHECK("")
return skeleton_data->getImagesPath().buffer();
}
String SpineNewSkeletonDataResource::get_audio_path() const {
CHECK("")
return skeleton_data->getAudioPath().buffer();
}
float SpineNewSkeletonDataResource::get_fps() const {
CHECK(0)
return skeleton_data->getFps();
}
void SpineNewSkeletonDataResource::set_fps(float v) {
CHECK();
skeleton_data->setFps(v);
}
Ref<SpineBoneData> SpineNewSkeletonDataResource::find_bone(const String &bone_name) {
if (bone_name.empty()) return NULL;
auto b = skeleton_data->findBone(S_T(bone_name));
if (b == NULL) return NULL;
Ref<SpineBoneData> gd_b(memnew(SpineBoneData));
gd_b->set_spine_object(b);
return gd_b;
}
Ref<SpineSlotData> SpineNewSkeletonDataResource::find_slot(const String &slot_name) {
if (slot_name.empty()) return NULL;
auto b = skeleton_data->findSlot(S_T(slot_name));
if (b == NULL) return NULL;
Ref<SpineSlotData> gd_b(memnew(SpineSlotData));
gd_b->set_spine_object(b);
return gd_b;
}
Ref<SpineSkin> SpineNewSkeletonDataResource::find_skin(const String &skin_name) {
if (skin_name.empty()) return NULL;
auto b = skeleton_data->findSkin(S_T(skin_name));
if (b == NULL) return NULL;
Ref<SpineSkin> gd_b(memnew(SpineSkin));
gd_b->set_spine_object(b);
return gd_b;
}
Ref<SpineEventData> SpineNewSkeletonDataResource::find_event(const String &event_data_name) {
if (event_data_name.empty()) return NULL;
auto b = skeleton_data->findEvent(S_T(event_data_name));
if (b == NULL) return NULL;
Ref<SpineEventData> gd_b(memnew(SpineEventData));
gd_b->set_spine_object(b);
return gd_b;
}
Ref<SpineIkConstraintData> SpineNewSkeletonDataResource::find_ik_constraint(const String &constraint_name) {
if (constraint_name.empty()) return NULL;
auto b = skeleton_data->findIkConstraint(S_T(constraint_name));
if (b == NULL) return NULL;
Ref<SpineIkConstraintData> gd_b(memnew(SpineIkConstraintData));
gd_b->set_spine_object(b);
return gd_b;
}
Ref<SpineTransformConstraintData> SpineNewSkeletonDataResource::find_transform_constraint(const String &constraint_name) {
if (constraint_name.empty()) return NULL;
auto b = skeleton_data->findTransformConstraint(S_T(constraint_name));
if (b == NULL) return NULL;
Ref<SpineTransformConstraintData> gd_b(memnew(SpineTransformConstraintData));
gd_b->set_spine_object(b);
return gd_b;
}
Ref<SpinePathConstraintData> SpineNewSkeletonDataResource::find_path_constraint(const String &constraint_name) {
if (constraint_name.empty()) return NULL;
auto b = skeleton_data->findPathConstraint(S_T(constraint_name));
if (b == NULL) return NULL;
Ref<SpinePathConstraintData> gd_b(memnew(SpinePathConstraintData));
gd_b->set_spine_object(b);
return gd_b;
}
Array SpineNewSkeletonDataResource::get_bones() {
auto bs = skeleton_data->getBones();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpineBoneData>(NULL);
else {
Ref<SpineBoneData> gd_b(memnew(SpineBoneData));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
Array SpineNewSkeletonDataResource::get_slots() {
auto bs = skeleton_data->getSlots();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpineSlotData>(NULL);
else {
Ref<SpineSlotData> gd_b(memnew(SpineSlotData));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
Array SpineNewSkeletonDataResource::get_skins() const {
auto bs = skeleton_data->getSkins();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpineSkin>(NULL);
else {
Ref<SpineSkin> gd_b(memnew(SpineSkin));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
Ref<SpineSkin> SpineNewSkeletonDataResource::get_default_skin() {
auto b = skeleton_data->getDefaultSkin();
if (b == NULL) return NULL;
Ref<SpineSkin> gd_b(memnew(SpineSkin));
gd_b->set_spine_object(b);
return gd_b;
}
void SpineNewSkeletonDataResource::set_default_skin(Ref<SpineSkin> v) {
if (v.is_valid()) {
skeleton_data->setDefaultSkin(v->get_spine_object());
} else
skeleton_data->setDefaultSkin(NULL);
}
Array SpineNewSkeletonDataResource::get_events() {
auto bs = skeleton_data->getEvents();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpineEventData>(NULL);
else {
Ref<SpineEventData> gd_b(memnew(SpineEventData));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
Array SpineNewSkeletonDataResource::get_animations() {
auto bs = skeleton_data->getAnimations();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpineAnimation>(NULL);
else {
Ref<SpineAnimation> gd_b(memnew(SpineAnimation));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
Array SpineNewSkeletonDataResource::get_ik_constraints() {
auto bs = skeleton_data->getIkConstraints();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpineIkConstraintData>(NULL);
else {
Ref<SpineIkConstraintData> gd_b(memnew(SpineIkConstraintData));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
Array SpineNewSkeletonDataResource::get_transform_constraints() {
auto bs = skeleton_data->getTransformConstraints();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpineTransformConstraintData>(NULL);
else {
Ref<SpineTransformConstraintData> gd_b(memnew(SpineTransformConstraintData));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
Array SpineNewSkeletonDataResource::get_path_constraints() {
auto bs = skeleton_data->getPathConstraints();
Array gd_bs;
gd_bs.resize(bs.size());
for (size_t i = 0; i < bs.size(); ++i) {
if (bs[i] == NULL) gd_bs[i] = Ref<SpinePathConstraintData>(NULL);
else {
Ref<SpinePathConstraintData> gd_b(memnew(SpinePathConstraintData));
gd_b->set_spine_object(bs[i]);
gd_bs[i] = gd_b;
}
}
return gd_bs;
}
#undef S_T
#undef CHECK_V
#undef CHECK
//External feature functions
void SpineNewSkeletonDataResource::get_animation_names(Vector<String> &res) const {
res.clear();
if (!is_skeleton_data_loaded()) {
return;
}
auto as = skeleton_data->getAnimations();
for (size_t i = 0; i < as.size(); ++i) {
auto a = as[i];
if (a) {
res.push_back(a->getName().buffer());
} else {
res.push_back("");
}
}
}
void SpineNewSkeletonDataResource::get_skin_names(Vector<String> &res) const {
res.clear();
if (!is_skeleton_data_loaded()) return;
auto as = get_skins();
res.resize(as.size());
for (size_t i = 0; i < as.size(); ++i) {
auto a = Ref<SpineSkin>(as[i]);
if (a.is_valid()) {
res.set(i, a->get_skin_name());
} else {
res.set(i, "");
}
}
}
void SpineNewSkeletonDataResource::_get_property_list(List<PropertyInfo> *p_list) const {
PropertyInfo p;
Vector<String> res;
p.name = "animations";
p.type = Variant::STRING;
get_animation_names(res);
p.hint_string = String(",").join(res);
p.hint = PROPERTY_HINT_ENUM;
p_list->push_back(p);
p.name = "skins";
p.type = Variant::STRING;
get_skin_names(res);
p.hint_string = String(",").join(res);
p.hint = PROPERTY_HINT_ENUM;
p_list->push_back(p);
}

View File

@ -21,86 +21,92 @@ protected:
private:
Ref<SpineAtlasResource> atlas_res;
Ref<SpineSkeletonFileResource> skeleton_file_res;
bool valid;
bool spine_object;
spine::SkeletonData *skeleton_data;
spine::AnimationStateData *animation_state_data;
void update_skeleton_data();
void load_res(spine::Atlas *atlas, const String &json, const Vector<uint8_t> &binary);
public:
SpineNewSkeletonDataResource();
virtual ~SpineNewSkeletonDataResource();
inline void set_spine_object(spine::SkeletonData *s) {
skeleton_data = s;
if (s)
spine_object = true;
}
inline spine::SkeletonData *get_spine_object() {
return skeleton_data;
}
bool is_skeleton_data_loaded() const;
void load_res(spine::Atlas *atlas, const String &json, const Vector<uint8_t> &binary);
void _get_property_list(List<PropertyInfo> *p_list) const;
void set_atlas_res(const Ref<SpineAtlasResource> &a);
void set_atlas_res(const Ref<SpineAtlasResource> &atlas);
Ref<SpineAtlasResource> get_atlas_res();
void set_skeleton_file_res(const Ref<SpineSkeletonFileResource> &s);
void set_skeleton_file_res(const Ref<SpineSkeletonFileResource> &skeleton_file);
Ref<SpineSkeletonFileResource> get_skeleton_file_res();
inline spine::SkeletonData *get_skeleton_data() { return skeleton_data; }
bool is_skeleton_data_loaded() const;
inline spine::AnimationStateData *get_animation_state_data() { return animation_state_data; }
void get_animation_names(Vector<String> &animation_names) const;
void get_animation_names(Vector<String> &l) const;
void get_skin_names(Vector<String> &l) const;
Ref<SpineBoneData> find_bone(const String &bone_name);
void _get_property_list(List<PropertyInfo> *p_list) const;
Ref<SpineSlotData> find_slot(const String &slot_name);
// Spine API
Ref<SpineBoneData> find_bone(const String &bone_name) const;
Ref<SpineSkin> find_skin(const String &skin_name);
Ref<SpineSlotData> find_slot(const String &slot_name) const;
Ref<SpineEventData> find_event(const String &event_data_name);
Ref<SpineSkin> find_skin(const String &skin_name) const;
Ref<SpineAnimation> find_animation(const String &animation_name);
Ref<SpineEventData> find_event(const String &event_data_name) const;
Ref<SpineIkConstraintData> find_ik_constraint(const String &constraint_name);
Ref<SpineTransformConstraintData> find_transform_constraint(const String &constraint_name);
Ref<SpinePathConstraintData> find_path_constraint(const String &constraint_name);
Ref<SpineAnimation> find_animation(const String &animation_name) const;
Ref<SpineIkConstraintData> find_ik_constraint(const String &constraint_name) const;
Ref<SpineTransformConstraintData> find_transform_constraint(const String &constraint_name) const;
Ref<SpinePathConstraintData> find_path_constraint(const String &constraint_name) const;
String get_skeleton_name() const;
Array get_bones() const;
Array get_slots() const;
Array get_bones();
Array get_slots();
Array get_skins() const;
Ref<SpineSkin> get_default_skin();
void set_default_skin(Ref<SpineSkin> v);
Ref<SpineSkin> get_default_skin() const;
Array get_events();
Array get_animations();
Array get_ik_constraints();
Array get_transform_constraints();
Array get_path_constraints();
void set_default_skin(Ref<SpineSkin> skin);
String get_skeleton_name();
void set_skeleton_name(const String &v);
Array get_events() const;
float get_x();
void set_x(float v);
Array get_animations() const;
float get_y();
void set_y(float v);
Array get_ik_constraints() const;
float get_width();
float get_height();
Array get_transform_constraints() const;
String get_version();
Array get_path_constraints() const;
float get_fps();
void set_fps(float v);
float get_x() const;
float get_y() const;
float get_width() const;
float get_height() const;
String get_version() const;
String get_hash() const;
String get_images_path() const;
String get_audio_path() const;
float get_fps() const;
};

View File

@ -0,0 +1,629 @@
/******************************************************************************
* 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 "SpineNewSprite.h"
#include "SpineEvent.h"
#include "SpineTrackEntry.h"
#include "SpineNewSkeleton.h"
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("get_bind_slot_nodes"), &SpineNewSprite::get_bind_slot_nodes);
ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineNewSprite::set_bind_slot_nodes);
ClassDB::bind_method(D_METHOD("get_overlap"), &SpineNewSprite::get_overlap);
ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineNewSprite::set_overlap);
ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineNewSprite::bone_get_global_transform);
ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineNewSprite::bone_set_global_transform);
ClassDB::bind_method(D_METHOD("set_process_mode", "v"), &SpineNewSprite::set_process_mode);
ClassDB::bind_method(D_METHOD("get_process_mode"), &SpineNewSprite::get_process_mode);
ClassDB::bind_method(D_METHOD("update_all", "delta"), &SpineNewSprite::_update_all);
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")));
ADD_SIGNAL(MethodInfo("animation_end", 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_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_PROPERTY(PropertyInfo(Variant::OBJECT, "skeleton_data_res", PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "SpineNewSkeletonDataResource"), "set_skeleton_data_res", "get_skeleton_data_res");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "overlap"), "set_overlap", "get_overlap");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bind_slot_nodes"), "set_bind_slot_nodes", "get_bind_slot_nodes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Process,Physics,Manual"), "set_process_mode", "get_process_mode");
BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process);
BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics);
BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual);
}
SpineNewSprite::SpineNewSprite() : overlap(false),
skeleton_clipper(nullptr),
process_mode(ProcessMode_Process) {
skeleton_clipper = new spine::SkeletonClipping();
}
SpineNewSprite::~SpineNewSprite() {
delete skeleton_clipper;
}
void SpineNewSprite::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
set_process_internal(process_mode == ProcessMode_Process);
set_physics_process_internal(process_mode == ProcessMode_Physics);
remove_redundant_mesh_instances();
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
if (process_mode == ProcessMode_Process)
_update_all(get_process_delta_time());
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (process_mode == ProcessMode_Physics)
_update_all(get_physics_process_delta_time());
} break;
}
}
void SpineNewSprite::_update_all(float delta) {
if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty())
return;
animation_state->update(delta);
if (!is_visible_in_tree())
return;
animation_state->apply(skeleton);
skeleton->update_world_transform();
update_mesh_from_skeleton(skeleton);
update();
update_bind_slot_nodes();
}
void SpineNewSprite::update_bind_slot_nodes() {
if (animation_state.is_valid() && skeleton.is_valid()) {
for (size_t i = 0, n = bind_slot_nodes.size(); i < n; ++i) {
auto a = bind_slot_nodes[i];
if (a.get_type() == Variant::DICTIONARY) {
auto d = (Dictionary) a;
if (d.has("slot_name") && d.has("node_path")) {
NodePath node_path = d["node_path"];
Node *node = get_node_or_null(node_path);
if (node && node->is_class("Node2D")) {
Node2D *node2d = (Node2D *) node;
String slot_name = d["slot_name"];
auto slot = skeleton->find_slot(slot_name);
if (slot.is_valid()) {
auto bone = slot->get_bone();
if (bone.is_valid()) {
update_bind_slot_node_transform(bone, node2d);
update_bind_slot_node_draw_order(slot_name, node2d);
}
}
}
}
} else if (a.get_type() == Variant::ARRAY) {
auto as = (Array) a;// 0: slot_name, 1: node_path
if (as.size() >= 2 && as[0].get_type() == Variant::STRING && as[1].get_type() == Variant::NODE_PATH) {
NodePath node_path = as[1];
Node *node = get_node_or_null(node_path);
if (node && node->is_class("Node2D")) {
Node2D *node2d = (Node2D *) node;
String slot_name = as[0];
auto slot = skeleton->find_slot(slot_name);
if (slot.is_valid()) {
auto bone = slot->get_bone();
if (bone.is_valid()) {
update_bind_slot_node_transform(bone, node2d);
update_bind_slot_node_draw_order(slot_name, node2d);
}
}
}
}
}
}
}
}
void SpineNewSprite::update_bind_slot_node_transform(Ref<SpineBone> 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) {
auto pos = mesh_ins->get_index();
// get child
auto node = find_child_node_by_node(node2d);
if (node && node->get_index() != pos + 1) {
move_child(node, pos + 1);
}
}
}
Node *SpineNewSprite::find_child_node_by_node(Node *node) {
if (node == nullptr) return nullptr;
while (node && node->get_parent() != this) node = node->get_parent();
return node;
}
void SpineNewSprite::set_skeleton_data_res(const Ref<SpineNewSkeletonDataResource> &s) {
skeleton_data_res = s;
_on_animation_data_changed();
}
Ref<SpineNewSkeletonDataResource> SpineNewSprite::get_skeleton_data_res() {
return skeleton_data_res;
}
void SpineNewSprite::_on_animation_data_created() {
skeleton = Ref<SpineNewSkeleton>(memnew(SpineNewSkeleton));
skeleton->set_skeleton_data_res(skeleton_data_res);
skeleton->set_spine_sprite(this);
animation_state = Ref<SpineAnimationState>(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() {
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();
}
}
}
Ref<SpineSkeleton> SpineNewSprite::get_skeleton() {
return skeleton;
}
Ref<SpineAnimationState> SpineNewSprite::get_animation_state() {
return animation_state;
}
void SpineNewSprite::gen_mesh_from_skeleton(Ref<SpineSkeleton> s) {
auto sk = s->get_spine_object();
for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) {
auto mesh_ins = memnew(SpineSpriteMeshInstance2D);
add_child(mesh_ins);
mesh_ins->set_position(Vector2(0, 0));
mesh_ins->set_owner(this);
mesh_instances.push_back(mesh_ins);
spine::Slot *slot = sk->getDrawOrder()[i];
mesh_ins->set_name(slot->getData().getName().buffer());
Ref<SpineSlot> gd_slot(memnew(SpineSlot));
gd_slot->set_spine_object(slot);
mesh_ins->set_slot(gd_slot);
Ref<CanvasItemMaterial> mat(memnew(CanvasItemMaterial));
CanvasItemMaterial::BlendMode blend_mode;
switch (slot->getData().getBlendMode()) {
case spine::BlendMode_Normal:
blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
break;
case spine::BlendMode_Additive:
blend_mode = CanvasItemMaterial::BLEND_MODE_ADD;
break;
case spine::BlendMode_Multiply:
blend_mode = CanvasItemMaterial::BLEND_MODE_MUL;
break;
case spine::BlendMode_Screen:
blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
break;
default:
blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
}
mat->set_blend_mode(blend_mode);
mesh_ins->set_material(mat);
}
}
void SpineNewSprite::remove_mesh_instances() {
for (size_t i = 0; i < mesh_instances.size(); ++i) {
remove_child(mesh_instances[i]);
memdelete(mesh_instances[i]);
}
mesh_instances.clear();
}
void SpineNewSprite::remove_redundant_mesh_instances() {
Vector<Node *> ms;
// remove the redundant mesh instances that added by duplicating
for (size_t i = 0, n = get_child_count(); i < n; ++i) {
auto node = get_child(i);
if (node && node->is_class("SpineNewSpriteMeshInstance2D")) {
if (mesh_instances.find((SpineSpriteMeshInstance2D *) node) == -1) {
ms.push_back(node);
}
}
}
for (size_t i = 0, n = ms.size(); i < n; ++i) {
remove_child(ms[i]);
memdelete(ms[i]);
}
ms.clear();
}
#define TEMP_COPY(t, get_res) \
do { \
auto &temp_uvs = get_res; \
t.setSize(temp_uvs.size(), 0); \
for (size_t j = 0; j < t.size(); ++j) { \
t[j] = temp_uvs[j]; \
} \
} while (false);
void SpineNewSprite::update_mesh_from_skeleton(Ref<SpineSkeleton> s) {
static const unsigned short VERTEX_STRIDE = 2;
static unsigned short quad_indices[] = {0, 1, 2, 2, 3, 0};
auto sk = s->get_spine_object();
for (size_t i = 0, n = sk->getSlots().size(); i < n; ++i) {
spine::Vector<float> vertices;
spine::Vector<float> uvs;
spine::Vector<unsigned short> indices;
spine::Slot *slot = sk->getDrawOrder()[i];
spine::Attachment *attachment = slot->getAttachment();
if (!attachment) {
mesh_instances[i]->set_visible(false);
skeleton_clipper->clipEnd(*slot);
continue;
}
mesh_instances[i]->set_visible(true);
spine::Color skeleton_color = sk->getColor();
spine::Color slot_color = slot->getColor();
spine::Color tint(skeleton_color.r * slot_color.r, skeleton_color.g * slot_color.g, skeleton_color.b * slot_color.b, skeleton_color.a * slot_color.a);
Ref<Texture> tex;
Ref<Texture> normal_tex;
size_t v_num = 0;
if (attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) {
spine::RegionAttachment *region_attachment = (spine::RegionAttachment *) attachment;
auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) region_attachment->getRendererObject())->page->getRendererObject();
tex = p_spine_renderer_object->texture;
normal_tex = p_spine_renderer_object->normal_map;
v_num = 4;
vertices.setSize(v_num * VERTEX_STRIDE, 0);
region_attachment->computeWorldVertices(*slot, vertices, 0);
TEMP_COPY(uvs, region_attachment->getUVs());
indices.setSize(sizeof(quad_indices) / sizeof(unsigned short), 0);
for (size_t j = 0, qn = indices.size(); j < qn; ++j) {
indices[j] = quad_indices[j];
}
auto attachment_color = region_attachment->getColor();
tint.r *= attachment_color.r;
tint.g *= attachment_color.g;
tint.b *= attachment_color.b;
tint.a *= attachment_color.a;
} else if (attachment->getRTTI().isExactly(spine::MeshAttachment::rtti)) {
spine::MeshAttachment *mesh = (spine::MeshAttachment *) attachment;
auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) mesh->getRendererObject())->page->getRendererObject();
tex = p_spine_renderer_object->texture;
normal_tex = p_spine_renderer_object->normal_map;
v_num = mesh->getWorldVerticesLength() / VERTEX_STRIDE;
vertices.setSize(mesh->getWorldVerticesLength(), 0);
mesh->computeWorldVertices(*slot, vertices);
TEMP_COPY(uvs, mesh->getUVs());
TEMP_COPY(indices, mesh->getTriangles());
auto attachment_color = mesh->getColor();
tint.r *= attachment_color.r;
tint.g *= attachment_color.g;
tint.b *= attachment_color.b;
tint.a *= attachment_color.a;
} else if (attachment->getRTTI().isExactly(spine::ClippingAttachment::rtti)) {
auto clip = (spine::ClippingAttachment *) attachment;
skeleton_clipper->clipStart(*slot, clip);
continue;
} else {
skeleton_clipper->clipEnd(*slot);
continue;
}
auto mesh_ins = mesh_instances[i];
VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item());
if (skeleton_clipper->isClipping()) {
skeleton_clipper->clipTriangles(vertices, indices, uvs, VERTEX_STRIDE);
if (skeleton_clipper->getClippedTriangles().size() == 0) {
skeleton_clipper->clipEnd(*slot);
continue;
}
auto &clipped_vertices = skeleton_clipper->getClippedVertices();
v_num = clipped_vertices.size() / VERTEX_STRIDE;
auto &clipped_uvs = skeleton_clipper->getClippedUVs();
auto &clipped_indices = skeleton_clipper->getClippedTriangles();
if (indices.size() > 0) {
Vector<Vector2> p_points, p_uvs;
Vector<Color> p_colors;
Vector<int> p_indices;
p_points.resize(v_num);
p_uvs.resize(v_num);
p_colors.resize(v_num);
for (size_t j = 0; j < v_num; j++) {
p_points.set(j, Vector2(clipped_vertices[j * VERTEX_STRIDE], -clipped_vertices[j * VERTEX_STRIDE + 1]));
p_uvs.set(j, Vector2(clipped_uvs[j * VERTEX_STRIDE], clipped_uvs[j * VERTEX_STRIDE + 1]));
p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a));
}
p_indices.resize(clipped_indices.size());
for (size_t j = 0; j < clipped_indices.size(); ++j) {
p_indices.set(j, clipped_indices[j]);
}
VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(),
p_indices,
p_points,
p_colors,
p_uvs,
Vector<int>(),
Vector<float>(),
tex.is_null() ? RID() : tex->get_rid(),
-1,
normal_tex.is_null() ? RID() : normal_tex->get_rid());
}
} else {
if (indices.size() > 0) {
Vector<Vector2> p_points, p_uvs;
Vector<Color> p_colors;
Vector<int> p_indices;
p_points.resize(v_num);
p_uvs.resize(v_num);
p_colors.resize(v_num);
for (size_t j = 0; j < v_num; j++) {
p_points.set(j, Vector2(vertices[j * VERTEX_STRIDE], -vertices[j * VERTEX_STRIDE + 1]));
p_uvs.set(j, Vector2(uvs[j * VERTEX_STRIDE], uvs[j * VERTEX_STRIDE + 1]));
p_colors.set(j, Color(tint.r, tint.g, tint.b, tint.a));
}
p_indices.resize(indices.size());
for (size_t j = 0; j < indices.size(); ++j) {
p_indices.set(j, indices[j]);
}
VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(),
p_indices,
p_points,
p_colors,
p_uvs,
Vector<int>(),
Vector<float>(),
tex.is_null() ? RID() : tex->get_rid(),
-1,
normal_tex.is_null() ? RID() : normal_tex->get_rid());
}
}
skeleton_clipper->clipEnd(*slot);
if (mesh_ins->get_material()->is_class("CanvasItemMaterial")) {
Ref<CanvasItemMaterial> mat = mesh_ins->get_material();
CanvasItemMaterial::BlendMode blend_mode;
switch (slot->getData().getBlendMode()) {
case spine::BlendMode_Normal:
blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
break;
case spine::BlendMode_Additive:
blend_mode = CanvasItemMaterial::BLEND_MODE_ADD;
break;
case spine::BlendMode_Multiply:
blend_mode = CanvasItemMaterial::BLEND_MODE_MUL;
break;
case spine::BlendMode_Screen:
blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
break;
default:
blend_mode = CanvasItemMaterial::BLEND_MODE_MIX;
}
mat->set_blend_mode(blend_mode);
}
}
skeleton_clipper->clipEnd();
}
void SpineNewSprite::callback(spine::AnimationState *state, spine::EventType type, spine::TrackEntry *entry, spine::Event *event) {
Ref<SpineTrackEntry> gd_entry(nullptr);
Ref<SpineEvent> gd_event(nullptr);
if (entry) {
gd_entry = Ref<SpineTrackEntry>(memnew(SpineTrackEntry));
gd_entry->set_spine_object(entry);
}
if (event) {
gd_event = Ref<SpineEvent>(memnew(SpineEvent));
gd_event->set_spine_object(event);
}
switch (type) {
case spine::EventType_Start: {
emit_signal("animation_start", animation_state, gd_entry, gd_event);
} break;
case spine::EventType_Interrupt: {
emit_signal("animation_interrupt", animation_state, gd_entry, gd_event);
} break;
case spine::EventType_End: {
emit_signal("animation_end", animation_state, gd_entry, gd_event);
} break;
case spine::EventType_Complete: {
emit_signal("animation_complete", animation_state, gd_entry, gd_event);
} break;
case spine::EventType_Dispose: {
emit_signal("animation_dispose", animation_state, gd_entry, gd_event);
} break;
case spine::EventType_Event: {
emit_signal("animation_event", animation_state, gd_entry, gd_event);
} break;
}
}
Array SpineNewSprite::get_bind_slot_nodes() {
return bind_slot_nodes;
}
void SpineNewSprite::set_bind_slot_nodes(Array v) {
bind_slot_nodes = v;
}
bool SpineNewSprite::get_overlap() {
return overlap;
}
void SpineNewSprite::set_overlap(bool v) {
overlap = v;
}
Transform2D SpineNewSprite::bone_get_global_transform(const String &bone_name) {
if (!animation_state.is_valid() && !skeleton.is_valid()) {
return get_global_transform();
}
auto bone = skeleton->find_bone(bone_name);
if (!bone.is_valid()) {
print_error(vformat("Bone: '%s' not found.", bone_name));
return get_global_transform();
}
return bone->get_godot_global_transform();
}
void SpineNewSprite::bone_set_global_transform(const String &bone_name, Transform2D transform) {
if (!animation_state.is_valid() && !skeleton.is_valid()) {
return;
}
auto bone = skeleton->find_bone(bone_name);
if (!bone.is_valid()) {
return;
}
bone->set_godot_global_transform(transform);
}
SpineNewSprite::ProcessMode SpineNewSprite::get_process_mode() {
return process_mode;
}
void SpineNewSprite::set_process_mode(SpineNewSprite::ProcessMode v) {
process_mode = v;
set_process_internal(process_mode == ProcessMode_Process);
set_physics_process_internal(process_mode == ProcessMode_Physics);
}
void SpineNewSprite::_get_property_list(List<PropertyInfo> *p_list) const {
Vector<String> animations;
Vector<String> 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 SpineNewSprite::_get(const StringName &p_property, Variant &r_value) const {
return false;
}
bool SpineNewSprite::_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_data()->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_data()->find_skin(skinName).is_valid()) {
skeleton->set_skin_by_name(skinName);
} else {
skeleton->set_skin(nullptr);
}
skeleton->set_to_setup_pose();
}
}
return false;
}

View File

@ -0,0 +1,118 @@
/******************************************************************************
* 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_SPINENEWSPRITE_H
#define GODOT_SPINENEWSPRITE_H
#include <scene/resources/texture.h>
#include "SpineAnimationState.h"
#include "SpineAnimationStateDataResource.h"
#include "SpineNewSkeleton.h"
#include "SpineSpriteMeshInstance2D.h"
class SpineNewSprite : public Node2D, public spine::AnimationStateListenerObject {
GDCLASS(SpineNewSprite, Node2D);
protected:
static void _bind_methods();
void _notification(int p_what);
void _get_property_list(List<PropertyInfo> *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();
public:
enum ProcessMode {
ProcessMode_Process,
ProcessMode_Physics,
ProcessMode_Manual
};
private:
Ref<SpineNewSkeletonDataResource> skeleton_data_res;
Ref<SpineNewSkeleton> skeleton;
Ref<SpineAnimationState> animation_state;
String preview_animation;
Array bind_slot_nodes;
bool overlap;
ProcessMode process_mode;
Vector<SpineSpriteMeshInstance2D *> mesh_instances;
spine::SkeletonClipping *skeleton_clipper;
public:
SpineNewSprite();
~SpineNewSprite();
void set_skeleton_data_res(const Ref<SpineNewSkeletonDataResource> &a);
Ref<SpineNewSkeletonDataResource> get_skeleton_data_res();
Ref<SpineSkeleton> get_skeleton();
Ref<SpineAnimationState> get_animation_state();
void gen_mesh_from_skeleton(Ref<SpineSkeleton> s);
void remove_mesh_instances();
void remove_redundant_mesh_instances();
void update_mesh_from_skeleton(Ref<SpineSkeleton> s);
void update_bind_slot_nodes();
void update_bind_slot_node_transform(Ref<SpineBone> bone, Node2D *node2d);
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 _on_animation_data_created();
void _on_animation_data_changed();
void _update_all(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);
bool get_overlap();
void set_overlap(bool v);
ProcessMode get_process_mode();
void set_process_mode(ProcessMode v);
};
VARIANT_ENUM_CAST(SpineNewSprite::ProcessMode);
#endif//GODOT_SPINENEWSPRITE_H

View File

@ -196,7 +196,7 @@ void SpineSprite::_on_animation_data_created() {
skeleton->set_spine_sprite(this);
animation_state = Ref<SpineAnimationState>(memnew(SpineAnimationState));
animation_state->load_animation_state(animation_state_data_res);
animation_state->create_animation_state(animation_state_data_res->get_animation_state_data());
animation_state->get_spine_object()->setListener(this);
animation_state->update(0);