浏览代码

Merge branch '4.2-beta' of https://github.com/esotericsoftware/spine-runtimes into 4.2-beta

badlogic 3 年之前
父节点
当前提交
5e8ec2fab7
共有 70 个文件被更改,包括 1705 次插入1424 次删除
  1. 2 0
      .gitignore
  2. 1 0
      spine-godot/build.bat
  3. 5 0
      spine-godot/build.sh
  4. 12 1
      spine-godot/example/assets/spineboy/spinebody-data-res.tres
  5. 17 13
      spine-godot/example/examples/mix-and-match/mix-and-match.gd
  6. 1 1
      spine-godot/example/examples/mix-and-match/mix-and-match.tscn
  7. 1 1
      spine-godot/example/examples/simple-input/spineboy-simple-input.gd
  8. 1 1
      spine-godot/setup.bat
  9. 17 4
      spine-godot/setup.sh
  10. 5 4
      spine-godot/spine_godot/GodotSpineExtension.cpp
  11. 0 5
      spine-godot/spine_godot/GodotSpineExtension.h
  12. 9 2
      spine-godot/spine_godot/SCsub
  13. 2 5
      spine-godot/spine_godot/SpineAnimation.cpp
  14. 5 6
      spine-godot/spine_godot/SpineAnimation.h
  15. 1 6
      spine-godot/spine_godot/SpineAnimationState.cpp
  16. 8 9
      spine-godot/spine_godot/SpineAnimationState.h
  17. 41 18
      spine-godot/spine_godot/SpineAtlasResource.cpp
  18. 21 18
      spine-godot/spine_godot/SpineAtlasResource.h
  19. 1 1
      spine-godot/spine_godot/SpineAttachment.cpp
  20. 5 4
      spine-godot/spine_godot/SpineAttachment.h
  21. 4 7
      spine-godot/spine_godot/SpineBone.cpp
  22. 32 33
      spine-godot/spine_godot/SpineBone.h
  23. 7 10
      spine-godot/spine_godot/SpineBoneData.cpp
  24. 13 14
      spine-godot/spine_godot/SpineBoneData.h
  25. 3 4
      spine-godot/spine_godot/SpineCollisionShapeProxy.cpp
  26. 1 1
      spine-godot/spine_godot/SpineCollisionShapeProxy.h
  27. 21 1
      spine-godot/spine_godot/SpineCommon.h
  28. 16 0
      spine-godot/spine_godot/SpineConstant.cpp
  29. 33 5
      spine-godot/spine_godot/SpineConstant.h
  30. 1 4
      spine-godot/spine_godot/SpineConstraintData.cpp
  31. 8 12
      spine-godot/spine_godot/SpineConstraintData.h
  32. 53 25
      spine-godot/spine_godot/SpineEditorPlugin.cpp
  33. 39 15
      spine-godot/spine_godot/SpineEditorPlugin.h
  34. 1 5
      spine-godot/spine_godot/SpineEvent.cpp
  35. 9 10
      spine-godot/spine_godot/SpineEvent.h
  36. 1 4
      spine-godot/spine_godot/SpineEventData.cpp
  37. 8 9
      spine-godot/spine_godot/SpineEventData.h
  38. 2 5
      spine-godot/spine_godot/SpineIkConstraint.cpp
  39. 10 11
      spine-godot/spine_godot/SpineIkConstraint.h
  40. 1 5
      spine-godot/spine_godot/SpineIkConstraintData.cpp
  41. 8 11
      spine-godot/spine_godot/SpineIkConstraintData.h
  42. 49 32
      spine-godot/spine_godot/SpinePathConstraint.cpp
  43. 13 18
      spine-godot/spine_godot/SpinePathConstraint.h
  44. 70 66
      spine-godot/spine_godot/SpinePathConstraintData.cpp
  45. 18 31
      spine-godot/spine_godot/SpinePathConstraintData.h
  46. 163 143
      spine-godot/spine_godot/SpineSkeleton.cpp
  47. 38 20
      spine-godot/spine_godot/SpineSkeleton.h
  48. 118 123
      spine-godot/spine_godot/SpineSkeletonDataResource.cpp
  49. 3 4
      spine-godot/spine_godot/SpineSkeletonDataResource.h
  50. 46 33
      spine-godot/spine_godot/SpineSkeletonFileResource.cpp
  51. 24 12
      spine-godot/spine_godot/SpineSkeletonFileResource.h
  52. 116 75
      spine-godot/spine_godot/SpineSkin.cpp
  53. 38 17
      spine-godot/spine_godot/SpineSkin.h
  54. 0 93
      spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp
  55. 0 93
      spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h
  56. 74 47
      spine-godot/spine_godot/SpineSlot.cpp
  57. 17 16
      spine-godot/spine_godot/SpineSlot.h
  58. 40 33
      spine-godot/spine_godot/SpineSlotData.cpp
  59. 15 24
      spine-godot/spine_godot/SpineSlotData.h
  60. 74 35
      spine-godot/spine_godot/SpineSprite.cpp
  61. 5 7
      spine-godot/spine_godot/SpineSprite.h
  62. 26 24
      spine-godot/spine_godot/SpineTimeline.cpp
  63. 9 10
      spine-godot/spine_godot/SpineTimeline.h
  64. 128 61
      spine-godot/spine_godot/SpineTrackEntry.cpp
  65. 39 24
      spine-godot/spine_godot/SpineTrackEntry.h
  66. 51 27
      spine-godot/spine_godot/SpineTransformConstraint.cpp
  67. 14 13
      spine-godot/spine_godot/SpineTransformConstraint.h
  68. 59 35
      spine-godot/spine_godot/SpineTransformConstraintData.cpp
  69. 16 11
      spine-godot/spine_godot/SpineTransformConstraintData.h
  70. 16 7
      spine-godot/spine_godot/register_types.cpp

+ 2 - 0
.gitignore

@@ -170,3 +170,5 @@ spine-godot/spine_godot/spine-cpp
 spine-godot/spine_godot/__pycache__
 spine-godot/example/.import
 spine-godot/spine_godot/*.obj
+*.bc
+spine-godot/example/.godot

+ 1 - 0
spine-godot/build.bat

@@ -0,0 +1 @@
+cd godot & git apply ../livepp.patch & scons target=debug custom_modules=..\spine_godot vsproj=yes livepp=%LIVEPP% --jobs=16 & cd ..

+ 5 - 0
spine-godot/build.sh

@@ -0,0 +1,5 @@
+#/bin/sh
+set -e
+pushd godot
+scons compiledb=yes custom_modules="../spine_godot" -j16
+popd

+ 12 - 1
spine-godot/example/assets/spineboy/spinebody-data-res.tres

@@ -1,8 +1,19 @@
-[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=2]
+[gd_resource type="SpineSkeletonDataResource" load_steps=5 format=2]
 
 [ext_resource path="res://assets/spineboy/spineboy.atlas" type="SpineAtlasResource" id=1]
 [ext_resource path="res://assets/spineboy/spineboy-pro.json" type="SpineSkeletonFileResource" id=2]
 
+[sub_resource type="SpineAnimationMix" id=1]
+from = "idle"
+to = "run"
+mix = 0.2
+
+[sub_resource type="SpineAnimationMix" id=2]
+from = "run"
+to = "idle"
+mix = 0.2
+
 [resource]
 atlas_res = ExtResource( 1 )
 skeleton_file_res = ExtResource( 2 )
+animation_mixes = [ SubResource( 1 ), SubResource( 2 ) ]

+ 17 - 13
spine-godot/example/examples/mix-and-match/mix-and-match.gd

@@ -2,17 +2,21 @@ extends SpineSprite
 
 func _ready():
 	var data = get_skeleton().get_data()
-	var customSkin = SpineSkin.new().init("custom-skin")
-	var skinBase = data.find_skin("skin-base")
-	customSkin.add_skin(skinBase)
-	customSkin.add_skin(data.find_skin("nose/short"))
-	customSkin.add_skin(data.find_skin("eyelids/girly"))
-	customSkin.add_skin(data.find_skin("eyes/violet"))
-	customSkin.add_skin(data.find_skin("hair/brown"))
-	customSkin.add_skin(data.find_skin("clothes/hoodie-orange"))
-	customSkin.add_skin(data.find_skin("legs/pants-jeans"))
-	customSkin.add_skin(data.find_skin("accessories/bag"))
-	customSkin.add_skin(data.find_skin("accessories/hat-red-yellow"))
-	get_skeleton().set_skin(customSkin);
-		
+	var custom_skin = SpineSkin.new().init("custom-skin")
+	var skin_base = data.find_skin("skin-base")
+	custom_skin.add_skin(skin_base)
+	custom_skin.add_skin(data.find_skin("nose/short"))
+	custom_skin.add_skin(data.find_skin("eyelids/girly"))
+	custom_skin.add_skin(data.find_skin("eyes/violet"))
+	custom_skin.add_skin(data.find_skin("hair/brown"))
+	custom_skin.add_skin(data.find_skin("clothes/hoodie-orange"))
+	custom_skin.add_skin(data.find_skin("legs/pants-jeans"))
+	custom_skin.add_skin(data.find_skin("accessories/bag"))
+	custom_skin.add_skin(data.find_skin("accessories/hat-red-yellow"))
+	get_skeleton().set_skin(custom_skin);
+
+	for el in custom_skin.get_attachments():
+		var entry: SpineSkinEntry = el
+		print(str(entry.get_slot_index()) + " " + entry.get_name())
+
 	get_animation_state().set_animation("dance", true, 0)

+ 1 - 1
spine-godot/example/examples/mix-and-match/mix-and-match.tscn

@@ -6,7 +6,7 @@
 [node name="Node2D" type="Node2D"]
 
 [node name="MixAndMatch" type="SpineSprite" parent="."]
-position = Vector2( 775.779, 516.856 )
+position = Vector2( 532.982, 480.287 )
 scale = Vector2( 0.441932, 0.441932 )
 skeleton_data_res = ExtResource( 1 )
 script = ExtResource( 2 )

+ 1 - 1
spine-godot/example/examples/simple-input/spineboy-simple-input.gd

@@ -3,7 +3,7 @@ extends SpineSprite
 func _ready():	
 	get_animation_state().set_animation("idle", true, 0)
 
-func _process(delta):
+func _process(_delta):
 	if Input.is_action_just_pressed("ui_left"):
 		get_animation_state().set_animation("run", true, 0)
 		get_skeleton().set_scale_x(-1)

+ 1 - 1
spine-godot/setup.bat

@@ -4,4 +4,4 @@ xcopy /E /I .idea godot\.idea
 copy custom.py godot
 rmdir spine_godot\spine-cpp /s /q
 xcopy /E /I ..\spine-cpp\spine-cpp spine_godot\spine-cpp
-cd godot & git apply ../livepp.patch & scons target=debug custom_modules=..\spine_godot vsproj=yes livepp=%LIVEPP% --jobs=16 & cd ..
+build.bat

+ 17 - 4
spine-godot/setup.sh

@@ -1,10 +1,23 @@
 #!/bin/bash
 set -e
+
+if [ "$#" -eq 0 ]; then
+	echo "Usage: ./setup.sh <godot_branch_or_tag>"
+	echo
+	echo "e.g.:"
+	echo "       ./setup.sh 3.4.4-stable"
+	echo "       ./setup.sh master"
+	read version
+	exit 1
+fi
+
+branch=${1%/}
+
 rm -rf godot
-git clone --depth 1 https://github.com/godotengine/godot.git -b 3.4.4-stable
+git clone --depth 1 https://github.com/godotengine/godot.git -b $branch
 cp -r .idea godot
 cp custom.py godot
 cp -r ../spine-cpp/spine-cpp spine_godot
-pushd godot
-scons compiledb=yes custom_modules="../spine_godot" -j16
-popd
+rm -rf example/.import
+rm -rf example/.godot
+./build.sh

+ 5 - 4
spine-godot/spine_godot/GodotSpineExtension.cpp

@@ -29,17 +29,18 @@
 
 #include "GodotSpineExtension.h"
 #include "core/os/memory.h"
+#include "core/version.h"
+#if VERSION_MAJOR > 3
+#include "core/io/file_access.h"
+#else
 #include "core/os/file_access.h"
-
+#endif
 #include <spine/SpineString.h>
 
 spine::SpineExtension *spine::getDefaultExtension() {
 	return new GodotSpineExtension();
 }
 
-GodotSpineExtension::GodotSpineExtension() {}
-GodotSpineExtension::~GodotSpineExtension() {}
-
 void *GodotSpineExtension::_alloc(size_t size, const char *file, int line) {
 	return memalloc(size);
 }

+ 0 - 5
spine-godot/spine_godot/GodotSpineExtension.h

@@ -33,11 +33,6 @@
 #include <spine/Extension.h>
 
 class GodotSpineExtension : public spine::SpineExtension {
-public:
-	GodotSpineExtension();
-
-	virtual ~GodotSpineExtension();
-
 protected:
 	virtual void *_alloc(size_t size, const char *file, int line);
 

+ 9 - 2
spine-godot/spine_godot/SCsub

@@ -1,8 +1,15 @@
 Import('env')
 
-env_spine_runtime = env.Clone()
 # Need to add the include path to env so the vsproj generator consumes it.
-env.Append(CPPPATH=["#../spine_godot/spine-cpp/include"])
+if env["vsproj"]:
+    env.Append(CPPPATH=["#../spine_godot/spine-cpp/include"])
+
+env_spine_runtime = env.Clone()
 env_spine_runtime.Append(CPPPATH=["#../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")
+
+# Needed on Clang to not have a gazillion -Winconsistent-missing-override warnings for GDCLASS
+# I do not understand why other modules using GDCLASS do not have this issue when compiling.
+if not env_spine_runtime.msvc:
+    env_spine_runtime.Append(CXXFLAGS=["-Wno-inconsistent-missing-override"])

+ 2 - 5
spine-godot/spine_godot/SpineAnimation.cpp

@@ -27,13 +27,13 @@
  * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-#include "common.h"
 #include "SpineAnimation.h"
 #include "SpineSkeleton.h"
 #include "SpineEvent.h"
 #include "SpineTimeline.h"
-
+#if VERSION_MAJOR == 3
 #include "core/method_bind_ext.gen.inc"
+#endif
 
 void SpineAnimation::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_name"), &SpineAnimation::get_name);
@@ -48,9 +48,6 @@ void SpineAnimation::_bind_methods() {
 SpineAnimation::SpineAnimation() : animation(nullptr) {
 }
 
-SpineAnimation::~SpineAnimation() {
-}
-
 String SpineAnimation::get_name() {
 	SPINE_CHECK(animation, "")
 	return animation->getName().buffer();

+ 5 - 6
spine-godot/spine_godot/SpineAnimation.h

@@ -30,16 +30,16 @@
 #ifndef GODOT_SPINEANIMATION_H
 #define GODOT_SPINEANIMATION_H
 
+#include "SpineCommon.h"
 #include "SpineConstant.h"
-#include "core/reference.h"
 #include <spine/Animation.h>
 
 class SpineEvent;
 class SpineSkeleton;
 class SpineTimeline;
 
-class SpineAnimation : public Reference {
-	GDCLASS(SpineAnimation, Reference);
+class SpineAnimation : public REFCOUNTED {
+	GDCLASS(SpineAnimation, REFCOUNTED);
 
 private:
 	spine::Animation *animation;
@@ -49,10 +49,9 @@ protected:
 
 public:
 	SpineAnimation();
-	~SpineAnimation();
 
-	void set_spine_object(spine::Animation *animation) { this->animation = animation; }
-	
+	void set_spine_object(spine::Animation *_animation) { this->animation = _animation; }
+
 	spine::Animation *get_spine_object() { return animation; }
 
 	void apply(Ref<SpineSkeleton> skeleton, float last_time, float time, bool loop, Array events, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction);

+ 1 - 6
spine-godot/spine_godot/SpineAnimationState.cpp

@@ -27,7 +27,6 @@
  * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-#include "common.h"
 #include "SpineAnimationState.h"
 
 void SpineAnimationState::_bind_methods() {
@@ -54,7 +53,7 @@ SpineAnimationState::~SpineAnimationState() {
 	delete animation_state;
 }
 
-void SpineAnimationState::set_skeleton_data_res(Ref<SpineSkeletonDataResource> data_res) {
+void SpineAnimationState::set_skeleton_data_res(const Ref<SpineSkeletonDataResource> &data_res) {
 	delete animation_state;
 	animation_state = nullptr;
 	skeleton_data_res = data_res;
@@ -62,10 +61,6 @@ void SpineAnimationState::set_skeleton_data_res(Ref<SpineSkeletonDataResource> d
 	animation_state = new spine::AnimationState(skeleton_data_res->get_animation_state_data());
 }
 
-Ref<SpineSkeletonDataResource> SpineAnimationState::get_skeleton_data_res() const {
-	return skeleton_data_res;
-}
-
 void SpineAnimationState::update(float delta) {
 	SPINE_CHECK(animation_state,)
 	animation_state->update(delta);

+ 8 - 9
spine-godot/spine_godot/SpineAnimationState.h

@@ -30,11 +30,12 @@
 #ifndef GODOT_SPINEANIMATIONSTATE_H
 #define GODOT_SPINEANIMATIONSTATE_H
 
+#include "SpineCommon.h"
 #include "SpineSkeleton.h"
 #include "SpineTrackEntry.h"
 
-class SpineAnimationState : public Reference {
-	GDCLASS(SpineAnimationState, Reference)
+class SpineAnimationState : public REFCOUNTED {
+	GDCLASS(SpineAnimationState, REFCOUNTED)
 
 protected:
 	static void _bind_methods();
@@ -46,12 +47,10 @@ private:
 public:
 	SpineAnimationState();
 	~SpineAnimationState();
-	
+
 	spine::AnimationState *get_spine_object() { return animation_state; }
 
-	void set_skeleton_data_res(Ref<SpineSkeletonDataResource> skeleton_data_res);
-	
-	Ref<SpineSkeletonDataResource> get_skeleton_data_res() const;
+	void set_skeleton_data_res(const Ref<SpineSkeletonDataResource> &skeleton_data_res);
 
 	void update(float delta);
 
@@ -68,17 +67,17 @@ public:
 	Ref<SpineTrackEntry> set_empty_animation(uint64_t track_id, float mix_duration);
 
 	Ref<SpineTrackEntry> add_empty_animation(uint64_t track_id, float mix_duration, float delay);
-	
+
 	void set_empty_animations(float mix_duration);
 
 	Ref<SpineTrackEntry> get_current(uint64_t track_index);
 
 	float get_time_scale();
-	
+
 	void set_time_scale(float time_scale);
 
 	void disable_queue();
-	
+
 	void enable_queue();
 };
 

+ 41 - 18
spine-godot/spine_godot/SpineAtlasResource.cpp

@@ -27,11 +27,10 @@
  * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-#include "core/io/json.h"
-#include "scene/resources/texture.h"
-
 #include "SpineAtlasResource.h"
 #include "SpineRendererObject.h"
+#include "core/io/json.h"
+#include "scene/resources/texture.h"
 #include <spine/TextureLoader.h>
 
 class GodotSpineTextureLoader : public spine::TextureLoader {
@@ -44,7 +43,7 @@ public:
 	GodotSpineTextureLoader(Array *_textures, Array *_normal_maps, const String &normal_map_prefix) : textures(_textures), normal_maps(_normal_maps), normal_map_prefix(normal_map_prefix) {
 	}
 
-	String fix_path(const String &path) {
+	static String fix_path(const String &path) {
 		if (path.size() > 5 && path[4] == '/' && path[5] == '/') return path;
 		const String prefix = "res:/";
 		auto i = path.find(prefix);
@@ -52,7 +51,7 @@ public:
 		if (sub_str_pos < 0) return path;
 		auto res = path.substr(sub_str_pos);
 
-		if (res.size() > 0) {
+		if (!EMPTY(res)) {
 			if (res[0] != '/') {
 				return prefix + "/" + res;
 			} else {
@@ -62,12 +61,16 @@ public:
 		return path;
 	}
 
-	virtual void load(spine::AtlasPage &page, const spine::String &path) {
+	void load(spine::AtlasPage &page, const spine::String &path) override {
 		Error error = OK;
 		auto fixed_path = fix_path(String(path.buffer()));
 
+#if VERSION_MAJOR > 3
+		Ref<Texture2D> texture = ResourceLoader::load(fixed_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error);
+#else
 		Ref<Texture> texture = ResourceLoader::load(fixed_path, "", false, &error);
-		if (error != OK) {
+#endif
+		if (error != OK || !texture.is_valid()) {
 			ERR_PRINT(vformat("Can't load texture: \"%s\"", String(path.buffer())));
 			auto renderer_object = memnew(SpineRendererObject);
 			renderer_object->texture = Ref<Texture>(nullptr);
@@ -81,20 +84,19 @@ public:
 		renderer_object->texture = texture;
 		renderer_object->normal_map = Ref<Texture>(nullptr);
 
-		String temp_path = fixed_path;
-		String new_path = vformat("%s/%s_%s", temp_path.get_base_dir(), normal_map_prefix, temp_path.get_file());
+		String new_path = vformat("%s/%s_%s", fixed_path.get_base_dir(), normal_map_prefix, fixed_path.get_file());
 		if (ResourceLoader::exists(new_path)) {
 			Ref<Texture> normal_map = ResourceLoader::load(new_path);
 			normal_maps->append(normal_map);
 			renderer_object->normal_map = normal_map;
 		}
-		
+
 		page.setRendererObject((void *) renderer_object);
 		page.width = texture->get_width();
 		page.height = texture->get_height();
 	}
 
-	virtual void unload(void *data) {
+	void unload(void *data) override {
 		auto renderer_object = (SpineRendererObject *) data;
 		Ref<Texture> &texture = renderer_object->texture;
 		if (texture.is_valid()) texture.unref();
@@ -160,16 +162,22 @@ Error SpineAtlasResource::load_from_atlas_file(const String &path) {
 }
 
 Error SpineAtlasResource::load_from_file(const String &path) {
-	Error err;
-	String json_string = FileAccess::get_file_as_string(path, &err);
-	if (err != OK) return err;
+	Error error;
+	String json_string = FileAccess::get_file_as_string(path, &error);
+	if (error != OK) return error;
 
+#if VERSION_MAJOR > 3
+	JSON json;
+	error = json.parse(json_string);
+	if (error != OK) return error;
+	Variant result = json.get_data();
+#else
 	String error_string;
 	int error_line;
-	JSON json;
 	Variant result;
-	err = json.parse(json_string, result, error_string, error_line);
-	if (err != OK) return err;
+	error = JSON::parse(json_string, result, error_string, error_line);
+	if (error != OK) return error;
+#endif
 
 	Dictionary content = Dictionary(result);
 	source_path = content["source_path"];
@@ -187,22 +195,37 @@ Error SpineAtlasResource::load_from_file(const String &path) {
 
 Error SpineAtlasResource::save_to_file(const String &path) {
 	Error err;
+#if VERSION_MAJOR > 3
+	Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err);
+	if (err != OK) return err;
+#else
 	FileAccess *file = FileAccess::open(path, FileAccess::WRITE, &err);
 	if (err != OK) {
 		if (file) file->close();
 		return err;
 	}
+#endif
 
 	Dictionary content;
 	content["source_path"] = source_path;
 	content["atlas_data"] = atlas_data;
 	content["normal_texture_prefix"] = normal_map_prefix;
+#if VERSION_MAJOR > 3
+	JSON json;
+	file->store_string(json.stringify(content));
+	file->flush();
+#else
 	file->store_string(JSON::print(content));
 	file->close();
+#endif
 	return OK;
 }
 
+#if VERSION_MAJOR > 3
+RES SpineAtlasResourceFormatLoader::load(const String &path, const String &original_path, Error *error, bool use_sub_threads, float *progress, CacheMode cache_mode) {
+#else
 RES SpineAtlasResourceFormatLoader::load(const String &path, const String &original_path, Error *error) {
+#endif
 	Ref<SpineAtlasResource> atlas = memnew(SpineAtlasResource);
 	atlas->load_from_file(path);
 	if (error) *error = OK;
@@ -224,7 +247,7 @@ bool SpineAtlasResourceFormatLoader::handles_type(const String &type) const {
 }
 
 Error SpineAtlasResourceFormatSaver::save(const String &path, const RES &resource, uint32_t flags) {
-	Ref<SpineAtlasResource> res = resource.get_ref_ptr();
+	Ref<SpineAtlasResource> res = resource;
 	return res->save_to_file(path);
 }
 

+ 21 - 18
spine-godot/spine_godot/SpineAtlasResource.h

@@ -30,18 +30,20 @@
 #ifndef GODOT_SPINEATLASRESOURCE_H
 #define GODOT_SPINEATLASRESOURCE_H
 
+#include "SpineCommon.h"
 #include "core/io/resource_loader.h"
 #include "core/io/resource_saver.h"
 #include "core/io/image_loader.h"
 #include <spine/Atlas.h>
 
+
 class GodotSpineTextureLoader;
 
 class SpineAtlasResource : public Resource {
 	GDCLASS(SpineAtlasResource, Resource)
 
 	void clear();
-	
+
 protected:
 	static void _bind_methods();
 
@@ -57,10 +59,7 @@ protected:
 
 public:
 	SpineAtlasResource();
-	
-	virtual ~SpineAtlasResource();
-	
-	String &get_atlas_data() { return atlas_data; }
+	~SpineAtlasResource() override;
 
 	spine::Atlas *get_spine_atlas() { return atlas; }
 
@@ -69,13 +68,13 @@ public:
 	Error load_from_atlas_file(const String &path);// .atlas
 
 	Error load_from_file(const String &path); // .spatlas
-	
+
 	Error save_to_file(const String &path);  // .spatlas
 
 	String get_source_path();
-	
+
 	Array get_textures();
-	
+
 	Array get_normal_maps();
 };
 
@@ -83,23 +82,27 @@ class SpineAtlasResourceFormatLoader : public ResourceFormatLoader {
 	GDCLASS(SpineAtlasResourceFormatLoader, ResourceFormatLoader)
 
 public:
-	virtual RES load(const String &path, const String &original_path, Error *error = nullptr);
-	
-	virtual void get_recognized_extensions(List<String> *extensions) const;
-	
-	virtual bool handles_type(const String &type) const;
-	
-	virtual String get_resource_type(const String &path) const;
+#if VERSION_MAJOR > 3
+	RES load(const String &path, const String &original_path, Error *error, bool use_sub_threads, float *progress, CacheMode cache_mode) override;
+#else
+	RES load(const String &path, const String &original_path, Error *error) override;
+#endif
+
+	void get_recognized_extensions(List<String> *extensions) const override;
+
+	bool handles_type(const String &type) const override;
+
+	String get_resource_type(const String &path) const override;
 };
 
 class SpineAtlasResourceFormatSaver : public ResourceFormatSaver {
 	GDCLASS(SpineAtlasResourceFormatSaver, ResourceFormatSaver)
 
 public:
-	Error save(const String &path, const RES &resource, uint32_t flags = 0) override;
-	
+	Error save(const String &path, const RES &resource, uint32_t flags) override;
+
 	void get_recognized_extensions(const RES &resource, List<String> *extensions) const override;
-	
+
 	bool recognize(const RES &resource) const override;
 };
 

+ 1 - 1
spine-godot/spine_godot/SpineAttachment.cpp

@@ -28,7 +28,7 @@
  *****************************************************************************/
 
 #include "SpineAttachment.h"
-#include "common.h"
+#include "SpineCommon.h"
 
 void SpineAttachment::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineAttachment::get_attachment_name);

+ 5 - 4
spine-godot/spine_godot/SpineAttachment.h

@@ -30,11 +30,12 @@
 #ifndef GODOT_SPINEATTACHMENT_H
 #define GODOT_SPINEATTACHMENT_H
 
+#include "SpineCommon.h"
 #include <spine/spine.h>
-#include "core/reference.h"
 
-class SpineAttachment : public Reference {
-	GDCLASS(SpineAttachment, Reference)
+
+class SpineAttachment : public REFCOUNTED {
+	GDCLASS(SpineAttachment, REFCOUNTED)
 
 protected:
 	static void _bind_methods();
@@ -44,7 +45,7 @@ private:
 
 public:
 	SpineAttachment();
-	~SpineAttachment();
+	~SpineAttachment() override;
 
 	void set_spine_object(spine::Attachment *_attachment) {
 		attachment = _attachment;

+ 4 - 7
spine-godot/spine_godot/SpineBone.cpp

@@ -30,7 +30,7 @@
 #include "SpineBone.h"
 #include "SpineSprite.h"
 #include "SpineSkeleton.h"
-#include "common.h"
+#include "SpineCommon.h"
 
 void SpineBone::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineBone::update_world_transform);
@@ -101,8 +101,6 @@ void SpineBone::_bind_methods() {
 
 SpineBone::SpineBone() : bone(nullptr), sprite(nullptr) {}
 
-SpineBone::~SpineBone() {}
-
 void SpineBone::set_spine_sprite(SpineSprite* _sprite) {
 	this->sprite = _sprite;
 }
@@ -429,12 +427,11 @@ void SpineBone::set_active(bool v) {
 }
 
 // External feature functions
-void SpineBone::apply_world_transform_2d(Variant o) {
+void SpineBone::apply_world_transform_2d(const Variant &o) {
 	SPINE_CHECK(bone,)
 	if (o.get_type() == Variant::OBJECT) {
-		auto node = (Node *) o;
-		if (node->is_class("Node2D")) {
-			auto node2d = (Node2D *) node;
+		auto node2d = Object::cast_to<Node2D>(o.operator Object*());
+		if (node2d) {			
 			// In godot the y-axis is nag to spine
 			node2d->set_transform(Transform2D(
 					get_a(), get_c(),

+ 32 - 33
spine-godot/spine_godot/SpineBone.h

@@ -30,16 +30,16 @@
 #ifndef GODOT_SPINEBONE_H
 #define GODOT_SPINEBONE_H
 
-#include <scene/2d/node_2d.h>
-#include <spine/spine.h>
-
+#include "SpineCommon.h"
 #include "SpineBoneData.h"
+#include "scene/2d/node_2d.h"
+#include <spine/Bone.h>
 
 class SpineSkeleton;
 class SpineSprite;
 
-class SpineBone : public Reference {
-	GDCLASS(SpineBone, Reference)
+class SpineBone : public REFCOUNTED {
+	GDCLASS(SpineBone, REFCOUNTED)
 
 protected:
 	static void _bind_methods();
@@ -50,7 +50,6 @@ private:
 
 public:
 	SpineBone();
-	~SpineBone();
 
 	void set_spine_object(spine::Bone *_bone) { bone = _bone; }
 
@@ -73,7 +72,7 @@ public:
 	void rotate_world(float degrees);
 
 	float get_world_to_local_rotation_x();
-	
+
 	float get_world_to_local_rotation_y();
 
 	Ref<SpineBoneData> get_data();
@@ -85,106 +84,106 @@ public:
 	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);
+	void apply_world_transform_2d(const Variant &o);
 
 	Transform2D get_godot_transform();
-	
+
 	void set_godot_transform(Transform2D trans);
 
 	Transform2D get_godot_global_transform();
-	
+
 	void set_godot_global_transform(Transform2D trans);
 };
 

+ 7 - 10
spine-godot/spine_godot/SpineBoneData.cpp

@@ -28,7 +28,7 @@
  *****************************************************************************/
 
 #include "SpineBoneData.h"
-#include "common.h"
+#include "SpineCommon.h"
 
 void SpineBoneData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_index"), &SpineBoneData::get_index);
@@ -61,9 +61,6 @@ void SpineBoneData::_bind_methods() {
 SpineBoneData::SpineBoneData() : bone_data(nullptr) {
 }
 
-SpineBoneData::~SpineBoneData() {
-}
-
 int SpineBoneData::get_index() {
 	SPINE_CHECK(bone_data, 0)
 	return bone_data->getIndex();
@@ -76,11 +73,11 @@ String SpineBoneData::get_bone_name() {
 
 Ref<SpineBoneData> SpineBoneData::get_parent() {
 	SPINE_CHECK(bone_data, nullptr)
-	auto p = bone_data->getParent();
-	if (p == nullptr) return nullptr;
-	Ref<SpineBoneData> gd_bone_data(memnew(SpineBoneData));
-	gd_bone_data->set_spine_object(p);
-	return gd_bone_data;
+	auto parent = bone_data->getParent();
+	if (!parent) return nullptr;
+	Ref<SpineBoneData> parent_ref(memnew(SpineBoneData));
+	parent_ref->set_spine_object(parent);
+	return parent_ref;
 }
 
 float SpineBoneData::get_length() {
@@ -192,4 +189,4 @@ Color SpineBoneData::get_color() {
 void SpineBoneData::set_color(Color color) {
 	SPINE_CHECK(bone_data,)
 	bone_data->getColor().set(color.r, color.g, color.b, color.a);
-}
+}

+ 13 - 14
spine-godot/spine_godot/SpineBoneData.h

@@ -30,12 +30,12 @@
 #ifndef GODOT_SPINEBONEDATA_H
 #define GODOT_SPINEBONEDATA_H
 
-#include "core/reference.h"
+#include "SpineCommon.h"
 #include "SpineConstant.h"
 #include <spine/BoneData.h>
 
-class SpineBoneData : public Reference {
-	GDCLASS(SpineBoneData, Reference);
+class SpineBoneData : public REFCOUNTED {
+	GDCLASS(SpineBoneData, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -45,7 +45,6 @@ private:
 
 public:
 	SpineBoneData();
-	~SpineBoneData();
 
 	void set_spine_object(spine::BoneData *_bone_data) { bone_data = _bone_data; }
 
@@ -58,43 +57,43 @@ public:
 	Ref<SpineBoneData> get_parent();
 
 	float get_length();
-	
+
 	void set_length(float v);
 
 	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);
 
 	SpineConstant::TransformMode get_transform_mode();
-	
+
 	void set_transform_mode(SpineConstant::TransformMode v);
 
 	bool is_skin_required();
-	
+
 	void set_skin_required(bool v);
 
 	Color get_color();

+ 3 - 4
spine-godot/spine_godot/SpineCollisionShapeProxy.cpp

@@ -28,7 +28,6 @@
  *****************************************************************************/
 
 #include "SpineCollisionShapeProxy.h"
-
 #include "SpineSprite.h"
 
 void SpineCollisionShapeProxy::_bind_methods() {
@@ -100,7 +99,7 @@ void SpineCollisionShapeProxy::set_slot(const String &slotName) {
 
 spine::Slot *SpineCollisionShapeProxy::get_spine_slot(const String &slotName) const {
 	auto sprite = get_spine_sprite();
-	if (sprite == NULL || slot_name.empty()) return NULL;
+	if (sprite == NULL || EMPTY(slot_name)) return NULL;
 	if (!sprite->get_skeleton().is_valid()) return NULL;
 	spine::Skeleton *skeleton = sprite->get_skeleton()->get_spine_object();
 	spine::Slot *slot = skeleton->findSlot(spine::String(slot_name.utf8()));
@@ -156,7 +155,7 @@ void SpineCollisionShapeProxy::_get_property_list(List<PropertyInfo> *p_list) co
 	p.name = "Slot";
 	p.type = Variant::STRING;
 	get_slot_names(slot_names);
-	if (slot_names.empty())
+	if (EMPTY(slot_names))
 		slot_names.push_back("None");
 	p.hint_string = String(",").join(slot_names);
 	p.hint = PROPERTY_HINT_ENUM;
@@ -189,6 +188,6 @@ void SpineCollisionShapeProxy::get_slot_names(Vector<String> &slot_names) const
 	for (size_t i = 0; i < slots.size(); ++i) {
 		auto slot = (Ref<SpineSlot>) slots[i];
 		if (slot.is_valid())
-			slot_names.set(i, slot->get_data()->get_slot_name());
+			slot_names.set(i, slot->get_data()->get_name());
 	}
 }

+ 1 - 1
spine-godot/spine_godot/SpineCollisionShapeProxy.h

@@ -31,7 +31,7 @@
 #define GODOT_SPINECOLLISIONSHAPEPROXY_H
 
 #include "scene/2d/collision_polygon_2d.h"
-#include <spine/spine.h>
+#include <spine/Slot.h>
 
 class SpineSprite;
 class SpineAnimationState;

+ 21 - 1
spine-godot/spine_godot/common.h → spine-godot/spine_godot/SpineCommon.h

@@ -30,7 +30,25 @@
 #ifndef SPINE_COMMON_H
 #define SPINE_COMMON_H
 
+#include "core/version.h"
+#if VERSION_MAJOR > 3
+#include "core/core_bind.h"
+#include "core/error/error_macros.h"
+#define REFCOUNTED RefCounted
+#define EMPTY(x) ((x).is_empty())
+#define EMPTY_PTR(x) ((x)->is_empty())
+#define INSTANTIATE(x) (x).instantiate()
+#define NOTIFY_PROPERTY_LIST_CHANGED() notify_property_list_changed()
+#else
+#include "core/object.h"
+#include "core/reference.h"
 #include "core/error_macros.h"
+#define REFCOUNTED Reference
+#define EMPTY(x) ((x).empty())
+#define EMPTY_PTR(x) ((x)->empty())
+#define INSTANTIATE(x) (x).instance()
+#define NOTIFY_PROPERTY_LIST_CHANGED() property_list_changed_notify()
+#endif
 
 #define SPINE_CHECK(obj, ret) \
  if (!(obj)) { \
@@ -38,4 +56,6 @@
   return ret; \
  }
 
-#endif
+#define SPINE_STRING(x) spine::String((x).utf8())
+
+#endif

+ 16 - 0
spine-godot/spine_godot/SpineConstant.cpp

@@ -64,4 +64,20 @@ void SpineConstant::_bind_methods() {
 	BIND_ENUM_CONSTANT(TransformMode_NoRotationOrReflection)
 	BIND_ENUM_CONSTANT(TransformMode_NoScale)
 	BIND_ENUM_CONSTANT(TransformMode_NoScaleOrReflection)
+
+	BIND_ENUM_CONSTANT(PositionMode_Fixed)
+	BIND_ENUM_CONSTANT(PositionMode_Percent)
+
+	BIND_ENUM_CONSTANT(SpacingMode_Length)
+	BIND_ENUM_CONSTANT(SpacingMode_Fixed)
+	BIND_ENUM_CONSTANT(SpacingMode_Percent)
+
+	BIND_ENUM_CONSTANT(RotateMode_Tangent)
+	BIND_ENUM_CONSTANT(RotateMode_Chain)
+	BIND_ENUM_CONSTANT(RotateMode_ChainScale)
+
+	BIND_ENUM_CONSTANT(BlendMode_Normal)
+	BIND_ENUM_CONSTANT(BlendMode_Additive)
+	BIND_ENUM_CONSTANT(BlendMode_Multiply)
+	BIND_ENUM_CONSTANT(BlendMode_Screen)
 }

+ 33 - 5
spine-godot/spine_godot/SpineConstant.h

@@ -30,7 +30,7 @@
 #ifndef GODOT_SPINECONSTANT_H
 #define GODOT_SPINECONSTANT_H
 
-#include "core/object.h"
+#include "SpineCommon.h"
 
 class SpineConstant : public Object {
 	GDCLASS(SpineConstant, Object);
@@ -81,11 +81,39 @@ public:
 		TransformMode_NoScale,
 		TransformMode_NoScaleOrReflection
 	};
+
+	enum PositionMode {
+		PositionMode_Fixed = 0,
+		PositionMode_Percent
+	};
+
+	enum SpacingMode {
+		SpacingMode_Length = 0,
+		SpacingMode_Fixed,
+		SpacingMode_Percent
+	};
+
+	enum RotateMode {
+		RotateMode_Tangent = 0,
+		RotateMode_Chain,
+		RotateMode_ChainScale
+	};
+
+	enum BlendMode {
+		BlendMode_Normal = 0,
+		BlendMode_Additive,
+		BlendMode_Multiply,
+		BlendMode_Screen
+	};
 };
 
-VARIANT_ENUM_CAST(SpineConstant::MixBlend);
-VARIANT_ENUM_CAST(SpineConstant::MixDirection);
-VARIANT_ENUM_CAST(SpineConstant::PropertyId);
-VARIANT_ENUM_CAST(SpineConstant::TransformMode);
+VARIANT_ENUM_CAST(SpineConstant::MixBlend)
+VARIANT_ENUM_CAST(SpineConstant::MixDirection)
+VARIANT_ENUM_CAST(SpineConstant::PropertyId)
+VARIANT_ENUM_CAST(SpineConstant::TransformMode)
+VARIANT_ENUM_CAST(SpineConstant::PositionMode)
+VARIANT_ENUM_CAST(SpineConstant::SpacingMode)
+VARIANT_ENUM_CAST(SpineConstant::RotateMode)
+VARIANT_ENUM_CAST(SpineConstant::BlendMode)
 
 #endif//GODOT_SPINECONSTANT_H

+ 1 - 4
spine-godot/spine_godot/SpineConstraintData.cpp

@@ -28,8 +28,8 @@
  *****************************************************************************/
 
 #include "SpineConstraintData.h"
+#include "SpineCommon.h"
 #include <spine/ConstraintData.h>
-#include "common.h"
 
 void SpineConstraintData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_constraint_name"), &SpineConstraintData::get_constraint_name);
@@ -42,9 +42,6 @@ void SpineConstraintData::_bind_methods() {
 SpineConstraintData::SpineConstraintData() : constraint_data(nullptr) {
 }
 
-SpineConstraintData::~SpineConstraintData() {
-}
-
 String SpineConstraintData::get_constraint_name() {
 	SPINE_CHECK(constraint_data, "")
 	return constraint_data->getName().buffer();

+ 8 - 12
spine-godot/spine_godot/SpineConstraintData.h

@@ -30,28 +30,24 @@
 #ifndef GODOT_SPINECONSTRAINTDATA_H
 #define GODOT_SPINECONSTRAINTDATA_H
 
-#include "core/reference.h"
+#include "SpineCommon.h"
+#include <spine/ConstraintData.h>
 
-namespace spine {
-	class ConstraintData;
-}
-
-class SpineConstraintData : public Reference {
-	GDCLASS(SpineConstraintData, Reference);
+class SpineConstraintData : public REFCOUNTED {
+	GDCLASS(SpineConstraintData, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
-	
+
 	spine::ConstraintData *constraint_data;
 
 public:
 	SpineConstraintData();
-	~SpineConstraintData();
 
 	void set_spine_object(spine::ConstraintData *_constraint_data) {
 		constraint_data = _constraint_data;
 	}
-	
+
 	spine::ConstraintData *get_spine_object() {
 		return constraint_data;
 	}
@@ -59,11 +55,11 @@ public:
 	String get_constraint_name();
 
 	uint64_t get_order();
-	
+
 	void set_order(uint64_t v);
 
 	bool is_skin_required();
-	
+
 	void set_skin_required(bool v);
 };
 

+ 53 - 25
spine-godot/spine_godot/SpineEditorPlugin.cpp

@@ -29,7 +29,6 @@
 
 #ifdef TOOLS_ENABLED
 #include "SpineEditorPlugin.h"
-
 #include "SpineAtlasResource.h"
 #include "SpineSkeletonFileResource.h"
 
@@ -43,7 +42,11 @@ Error SpineAtlasResourceImportPlugin::import(const String &source_file, const St
 	return error;
 }
 
+#if VERSION_MAJOR > 3
+void SpineAtlasResourceImportPlugin::get_import_options(const String &path, List<ImportOption> *options, int preset) const {
+#else
 void SpineAtlasResourceImportPlugin::get_import_options(List<ImportOption> *options, int preset) const {
+#endif
 	if (preset == 0) {
 		ImportOption op;
 		op.option.name = "normal_map_prefix";
@@ -79,15 +82,16 @@ SpineEditorPlugin::SpineEditorPlugin(EditorNode *node) {
 	add_inspector_plugin(memnew(SpineSkeletonDataResourceInspectorPlugin));
 }
 
-SpineEditorPlugin::~SpineEditorPlugin() {
-}
-
 bool SpineSkeletonDataResourceInspectorPlugin::can_handle(Object *object) {
 	return object->is_class("SpineSkeletonDataResource");
 }
 
+#if VERSION_MAJOR > 3
+bool SpineSkeletonDataResourceInspectorPlugin:: parse_property(Object *object, const Variant::Type type, const String &path, const PropertyHint hint, const String &hint_text, const uint32_t usage, const bool wide) {
+#else
 bool SpineSkeletonDataResourceInspectorPlugin::parse_property(Object *object, Variant::Type type, const String &path,
                                                         PropertyHint hint, const String &hint_text, int usage) {
+#endif
 	if (path == "animation_mixes") {
 		Ref<SpineSkeletonDataResource> skeleton_data = Object::cast_to<SpineSkeletonDataResource>(object);
 		if (!skeleton_data.is_valid() || !skeleton_data->is_skeleton_data_loaded()) return true;
@@ -100,7 +104,7 @@ bool SpineSkeletonDataResourceInspectorPlugin::parse_property(Object *object, Va
 }
 
 SpineEditorPropertyAnimationMixes::SpineEditorPropertyAnimationMixes(): skeleton_data(nullptr), container(nullptr), updating(false) {
-	array_object.instance();
+	INSTANTIATE(array_object);
 }
 
 void SpineEditorPropertyAnimationMixes::_bind_methods() {
@@ -118,7 +122,7 @@ void SpineEditorPropertyAnimationMixes::add_mix() {
 	mix->set_from(animation_names[0]);
 	mix->set_to(animation_names[0]);
 	mix->set_mix(0);
-	
+
 	Array mixes = skeleton_data->get_animation_mixes().duplicate();
 	mixes.push_back(mix);
 	emit_changed(get_edited_property(), mixes);
@@ -128,13 +132,17 @@ void SpineEditorPropertyAnimationMixes::delete_mix(int64_t idx) {
 	if (!skeleton_data.is_valid() || !skeleton_data->is_skeleton_data_loaded() || updating) return;
 
 	auto mixes = skeleton_data->get_animation_mixes().duplicate();
-	mixes.remove(idx);
+#if VERSION_MAJOR > 3
+	mixes.remove_at((int)idx);
+#else
+	mixes.remove((int)idx);
+#endif
 	emit_changed(get_edited_property(), mixes);
 }
 
 void SpineEditorPropertyAnimationMixes::update_mix_property(int64_t index) {
 	if (index < 0 || index > mix_properties.size()) return;
-	mix_properties[index]->update_property();
+	mix_properties[(int)index]->update_property();
 }
 
 void SpineEditorPropertyAnimationMixes::update_property() {
@@ -142,7 +150,7 @@ void SpineEditorPropertyAnimationMixes::update_property() {
 	updating = true;
 
 	mix_properties.clear();
-	
+
 	if (container) {
 		set_bottom_editor(nullptr);
 		memdelete(container);
@@ -154,14 +162,14 @@ void SpineEditorPropertyAnimationMixes::update_property() {
 		updating = false;
 		return;
 	}
-	
+
 	Vector<String> animation_names;
 	skeleton_data->get_animation_names(animation_names);
-	
+
 	container = memnew(VBoxContainer);
 	add_child(container);
 	set_bottom_editor(container);
-	
+
 	Array mixes = skeleton_data->get_animation_mixes();
 	array_object->set_array(mixes);
 	for (int i = 0; i < mixes.size(); i++) {
@@ -171,7 +179,7 @@ void SpineEditorPropertyAnimationMixes::update_property() {
 		auto hbox = memnew(HBoxContainer);
 		hbox->set_h_size_flags(SIZE_EXPAND_FILL);
 		container->add_child(hbox);
-		
+
 		auto mix_property = memnew(SpineEditorPropertyAnimationMix);
 		mix_property->set_h_size_flags(SIZE_EXPAND_FILL);
 		mix_property->set_name_split_ratio(0);
@@ -180,35 +188,43 @@ void SpineEditorPropertyAnimationMixes::update_property() {
 		mix_property->set_object_and_property(*array_object, property_name);
 		mix_property->update_property();
 		mix_properties.push_back(mix_property);
-		
+
 		auto delete_button = memnew(Button);
 		hbox->add_child(delete_button);
 		delete_button->set_text("Remove");
+#if VERSION_MAJOR > 3
+		delete_button->connect("pressed", callable_mp(this, &SpineEditorPropertyAnimationMixes::delete_mix), varray(i));
+#else
 		delete_button->connect("pressed", this, "delete_mix", varray(i));
+#endif
 	}
 
 	auto add_mix_button = memnew(Button);
 	add_mix_button->set_text("Add mix");
+#if VERSION_MAJOR > 3
+	add_mix_button->connect("pressed", callable_mp(this, &SpineEditorPropertyAnimationMixes::add_mix));
+#else
 	add_mix_button->connect("pressed", this, "add_mix");
+#endif
 	container->add_child(add_mix_button);
 
 	updating = false;
 }
 
-SpineEditorPropertyAnimationMix::SpineEditorPropertyAnimationMix(): skeleton_data(nullptr), container(nullptr), updating(false) {
+SpineEditorPropertyAnimationMix::SpineEditorPropertyAnimationMix(): mixes_property(nullptr), skeleton_data(nullptr), index(0), container(nullptr), updating(false) {
 }
 
-void SpineEditorPropertyAnimationMix::setup(SpineEditorPropertyAnimationMixes *mixes_property, Ref<SpineSkeletonDataResource> skeleton_data, int index) {
-	this->mixes_property = mixes_property;
-	this->skeleton_data = skeleton_data;
-	this->index = index;
+void SpineEditorPropertyAnimationMix::setup(SpineEditorPropertyAnimationMixes *_mixes_property, const Ref<SpineSkeletonDataResource> &_skeleton_data, int _index) {
+	this->mixes_property = _mixes_property;
+	this->skeleton_data = _skeleton_data;
+	this->index = _index;
 }
 
 void SpineEditorPropertyAnimationMix::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("data_changed"), &SpineEditorPropertyAnimationMix::data_changed);
 }
 
-void SpineEditorPropertyAnimationMix::data_changed(const String &property, Variant value, const String &name, bool changing) {
+void SpineEditorPropertyAnimationMix::data_changed(const String &property, const Variant &value, const String &name, bool changing) {
 	auto mix = Object::cast_to<SpineAnimationMix>(get_edited_object()->get(get_edited_property()));
 
 	UndoRedo *undo_redo = EditorNode::get_undo_redo();
@@ -228,7 +244,7 @@ void SpineEditorPropertyAnimationMix::data_changed(const String &property, Varia
 void SpineEditorPropertyAnimationMix::update_property() {
 	if (updating) return;
 	updating = true;
-	
+
 	if (container) {
 		memdelete(container);
 		container->queue_delete();
@@ -245,14 +261,14 @@ void SpineEditorPropertyAnimationMix::update_property() {
 		updating = false;
 		return;
 	}
-	
+
 	Vector<String> animation_names;
 	skeleton_data->get_animation_names(animation_names);
-	
+
 	container = memnew(HBoxContainer);
 	container->set_h_size_flags(SIZE_EXPAND_FILL);
 	add_child(container);
-	
+
 	auto from_enum = memnew(EditorPropertyTextEnum);
 	from_enum->set_h_size_flags(SIZE_EXPAND_FILL);
 	from_enum->set_name_split_ratio(0);
@@ -260,7 +276,11 @@ void SpineEditorPropertyAnimationMix::update_property() {
 	from_enum->setup(animation_names);
 	from_enum->set_object_and_property(mix, "from");
 	from_enum->update_property();
+#if VERSION_MAJOR > 3
+	from_enum->connect("property_changed", callable_mp(this, &SpineEditorPropertyAnimationMix::data_changed));
+#else
 	from_enum->connect("property_changed", this, "data_changed");
+#endif
 	container->add_child(from_enum);
 
 	auto to_enum = memnew(EditorPropertyTextEnum);
@@ -270,7 +290,11 @@ void SpineEditorPropertyAnimationMix::update_property() {
 	to_enum->setup(animation_names);
 	to_enum->set_object_and_property(mix, "to");
 	to_enum->update_property();
+#if VERSION_MAJOR > 3
+	to_enum->connect("property_changed", callable_mp(this, &SpineEditorPropertyAnimationMix::data_changed));
+#else
 	to_enum->connect("property_changed", this, "data_changed");
+#endif
 	container->add_child(to_enum);
 
 	auto mix_float = memnew(EditorPropertyFloat);
@@ -280,9 +304,13 @@ void SpineEditorPropertyAnimationMix::update_property() {
 	mix_float->setup(0, 9999999, 0.001, true, false, false, false);
 	mix_float->set_object_and_property(mix, "mix");
 	mix_float->update_property();
+#if VERSION_MAJOR > 3
+	mix_float->connect("property_changed", callable_mp(this, &SpineEditorPropertyAnimationMix::data_changed));
+#else
 	mix_float->connect("property_changed", this, "data_changed");
+#endif
 	container->add_child(mix_float);
-	
+
 	updating = false;
 }
 

+ 39 - 15
spine-godot/spine_godot/SpineEditorPlugin.h

@@ -29,12 +29,13 @@
 
 #ifndef GODOT_SPINEEDITORPLUGIN_H
 #define GODOT_SPINEEDITORPLUGIN_H
-#include "editor/editor_properties_array_dict.h"
 
 #ifdef TOOLS_ENABLED
-#include "editor/editor_node.h"
+#include "SpineCommon.h"
 #include "SpineSprite.h"
+#include "editor/editor_node.h"
 #include "editor/editor_properties.h"
+#include "editor/editor_properties_array_dict.h"
 
 class SpineAtlasResourceImportPlugin : public EditorImportPlugin {
 	GDCLASS(SpineAtlasResourceImportPlugin, EditorImportPlugin)
@@ -54,9 +55,17 @@ public:
 
 	String get_resource_type() const override { return "SpineAtlasResource"; }
 
+#if VERSION_MAJOR > 3
+	int get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
+
+	void get_import_options(const String &path, List<ImportOption> *options, int preset) const override;
+
+	bool get_option_visibility(const String &path, const String &option, const Map<StringName, Variant> &options) const override { return true; }
+#else
 	void get_import_options(List<ImportOption> *options, int preset) const override;
 
 	bool get_option_visibility(const String &option, const Map<StringName, Variant> &options) const override { return true; }
+#endif
 
 	Error import(const String &source_file, const String &save_path, const Map<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) override;
 };
@@ -79,10 +88,17 @@ public:
 
 	String get_resource_type() const override { return "SpineSkeletonFileResource"; }
 
-	void get_import_options(List<ImportOption> *options, int preset) const override {}
+#if VERSION_MAJOR > 3
+	int get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
 
-	bool get_option_visibility(const String &option, const Map<StringName, Variant> &options) const override { return true; }
+	void get_import_options(const String &path, List<ImportOption> *options, int preset) const override { }
+
+	bool get_option_visibility(const String &path, const String &option, const Map<StringName, Variant> &options) const override { return true; }
+#else
+	void get_import_options(List<ImportOption> *options, int preset) const override { }
 
+	bool get_option_visibility(const String &option, const Map<StringName, Variant> &options) const override { return true; }
+#endif
 	Error import(const String &source_file, const String &save_path, const Map<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) override;
 };
 
@@ -104,10 +120,17 @@ public:
 
 	String get_resource_type() const override { return "SpineSkeletonFileResource"; }
 
-	void get_import_options(List<ImportOption> *options, int preset) const override {}
+#if VERSION_MAJOR > 3
+	int get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
 
-	bool get_option_visibility(const String &option, const Map<StringName, Variant> &options) const override { return true; }
+	void get_import_options(const String &path, List<ImportOption> *options, int preset) const override { }
+
+	bool get_option_visibility(const String &path, const String &option, const Map<StringName, Variant> &options) const override { return true; }
+#else
+	void get_import_options(List<ImportOption> *options, int preset) const override { }
 
+	bool get_option_visibility(const String &option, const Map<StringName, Variant> &options) const override { return true; }
+#endif
 	Error import(const String &source_file, const String &save_path, const Map<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) override;
 };
 
@@ -115,12 +138,9 @@ class SpineEditorPlugin : public EditorPlugin {
 	GDCLASS(SpineEditorPlugin, EditorPlugin)
 
 public:
-	SpineEditorPlugin(EditorNode *node);
-	~SpineEditorPlugin();
+	explicit SpineEditorPlugin(EditorNode *node);
 
 	String get_name() const override { return "SpineEditorPlugin"; }
-
-	bool has_main_screen() const { return false; }
 };
 
 class SpineSkeletonDataResourceInspectorPlugin: public EditorInspectorPlugin {
@@ -130,7 +150,11 @@ public:
 	SpineSkeletonDataResourceInspectorPlugin() = default;
 
 	bool can_handle(Object *object) override;
+#if VERSION_MAJOR > 3
+	bool parse_property(Object *object, Variant::Type type, const String &path, PropertyHint hint, const String &hint_text, uint32_t usage, bool wide) override;
+#else
 	bool parse_property(Object *object, Variant::Type type, const String &path, PropertyHint hint, const String &hint_text, int usage) override;
+#endif
 };
 
 class SpineEditorPropertyAnimationMix;
@@ -150,8 +174,8 @@ class SpineEditorPropertyAnimationMixes: public EditorProperty {
 	void update_mix_property(int64_t index);
 public:
 	SpineEditorPropertyAnimationMixes();
-	void setup(Ref<SpineSkeletonDataResource> skeleton_data) { this->skeleton_data = skeleton_data; };
-	virtual void update_property();
+	void setup(const Ref<SpineSkeletonDataResource> &_skeleton_data) { this->skeleton_data = _skeleton_data; };
+	void update_property() override;
 };
 
 class SpineEditorPropertyAnimationMix: public EditorProperty {
@@ -164,11 +188,11 @@ class SpineEditorPropertyAnimationMix: public EditorProperty {
 	bool updating;
 
 	static void _bind_methods();
-	void data_changed(const String &property, Variant value, const String &name, bool changing);
+	void data_changed(const String &property, const Variant &value, const String &name, bool changing);
 public:
 	SpineEditorPropertyAnimationMix();
-	void setup(SpineEditorPropertyAnimationMixes *mixes_property, Ref<SpineSkeletonDataResource> skeleton_data, int index);
-	virtual void update_property();
+	void setup(SpineEditorPropertyAnimationMixes *mixes_property, const Ref<SpineSkeletonDataResource> &skeleton_data, int index);
+	void update_property() override;
 };
 
 #endif

+ 1 - 5
spine-godot/spine_godot/SpineEvent.cpp

@@ -28,8 +28,7 @@
  *****************************************************************************/
 
 #include "SpineEvent.h"
-#include <spine/Event.h>
-#include "common.h"
+#include "SpineCommon.h"
 
 void SpineEvent::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_data"), &SpineEvent::get_data);
@@ -49,9 +48,6 @@ void SpineEvent::_bind_methods() {
 SpineEvent::SpineEvent() : event(nullptr) {
 }
 
-SpineEvent::~SpineEvent() {
-}
-
 Ref<SpineEventData> SpineEvent::get_data() {
 	SPINE_CHECK(event, nullptr)
 	Ref<SpineEventData> event_data(memnew(SpineEventData));

+ 9 - 10
spine-godot/spine_godot/SpineEvent.h

@@ -30,12 +30,12 @@
 #ifndef GODOT_SPINEEVENT_H
 #define GODOT_SPINEEVENT_H
 
+#include "SpineCommon.h"
 #include "SpineEventData.h"
-#include "core/reference.h"
 #include <spine/Event.h>
 
-class SpineEvent : public Reference {
-	GDCLASS(SpineEvent, Reference)
+class SpineEvent : public REFCOUNTED {
+	GDCLASS(SpineEvent, REFCOUNTED)
 
 protected:
 	static void _bind_methods();
@@ -45,34 +45,33 @@ private:
 
 public:
 	SpineEvent();
-	~SpineEvent();
 
 	void set_spine_object(spine::Event *_event) { event = _event; }
 
 	spine::Event *get_spine_object() const { return event; }
-	
+
 	Ref<SpineEventData> get_data();
 
 	float get_time();
 
 	int get_int_value();
-	
+
 	void set_int_value(int v);
 
 	float get_float_value();
-	
+
 	void set_float_value(float v);
 
 	String get_string_value();
-	
+
 	void set_string_value(const String &v);
 
 	float get_volume();
-	
+
 	void set_volume(float v);
 
 	float get_balance();
-	
+
 	void set_balance(float v);
 };
 

+ 1 - 4
spine-godot/spine_godot/SpineEventData.cpp

@@ -28,7 +28,7 @@
  *****************************************************************************/
 
 #include "SpineEventData.h"
-#include "common.h"
+#include "SpineCommon.h"
 
 void SpineEventData::_bind_methods() {
  ClassDB::bind_method(D_METHOD("get_event_name"), &SpineEventData::get_event_name);
@@ -47,9 +47,6 @@ void SpineEventData::_bind_methods() {
 SpineEventData::SpineEventData() : event_data(nullptr) {
 }
 
-SpineEventData::~SpineEventData() {
-}
-
 String SpineEventData::get_event_name() {
  SPINE_CHECK(event_data, "")
  return event_data->getName().buffer();

+ 8 - 9
spine-godot/spine_godot/SpineEventData.h

@@ -30,11 +30,11 @@
 #ifndef GODOT_SPINEEVENTDATA_H
 #define GODOT_SPINEEVENTDATA_H
 
-#include "core/reference.h"
+#include "SpineCommon.h"
 #include <spine/EventData.h>
 
-class SpineEventData : public Reference {
-	GDCLASS(SpineEventData, Reference);
+class SpineEventData : public REFCOUNTED {
+	GDCLASS(SpineEventData, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -44,7 +44,6 @@ private:
 
 public:
 	SpineEventData();
-	~SpineEventData();
 
 	void set_spine_object(spine::EventData *_event_data) { event_data = _event_data; }
 
@@ -53,23 +52,23 @@ public:
 	String get_event_name();
 
 	int get_int_value();
-	
+
 	void set_int_value(int v);
 
 	float get_float_value();
-	
+
 	void set_float_value(float v);
 
 	String get_string_value();
-	
+
 	void set_string_value(const String &v);
 
 	float get_volume();
-	
+
 	void set_volume(float v);
 
 	float get_balance();
-	
+
 	void set_balance(float v);
 };
 

+ 2 - 5
spine-godot/spine_godot/SpineIkConstraint.cpp

@@ -29,7 +29,7 @@
 
 #include "SpineIkConstraint.h"
 #include "SpineBone.h"
-#include "common.h"
+#include "SpineCommon.h"
 
 void SpineIkConstraint::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("update"), &SpineIkConstraint::update);
@@ -55,9 +55,6 @@ void SpineIkConstraint::_bind_methods() {
 SpineIkConstraint::SpineIkConstraint() : ik_constraint(nullptr) {
 }
 
-SpineIkConstraint::~SpineIkConstraint() {
-}
-
 void SpineIkConstraint::update() {
 	SPINE_CHECK(ik_constraint,)
 	ik_constraint->update();
@@ -154,7 +151,7 @@ void SpineIkConstraint::set_softness(float v) {
 }
 
 bool SpineIkConstraint::is_active() {
-	SPINE_CHECK(ik_constraint, nullptr)
+	SPINE_CHECK(ik_constraint, false)
 	return ik_constraint->isActive();
 }
 void SpineIkConstraint::set_active(bool v) {

+ 10 - 11
spine-godot/spine_godot/SpineIkConstraint.h

@@ -35,8 +35,8 @@
 
 class SpineBone;
 
-class SpineIkConstraint : public Reference {
-	GDCLASS(SpineIkConstraint, Reference);
+class SpineIkConstraint : public REFCOUNTED {
+	GDCLASS(SpineIkConstraint, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -46,12 +46,11 @@ private:
 
 public:
 	SpineIkConstraint();
-	~SpineIkConstraint();
 
 	void set_spine_object(spine::IkConstraint *_ik_constraint) { ik_constraint = _ik_constraint; }
 
 	spine::IkConstraint *get_spine_object() { return ik_constraint; }
-	
+
 	void update();
 
 	int get_order();
@@ -61,31 +60,31 @@ public:
 	Array get_bones();
 
 	Ref<SpineBone> get_target();
-	
+
 	void set_target(Ref<SpineBone> v);
 
 	int get_bend_direction();
-	
+
 	void set_bend_direction(int v);
 
 	bool get_compress();
-	
+
 	void set_compress(bool v);
 
 	bool get_stretch();
-	
+
 	void set_stretch(bool v);
 
 	float get_mix();
-	
+
 	void set_mix(float v);
 
 	float get_softness();
-	
+
 	void set_softness(float v);
 
 	bool is_active();
-	
+
 	void set_active(bool v);
 };
 

+ 1 - 5
spine-godot/spine_godot/SpineIkConstraintData.cpp

@@ -28,8 +28,7 @@
  *****************************************************************************/
 
 #include "SpineIkConstraintData.h"
-
-#include "common.h"
+#include "SpineCommon.h"
 
 void SpineIkConstraintData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_bones"), &SpineIkConstraintData::get_bones);
@@ -49,9 +48,6 @@ void SpineIkConstraintData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_softness", "v"), &SpineIkConstraintData::set_softness);
 }
 
-SpineIkConstraintData::SpineIkConstraintData() {}
-SpineIkConstraintData::~SpineIkConstraintData() {}
-
 Array SpineIkConstraintData::get_bones() {
 	Array result;
 	SPINE_CHECK(constraint_data, result)

+ 8 - 11
spine-godot/spine_godot/SpineIkConstraintData.h

@@ -38,42 +38,39 @@ class SpineIkConstraintData : public SpineConstraintData {
 	GDCLASS(SpineIkConstraintData, SpineConstraintData)
 
 	spine::IkConstraintData *get_spine_constraint_data() { return (spine::IkConstraintData *)get_spine_object(); }
-	
+
 protected:
 	static void _bind_methods();
 
 public:
-	SpineIkConstraintData();
-	~SpineIkConstraintData();
-
 	Array get_bones();
 
 	Ref<SpineBoneData> get_target();
-	
+
 	void set_target(Ref<SpineBoneData> v);
 
 	int get_bend_direction();
-	
+
 	void set_bend_direction(int v);
 
 	bool get_compress();
-	
+
 	void set_compress(bool v);
 
 	bool get_stretch();
-	
+
 	void set_stretch(bool v);
 
 	bool get_uniform();
-	
+
 	void set_uniform(bool v);
 
 	float get_mix();
-	
+
 	void set_mix(float v);
 
 	float get_softness();
-	
+
 	void set_softness(float v);
 };
 

+ 49 - 32
spine-godot/spine_godot/SpinePathConstraint.cpp

@@ -28,9 +28,10 @@
  *****************************************************************************/
 
 #include "SpinePathConstraint.h"
+#include "SpineBone.h"
+#include "SpineCommon.h"
 
 void SpinePathConstraint::_bind_methods() {
-	// ClassDB::bind_method(D_METHOD("apply"), &SpinePathConstraint::apply);
 	ClassDB::bind_method(D_METHOD("update"), &SpinePathConstraint::update);
 	ClassDB::bind_method(D_METHOD("get_order"), &SpinePathConstraint::get_order);
 	ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraint::get_position);
@@ -51,95 +52,111 @@ void SpinePathConstraint::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_active", "v"), &SpinePathConstraint::set_active);
 }
 
-SpinePathConstraint::SpinePathConstraint() : path_constraint(NULL) {}
-SpinePathConstraint::~SpinePathConstraint() {}
-
-// void SpinePathConstraint::apply(){
-// 	path_constraint->apply();
-// }
+SpinePathConstraint::SpinePathConstraint() : path_constraint(nullptr) {
+}
 
 void SpinePathConstraint::update() {
+	SPINE_CHECK(path_constraint,)
 	path_constraint->update();
 }
 
 int SpinePathConstraint::get_order() {
+	SPINE_CHECK(path_constraint, 0)
 	return path_constraint->getOrder();
 }
 
 float SpinePathConstraint::get_position() {
+	SPINE_CHECK(path_constraint, 0)
 	return path_constraint->getPosition();
 }
+
 void SpinePathConstraint::set_position(float v) {
+	SPINE_CHECK(path_constraint,)
 	path_constraint->setPosition(v);
 }
 
 float SpinePathConstraint::get_spacing() {
+	SPINE_CHECK(path_constraint, 0)
 	return path_constraint->getSpacing();
 }
+
 void SpinePathConstraint::set_spacing(float v) {
+	SPINE_CHECK(path_constraint,)
 	path_constraint->setSpacing(v);
 }
 
 float SpinePathConstraint::get_mix_rotate() {
+	SPINE_CHECK(path_constraint, 0)
 	return path_constraint->getMixRotate();
 }
+
 void SpinePathConstraint::set_mix_rotate(float v) {
+	SPINE_CHECK(path_constraint,)
 	path_constraint->setMixRotate(v);
 }
 
 float SpinePathConstraint::get_mix_x() {
+	SPINE_CHECK(path_constraint, 0)
 	return path_constraint->getMixX();
 }
+
 void SpinePathConstraint::set_mix_x(float v) {
+	SPINE_CHECK(path_constraint,)
 	path_constraint->setMixX(v);
 }
 
 float SpinePathConstraint::get_mix_y() {
+	SPINE_CHECK(path_constraint, 0)
 	return path_constraint->getMixY();
 }
+
 void SpinePathConstraint::set_mix_y(float v) {
+	SPINE_CHECK(path_constraint,)
 	path_constraint->setMixY(v);
 }
 
 Array SpinePathConstraint::get_bones() {
-	auto &bs = path_constraint->getBones();
-	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<SpineBone>(NULL);
-		Ref<SpineBone> gd_b(memnew(SpineBone));
-		gd_b->set_spine_object(b);
-		gd_bs[i] = gd_b;
+	Array result;
+	SPINE_CHECK(path_constraint, result)
+	auto &bones = path_constraint->getBones();
+	result.resize((int)bones.size());
+	for (int i = 0; i < bones.size(); ++i) {
+		auto bone = bones[i];
+		Ref<SpineBone> bone_ref(memnew(SpineBone));
+		bone_ref->set_spine_object(bone);
+		result[i] = bone_ref;
 	}
-	return gd_bs;
+	return result;
 }
 
 Ref<SpineSlot> SpinePathConstraint::get_target() {
-	auto s = path_constraint->getTarget();
-	if (s == NULL) return NULL;
-	Ref<SpineSlot> gd_s(memnew(SpineSlot));
-	gd_s->set_spine_object(s);
-	return gd_s;
+	SPINE_CHECK(path_constraint, nullptr)
+	auto target = path_constraint->getTarget();
+	if (!target) return nullptr;
+	Ref<SpineSlot> target_ref(memnew(SpineSlot));
+	target_ref->set_spine_object(target);
+	return target_ref;
 }
+
 void SpinePathConstraint::set_target(Ref<SpineSlot> v) {
-	if (v.is_valid()) {
-		path_constraint->setTarget(v->get_spine_object());
-	} else {
-		path_constraint->setTarget(NULL);
-	}
+	SPINE_CHECK(path_constraint,)
+	path_constraint->setTarget(v.is_valid() ? v->get_spine_object() : nullptr);
 }
 
 Ref<SpinePathConstraintData> SpinePathConstraint::get_data() {
-	auto &sd = path_constraint->getData();
-	Ref<SpinePathConstraintData> gd_sd(memnew(SpinePathConstraintData));
-	gd_sd->set_spine_object(&sd);
-	return gd_sd;
+	SPINE_CHECK(path_constraint, nullptr)
+	auto &data = path_constraint->getData();
+	Ref<SpinePathConstraintData> data_ref(memnew(SpinePathConstraintData));
+	data_ref->set_spine_object(&data);
+	return data_ref;
 }
 
 bool SpinePathConstraint::is_active() {
+	SPINE_CHECK(path_constraint, false)
 	return path_constraint->isActive();
 }
+
 void SpinePathConstraint::set_active(bool v) {
+	SPINE_CHECK(path_constraint,)
 	path_constraint->setActive(v);
-}
+}

+ 13 - 18
spine-godot/spine_godot/SpinePathConstraint.h

@@ -30,16 +30,12 @@
 #ifndef GODOT_SPINEPATHCONSTRAINT_H
 #define GODOT_SPINEPATHCONSTRAINT_H
 
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
-
-#include "SpineBone.h"
-#include "SpineSlot.h"
 #include "SpinePathConstraintData.h"
+#include "SpineSlot.h"
+#include <spine/PathConstraint.h>
 
-class SpinePathConstraint : public Reference {
-	GDCLASS(SpinePathConstraint, Reference);
+class SpinePathConstraint : public REFCOUNTED {
+	GDCLASS(SpinePathConstraint, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -49,45 +45,44 @@ private:
 
 public:
 	SpinePathConstraint();
-	~SpinePathConstraint();
-
-	inline void set_spine_object(spine::PathConstraint *pc) {
-		path_constraint = pc;
-	}
-	inline spine::PathConstraint *get_spine_object() {
-		return path_constraint;
-	}
 
-	// The spine-runtime-cpp 4.0 seems to not have a apply function implementation.
-	// void apply();
+	void set_spine_object(spine::PathConstraint *_path_constraint) { path_constraint = _path_constraint; }
+	spine::PathConstraint *get_spine_object() { return path_constraint; }
 
 	void update();
 
 	int get_order();
 
 	float get_position();
+
 	void set_position(float v);
 
 	float get_spacing();
+
 	void set_spacing(float v);
 
 	float get_mix_rotate();
+
 	void set_mix_rotate(float v);
 
 	float get_mix_x();
+
 	void set_mix_x(float v);
 
 	float get_mix_y();
+
 	void set_mix_y(float v);
 
 	Array get_bones();
 
 	Ref<SpineSlot> get_target();
+
 	void set_target(Ref<SpineSlot> v);
 
 	Ref<SpinePathConstraintData> get_data();
 
 	bool is_active();
+
 	void set_active(bool v);
 };
 

+ 70 - 66
spine-godot/spine_godot/SpinePathConstraintData.cpp

@@ -28,141 +28,145 @@
  *****************************************************************************/
 
 #include "SpinePathConstraintData.h"
-
+#include "SpineCommon.h"
 
 void SpinePathConstraintData::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpinePathConstraintData::get_bones);
+	ClassDB::bind_method(D_METHOD("get_bones"), &SpinePathConstraintData::get_bones);
 	ClassDB::bind_method(D_METHOD("get_target"), &SpinePathConstraintData::get_target);
-	ClassDB::bind_method(D_METHOD("set_target", "V"), &SpinePathConstraintData::set_target);
+	ClassDB::bind_method(D_METHOD("set_target", "v"), &SpinePathConstraintData::set_target);
 	ClassDB::bind_method(D_METHOD("get_position_mode"), &SpinePathConstraintData::get_position_mode);
-	ClassDB::bind_method(D_METHOD("set_position_mode", "V"), &SpinePathConstraintData::set_position_mode);
+	ClassDB::bind_method(D_METHOD("set_position_mode", "v"), &SpinePathConstraintData::set_position_mode);
 	ClassDB::bind_method(D_METHOD("get_spacing_mode"), &SpinePathConstraintData::get_spacing_mode);
-	ClassDB::bind_method(D_METHOD("set_spacing_mode", "V"), &SpinePathConstraintData::set_spacing_mode);
+	ClassDB::bind_method(D_METHOD("set_spacing_mode", "v"), &SpinePathConstraintData::set_spacing_mode);
 	ClassDB::bind_method(D_METHOD("get_rotate_mode"), &SpinePathConstraintData::get_rotate_mode);
-	ClassDB::bind_method(D_METHOD("set_rotate_mode", "V"), &SpinePathConstraintData::set_rotate_mode);
+	ClassDB::bind_method(D_METHOD("set_rotate_mode", "v"), &SpinePathConstraintData::set_rotate_mode);
 	ClassDB::bind_method(D_METHOD("get_offset_rotation"), &SpinePathConstraintData::get_offset_rotation);
-	ClassDB::bind_method(D_METHOD("set_offset_rotation", "V"), &SpinePathConstraintData::set_offset_rotation);
+	ClassDB::bind_method(D_METHOD("set_offset_rotation", "v"), &SpinePathConstraintData::set_offset_rotation);
 	ClassDB::bind_method(D_METHOD("get_position"), &SpinePathConstraintData::get_position);
-	ClassDB::bind_method(D_METHOD("set_position", "V"), &SpinePathConstraintData::set_position);
+	ClassDB::bind_method(D_METHOD("set_position", "v"), &SpinePathConstraintData::set_position);
 	ClassDB::bind_method(D_METHOD("get_spacing"), &SpinePathConstraintData::get_spacing);
-	ClassDB::bind_method(D_METHOD("set_spacing", "V"), &SpinePathConstraintData::set_spacing);
+	ClassDB::bind_method(D_METHOD("set_spacing", "v"), &SpinePathConstraintData::set_spacing);
 	ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpinePathConstraintData::get_mix_rotate);
-	ClassDB::bind_method(D_METHOD("set_mix_rotate", "V"), &SpinePathConstraintData::set_mix_rotate);
+	ClassDB::bind_method(D_METHOD("set_mix_rotate", "v"), &SpinePathConstraintData::set_mix_rotate);
 	ClassDB::bind_method(D_METHOD("get_mix_x"), &SpinePathConstraintData::get_mix_x);
-	ClassDB::bind_method(D_METHOD("set_mix_x", "V"), &SpinePathConstraintData::set_mix_x);
+	ClassDB::bind_method(D_METHOD("set_mix_x", "v"), &SpinePathConstraintData::set_mix_x);
 	ClassDB::bind_method(D_METHOD("get_mix_y"), &SpinePathConstraintData::get_mix_y);
-	ClassDB::bind_method(D_METHOD("set_mix_y", "V"), &SpinePathConstraintData::set_mix_y);
-
-	BIND_ENUM_CONSTANT(POSITIONMODE_FIXED);
-	BIND_ENUM_CONSTANT(POSITIONMODE_PERCENT);
-
-	BIND_ENUM_CONSTANT(SPACINGMODE_LENGTH);
-	BIND_ENUM_CONSTANT(SPACINGMODE_FIXED);
-	BIND_ENUM_CONSTANT(SPACINGMODE_PERCENT);
-
-	BIND_ENUM_CONSTANT(ROTATEMODE_TANGENT);
-	BIND_ENUM_CONSTANT(ROTATEMODE_CHAIN);
-	BIND_ENUM_CONSTANT(ROTATEMODE_CHAINSCALE);
+	ClassDB::bind_method(D_METHOD("set_mix_y", "v"), &SpinePathConstraintData::set_mix_y);
 }
 
-SpinePathConstraintData::SpinePathConstraintData() {}
-SpinePathConstraintData::~SpinePathConstraintData() {}
-
 Array SpinePathConstraintData::get_bones() {
-	auto bs = get_spine_constraint_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;
-		}
+	Array result;
+	SPINE_CHECK(get_spine_constraint_data(), result)
+	auto bones = get_spine_constraint_data()->getBones();
+	result.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]);
+		result[i] = bone_ref;
 	}
-	return gd_bs;
+	return result;
 }
 
 Ref<SpineSlotData> SpinePathConstraintData::get_target() {
-	auto s = get_spine_constraint_data()->getTarget();
-	if (s == NULL) return NULL;
-	Ref<SpineSlotData> gd_s(memnew(SpineSlotData));
-	gd_s->set_spine_object(s);
-	return gd_s;
+	SPINE_CHECK(get_spine_constraint_data(), nullptr)
+	auto slot = get_spine_constraint_data()->getTarget();
+	if (!slot) return nullptr;
+	Ref<SpineSlotData> slot_ref(memnew(SpineSlotData));
+	slot_ref->set_spine_object(slot);
+	return slot_ref;
 }
+
 void SpinePathConstraintData::set_target(Ref<SpineSlotData> v) {
-	if (v.is_valid()) {
-		get_spine_constraint_data()->setTarget(v->get_spine_object());
-	} else {
-		get_spine_constraint_data()->setTarget(NULL);
-	}
+	SPINE_CHECK(get_spine_constraint_data(),)
+	get_spine_constraint_data()->setTarget(v.is_valid() ? v->get_spine_object() : nullptr);
 }
 
-SpinePathConstraintData::PositionMode SpinePathConstraintData::get_position_mode() {
-	auto m = (int) get_spine_constraint_data()->getPositionMode();
-	return (PositionMode) m;
+SpineConstant::PositionMode SpinePathConstraintData::get_position_mode() {
+	SPINE_CHECK(get_spine_constraint_data(), SpineConstant::PositionMode_Fixed)
+	return (SpineConstant::PositionMode) get_spine_constraint_data()->getPositionMode();
 }
-void SpinePathConstraintData::set_position_mode(PositionMode v) {
-	auto m = (int) v;
-	get_spine_constraint_data()->setPositionMode((spine::PositionMode) m);
+
+void SpinePathConstraintData::set_position_mode(SpineConstant::PositionMode v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
+	get_spine_constraint_data()->setPositionMode((spine::PositionMode)v);
 }
 
-SpinePathConstraintData::SpacingMode SpinePathConstraintData::get_spacing_mode() {
-	auto m = (int) get_spine_constraint_data()->getSpacingMode();
-	return (SpacingMode) m;
+SpineConstant::SpacingMode SpinePathConstraintData::get_spacing_mode() {
+	SPINE_CHECK(get_spine_constraint_data(),SpineConstant::SpacingMode_Fixed)
+	return (SpineConstant::SpacingMode) get_spine_constraint_data()->getSpacingMode();
 }
-void SpinePathConstraintData::set_spacing_mode(SpacingMode v) {
-	auto m = (int) v;
-	get_spine_constraint_data()->setSpacingMode((spine::SpacingMode) m);
+
+void SpinePathConstraintData::set_spacing_mode(SpineConstant::SpacingMode v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
+	get_spine_constraint_data()->setSpacingMode((spine::SpacingMode) v);
 }
 
-SpinePathConstraintData::RotateMode SpinePathConstraintData::get_rotate_mode() {
-	auto m = (int) get_spine_constraint_data()->getRotateMode();
-	return (RotateMode) m;
+SpineConstant::RotateMode SpinePathConstraintData::get_rotate_mode() {
+	SPINE_CHECK(get_spine_constraint_data(),SpineConstant::RotateMode_Tangent)
+	return (SpineConstant::RotateMode)get_spine_constraint_data()->getRotateMode();
 }
-void SpinePathConstraintData::set_rotate_mode(RotateMode v) {
-	auto m = (int) v;
-	get_spine_constraint_data()->setRotateMode((spine::RotateMode) m);
+
+void SpinePathConstraintData::set_rotate_mode(SpineConstant::RotateMode v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
+	get_spine_constraint_data()->setRotateMode((spine::RotateMode) v);
 }
 
 float SpinePathConstraintData::get_offset_rotation() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
 	return get_spine_constraint_data()->getOffsetRotation();
 }
+
 void SpinePathConstraintData::set_offset_rotation(float v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
 	get_spine_constraint_data()->setOffsetRotation(v);
 }
 
 float SpinePathConstraintData::get_position() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
 	return get_spine_constraint_data()->getPosition();
 }
+
 void SpinePathConstraintData::set_position(float v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
 	get_spine_constraint_data()->setPosition(v);
 }
 
 float SpinePathConstraintData::get_spacing() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
 	return get_spine_constraint_data()->getSpacing();
 }
+
 void SpinePathConstraintData::set_spacing(float v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
 	get_spine_constraint_data()->setSpacing(v);
 }
 
 float SpinePathConstraintData::get_mix_rotate() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
 	return get_spine_constraint_data()->getMixRotate();
 }
+
 void SpinePathConstraintData::set_mix_rotate(float v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
 	get_spine_constraint_data()->setMixRotate(v);
 }
 
 float SpinePathConstraintData::get_mix_x() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
 	return get_spine_constraint_data()->getMixX();
 }
+
 void SpinePathConstraintData::set_mix_x(float v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
 	get_spine_constraint_data()->setMixX(v);
 }
 
 float SpinePathConstraintData::get_mix_y() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
 	return get_spine_constraint_data()->getMixY();
 }
+
 void SpinePathConstraintData::set_mix_y(float v) {
+	SPINE_CHECK(get_spine_constraint_data(),)
 	get_spine_constraint_data()->setMixY(v);
-}
+}

+ 18 - 31
spine-godot/spine_godot/SpinePathConstraintData.h

@@ -31,6 +31,7 @@
 #define GODOT_SPINEPATHCONSTRAINTDATA_H
 
 #include "SpineConstraintData.h"
+#include "SpineConstant.h"
 #include "SpineBoneData.h"
 #include "SpineSlotData.h"
 #include <spine/PathConstraintData.h>
@@ -39,65 +40,51 @@ class SpinePathConstraintData : public SpineConstraintData {
 	GDCLASS(SpinePathConstraintData, SpineConstraintData);
 
 	spine::PathConstraintData *get_spine_constraint_data() { return (spine::PathConstraintData *)get_spine_object(); }
-	
+
 protected:
 	static void _bind_methods();
 
 public:
-	SpinePathConstraintData();
-	~SpinePathConstraintData();
-
-	enum PositionMode {
-		POSITIONMODE_FIXED = 0,
-		POSITIONMODE_PERCENT
-	};
-
-	enum SpacingMode {
-		SPACINGMODE_LENGTH = 0,
-		SPACINGMODE_FIXED,
-		SPACINGMODE_PERCENT
-	};
-
-	enum RotateMode {
-		ROTATEMODE_TANGENT = 0,
-		ROTATEMODE_CHAIN,
-		ROTATEMODE_CHAINSCALE
-	};
-
 	Array get_bones();
 
 	Ref<SpineSlotData> get_target();
+
 	void set_target(Ref<SpineSlotData> v);
 
-	PositionMode get_position_mode();
-	void set_position_mode(PositionMode v);
+	SpineConstant::PositionMode get_position_mode();
+
+	void set_position_mode(SpineConstant::PositionMode v);
 
-	SpacingMode get_spacing_mode();
-	void set_spacing_mode(SpacingMode v);
+	SpineConstant::SpacingMode get_spacing_mode();
 
-	RotateMode get_rotate_mode();
-	void set_rotate_mode(RotateMode v);
+	void set_spacing_mode(SpineConstant::SpacingMode v);
+
+	SpineConstant::RotateMode get_rotate_mode();
+
+	void set_rotate_mode(SpineConstant::RotateMode v);
 
 	float get_offset_rotation();
+
 	void set_offset_rotation(float v);
 
 	float get_position();
+
 	void set_position(float v);
 
 	float get_spacing();
+
 	void set_spacing(float v);
 
 	float get_mix_rotate();
+
 	void set_mix_rotate(float v);
 
 	float get_mix_x();
+
 	void set_mix_x(float v);
 
 	float get_mix_y();
+
 	void set_mix_y(float v);
 };
-
-VARIANT_ENUM_CAST(SpinePathConstraintData::PositionMode);
-VARIANT_ENUM_CAST(SpinePathConstraintData::SpacingMode);
-VARIANT_ENUM_CAST(SpinePathConstraintData::RotateMode);
 #endif//GODOT_SPINEPATHCONSTRAINTDATA_H

+ 163 - 143
spine-godot/spine_godot/SpineSkeleton.cpp

@@ -28,6 +28,7 @@
  *****************************************************************************/
 
 #include "SpineSkeleton.h"
+#include "SpineCommon.h"
 
 void SpineSkeleton::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineSkeleton::update_world_transform);
@@ -49,14 +50,14 @@ void SpineSkeleton::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_data"), &SpineSkeleton::get_skeleton_data_res);
 	ClassDB::bind_method(D_METHOD("get_bones"), &SpineSkeleton::get_bones);
 	ClassDB::bind_method(D_METHOD("get_slots"), &SpineSkeleton::get_slots);
-	ClassDB::bind_method(D_METHOD("get_draw_orders"), &SpineSkeleton::get_draw_orders);
+	ClassDB::bind_method(D_METHOD("get_draw_order"), &SpineSkeleton::get_draw_order);
 	ClassDB::bind_method(D_METHOD("get_ik_constraints"), &SpineSkeleton::get_ik_constraints);
 	ClassDB::bind_method(D_METHOD("get_path_constraints"), &SpineSkeleton::get_path_constraints);
 	ClassDB::bind_method(D_METHOD("get_transform_constraints"), &SpineSkeleton::get_transform_constraints);
 	ClassDB::bind_method(D_METHOD("get_skin"), &SpineSkeleton::get_skin);
 	ClassDB::bind_method(D_METHOD("get_color"), &SpineSkeleton::get_color);
 	ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSkeleton::set_color);
-	ClassDB::bind_method(D_METHOD("set_position", "pos"), &SpineSkeleton::set_position);
+	ClassDB::bind_method(D_METHOD("set_position", "position"), &SpineSkeleton::set_position);
 	ClassDB::bind_method(D_METHOD("get_x"), &SpineSkeleton::get_x);
 	ClassDB::bind_method(D_METHOD("set_x", "v"), &SpineSkeleton::set_x);
 	ClassDB::bind_method(D_METHOD("get_y"), &SpineSkeleton::get_y);
@@ -86,30 +87,34 @@ Ref<SpineSkeletonDataResource> SpineSkeleton::get_skeleton_data_res() const {
 	return skeleton_data_res;
 }
 
-void SpineSkeleton::set_spine_sprite(SpineSprite* sprite) {
-	this->sprite = sprite;
+void SpineSkeleton::set_spine_sprite(SpineSprite* _sprite) {
+	this->sprite = _sprite;
 }
 
-#define S_T(x) (spine::String((x).utf8()))
 void SpineSkeleton::update_world_transform() {
+	SPINE_CHECK(skeleton,)
 	skeleton->updateWorldTransform();
 }
 
 void SpineSkeleton::set_to_setup_pose() {
+	SPINE_CHECK(skeleton,)
 	skeleton->setToSetupPose();
 }
 
 void SpineSkeleton::set_bones_to_setup_pose() {
+	SPINE_CHECK(skeleton,)
 	skeleton->setBonesToSetupPose();
 }
 
 void SpineSkeleton::set_slots_to_setup_pose() {
+	SPINE_CHECK(skeleton,)
 	skeleton->setSlotsToSetupPose();
 }
 
 Ref<SpineBone> SpineSkeleton::find_bone(const String &name) {
-	if (name.empty()) return nullptr;
-	auto bone = skeleton->findBone(S_T(name));
+	SPINE_CHECK(skeleton, nullptr)
+	if (EMPTY(name)) return nullptr;
+	auto bone = skeleton->findBone(SPINE_STRING(name));
 	if (!bone) return nullptr;
 	Ref<SpineBone> bone_ref(memnew(SpineBone));
 	bone_ref->set_spine_object(bone);
@@ -118,8 +123,9 @@ Ref<SpineBone> SpineSkeleton::find_bone(const String &name) {
 }
 
 Ref<SpineSlot> SpineSkeleton::find_slot(const String &name) {
-	if (name.empty()) return nullptr;
-	auto slot = skeleton->findSlot(S_T(name));
+	SPINE_CHECK(skeleton, nullptr)
+	if (EMPTY(name)) return nullptr;
+	auto slot = skeleton->findSlot(SPINE_STRING(name));
 	if (!slot) return nullptr;
 	Ref<SpineSlot> slot_ref(memnew(SpineSlot));
 	slot_ref->set_spine_object(slot);
@@ -127,217 +133,231 @@ Ref<SpineSlot> SpineSkeleton::find_slot(const String &name) {
 }
 
 void SpineSkeleton::set_skin_by_name(const String &skin_name) {
-	skeleton->setSkin(S_T(skin_name));
+	SPINE_CHECK(skeleton,)
+	skeleton->setSkin(SPINE_STRING(skin_name));
 }
+
 void SpineSkeleton::set_skin(Ref<SpineSkin> new_skin) {
-	if (new_skin.is_valid())
-		skeleton->setSkin(new_skin->get_spine_object());
-	else
-		skeleton->setSkin(nullptr);
+	SPINE_CHECK(skeleton,)
+	skeleton->setSkin(new_skin.is_valid() ? new_skin->get_spine_object() : nullptr);
 }
 
 Ref<SpineAttachment> SpineSkeleton::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;
+	SPINE_CHECK(skeleton, nullptr)
+	auto attachment = skeleton->getAttachment(SPINE_STRING(slot_name), SPINE_STRING(attachment_name));
+	if (!attachment) return nullptr;
+	Ref<SpineAttachment> attachment_ref(memnew(SpineAttachment));
+	attachment_ref->set_spine_object(attachment);
+	return attachment_ref;
 }
 
 Ref<SpineAttachment> SpineSkeleton::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;
+	SPINE_CHECK(skeleton, nullptr)
+	auto attachment = skeleton->getAttachment(slot_index, SPINE_STRING(attachment_name));
+	if (!attachment) return nullptr;
+	Ref<SpineAttachment> attachment_ref(memnew(SpineAttachment));
+	attachment_ref->set_spine_object(attachment);
+	return attachment_ref;
 }
 
 void SpineSkeleton::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));
+	SPINE_CHECK(skeleton,)
+	skeleton->setAttachment(SPINE_STRING(slot_name), SPINE_STRING(attachment_name));
 }
 
 Ref<SpineIkConstraint> SpineSkeleton::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;
+	SPINE_CHECK(skeleton, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton->findIkConstraint(SPINE_STRING(constraint_name));
+	if (!constraint) return nullptr;
+	Ref<SpineIkConstraint> constraint_ref(memnew(SpineIkConstraint));
+	constraint_ref->set_spine_object(constraint);
+	return constraint_ref;
 }
+
 Ref<SpineTransformConstraint> SpineSkeleton::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;
+	SPINE_CHECK(skeleton, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton->findTransformConstraint(SPINE_STRING(constraint_name));
+	if (!constraint) return nullptr;
+	Ref<SpineTransformConstraint> constraint_ref(memnew(SpineTransformConstraint));
+	constraint_ref->set_spine_object(constraint);
+	return constraint_ref;
 }
+
 Ref<SpinePathConstraint> SpineSkeleton::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;
+	SPINE_CHECK(skeleton, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton->findPathConstraint(SPINE_STRING(constraint_name));
+	if (!constraint) return nullptr;
+	Ref<SpinePathConstraint> constraint_ref(memnew(SpinePathConstraint));
+	constraint_ref->set_spine_object(constraint);
+	return constraint_ref;
 }
 
-Dictionary SpineSkeleton::get_bounds() {
+Rect2 SpineSkeleton::get_bounds() {
+	SPINE_CHECK(skeleton, Rect2(0, 0, 0, 0))
 	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;
+	skeleton->getBounds(x, y, w, h, bounds_vertex_buffer);
+	return Rect2(x, y, w, h);
 }
 
 Ref<SpineBone> SpineSkeleton::get_root_bone() {
-	auto b = skeleton->getRootBone();
-	if (b == nullptr) return nullptr;
-	Ref<SpineBone> gd_b(memnew(SpineBone));
-	gd_b->set_spine_object(b);
-	gd_b->set_spine_sprite(sprite);
-	return gd_b;
+	SPINE_CHECK(skeleton, nullptr)
+	auto bone = skeleton->getRootBone();
+	if (!bone) return nullptr;
+	Ref<SpineBone> bone_ref(memnew(SpineBone));
+	bone_ref->set_spine_object(bone);
+	bone_ref->set_spine_sprite(sprite);
+	return bone_ref;
 }
 
 Array SpineSkeleton::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<SpineBone>(nullptr);
-		Ref<SpineBone> gd_a(memnew(SpineBone));
-		gd_a->set_spine_object(b);
-		gd_a->set_spine_sprite(sprite);
-		gd_as[i] = gd_a;
+	Array result;
+	SPINE_CHECK(skeleton, result)
+	auto &bones = skeleton->getBones();
+	result.resize((int)bones.size());
+	for (int i = 0; i < result.size(); ++i) {
+		auto bone = bones[i];
+		Ref<SpineBone> bone_ref(memnew(SpineBone));
+		bone_ref->set_spine_object(bone);
+		bone_ref->set_spine_sprite(sprite);
+		result[i] = bone_ref;
 	}
-	return gd_as;
+	return result;
 }
+
 Array SpineSkeleton::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;
+	Array result;
+	SPINE_CHECK(skeleton, result)
+	auto &slots = skeleton->getSlots();
+	result.resize((int)slots.size());
+	for (int i = 0; i < result.size(); ++i) {
+		auto slot = slots[i];
+		Ref<SpineSlot> slot_ref(memnew(SpineSlot));
+		slot_ref->set_spine_object(slot);
+		result[i] = slot_ref;
 	}
-	return gd_as;
-}
-Array SpineSkeleton::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 result;
+}
+
+Array SpineSkeleton::get_draw_order() {
+	Array result;
+	SPINE_CHECK(skeleton, result)
+	auto &slots = skeleton->getDrawOrder();
+	result.resize((int)slots.size());
+	for (int i = 0; i < result.size(); ++i) {
+		auto slot = slots[i];
+		Ref<SpineSlot> slot_ref(memnew(SpineSlot));
+		slot_ref->set_spine_object(slot);
+		result[i] = slot_ref;
 	}
-	return gd_as;
+	return result;
 }
+
 Array SpineSkeleton::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;
+	Array result;
+	SPINE_CHECK(skeleton, result)
+	auto &constraints = skeleton->getIkConstraints();
+	result.resize((int)constraints.size());
+	for (int i = 0; i < result.size(); ++i) {
+		auto constraint = constraints[i];
+		Ref<SpineIkConstraint> constraint_ref(memnew(SpineIkConstraint));
+		constraint_ref->set_spine_object(constraint);
+		result[i] = constraint_ref;
 	}
-	return gd_as;
+	return result;
 }
+
 Array SpineSkeleton::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;
+	Array result;
+	SPINE_CHECK(skeleton, result)
+	auto &constraints = skeleton->getPathConstraints();
+	result.resize((int)constraints.size());
+	for (int i = 0; i < result.size(); ++i) {
+		auto constraint = constraints[i];
+		Ref<SpinePathConstraint> constraint_ref(memnew(SpinePathConstraint));
+		constraint_ref->set_spine_object(constraint);
+		result[i] = constraint_ref;
 	}
-	return gd_as;
+	return result;
 }
 Array SpineSkeleton::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;
+	Array result;
+	SPINE_CHECK(skeleton, result)
+	auto &constraints = skeleton->getTransformConstraints();
+	result.resize((int)constraints.size());
+	for (int i = 0; i < result.size(); ++i) {
+		auto constraint = constraints[i];
+		Ref<SpineTransformConstraint> constraint_ref(memnew(SpineTransformConstraint));
+		constraint_ref->set_spine_object(constraint);
+		result[i] = constraint_ref;
 	}
-	return gd_as;
+	return result;
 }
 
 Ref<SpineSkin> SpineSkeleton::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;
+	SPINE_CHECK(skeleton, nullptr)
+	auto skin = skeleton->getSkin();
+	if (!skin) return nullptr;
+	Ref<SpineSkin> skin_ref(memnew(SpineSkin));
+	skin_ref->set_spine_object(skin);
+	return skin_ref;
 }
 
 Color SpineSkeleton::get_color() {
-	auto &c = skeleton->getColor();
-	return Color(c.r, c.g, c.b, c.a);
+	SPINE_CHECK(skeleton, Color(0, 0, 0, 0))
+	auto &color = skeleton->getColor();
+	return Color(color.r, color.g, color.b, color.a);
 }
+
 void SpineSkeleton::set_color(Color v) {
-	auto &c = skeleton->getColor();
-	c.set(v.r, v.g, v.b, v.a);
+	SPINE_CHECK(skeleton,)
+	auto &color = skeleton->getColor();
+	color.set(v.r, v.g, v.b, v.a);
 }
 
-void SpineSkeleton::set_position(Vector2 pos) {
-	skeleton->setPosition(pos.x, pos.y);
+void SpineSkeleton::set_position(Vector2 position) {
+	SPINE_CHECK(skeleton,)
+	skeleton->setPosition(position.x, position.y);
 }
 
 float SpineSkeleton::get_x() {
+	SPINE_CHECK(skeleton, 0)
 	return skeleton->getX();
 }
+
 void SpineSkeleton::set_x(float v) {
+	SPINE_CHECK(skeleton,)
 	skeleton->setX(v);
 }
 
 float SpineSkeleton::get_y() {
+	SPINE_CHECK(skeleton, 0)
 	return skeleton->getY();
 }
+
 void SpineSkeleton::set_y(float v) {
+	SPINE_CHECK(skeleton,)
 	skeleton->setY(v);
 }
 
 float SpineSkeleton::get_scale_x() {
+	SPINE_CHECK(skeleton, 1)
 	return skeleton->getScaleX();
 }
+
 void SpineSkeleton::set_scale_x(float v) {
+	SPINE_CHECK(skeleton,)
 	skeleton->setScaleX(v);
 }
 
 float SpineSkeleton::get_scale_y() {
+	SPINE_CHECK(skeleton, 1)
 	return skeleton->getScaleY();
 }
+
 void SpineSkeleton::set_scale_y(float v) {
+	SPINE_CHECK(skeleton,)
 	skeleton->setScaleY(v);
 }

+ 38 - 20
spine-godot/spine_godot/SpineSkeleton.h

@@ -30,8 +30,7 @@
 #ifndef GODOT_SPINESKELETON_H
 #define GODOT_SPINESKELETON_H
 
-#include <spine/spine.h>
-
+#include "SpineCommon.h"
 #include "SpineSkeletonDataResource.h"
 #include "SpineBone.h"
 #include "SpineSlot.h"
@@ -41,32 +40,37 @@
 
 class SpineSprite;
 
-class SpineSkeleton : public Reference {
-	GDCLASS(SpineSkeleton, Reference);
+class SpineSkeleton : public REFCOUNTED {
+	GDCLASS(SpineSkeleton, REFCOUNTED);
+
+	friend class SpineBone;
+	friend class SpineSlot;
+	friend class SpineTimeline;
+	friend class SpineSprite;
+	friend class SpineAnimation;
+	friend class SpineAnimationState;
+	friend class SpineCollisionShapeProxy;
 
 protected:
 	static void _bind_methods();
 
+	void set_skeleton_data_res(Ref<SpineSkeletonDataResource> data_res);
+	Ref<SpineSkeletonDataResource> get_skeleton_data_res() const;
+
+	void set_spine_object(spine::Skeleton *s) { skeleton = s; }
+	spine::Skeleton *get_spine_object() { return skeleton; }
+
+	void set_spine_sprite(SpineSprite *sprite);
+
 private:
 	spine::Skeleton *skeleton;
 	SpineSprite *sprite;
 	Ref<SpineSkeletonDataResource> skeleton_data_res;
+	spine::Vector<float> bounds_vertex_buffer;
 
 public:
 	SpineSkeleton();
-	~SpineSkeleton();
-
-	void set_skeleton_data_res(Ref<SpineSkeletonDataResource> data_res);
-	Ref<SpineSkeletonDataResource> get_skeleton_data_res() const;
-
-	inline void set_spine_object(spine::Skeleton *s) {
-		skeleton = s;
-	}
-	inline spine::Skeleton *get_spine_object() {
-		return skeleton;
-	}
-
-	void set_spine_sprite(SpineSprite *sprite);
+	~SpineSkeleton() override;
 
 	void update_world_transform();
 
@@ -81,45 +85,59 @@ public:
 	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();
+	Rect2 get_bounds();
 
 	Ref<SpineBone> get_root_bone();
 
 	Array get_bones();
+
 	Array get_slots();
-	Array get_draw_orders();
+
+	Array get_draw_order();
+
 	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);
+	void set_position(Vector2 position);
 
 	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);
 };
 

+ 118 - 123
spine-godot/spine_godot/SpineSkeletonDataResource.cpp

@@ -28,7 +28,7 @@
  *****************************************************************************/
 
 #include "SpineSkeletonDataResource.h"
-
+#include "SpineCommon.h"
 #include "core/io/marshalls.h"
 
 void SpineAnimationMix::_bind_methods() {
@@ -41,33 +41,34 @@ void SpineAnimationMix::_bind_methods() {
 
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "from"), "set_from", "get_from");
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "to"), "set_to", "get_to");
+#if VERSION_MAJOR > 3
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix"), "set_mix", "get_mix");
+#else
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "mix"), "set_mix", "get_mix");
+#endif
 }
 
 SpineAnimationMix::SpineAnimationMix(): from(""), to(""), mix(0) {
 }
 
-SpineAnimationMix::~SpineAnimationMix() {
-}
-
-void SpineAnimationMix::set_from(const StringName &from) {
-	this->from = from;
+void SpineAnimationMix::set_from(const StringName &_from) {
+	this->from = _from;
 }
 
 String SpineAnimationMix::get_from() {
 	return from;
 }
 
-void SpineAnimationMix::set_to(const StringName &to) {
-	this->to = to;
+void SpineAnimationMix::set_to(const StringName &_to) {
+	this->to = _to;
 }
 
 String SpineAnimationMix::get_to() {
 	return to;
 }
 
-void SpineAnimationMix::set_mix(float mix) {
-	this->mix = mix;
+void SpineAnimationMix::set_mix(float _mix) {
+	this->mix = _mix;
 }
 
 float SpineAnimationMix::get_mix() {
@@ -119,11 +120,15 @@ void SpineSkeletonDataResource::_bind_methods() {
 
 	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");
+#if VERSION_MAJOR > 3
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_mix"), "set_default_mix", "get_default_mix");
+#else
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "default_mix"), "set_default_mix", "get_default_mix");
+#endif
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animation_mixes"), "set_animation_mixes", "get_animation_mixes");
 }
 
-SpineSkeletonDataResource::SpineSkeletonDataResource() : skeleton_data(nullptr), animation_state_data(nullptr), default_mix(0) {
+SpineSkeletonDataResource::SpineSkeletonDataResource() : default_mix(0), skeleton_data(nullptr), animation_state_data(nullptr) {
 }
 
 SpineSkeletonDataResource::~SpineSkeletonDataResource() {
@@ -142,32 +147,32 @@ void SpineSkeletonDataResource::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());
+		load_resources(atlas_res->get_spine_atlas(), skeleton_file_res->get_json(), skeleton_file_res->get_binary());
 	}
 	emit_signal("skeleton_data_changed");
 #ifdef TOOLS_ENABLED
-	property_list_changed_notify();
+	NOTIFY_PROPERTY_LIST_CHANGED();
 #endif
 }
 
-void SpineSkeletonDataResource::load_res(spine::Atlas *atlas, const String &json, const Vector<uint8_t> &binary) {
-	if ((json.empty() && binary.empty()) || atlas == nullptr) return;
+void SpineSkeletonDataResource::load_resources(spine::Atlas *atlas, const String &json, const Vector<uint8_t> &binary) {
+	if ((EMPTY(json) && EMPTY(binary)) || atlas == nullptr) return;
 
 	spine::SkeletonData *data;
-	if (!json.empty()) {
+	if (!EMPTY(json)) {
 		spine::SkeletonJson skeletonJson(atlas);
 		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());
+			ERR_PRINT(String("Error while loading skeleton data: ") + get_path());
+			ERR_PRINT(String("Error message: ") + skeletonJson.getError().buffer());
 			return;
 		}
 	} else {
 		spine::SkeletonBinary skeletonBinary(atlas);
 		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());
+			ERR_PRINT(String("Error while loading skeleton data: ") + get_path());
+			ERR_PRINT(String("Error message: ") + skeletonBinary.getError().buffer());
 			return;
 		}
 	}
@@ -218,8 +223,8 @@ void SpineSkeletonDataResource::get_skin_names(Vector<String> &skin_names) const
 	}
 }
 
-void SpineSkeletonDataResource::set_default_mix(float default_mix) {
-	this->default_mix = default_mix;
+void SpineSkeletonDataResource::set_default_mix(float _default_mix) {
+	this->default_mix = _default_mix;
 	update_mixes();
 }
 
@@ -227,16 +232,16 @@ float SpineSkeletonDataResource::get_default_mix() {
 	return default_mix;
 }
 
-void SpineSkeletonDataResource::set_animation_mixes(Array animation_mixes) {
-	for (int i = 0; i < animation_mixes.size(); i++) {
-		auto objectId = Object::cast_to<EncodedObjectAsID>(animation_mixes[0]);
+void SpineSkeletonDataResource::set_animation_mixes(Array _animation_mixes) {
+	for (int i = 0; i < _animation_mixes.size(); i++) {
+		auto objectId = Object::cast_to<EncodedObjectAsID>(_animation_mixes[0]);
 		if (objectId) {
 			ERR_PRINT("Live-editing of animation mixes is not supported.");
 			return;
 		}
 	}
-	
-	this->animation_mixes = animation_mixes;
+
+	this->animation_mixes = _animation_mixes;
 	update_mixes();
 }
 
@@ -264,18 +269,10 @@ void SpineSkeletonDataResource::update_mixes() {
 	}
 }
 
-
-#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> SpineSkeletonDataResource::find_animation(const String &animation_name) const {
-	CHECK(nullptr)
-	if (animation_name.empty()) return nullptr;
-	auto animation = skeleton_data->findAnimation(S_T(animation_name));
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(animation_name)) return nullptr;
+	auto animation = skeleton_data->findAnimation(SPINE_STRING(animation_name));
 	if (!animation) return nullptr;
 	Ref<SpineAnimation> animation_ref(memnew(SpineAnimation));
 	animation_ref->set_spine_object(animation);
@@ -283,67 +280,68 @@ Ref<SpineAnimation> SpineSkeletonDataResource::find_animation(const String &anim
 }
 
 Ref<SpineBoneData> SpineSkeletonDataResource::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;
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(bone_name)) return nullptr;
+	auto bone = skeleton_data->findBone(SPINE_STRING(bone_name));
+	if (!bone) return nullptr;
 	Ref<SpineBoneData> bone_ref(memnew(SpineBoneData));
 	bone_ref->set_spine_object(bone);
 	return bone_ref;
 }
 
 Ref<SpineSlotData> SpineSkeletonDataResource::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;
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(slot_name)) return nullptr;
+	auto slot = skeleton_data->findSlot(SPINE_STRING(slot_name));
+	if (!slot) return nullptr;
 	Ref<SpineSlotData> slot_ref(memnew(SpineSlotData));
 	slot_ref->set_spine_object(slot);
 	return slot_ref;
 }
 
 Ref<SpineSkin> SpineSkeletonDataResource::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;
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(skin_name)) return nullptr;
+	auto skin = skeleton_data->findSkin(SPINE_STRING(skin_name));
+	if (!skin) return nullptr;
 	Ref<SpineSkin> skin_ref(memnew(SpineSkin));
 	skin_ref->set_spine_object(skin);
 	return skin_ref;
 }
 
 Ref<SpineEventData> SpineSkeletonDataResource::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;
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(event_data_name)) return nullptr;
+	auto event = skeleton_data->findEvent(SPINE_STRING(event_data_name));
+	if (!event) return nullptr;
 	Ref<SpineEventData> event_ref(memnew(SpineEventData));
 	event_ref->set_spine_object(event);
 	return event_ref;
 }
 
 Ref<SpineIkConstraintData> SpineSkeletonDataResource::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;
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton_data->findIkConstraint(SPINE_STRING(constraint_name));
+	if (!constraint) return nullptr;
 	Ref<SpineIkConstraintData> constraint_ref(memnew(SpineIkConstraintData));
 	constraint_ref->set_spine_object(constraint);
 	return constraint_ref;
 }
+
 Ref<SpineTransformConstraintData> SpineSkeletonDataResource::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;
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton_data->findTransformConstraint(SPINE_STRING(constraint_name));
+	if (!constraint) return nullptr;
 	Ref<SpineTransformConstraintData> constraint_ref(memnew(SpineTransformConstraintData));
 	constraint_ref->set_spine_object(constraint);
 	return constraint_ref;
 }
 Ref<SpinePathConstraintData> SpineSkeletonDataResource::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));
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton_data->findPathConstraint(SPINE_STRING(constraint_name));
 	if (constraint == nullptr) return nullptr;
 	Ref<SpinePathConstraintData> constraint_ref(memnew(SpinePathConstraintData));
 	constraint_ref->set_spine_object(constraint);
@@ -351,173 +349,170 @@ Ref<SpinePathConstraintData> SpineSkeletonDataResource::find_path_constraint(con
 }
 
 String SpineSkeletonDataResource::get_skeleton_name() const{
-	CHECK("")
+	SPINE_CHECK(skeleton_data, "")
 	return skeleton_data->getName().buffer();
 }
 
 Array SpineSkeletonDataResource::get_bones() const {
-	Array bone_refs;
-	CHECK(bone_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto bones = skeleton_data->getBones();
-	bone_refs.resize((int)bones.size());
+	result.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;
+		result[i] = bone_ref;
 	}
-	return bone_refs;
+	return result;
 }
 
 Array SpineSkeletonDataResource::get_slots() const {
-	Array slot_refs;
-	CHECK(slot_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto slots = skeleton_data->getSlots();
-	slot_refs.resize((int)slots.size());
+	result.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;
+		result[i] = slot_ref;
 	}
-	return slot_refs;
+	return result;
 }
 
 Array SpineSkeletonDataResource::get_skins() const {
-	Array skin_refs;
-	CHECK(skin_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto skins = skeleton_data->getSkins();
-	skin_refs.resize((int)skins.size());
+	result.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;
+		result[i] = skin_ref;
 	}
-	return skin_refs;
+	return result;
 }
 
 Ref<SpineSkin> SpineSkeletonDataResource::get_default_skin() const {
-	CHECK(nullptr)
+	SPINE_CHECK(skeleton_data, nullptr)
 	auto skin = skeleton_data->getDefaultSkin();
-	if (skin == nullptr) return nullptr;
+	if (skin) return nullptr;
 	Ref<SpineSkin> skin_ref(memnew(SpineSkin));
 	skin_ref->set_spine_object(skin);
 	return skin_ref;
 }
 
 void SpineSkeletonDataResource::set_default_skin(Ref<SpineSkin> skin) {
-	CHECK()
-	if (skin.is_valid())
-		skeleton_data->setDefaultSkin(skin->get_spine_object());
-	else
-		skeleton_data->setDefaultSkin(nullptr);
+	SPINE_CHECK(skeleton_data,)
+	skeleton_data->setDefaultSkin(skin.is_valid() ? skin->get_spine_object() : nullptr);
 }
 
 Array SpineSkeletonDataResource::get_events() const {
-	Array event_refs;
-	CHECK(event_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto events = skeleton_data->getEvents();
-	event_refs.resize((int)events.size());
+	result.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;
+		result[i] = event_ref;
 	}
-	return event_refs;
+	return result;
 }
 
 Array SpineSkeletonDataResource::get_animations() const {
-	Array animation_refs;
-	CHECK(animation_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto animations = skeleton_data->getAnimations();
-	animation_refs.resize((int)animations.size());
+	result.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;
+		result[i] = animation_ref;
 	}
-	return animation_refs;
+	return result;
 }
 
 Array SpineSkeletonDataResource::get_ik_constraints() const {
-	Array constraint_refs;
-	CHECK(constraint_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto constraints = skeleton_data->getIkConstraints();
-	constraint_refs.resize((int)constraints.size());
+	result.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;
+		result[i] = constraint_ref;
 	}
-	return constraint_refs;
+	return result;
 }
 
 Array SpineSkeletonDataResource::get_transform_constraints() const {
-	Array constraint_refs;
-	CHECK(constraint_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto constraints = skeleton_data->getTransformConstraints();
-	constraint_refs.resize((int)constraints.size());
+	result.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;
+		result[i] = constraint_ref;
 	}
-	return constraint_refs;
+	return result;
 }
 
 Array SpineSkeletonDataResource::get_path_constraints() const {
-	Array constraint_refs;
-	CHECK(constraint_refs)
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
 	auto constraints = skeleton_data->getPathConstraints();
-	constraint_refs.resize((int)constraints.size());
+	result.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;
+		result[i] = constraint_ref;
 	}
-	return constraint_refs;
+	return result;
 }
 
 float SpineSkeletonDataResource::get_x() const{
-	CHECK(0)
+	SPINE_CHECK(skeleton_data, 0)
 	return skeleton_data->getX();
 }
 
 float SpineSkeletonDataResource::get_y() const {
-	CHECK(0)
+	SPINE_CHECK(skeleton_data, 0)
 	return skeleton_data->getY();
 }
 
 float SpineSkeletonDataResource::get_width() const{
-	CHECK(0)
+	SPINE_CHECK(skeleton_data, 0)
 	return skeleton_data->getWidth();
 }
 
 float SpineSkeletonDataResource::get_height() const {
-	CHECK(0)
+	SPINE_CHECK(skeleton_data, 0)
 	return skeleton_data->getHeight();
 }
 
 String SpineSkeletonDataResource::get_version() const {
-	CHECK("")
+	SPINE_CHECK(skeleton_data, "")
 	return skeleton_data->getVersion().buffer();
 }
 
 String SpineSkeletonDataResource::get_hash() const {
-	CHECK("")
+	SPINE_CHECK(skeleton_data, "")
 	return skeleton_data->getHash().buffer();
 }
 
-
 String SpineSkeletonDataResource::get_images_path() const {
-	CHECK("")
+	SPINE_CHECK(skeleton_data, "")
 	return skeleton_data->getImagesPath().buffer();
 }
 
 String SpineSkeletonDataResource::get_audio_path() const {
-	CHECK("")
+	SPINE_CHECK(skeleton_data, "")
 	return skeleton_data->getAudioPath().buffer();
 }
 
 float SpineSkeletonDataResource::get_fps() const {
-	CHECK(0)
+	SPINE_CHECK(skeleton_data, 0)
 	return skeleton_data->getFps();
 }
+//

+ 3 - 4
spine-godot/spine_godot/SpineSkeletonDataResource.h

@@ -23,7 +23,6 @@ protected:
 	float mix;
 public:
 	SpineAnimationMix();
-	~SpineAnimationMix();
 
 	void set_from(const StringName &from);
 
@@ -55,7 +54,7 @@ private:
 
 	void update_skeleton_data();
 
-	void load_res(spine::Atlas *atlas, const String &json, const Vector<uint8_t> &binary);
+	void load_resources(spine::Atlas *atlas, const String &json, const Vector<uint8_t> &binary);
 
 public:
 	SpineSkeletonDataResource();
@@ -69,9 +68,9 @@ public:
 	void set_skeleton_file_res(const Ref<SpineSkeletonFileResource> &skeleton_file);
 	Ref<SpineSkeletonFileResource> get_skeleton_file_res();
 
-	inline spine::SkeletonData *get_skeleton_data() const { return skeleton_data; }
+	spine::SkeletonData *get_skeleton_data() const { return skeleton_data; }
 
-	inline spine::AnimationStateData *get_animation_state_data() const { return animation_state_data; }
+	spine::AnimationStateData *get_animation_state_data() const { return animation_state_data; }
 
 	void get_animation_names(Vector<String> &animation_names) const;
 

+ 46 - 33
spine-godot/spine_godot/SpineSkeletonFileResource.cpp

@@ -28,67 +28,80 @@
  *****************************************************************************/
 
 #include "SpineSkeletonFileResource.h"
+#if VERSION_MAJOR > 3
+#include "core/io/file_access.h"
+#else
+#include "core/os/file_access.h"
+#endif
 
 void SpineSkeletonFileResource::_bind_methods() {
 }
 
-Error SpineSkeletonFileResource::load_from_file(const String &p_path) {
-	Error err;
-
-	if (p_path.ends_with("spjson"))
-		json = FileAccess::get_file_as_string(p_path, &err);
+Error SpineSkeletonFileResource::load_from_file(const String &path) {
+	Error error;
+	if (path.ends_with("spjson"))
+		json = FileAccess::get_file_as_string(path, &error);
 	else
-		binary = FileAccess::get_file_as_array(p_path, &err);
-	return err;
+		binary = FileAccess::get_file_as_array(path, &error);
+	return error;
 }
 
-Error SpineSkeletonFileResource::save_to_file(const String &p_path) {
-	Error err;
-	FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
-	if (err != OK) {
+Error SpineSkeletonFileResource::save_to_file(const String &path) {
+	Error error;
+#if VERSION_MAJOR > 3
+	Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &error);
+	if (error != OK) return error;
+#else
+	FileAccess *file = FileAccess::open(path, FileAccess::WRITE, &error);
+	if (error != OK) {
 		if (file) file->close();
-		return err;
+		return error;
 	}
-
+#endif
 	if (!is_binary())
 		file->store_string(json);
 	else
 		file->store_buffer(binary.ptr(), binary.size());
+#if VERSION_MAJOR > 3
+	file->flush();
+#else
 	file->close();
-
+#endif
 	return OK;
 }
 
-RES SpineSkeletonFileResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error) {
-	Ref<SpineSkeletonFileResource> skeleton = memnew(SpineSkeletonFileResource);
-	skeleton->load_from_file(p_path);
-
-	if (r_error) {
-		*r_error = OK;
-	}
-	return skeleton;
+#if VERSION_MAJOR > 3
+RES SpineSkeletonFileResourceFormatLoader::load(const String &path, const String &original_path, Error *error, bool use_sub_threads, float *progress, CacheMode cache_mode) {
+#else
+RES SpineSkeletonFileResourceFormatLoader::load(const String &path, const String &original_path, Error *error) {
+#endif
+	Ref<SpineSkeletonFileResource> skeleton_file = memnew(SpineSkeletonFileResource);
+	skeleton_file->load_from_file(path);
+	if (error) *error = OK;
+	return skeleton_file;
 }
 
-void SpineSkeletonFileResourceFormatLoader::get_recognized_extensions(List<String> *r_extensions) const {
-	r_extensions->push_back("spjson");
-	r_extensions->push_back("spskel");
+void SpineSkeletonFileResourceFormatLoader::get_recognized_extensions(List<String> *extensions) const {
+	extensions->push_back("spjson");
+	extensions->push_back("spskel");
 }
 
-String SpineSkeletonFileResourceFormatLoader::get_resource_type(const String &p_path) const {
+String SpineSkeletonFileResourceFormatLoader::get_resource_type(const String &path) const {
 	return "SpineSkeletonFileResource";
 }
 
-bool SpineSkeletonFileResourceFormatLoader::handles_type(const String &p_type) const {
-	return p_type == "SpineSkeletonFileResource" || ClassDB::is_parent_class(p_type, "SpineSkeletonFileResource");
+bool SpineSkeletonFileResourceFormatLoader::handles_type(const String &type) const {
+	return type == "SpineSkeletonFileResource" || ClassDB::is_parent_class(type, "SpineSkeletonFileResource");
 }
-Error SpineSkeletonFileResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
-	Ref<SpineSkeletonFileResource> res = p_resource.get_ref_ptr();
-	Error error = res->save_to_file(p_path);
+
+Error SpineSkeletonFileResourceFormatSaver::save(const String &path, const RES &resource, uint32_t flags) {
+	Ref<SpineSkeletonFileResource> res = resource;
+	Error error = res->save_to_file(path);
 	return error;
 }
 
-void SpineSkeletonFileResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
-	if (Object::cast_to<SpineSkeletonFileResource>(*p_resource)) {
+void SpineSkeletonFileResourceFormatSaver::get_recognized_extensions(const RES &resource, List<String> *p_extensions) const {
+	if (Object::cast_to<SpineSkeletonFileResource>(*resource)) {
 		p_extensions->push_back("spjson");
 		p_extensions->push_back("spskel");
 	}

+ 24 - 12
spine-godot/spine_godot/SpineSkeletonFileResource.h

@@ -30,7 +30,7 @@
 #ifndef GODOT_SPINESKELETONFILERESOURCE_H
 #define GODOT_SPINESKELETONFILERESOURCE_H
 
-#include "core/variant_parser.h"
+#include "SpineCommon.h"
 #include "core/io/resource_loader.h"
 #include "core/io/resource_saver.h"
 
@@ -44,30 +44,42 @@ protected:
 	Vector<uint8_t> binary;
 
 public:
-	inline const bool is_binary() { return !binary.empty(); }
-	inline const Vector<uint8_t> &get_binary() { return binary; }
-	inline const String &get_json() { return json; }
+	bool is_binary() { return binary.size() > 0; }
 
-	Error load_from_file(const String &p_path);
-	Error save_to_file(const String &p_path);
+	const Vector<uint8_t> &get_binary() { return binary; }
+
+	const String &get_json() { return json; }
+
+	Error load_from_file(const String &path);
+
+	Error save_to_file(const String &path);
 };
 
 class SpineSkeletonFileResourceFormatLoader : public ResourceFormatLoader {
 	GDCLASS(SpineSkeletonFileResourceFormatLoader, ResourceFormatLoader);
 
 public:
-	virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL);
-	virtual void get_recognized_extensions(List<String> *r_extensions) const;
-	virtual bool handles_type(const String &p_type) const;
-	virtual String get_resource_type(const String &p_path) const;
+#if VERSION_MAJOR > 3
+	RES load(const String &path, const String &original_path, Error *error, bool use_sub_threads, float *progress, CacheMode cache_mode);
+#else
+	RES load(const String &path, const String &original_path, Error *error) override;
+#endif
+
+	void get_recognized_extensions(List<String> *extensions) const override;
+
+	bool handles_type(const String &type) const override;
+
+	String get_resource_type(const String &path) const override;
 };
 
 class SpineSkeletonFileResourceFormatSaver : public ResourceFormatSaver {
 	GDCLASS(SpineSkeletonFileResourceFormatSaver, ResourceFormatSaver);
 
 public:
-	Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) override;
-	void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const override;
+	Error save(const String &path, const RES &resource, uint32_t flags) override;
+
+	void get_recognized_extensions(const RES &resource, List<String> *p_extensions) const override;
+
 	bool recognize(const RES &p_resource) const override;
 };
 

+ 116 - 75
spine-godot/spine_godot/SpineSkin.cpp

@@ -28,9 +28,9 @@
  *****************************************************************************/
 
 #include "SpineSkin.h"
-
 #include "SpineBoneData.h"
 #include "SpineConstraintData.h"
+#include "SpineCommon.h"
 
 void SpineSkin::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("init", "name"), &SpineSkin::init);
@@ -39,123 +39,164 @@ void SpineSkin::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("remove_attachment", "slot_index", "name"), &SpineSkin::remove_attachment);
 	ClassDB::bind_method(D_METHOD("find_names_for_slot", "slot_index"), &SpineSkin::find_names_for_slot);
 	ClassDB::bind_method(D_METHOD("find_attachments_for_slot", "slot_index"), &SpineSkin::find_attachments_for_slot);
-	ClassDB::bind_method(D_METHOD("get_skin_name"), &SpineSkin::get_skin_name);
+	ClassDB::bind_method(D_METHOD("get_name"), &SpineSkin::get_name);
 	ClassDB::bind_method(D_METHOD("add_skin", "other"), &SpineSkin::add_skin);
 	ClassDB::bind_method(D_METHOD("copy_skin", "other"), &SpineSkin::copy_skin);
 	ClassDB::bind_method(D_METHOD("get_attachments"), &SpineSkin::get_attachments);
-	ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineSkin::get_bones);
-	ClassDB::bind_method(D_METHOD("get_all_constraint_data"), &SpineSkin::get_constraint);
+	ClassDB::bind_method(D_METHOD("get_bones"), &SpineSkin::get_bones);
+	ClassDB::bind_method(D_METHOD("get_constraints"), &SpineSkin::get_constraints);
+}
+
+SpineSkin::SpineSkin() : skin(nullptr), owns_skin(false) {
 }
 
-SpineSkin::SpineSkin() : skin(NULL) {}
-SpineSkin::~SpineSkin() {}
+SpineSkin::~SpineSkin() {
+	if (owns_skin) delete skin;
+}
 
-#define S_T(x) (spine::String(x.utf8()))
 Ref<SpineSkin> SpineSkin::init(const String &name) {
-	skin = new spine::Skin(S_T(name));
+	if (skin) {
+		ERR_PRINT("Can not initialize an already initialized skin.");
+		return this;
+	}
+	owns_skin = true;
+	skin = new spine::Skin(SPINE_STRING(name));
 	return this;
 }
 
 void SpineSkin::set_attachment(uint64_t slot_index, const String &name, Ref<SpineAttachment> attachment) {
-	if (!attachment.is_valid()) {
-		ERR_PRINT("attachment is invalid!");
-		return;
-	}
-	skin->setAttachment(slot_index, S_T(name), attachment->get_spine_object());
+	SPINE_CHECK(skin,)
+	skin->setAttachment(slot_index, SPINE_STRING(name), attachment.is_valid() ? attachment->get_spine_object() : nullptr);
 }
 
 Ref<SpineAttachment> SpineSkin::get_attachment(uint64_t slot_index, const String &name) {
-	auto a = skin->getAttachment(slot_index, S_T(name));
-	if (a == NULL) return NULL;
-	Ref<SpineAttachment> gd_attachment(memnew(SpineAttachment));
-	gd_attachment->set_spine_object(a);
-	return gd_attachment;
+	SPINE_CHECK(skin, nullptr)
+	auto attachment = skin->getAttachment(slot_index, SPINE_STRING(name));
+	if (attachment) return nullptr;
+	Ref<SpineAttachment> attachment_ref(memnew(SpineAttachment));
+	attachment_ref->set_spine_object(attachment);
+	return attachment_ref;
 }
 
 void SpineSkin::remove_attachment(uint64_t slot_index, const String &name) {
-	skin->removeAttachment(slot_index, S_T(name));
+	SPINE_CHECK(skin,)
+	skin->removeAttachment(slot_index, SPINE_STRING(name));
 }
 
 Array SpineSkin::find_names_for_slot(uint64_t slot_index) {
+	Array result;
+	SPINE_CHECK(skin, result)
 	spine::Vector<spine::String> names;
 	skin->findNamesForSlot(slot_index, names);
-	Array gd_names;
-	gd_names.resize(names.size());
-	for (size_t i = 0; i < names.size(); ++i) {
-		gd_names[i] = names[i].buffer();
+	result.resize((int)names.size());
+	for (int i = 0; i < names.size(); ++i) {
+		result[i] = names[i].buffer();
 	}
-	return gd_names;
+	return result;
 }
 
 Array SpineSkin::find_attachments_for_slot(uint64_t slot_index) {
-	spine::Vector<spine::Attachment *> as;
-	skin->findAttachmentsForSlot(slot_index, as);
-	Array gd_as;
-	gd_as.resize(as.size());
-	for (size_t i = 0; i < as.size(); ++i) {
-		if (as[i] == NULL) gd_as[i] = Ref<SpineAttachment>(NULL);
-		else {
-			Ref<SpineAttachment> gd_a(memnew(SpineAttachment));
-			gd_a->set_spine_object(as[i]);
-			gd_as[i] = gd_a;
+	Array result;
+	SPINE_CHECK(skin, result)
+	spine::Vector<spine::Attachment *> attachments;
+	skin->findAttachmentsForSlot(slot_index, attachments);
+	result.resize((int)attachments.size());
+	for (int i = 0; i < attachments.size(); ++i) {
+		if (!attachments[i]) {
+			result[i] = Ref<SpineAttachment>(nullptr);
+		} else {
+			Ref<SpineAttachment> attachment_ref(memnew(SpineAttachment));
+			attachment_ref->set_spine_object(attachments[i]);
+			result[i] = attachment_ref;
 		}
 	}
-	return gd_as;
+	return result;
 }
 
-String SpineSkin::get_skin_name() {
+String SpineSkin::get_name() {
+	SPINE_CHECK(skin, "")
 	return skin->getName().buffer();
 }
 
 void SpineSkin::add_skin(Ref<SpineSkin> other) {
-	if (other.is_valid() && other->get_spine_object()) {
-		skin->addSkin(other->get_spine_object());
-	} else {
-		ERR_PRINT("other is NULL!");
+	SPINE_CHECK(skin,)
+	if (!other.is_valid() || !other->get_spine_object()) {
+		ERR_PRINT("other is not a valid SpineSkin.");
+		return;
 	}
+	skin->addSkin(other->get_spine_object());
 }
 
 void SpineSkin::copy_skin(Ref<SpineSkin> other) {
-	if (other.is_valid() && other->get_spine_object()) {
-		skin->copySkin(other->get_spine_object());
-	} else {
-		ERR_PRINT("other is NULL!");
+	SPINE_CHECK(skin,)
+	if (!other.is_valid() || !other->get_spine_object()) {
+		ERR_PRINT("other is not a valid SpineSkin.");
+		return;
 	}
+	skin->copySkin(other->get_spine_object());
 }
 
-Ref<SpineSkinAttachmentMapEntries> SpineSkin::get_attachments() {
-	auto *es = new spine::Skin::AttachmentMap::Entries(skin->getAttachments());
-	Ref<SpineSkinAttachmentMapEntries> gd_es(memnew(SpineSkinAttachmentMapEntries));
-	gd_es->set_spine_object(es);
-	return gd_es;
+Array SpineSkin::get_attachments() {
+	Array result;
+	SPINE_CHECK(skin, result)
+	auto entries = skin->getAttachments();
+	while(entries.hasNext()) {
+		spine::Skin::AttachmentMap::Entry &entry = entries.next();
+		Ref<SpineSkinEntry> entry_ref = memnew(SpineSkinEntry);
+		Ref<SpineAttachment> attachment_ref = nullptr;
+		if (entry._attachment) {
+			attachment_ref = Ref<SpineAttachment>(memnew(SpineAttachment));
+			attachment_ref->set_spine_object(entry._attachment);
+		}
+		entry_ref->init(entry._slotIndex, entry._name.buffer(), attachment_ref);
+		result.push_back(entry_ref);
+	}
+	return result;
 }
 
 Array SpineSkin::get_bones() {
-	auto bs = skin->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;
-		}
+	Array result;
+	SPINE_CHECK(skin, result)
+	auto bones = skin->getBones();
+	result.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]);
+		result[i] = bone_ref;
 	}
-	return gd_bs;
-}
-
-Array SpineSkin::get_constraint() {
-	auto cs = skin->getConstraints();
-	Array gd_cs;
-	gd_cs.resize(cs.size());
-	for (size_t i = 0; i < cs.size(); ++i) {
-		if (cs[i] == NULL) gd_cs[i] = Ref<SpineConstraintData>(NULL);
-		else {
-			Ref<SpineConstraintData> gd_c(memnew(SpineConstraintData));
-			gd_c->set_spine_object(cs[i]);
-			gd_cs[i] = gd_c;
-		}
+	return result;
+}
+
+Array SpineSkin::get_constraints() {
+	Array result;
+	SPINE_CHECK(skin, result)
+	auto constraints = skin->getConstraints();
+	result.resize((int)constraints.size());
+	for (int i = 0; i < constraints.size(); ++i) {
+		Ref<SpineConstraintData> constraint_ref(memnew(SpineConstraintData));
+		constraint_ref->set_spine_object(constraints[i]);
+		result[i] = constraint_ref;
 	}
-	return gd_cs;
-}
+	return result;
+}
+
+void SpineSkinEntry::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("get_slot_index"), &SpineSkinEntry::get_slot_index);
+	ClassDB::bind_method(D_METHOD("get_name"), &SpineSkinEntry::get_name);
+	ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSkinEntry::get_attachment);
+}
+
+SpineSkinEntry::SpineSkinEntry() : slot_index(0) {
+}
+
+int SpineSkinEntry::get_slot_index() {
+	return slot_index;
+}
+
+const String &SpineSkinEntry::get_name() {
+	return name;
+}
+
+Ref<SpineAttachment> SpineSkinEntry::get_attachment() {
+	return attachment;
+}

+ 38 - 17
spine-godot/spine_godot/SpineSkin.h

@@ -30,32 +30,25 @@
 #ifndef GODOT_SPINESKIN_H
 #define GODOT_SPINESKIN_H
 
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
-
+#include "SpineCommon.h"
 #include "SpineAttachment.h"
-#include "SpineSkinAttachmentMapEntries.h"
 
-class SpineSkin : public Reference {
-	GDCLASS(SpineSkin, Reference);
+class SpineSkin : public REFCOUNTED {
+	GDCLASS(SpineSkin, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
 
 private:
 	spine::Skin *skin;
+	bool owns_skin;
 
 public:
 	SpineSkin();
-	~SpineSkin();
+	~SpineSkin() override;
 
-	inline void set_spine_object(spine::Skin *s) {
-		skin = s;
-	}
-	spine::Skin *get_spine_object() {
-		return skin;
-	}
+	void set_spine_object(spine::Skin *s) { skin = s; }
+	spine::Skin *get_spine_object() { return skin; }
 
 	Ref<SpineSkin> init(const String &name);
 
@@ -69,17 +62,45 @@ public:
 
 	Array find_attachments_for_slot(uint64_t slot_index);
 
-	String get_skin_name();
+	String get_name();
 
 	void add_skin(Ref<SpineSkin> other);
 
 	void copy_skin(Ref<SpineSkin> other);
 
-	Ref<SpineSkinAttachmentMapEntries> get_attachments();
+	Array get_attachments();
 
 	Array get_bones();
 
-	Array get_constraint();
+	Array get_constraints();
+};
+
+class SpineSkinEntry : public REFCOUNTED {
+GDCLASS(SpineSkinEntry, REFCOUNTED);
+
+	friend class SpineSkin;
+
+protected:
+	static void _bind_methods();
+
+	void init(int _slot_index, const String &_name, Ref<SpineAttachment> _attachment) {
+		this->slot_index = _slot_index;
+		this->name = _name;
+		this->attachment = _attachment;
+	}
+private:
+	int slot_index;
+	String name;
+	Ref<SpineAttachment> attachment;
+
+public:
+	SpineSkinEntry();
+
+	int get_slot_index();
+
+	const String &get_name();
+
+	Ref<SpineAttachment> get_attachment();
 };
 
 #endif//GODOT_SPINESKIN_H

+ 0 - 93
spine-godot/spine_godot/SpineSkinAttachmentMapEntries.cpp

@@ -1,93 +0,0 @@
-/******************************************************************************
- * 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 "SpineSkinAttachmentMapEntries.h"
-
-void SpineSkinAttachmentMapEntry::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("get_slot_index"), &SpineSkinAttachmentMapEntry::get_slot_index);
-	ClassDB::bind_method(D_METHOD("set_slot_index", "v"), &SpineSkinAttachmentMapEntry::set_slot_index);
-	ClassDB::bind_method(D_METHOD("get_entry_name"), &SpineSkinAttachmentMapEntry::get_entry_name);
-	ClassDB::bind_method(D_METHOD("set_entry_name", "v"), &SpineSkinAttachmentMapEntry::set_entry_name);
-	ClassDB::bind_method(D_METHOD("get_attachment"), &SpineSkinAttachmentMapEntry::get_attachment);
-	ClassDB::bind_method(D_METHOD("set_attachment", "v"), &SpineSkinAttachmentMapEntry::set_attachment);
-}
-
-SpineSkinAttachmentMapEntry::SpineSkinAttachmentMapEntry() : entry(NULL) {}
-SpineSkinAttachmentMapEntry::~SpineSkinAttachmentMapEntry() {}
-
-uint64_t SpineSkinAttachmentMapEntry::get_slot_index() {
-	return entry->_slotIndex;
-}
-void SpineSkinAttachmentMapEntry::set_slot_index(uint64_t v) {
-	entry->_slotIndex = v;
-}
-
-String SpineSkinAttachmentMapEntry::get_entry_name() {
-	return entry->_name.buffer();
-}
-void SpineSkinAttachmentMapEntry::set_entry_name(const String &v) {
-	entry->_name = spine::String(v.utf8());
-}
-
-Ref<SpineAttachment> SpineSkinAttachmentMapEntry::get_attachment() {
-	if (entry->_attachment == NULL) return NULL;
-	Ref<SpineAttachment> gd_attachment(memnew(SpineAttachment));
-	gd_attachment->set_spine_object(entry->_attachment);
-	return gd_attachment;
-}
-void SpineSkinAttachmentMapEntry::set_attachment(Ref<SpineAttachment> v) {
-	if (v.is_valid()) {
-		entry->_attachment = v->get_spine_object();
-	} else {
-		entry->_attachment = NULL;
-	}
-}
-
-void SpineSkinAttachmentMapEntries::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("has_next"), &SpineSkinAttachmentMapEntries::has_next);
-	ClassDB::bind_method(D_METHOD("next"), &SpineSkinAttachmentMapEntries::next);
-}
-
-SpineSkinAttachmentMapEntries::SpineSkinAttachmentMapEntries() : entries(NULL) {}
-SpineSkinAttachmentMapEntries::~SpineSkinAttachmentMapEntries() {
-	if (entries) {
-		delete entries;
-		return;
-	}
-}
-
-bool SpineSkinAttachmentMapEntries::has_next() {
-	return entries->hasNext();
-}
-Ref<SpineSkinAttachmentMapEntry> SpineSkinAttachmentMapEntries::next() {
-	auto &e = entries->next();
-	Ref<SpineSkinAttachmentMapEntry> gd_entry(memnew(SpineSkinAttachmentMapEntry));
-	gd_entry->set_spine_object(&e);
-	return gd_entry;
-}

+ 0 - 93
spine-godot/spine_godot/SpineSkinAttachmentMapEntries.h

@@ -1,93 +0,0 @@
-/******************************************************************************
- * 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_SPINESKINATTACHMENTMAPENTRIES_H
-#define GODOT_SPINESKINATTACHMENTMAPENTRIES_H
-
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
-
-#include "SpineAttachment.h"
-
-class SpineSkinAttachmentMapEntry : public Reference {
-	GDCLASS(SpineSkinAttachmentMapEntry, Reference);
-
-protected:
-	static void _bind_methods();
-
-private:
-	spine::Skin::AttachmentMap::Entry *entry;
-
-public:
-	SpineSkinAttachmentMapEntry();
-	~SpineSkinAttachmentMapEntry();
-
-	inline void set_spine_object(spine::Skin::AttachmentMap::Entry *e) {
-		entry = e;
-	}
-	inline spine::Skin::AttachmentMap::Entry *get_spine_object() {
-		return entry;
-	}
-
-	uint64_t get_slot_index();
-	void set_slot_index(uint64_t v);
-
-	String get_entry_name();
-	void set_entry_name(const String &v);
-
-	Ref<SpineAttachment> get_attachment();
-	void set_attachment(Ref<SpineAttachment> v);
-};
-
-class SpineSkinAttachmentMapEntries : public Reference {
-	GDCLASS(SpineSkinAttachmentMapEntries, Reference);
-
-protected:
-	static void _bind_methods();
-
-private:
-	spine::Skin::AttachmentMap::Entries *entries;
-
-public:
-	SpineSkinAttachmentMapEntries();
-	~SpineSkinAttachmentMapEntries();
-
-	inline void set_spine_object(spine::Skin::AttachmentMap::Entries *e) {
-		entries = e;
-	}
-	inline spine::Skin::AttachmentMap::Entries *get_spine_object() {
-		return entries;
-	}
-
-	bool has_next();
-	Ref<SpineSkinAttachmentMapEntry> next();
-};
-
-#endif//GODOT_SPINESKINATTACHMENTMAPENTRIES_H

+ 74 - 47
spine-godot/spine_godot/SpineSlot.cpp

@@ -28,13 +28,12 @@
  *****************************************************************************/
 
 #include "SpineSlot.h"
-
 #include "SpineBone.h"
 #include "SpineSkeleton.h"
-
+#include "SpineCommon.h"
 
 void SpineSlot::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("set_to_setup_pos"), &SpineSlot::set_to_setup_pos);
+	ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineSlot::set_to_setup_pose);
 	ClassDB::bind_method(D_METHOD("get_data"), &SpineSlot::get_data);
 	ClassDB::bind_method(D_METHOD("get_bone"), &SpineSlot::get_bone);
 	ClassDB::bind_method(D_METHOD("get_skeleton"), &SpineSlot::get_skeleton);
@@ -49,93 +48,121 @@ void SpineSlot::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_attachment_state", "v"), &SpineSlot::set_attachment_state);
 	ClassDB::bind_method(D_METHOD("get_deform"), &SpineSlot::get_deform);
 	ClassDB::bind_method(D_METHOD("set_deform", "v"), &SpineSlot::set_deform);
+	ClassDB::bind_method(D_METHOD("get_sequence_index"), &SpineSlot::get_sequence_index);
+	ClassDB::bind_method(D_METHOD("set_sequence_index", "v"), &SpineSlot::set_sequence_index);
 }
 
-SpineSlot::SpineSlot() : slot(NULL) {}
-SpineSlot::~SpineSlot() {}
+SpineSlot::SpineSlot() : slot(nullptr) {
+}
 
-void SpineSlot::set_to_setup_pos() {
+void SpineSlot::set_to_setup_pose() {
+	SPINE_CHECK(slot,)
 	slot->setToSetupPose();
 }
 
 Ref<SpineSlotData> SpineSlot::get_data() {
-	auto &sd = slot->getData();
-	Ref<SpineSlotData> gd_sd(memnew(SpineSlotData));
-	gd_sd->set_spine_object(&sd);
-	return gd_sd;
+	SPINE_CHECK(slot, nullptr)
+	auto &slot_data = slot->getData();
+	Ref<SpineSlotData> slot_data_ref(memnew(SpineSlotData));
+	slot_data_ref->set_spine_object(&slot_data);
+	return slot_data_ref;
 }
 
 Ref<SpineBone> SpineSlot::get_bone() {
-	auto &b = slot->getBone();
-	Ref<SpineBone> gd_b(memnew(SpineBone));
-	gd_b->set_spine_object(&b);
-	return gd_b;
+	SPINE_CHECK(slot, nullptr)
+	auto &bone = slot->getBone();
+	Ref<SpineBone> bone_ref(memnew(SpineBone));
+	bone_ref->set_spine_object(&bone);
+	return bone_ref;
 }
 
 Ref<SpineSkeleton> SpineSlot::get_skeleton() {
-	auto &s = slot->getSkeleton();
-	Ref<SpineSkeleton> gd_s(memnew(SpineSkeleton));
-	gd_s->set_spine_object(&s);
-	return gd_s;
+	SPINE_CHECK(slot, nullptr)
+	auto &skeleton = slot->getSkeleton();
+	Ref<SpineSkeleton> skeleton_ref(memnew(SpineSkeleton));
+	skeleton_ref->set_spine_object(&skeleton);
+	return skeleton_ref;
 }
 
 Color SpineSlot::get_color() {
-	auto &c = slot->getColor();
-	return Color(c.r, c.g, c.b, c.a);
+	SPINE_CHECK(slot, Color(0, 0, 0, 0))
+	auto &color = slot->getColor();
+	return Color(color.r, color.g, color.b, color.a);
 }
+
 void SpineSlot::set_color(Color v) {
-	auto &c = slot->getColor();
-	c.set(v.r, v.g, v.b, v.a);
+	SPINE_CHECK(slot,)
+	auto &color = slot->getColor();
+	color.set(v.r, v.g, v.b, v.a);
 }
 
 Color SpineSlot::get_dark_color() {
-	auto &c = slot->getDarkColor();
-	return Color(c.r, c.g, c.b, c.a);
+	SPINE_CHECK(slot, Color(0, 0, 0, 0))
+	auto &color = slot->getDarkColor();
+	return Color(color.r, color.g, color.b, color.a);
 }
+
 void SpineSlot::set_dark_color(Color v) {
-	auto &c = slot->getDarkColor();
-	c.set(v.r, v.g, v.b, v.a);
+	SPINE_CHECK(slot,)
+	auto &color = slot->getDarkColor();
+	color.set(v.r, v.g, v.b, v.a);
 }
 
 bool SpineSlot::has_dark_color() {
+	SPINE_CHECK(slot, false)
 	return slot->hasDarkColor();
 }
 
 Ref<SpineAttachment> SpineSlot::get_attachment() {
-	auto a = slot->getAttachment();
-	if (a == NULL) return NULL;
-	Ref<SpineAttachment> gd_a(memnew(SpineAttachment));
-	gd_a->set_spine_object(a);
-	return gd_a;
+	SPINE_CHECK(slot, nullptr)
+	auto attachment = slot->getAttachment();
+	if (!attachment) return nullptr;
+	Ref<SpineAttachment> attachment_ref(memnew(SpineAttachment));
+	attachment_ref->set_spine_object(attachment);
+	return attachment_ref;
 }
+
 void SpineSlot::set_attachment(Ref<SpineAttachment> v) {
-	if (v.is_valid()) {
-		slot->setAttachment(v->get_spine_object());
-	} else {
-		slot->setAttachment(NULL);
-	}
+	SPINE_CHECK(slot,)
+	slot->setAttachment(v.is_valid() ? v->get_spine_object() : nullptr);
 }
 
 int SpineSlot::get_attachment_state() {
+	SPINE_CHECK(slot, 0)
 	return slot->getAttachmentState();
 }
+
 void SpineSlot::set_attachment_state(int v) {
+	SPINE_CHECK(slot,)
 	slot->setAttachmentState(v);
 }
 
 Array SpineSlot::get_deform() {
-	auto &ds = slot->getDeform();
-	Array gd_ds;
-	gd_ds.resize(ds.size());
-	for (size_t i = 0; i < ds.size(); ++i) {
-		gd_ds[i] = ds[i];
+	Array result;
+	SPINE_CHECK(slot, result)
+	auto &deform = slot->getDeform();
+	result.resize((int)deform.size());
+	for (int i = 0; i < deform.size(); ++i) {
+		result[i] = deform[i];
 	}
-	return gd_ds;
+	return result;
 }
-void SpineSlot::set_deform(Array gd_ds) {
-	auto &ds = slot->getDeform();
-	ds.setSize(gd_ds.size(), 0);
-	for (size_t i = 0; i < gd_ds.size(); ++i) {
-		ds[i] = gd_ds[i];
+
+void SpineSlot::set_deform(Array v) {
+	SPINE_CHECK(slot,)
+	auto &deform = slot->getDeform();
+	deform.setSize(v.size(), 0);
+	for (int i = 0; i < v.size(); ++i) {
+		deform[i] = v[i];
 	}
 }
+
+int SpineSlot::get_sequence_index() {
+	SPINE_CHECK(slot, 0)
+	return slot->getAttachmentState();
+}
+
+void SpineSlot::set_sequence_index(int v) {
+	SPINE_CHECK(slot,)
+	slot->setAttachmentState(v);
+}

+ 17 - 16
spine-godot/spine_godot/SpineSlot.h

@@ -30,19 +30,16 @@
 #ifndef GODOT_SPINESLOT_H
 #define GODOT_SPINESLOT_H
 
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
-
+#include "SpineCommon.h"
 #include "SpineSlotData.h"
 #include "SpineAttachment.h"
+#include "SpineBone.h"
 
+// Breaks cyclic dependency.
 class SpineSkeleton;
 
-class SpineBone;
-
-class SpineSlot : public Reference {
-	GDCLASS(SpineSlot, Reference);
+class SpineSlot : public REFCOUNTED {
+	GDCLASS(SpineSlot, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -52,16 +49,11 @@ private:
 
 public:
 	SpineSlot();
-	~SpineSlot();
 
-	inline void set_spine_object(spine::Slot *s) {
-		slot = s;
-	}
-	inline spine::Slot *get_spine_object() {
-		return slot;
-	}
+	void set_spine_object(spine::Slot *s) { slot = s; }
+	spine::Slot *get_spine_object() { return slot; }
 
-	void set_to_setup_pos();
+	void set_to_setup_pose();
 
 	Ref<SpineSlotData> get_data();
 
@@ -70,21 +62,30 @@ public:
 	Ref<SpineSkeleton> get_skeleton();
 
 	Color get_color();
+
 	void set_color(Color v);
 
 	Color get_dark_color();
+
 	void set_dark_color(Color v);
 
 	bool has_dark_color();
 
 	Ref<SpineAttachment> get_attachment();
+
 	void set_attachment(Ref<SpineAttachment> v);
 
 	int get_attachment_state();
+
 	void set_attachment_state(int v);
 
 	Array get_deform();
+
 	void set_deform(Array v);
+
+	int get_sequence_index();
+
+	void set_sequence_index(int v);
 };
 
 #endif//GODOT_SPINESLOT_H

+ 40 - 33
spine-godot/spine_godot/SpineSlotData.cpp

@@ -28,13 +28,16 @@
  *****************************************************************************/
 
 #include "SpineSlotData.h"
+#include "SpineCommon.h"
 
 void SpineSlotData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_index"), &SpineSlotData::get_index);
-	ClassDB::bind_method(D_METHOD("get_slot_name"), &SpineSlotData::get_slot_name);
+	ClassDB::bind_method(D_METHOD("get_name"), &SpineSlotData::get_name);
 	ClassDB::bind_method(D_METHOD("get_bone_data"), &SpineSlotData::get_bone_data);
 	ClassDB::bind_method(D_METHOD("get_color"), &SpineSlotData::get_color);
+	ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSlotData::set_color);
 	ClassDB::bind_method(D_METHOD("get_dark_color"), &SpineSlotData::get_dark_color);
+	ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlotData::set_dark_color);
 	ClassDB::bind_method(D_METHOD("has_dark_color"), &SpineSlotData::has_dark_color);
 	ClassDB::bind_method(D_METHOD("set_has_dark_color", "v"), &SpineSlotData::set_has_dark_color);
 	ClassDB::bind_method(D_METHOD("get_attachment_name"), &SpineSlotData::get_attachment_name);
@@ -42,73 +45,77 @@ void SpineSlotData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpineSlotData::get_blend_mode);
 	ClassDB::bind_method(D_METHOD("set_blend_mode", "v"), &SpineSlotData::set_blend_mode);
 
-	ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineSlotData::set_color);
-	ClassDB::bind_method(D_METHOD("set_dark_color", "v"), &SpineSlotData::set_dark_color);
-
-	BIND_ENUM_CONSTANT(BLENDMODE_NORMAL);
-	BIND_ENUM_CONSTANT(BLENDMODE_ADDITIVE);
-	BIND_ENUM_CONSTANT(BLENDMODE_MULTIPLY);
-	BIND_ENUM_CONSTANT(BLENDMODE_SCREEN);
 }
 
-SpineSlotData::SpineSlotData() : slot_data(NULL) {}
-SpineSlotData::~SpineSlotData() {}
+SpineSlotData::SpineSlotData() : slot_data(nullptr) {
+}
 
-#define S_T(x) (spine::String(x.utf8()))
 int SpineSlotData::get_index() {
+	SPINE_CHECK(slot_data, 0)
 	return slot_data->getIndex();
 }
 
-String SpineSlotData::get_slot_name() {
+String SpineSlotData::get_name() {
+	SPINE_CHECK(slot_data, String(""))
 	return slot_data->getName().buffer();
 }
 
 Ref<SpineBoneData> SpineSlotData::get_bone_data() {
-	auto &bd = slot_data->getBoneData();
-	Ref<SpineBoneData> gd_bone_data(memnew(SpineBoneData));
-	gd_bone_data->set_spine_object(&bd);
-	return gd_bone_data;
+	SPINE_CHECK(slot_data, nullptr)
+	auto &bone_data = slot_data->getBoneData();
+	Ref<SpineBoneData> bone_data_ref(memnew(SpineBoneData));
+	bone_data_ref->set_spine_object(&bone_data);
+	return bone_data_ref;
 }
 
 Color SpineSlotData::get_color() {
-	auto &c = slot_data->getColor();
-	return Color(c.r, c.g, c.b, c.a);
+	SPINE_CHECK(slot_data, Color(0, 0, 0, 0))
+	auto &color = slot_data->getColor();
+	return Color(color.r, color.g, color.b, color.a);
 }
+
 void SpineSlotData::set_color(Color v) {
-	auto &c = slot_data->getColor();
-	c.set(v.r, v.g, v.b, v.a);
+	SPINE_CHECK(slot_data,)
+	auto &color = slot_data->getColor();
+	color.set(v.r, v.g, v.b, v.a);
 }
 
 Color SpineSlotData::get_dark_color() {
-	auto &c = slot_data->getDarkColor();
-	return Color(c.r, c.g, c.b, c.a);
+	SPINE_CHECK(slot_data, Color(0, 0, 0, 0))
+	auto &color = slot_data->getDarkColor();
+	return Color(color.r, color.g, color.b, color.a);
 }
+
 void SpineSlotData::set_dark_color(Color v) {
-	auto &c = slot_data->getDarkColor();
-	c.set(v.r, v.g, v.b, v.a);
+	SPINE_CHECK(slot_data,)
+	auto &color = slot_data->getDarkColor();
+	color.set(v.r, v.g, v.b, v.a);
 }
 
 bool SpineSlotData::has_dark_color() {
+	SPINE_CHECK(slot_data, false)
 	return slot_data->hasDarkColor();
 }
+
 void SpineSlotData::set_has_dark_color(bool v) {
+	SPINE_CHECK(slot_data,)
 	slot_data->setHasDarkColor(v);
 }
 
 String SpineSlotData::get_attachment_name() {
+	SPINE_CHECK(slot_data, "")
 	return slot_data->getAttachmentName().buffer();
 }
 void SpineSlotData::set_attachment_name(const String &v) {
-	slot_data->setAttachmentName(S_T(v));
+	SPINE_CHECK(slot_data,)
+	slot_data->setAttachmentName(SPINE_STRING(v));
 }
 
-SpineSlotData::BlendMode SpineSlotData::get_blend_mode() {
-	auto bm = (int) slot_data->getBlendMode();
-	return (BlendMode) bm;
+SpineConstant::BlendMode SpineSlotData::get_blend_mode() {
+	SPINE_CHECK(slot_data, SpineConstant::BlendMode_Normal)
+	return (SpineConstant::BlendMode)slot_data->getBlendMode();
 }
-void SpineSlotData::set_blend_mode(BlendMode v) {
-	auto bm = (int) v;
-	slot_data->setBlendMode((spine::BlendMode) bm);
+void SpineSlotData::set_blend_mode(SpineConstant::BlendMode v) {
+	SPINE_CHECK(slot_data,)
+	slot_data->setBlendMode((spine::BlendMode) v);
 }
-
-#undef S_T

+ 15 - 24
spine-godot/spine_godot/SpineSlotData.h

@@ -29,14 +29,13 @@
 
 #ifndef GODOT_SPINESLOTDATA_H
 #define GODOT_SPINESLOTDATA_H
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
 
+#include "SpineCommon.h"
 #include "SpineBoneData.h"
+#include <spine/SlotData.h>
 
-class SpineSlotData : public Reference {
-	GDCLASS(SpineSlotData, Reference);
+class SpineSlotData : public REFCOUNTED {
+	GDCLASS(SpineSlotData, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -46,43 +45,35 @@ private:
 
 public:
 	SpineSlotData();
-	~SpineSlotData();
-
-	inline void set_spine_object(spine::SlotData *s) {
-		slot_data = s;
-	}
-	inline spine::SlotData *get_spine_object() {
-		return slot_data;
-	}
-
-	enum BlendMode {
-		BLENDMODE_NORMAL = 0,
-		BLENDMODE_ADDITIVE,
-		BLENDMODE_MULTIPLY,
-		BLENDMODE_SCREEN
-	};
+
+	void set_spine_object(spine::SlotData *s) { slot_data = s; }
+	spine::SlotData *get_spine_object() { return slot_data; }
 
 	int get_index();
 
-	String get_slot_name();
+	String get_name();
 
 	Ref<SpineBoneData> get_bone_data();
 
 	Color get_color();
+
 	void set_color(Color c);
 
 	Color get_dark_color();
+
 	void set_dark_color(Color c);
 
 	bool has_dark_color();
+
 	void set_has_dark_color(bool v);
 
 	String get_attachment_name();
+
 	void set_attachment_name(const String &v);
 
-	BlendMode get_blend_mode();
-	void set_blend_mode(BlendMode v);
+	SpineConstant::BlendMode get_blend_mode();
+
+	void set_blend_mode(SpineConstant::BlendMode v);
 };
 
-VARIANT_ENUM_CAST(SpineSlotData::BlendMode);
 #endif//GODOT_SPINESLOTDATA_H

+ 74 - 35
spine-godot/spine_godot/SpineSprite.cpp

@@ -46,9 +46,6 @@ void SpineSprite::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_bind_slot_nodes"), &SpineSprite::get_bind_slot_nodes);
 	ClassDB::bind_method(D_METHOD("set_bind_slot_nodes", "v"), &SpineSprite::set_bind_slot_nodes);
 
-	ClassDB::bind_method(D_METHOD("get_overlap"), &SpineSprite::get_overlap);
-	ClassDB::bind_method(D_METHOD("set_overlap", "v"), &SpineSprite::set_overlap);
-
 	ClassDB::bind_method(D_METHOD("bone_get_global_transform", "bone_name"), &SpineSprite::bone_get_global_transform);
 	ClassDB::bind_method(D_METHOD("bone_set_global_transform", "bone_name", "global_transform"), &SpineSprite::bone_set_global_transform);
 
@@ -65,14 +62,13 @@ void SpineSprite::_bind_methods() {
 	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, "SpineSkeletonDataResource"), "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);
+	BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Process)
+	BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Physics)
+	BIND_ENUM_CONSTANT(ProcessMode::ProcessMode_Manual)
 }
 
 SpineSprite::SpineSprite() : overlap(false), process_mode(ProcessMode_Process), skeleton_clipper(nullptr) {
@@ -121,8 +117,13 @@ void SpineSprite::_on_skeleton_data_changed() {
 	animation_state.unref();
 
 	if (skeleton_data_res.is_valid()) {
+#if VERSION_MAJOR > 3
+		if (!skeleton_data_res->is_connected("skeleton_data_changed", callable_mp(this, &SpineSprite::_on_skeleton_data_changed)))
+			skeleton_data_res->connect("skeleton_data_changed", callable_mp(this, &SpineSprite::_on_skeleton_data_changed));
+#else
 		if (!skeleton_data_res->is_connected("skeleton_data_changed", this, "_on_skeleton_data_changed"))
 			skeleton_data_res->connect("skeleton_data_changed", this, "_on_skeleton_data_changed");
+#endif
 	}
 
 	if (skeleton_data_res.is_valid() && skeleton_data_res->is_skeleton_data_loaded()) {
@@ -146,7 +147,7 @@ void SpineSprite::_on_skeleton_data_changed() {
 		}
 	}
 
-	property_list_changed_notify();
+	NOTIFY_PROPERTY_LIST_CHANGED();
 }
 
 Ref<SpineSkeleton> SpineSprite::get_skeleton() {
@@ -162,20 +163,25 @@ void SpineSprite::_notification(int p_what) {
 		case NOTIFICATION_READY: {
 			set_process_internal(process_mode == ProcessMode_Process);
 			set_physics_process_internal(process_mode == ProcessMode_Physics);
-		} break;
+			break;
+		}
 		case NOTIFICATION_INTERNAL_PROCESS: {
 			if (process_mode == ProcessMode_Process)
 				_update_all(get_process_delta_time());
-		} break;
+			break;
+		}
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
 			if (process_mode == ProcessMode_Physics)
 				_update_all(get_physics_process_delta_time());
-		} break;
+			break;
+		}
+		default:
+			break;
 	}
 }
 
 void SpineSprite::_update_all(float delta) {
-	if (!(skeleton.is_valid() && animation_state.is_valid()) || mesh_instances.empty())
+	if (!(skeleton.is_valid() && animation_state.is_valid()) || EMPTY(mesh_instances))
 		return;
 
 	animation_state->update(delta);
@@ -191,7 +197,7 @@ void SpineSprite::_update_all(float delta) {
 
 void SpineSprite::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) {
+		for (int 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;
@@ -199,14 +205,14 @@ void SpineSprite::update_bind_slot_nodes() {
 					NodePath node_path = d["node_path"];
 					Node *node = get_node_or_null(node_path);
 					if (node && node->is_class("Node2D")) {
-						Node2D *node2d = (Node2D *) node;
+						auto *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);
+								bone->apply_world_transform_2d(node2d);
 								update_bind_slot_node_draw_order(slot_name, node2d);
 							}
 						}
@@ -218,14 +224,14 @@ void SpineSprite::update_bind_slot_nodes() {
 					NodePath node_path = as[1];
 					Node *node = get_node_or_null(node_path);
 					if (node && node->is_class("Node2D")) {
-						Node2D *node2d = (Node2D *) node;
+						auto *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);
+								bone->apply_world_transform_2d(node2d);
 								update_bind_slot_node_draw_order(slot_name, node2d);
 							}
 						}
@@ -236,11 +242,22 @@ void SpineSprite::update_bind_slot_nodes() {
 	}
 }
 
-void SpineSprite::update_bind_slot_node_transform(Ref<SpineBone> bone, Node2D *node2d) {
-	bone->apply_world_transform_2d(node2d);
-}
-
 void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node2D *node2d) {
+#if VERSION_MAJOR > 3
+	auto nodes = find_nodes(slot_name);
+	if (!nodes.is_empty()) {
+		auto mesh_ins = Object::cast_to<MeshInstance2D>(nodes[0]);
+		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);
+			}
+		}
+	}
+#else
 	auto mesh_ins = find_node(slot_name);
 	if (mesh_ins) {
 		auto pos = mesh_ins->get_index();
@@ -251,6 +268,7 @@ void SpineSprite::update_bind_slot_node_draw_order(const String &slot_name, Node
 			move_child(node, pos + 1);
 		}
 	}
+#endif
 }
 Node *SpineSprite::find_child_node_by_node(Node *node) {
 	if (node == nullptr) return nullptr;
@@ -283,9 +301,9 @@ void SpineSprite::remove_meshes() {
 #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];                 \
+		(t).setSize(temp_uvs.size(), 0);          \
+		for (size_t j = 0; j < (t).size(); ++j) { \
+			(t)[j] = temp_uvs[j];                 \
 		}                                       \
 	} while (false);
 
@@ -294,7 +312,7 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 	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) {
+	for (int i = 0, n = sk->getSlots().size(); i < n; ++i) {
 		spine::Vector<float> vertices;
 		spine::Vector<float> uvs;
 		spine::Vector<unsigned short> indices;
@@ -319,7 +337,7 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 		size_t v_num = 0;
 
 		if (attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) {
-			spine::RegionAttachment *region_attachment = (spine::RegionAttachment *) attachment;
+			auto *region_attachment = (spine::RegionAttachment *) attachment;
 
 			auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) region_attachment->getRendererObject())->page->getRendererObject();
 			tex = p_spine_renderer_object->texture;
@@ -343,7 +361,7 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 			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 *mesh = (spine::MeshAttachment *) attachment;
 
 			auto p_spine_renderer_object = (SpineRendererObject *) ((spine::AtlasRegion *) mesh->getRendererObject())->page->getRendererObject();
 			tex = p_spine_renderer_object->texture;
@@ -371,7 +389,11 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 		}
 
 		auto mesh_ins = mesh_instances[i];
+#if VERSION_MAJOR > 3
+		RenderingServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item());
+#else
 		VisualServer::get_singleton()->canvas_item_clear(mesh_ins->get_canvas_item());
+#endif
 
 		if (skeleton_clipper->isClipping()) {
 			skeleton_clipper->clipTriangles(vertices, indices, uvs, VERTEX_STRIDE);
@@ -403,6 +425,18 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 					p_indices.set(j, clipped_indices[j]);
 				}
 
+#if VERSION_MAJOR > 3
+				RenderingServer::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
+																			  );
+#else
 				VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(),
 																			  p_indices,
 																			  p_points,
@@ -413,6 +447,7 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 																			  tex.is_null() ? RID() : tex->get_rid(),
 																			  -1,
 																			  normal_tex.is_null() ? RID() : normal_tex->get_rid());
+#endif
 			}
 		} else {
 			if (indices.size() > 0) {
@@ -432,6 +467,17 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 					p_indices.set(j, indices[j]);
 				}
 
+#if VERSION_MAJOR > 3
+				RenderingServer::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);
+#else
 				VisualServer::get_singleton()->canvas_item_add_triangle_array(mesh_ins->get_canvas_item(),
 																			  p_indices,
 																			  p_points,
@@ -442,6 +488,7 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> s) {
 																			  tex.is_null() ? RID() : tex->get_rid(),
 																			  -1,
 																			  normal_tex.is_null() ? RID() : normal_tex->get_rid());
+#endif
 			}
 		}
 		skeleton_clipper->clipEnd(*slot);
@@ -496,14 +543,6 @@ void SpineSprite::set_bind_slot_nodes(Array v) {
 	bind_slot_nodes = v;
 }
 
-bool SpineSprite::get_overlap() {
-	return overlap;
-}
-
-void SpineSprite::set_overlap(bool v) {
-	overlap = v;
-}
-
 Transform2D SpineSprite::bone_get_global_transform(const String &bone_name) {
 	if (!animation_state.is_valid() && !skeleton.is_valid()) {
 		return get_global_transform();

+ 5 - 7
spine-godot/spine_godot/SpineSprite.h

@@ -30,12 +30,11 @@
 #ifndef GODOT_SPINESPRITE_H
 #define GODOT_SPINESPRITE_H
 
-#include "scene/2d/node_2d.h"
-#include "scene/resources/texture.h"
-
 #include "SpineSkeleton.h"
 #include "SpineAnimationState.h"
+#include "scene/2d/node_2d.h"
 #include "scene/2d/mesh_instance_2d.h"
+#include "scene/resources/texture.h"
 
 class SpineSprite : public Node2D, public spine::AnimationStateListenerObject {
 	GDCLASS(SpineSprite, Node2D);
@@ -90,7 +89,6 @@ public:
 	void update_meshes(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);
 
@@ -101,15 +99,15 @@ public:
 	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);
+	void bone_set_global_transform(const String &bone_name, Transform2D transform);
 
 	ProcessMode get_process_mode();
+
 	void set_process_mode(ProcessMode v);
 
 #ifdef TOOLS_ENABLED

+ 26 - 24
spine-godot/spine_godot/SpineTimeline.cpp

@@ -30,7 +30,9 @@
 #include "SpineTimeline.h"
 #include "SpineSkeleton.h"
 #include "SpineEvent.h"
+#if VERSION_MAJOR == 3
 #include "core/method_bind_ext.gen.inc"
+#endif
 
 void SpineTimeline::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "events", "alpha", "blend", "direction"), &SpineTimeline::apply);
@@ -42,58 +44,58 @@ void SpineTimeline::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_type"), &SpineTimeline::get_type);
 }
 
-SpineTimeline::SpineTimeline() : timeline(NULL) {
+SpineTimeline::SpineTimeline() : timeline(nullptr) {
 }
 
-SpineTimeline::~SpineTimeline() {
-}
-
-void SpineTimeline::apply(Ref<SpineSkeleton> skeleton, float lastTime, float time, Array events, float alpha,
+void SpineTimeline::apply(Ref<SpineSkeleton> skeleton, float last_time, float time, Array events, float alpha,
 						  SpineConstant::MixBlend blend, SpineConstant::MixDirection direction) {
-	spine::Vector<spine::Event *> spineEvents;
-	spineEvents.setSize(events.size(), nullptr);
-	for (size_t i = 0; i < events.size(); ++i) {
-		events[i] = ((Ref<SpineEvent>) spineEvents[i])->get_spine_object();
+	SPINE_CHECK(timeline,)
+	spine::Vector<spine::Event *> spine_events;
+	spine_events.setSize((int)events.size(), nullptr);
+	for (int i = 0; i < events.size(); ++i) {
+		events[i] = ((Ref<SpineEvent>) spine_events[i])->get_spine_object();
 	}
-	timeline->apply(*(skeleton->get_spine_object()), lastTime, time, &spineEvents, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction);
+	timeline->apply(*(skeleton->get_spine_object()), last_time, time, &spine_events, alpha, (spine::MixBlend) blend, (spine::MixDirection) direction);
 }
 
-int64_t SpineTimeline::get_frame_entries() {
-	return timeline->getFrameEntries();
+int SpineTimeline::get_frame_entries() {
+	SPINE_CHECK(timeline, 0)
+	return (int)timeline->getFrameEntries();
 }
 
-int64_t SpineTimeline::get_frame_count() {
-	return timeline->getFrameCount();
+int SpineTimeline::get_frame_count() {
+	SPINE_CHECK(timeline, 0)
+	return (int)timeline->getFrameCount();
 }
 
 Array SpineTimeline::get_frames() {
-	auto &frames = timeline->getFrames();
 	Array result;
-	result.resize(frames.size());
-
-	for (size_t i = 0; i < result.size(); ++i) {
+	SPINE_CHECK(timeline, result)
+	auto &frames = timeline->getFrames();
+	result.resize((int)frames.size());
+	for (int i = 0; i < result.size(); ++i) {
 		result[i] = frames[i];
 	}
-
 	return result;
 }
 
 float SpineTimeline::get_duration() {
+	SPINE_CHECK(timeline, 0)
 	return timeline->getDuration();
 }
 
 Array SpineTimeline::get_property_ids() {
-	auto &ids = timeline->getPropertyIds();
 	Array result;
-	result.resize(ids.size());
-
-	for (size_t i = 0; i < result.size(); ++i) {
+	SPINE_CHECK(timeline, result)
+	auto &ids = timeline->getPropertyIds();
+	result.resize((int)ids.size());
+	for (int i = 0; i < result.size(); ++i) {
 		result[i] = (int64_t) ids[i];
 	}
-
 	return result;
 }
 
 String SpineTimeline::get_type() {
+	SPINE_CHECK(timeline, "")
 	return timeline->getRTTI().getClassName();
 }

+ 9 - 10
spine-godot/spine_godot/SpineTimeline.h

@@ -30,15 +30,15 @@
 #ifndef GODOT_SPINETIMELINE_H
 #define GODOT_SPINETIMELINE_H
 
-#include "spine/Timeline.h"
+#include "SpineCommon.h"
 #include "SpineConstant.h"
-#include "core/reference.h"
+#include <spine/Timeline.h>
 
 class SpineSkeleton;
 class SpineEvent;
 
-class SpineTimeline : public Reference {
-	GDCLASS(SpineTimeline, Reference);
+class SpineTimeline : public REFCOUNTED {
+	GDCLASS(SpineTimeline, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -48,16 +48,15 @@ private:
 
 public:
 	SpineTimeline();
-	~SpineTimeline();
 
-	inline void set_spine_object(spine::Timeline *timeline) { this->timeline = timeline; }
-	inline spine::Timeline *get_spine_object() { return timeline; }
+	void set_spine_object(spine::Timeline *_timeline) { this->timeline = _timeline; }
+	spine::Timeline *get_spine_object() { return timeline; }
 
-	void apply(Ref<SpineSkeleton> skeleton, float lastTime, float time, Array events, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction);
+	void apply(Ref<SpineSkeleton> skeleton, float last_time, float time, Array events, float alpha, SpineConstant::MixBlend blend, SpineConstant::MixDirection direction);
 
-	int64_t get_frame_entries();
+	int get_frame_entries();
 
-	int64_t get_frame_count();
+	int get_frame_count();
 
 	Array get_frames();
 

+ 128 - 61
spine-godot/spine_godot/SpineTrackEntry.cpp

@@ -28,238 +28,305 @@
  *****************************************************************************/
 
 #include "SpineTrackEntry.h"
+#include "SpineCommon.h"
 
 void SpineTrackEntry::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_track_index"), &SpineTrackEntry::get_track_index);
-
 	ClassDB::bind_method(D_METHOD("get_animation"), &SpineTrackEntry::get_animation);
-
+	ClassDB::bind_method(D_METHOD("get_previous"), &SpineTrackEntry::get_previous);
 	ClassDB::bind_method(D_METHOD("get_loop"), &SpineTrackEntry::get_loop);
 	ClassDB::bind_method(D_METHOD("set_loop", "v"), &SpineTrackEntry::set_loop);
-
 	ClassDB::bind_method(D_METHOD("get_hold_previous"), &SpineTrackEntry::get_hold_previous);
 	ClassDB::bind_method(D_METHOD("set_hold_previous", "v"), &SpineTrackEntry::set_hold_previous);
-
 	ClassDB::bind_method(D_METHOD("get_reverse"), &SpineTrackEntry::get_reverse);
 	ClassDB::bind_method(D_METHOD("set_reverse", "v"), &SpineTrackEntry::set_reverse);
-
+	ClassDB::bind_method(D_METHOD("get_shortest_rotation"), &SpineTrackEntry::get_shortest_rotation);
+	ClassDB::bind_method(D_METHOD("set_shortest_rotation", "v"), &SpineTrackEntry::set_shortest_rotation);
 	ClassDB::bind_method(D_METHOD("get_delay"), &SpineTrackEntry::get_delay);
 	ClassDB::bind_method(D_METHOD("set_delay", "v"), &SpineTrackEntry::set_delay);
-
 	ClassDB::bind_method(D_METHOD("get_track_time"), &SpineTrackEntry::get_track_time);
 	ClassDB::bind_method(D_METHOD("set_track_time", "v"), &SpineTrackEntry::set_track_time);
-
 	ClassDB::bind_method(D_METHOD("get_track_end"), &SpineTrackEntry::get_track_end);
 	ClassDB::bind_method(D_METHOD("set_track_end", "v"), &SpineTrackEntry::set_track_end);
-
 	ClassDB::bind_method(D_METHOD("get_animation_start"), &SpineTrackEntry::get_animation_start);
 	ClassDB::bind_method(D_METHOD("set_animation_start", "v"), &SpineTrackEntry::set_animation_start);
-
+	ClassDB::bind_method(D_METHOD("get_animation_end"), &SpineTrackEntry::get_animation_end);
+	ClassDB::bind_method(D_METHOD("set_animation_end", "v"), &SpineTrackEntry::set_animation_end);
 	ClassDB::bind_method(D_METHOD("get_animation_last"), &SpineTrackEntry::get_animation_last);
 	ClassDB::bind_method(D_METHOD("set_animation_last", "v"), &SpineTrackEntry::set_animation_last);
-
 	ClassDB::bind_method(D_METHOD("get_animation_time"), &SpineTrackEntry::get_animation_time);
-
 	ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineTrackEntry::get_time_scale);
 	ClassDB::bind_method(D_METHOD("set_time_scale", "v"), &SpineTrackEntry::set_time_scale);
-
 	ClassDB::bind_method(D_METHOD("get_alpha"), &SpineTrackEntry::get_alpha);
 	ClassDB::bind_method(D_METHOD("set_alpha", "v"), &SpineTrackEntry::set_alpha);
-
 	ClassDB::bind_method(D_METHOD("get_event_threshold"), &SpineTrackEntry::get_event_threshold);
 	ClassDB::bind_method(D_METHOD("set_event_threshold", "v"), &SpineTrackEntry::set_event_threshold);
-
 	ClassDB::bind_method(D_METHOD("get_attachment_threshold"), &SpineTrackEntry::get_attachment_threshold);
 	ClassDB::bind_method(D_METHOD("set_attachment_threshold", "v"), &SpineTrackEntry::set_attachment_threshold);
-
 	ClassDB::bind_method(D_METHOD("get_draw_order_threshold"), &SpineTrackEntry::get_draw_order_threshold);
 	ClassDB::bind_method(D_METHOD("set_draw_order_threshold", "v"), &SpineTrackEntry::set_draw_order_threshold);
-
 	ClassDB::bind_method(D_METHOD("get_next"), &SpineTrackEntry::get_next);
-
 	ClassDB::bind_method(D_METHOD("is_complete"), &SpineTrackEntry::is_complete);
-
 	ClassDB::bind_method(D_METHOD("get_mix_time"), &SpineTrackEntry::get_mix_time);
 	ClassDB::bind_method(D_METHOD("set_mix_time", "v"), &SpineTrackEntry::set_mix_time);
-
 	ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineTrackEntry::get_mix_duration);
 	ClassDB::bind_method(D_METHOD("set_mix_duration", "v"), &SpineTrackEntry::set_mix_duration);
-
 	ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineTrackEntry::get_mix_blend);
 	ClassDB::bind_method(D_METHOD("set_mix_blend", "v"), &SpineTrackEntry::set_mix_blend);
-
 	ClassDB::bind_method(D_METHOD("get_mixing_from"), &SpineTrackEntry::get_mixing_from);
 	ClassDB::bind_method(D_METHOD("get_mixing_to"), &SpineTrackEntry::get_mixing_to);
-
 	ClassDB::bind_method(D_METHOD("reset_rotation_directions"), &SpineTrackEntry::reset_rotation_directions);
-
-	BIND_ENUM_CONSTANT(MIXBLEND_SETUP);
-	BIND_ENUM_CONSTANT(MIXBLEND_FIRST);
-	BIND_ENUM_CONSTANT(MIXBLEND_REPLACE);
-	BIND_ENUM_CONSTANT(MIXBLEND_ADD);
+	ClassDB::bind_method(D_METHOD("get_track_complete"), &SpineTrackEntry::get_track_complete);
 }
 
-SpineTrackEntry::SpineTrackEntry() : track_entry(NULL) {}
-SpineTrackEntry::~SpineTrackEntry() {}
+SpineTrackEntry::SpineTrackEntry() : track_entry(nullptr) {
+}
 
 int SpineTrackEntry::get_track_index() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getTrackIndex();
 }
 
 Ref<SpineAnimation> SpineTrackEntry::get_animation() {
-	Ref<SpineAnimation> gd_anim(memnew(SpineAnimation));
-	auto anim = track_entry->getAnimation();
-	if (anim == NULL) return NULL;
-	gd_anim->set_spine_object(anim);
-	return gd_anim;
+	SPINE_CHECK(track_entry, nullptr)
+	auto animation = track_entry->getAnimation();
+	if (!animation) return nullptr;
+	Ref<SpineAnimation> animation_ref(memnew(SpineAnimation));
+	animation_ref->set_spine_object(animation);
+	return animation_ref;
+}
+
+Ref<SpineTrackEntry> SpineTrackEntry::get_previous() {
+	SPINE_CHECK(track_entry, nullptr)
+	auto previous = track_entry->getPrevious();
+	if (!previous) return nullptr;
+	Ref<SpineTrackEntry> previous_ref(memnew(SpineTrackEntry));
+	previous_ref->set_spine_object(previous);
+	return previous_ref;
 }
 
 bool SpineTrackEntry::get_loop() {
+	SPINE_CHECK(track_entry, false)
 	return track_entry->getLoop();
 }
+
 void SpineTrackEntry::set_loop(bool v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setLoop(v);
 }
 
 bool SpineTrackEntry::get_hold_previous() {
+	SPINE_CHECK(track_entry, false)
 	return track_entry->getHoldPrevious();
 }
+
 void SpineTrackEntry::set_hold_previous(bool v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setHoldPrevious(v);
 }
 
+bool SpineTrackEntry::get_reverse() {
+	SPINE_CHECK(track_entry, false)
+	return track_entry->getReverse();
+}
+
+void SpineTrackEntry::set_reverse(bool v) {
+	SPINE_CHECK(track_entry,)
+	track_entry->setReverse(v);
+}
+
+bool  SpineTrackEntry::get_shortest_rotation() {
+	SPINE_CHECK(track_entry, false)
+	return track_entry->getShortestRotation();
+}
+
+void  SpineTrackEntry::set_shortest_rotation(bool v) {
+	SPINE_CHECK(track_entry,)
+	track_entry->setShortestRotation(v);
+}
+
 float SpineTrackEntry::get_delay() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getDelay();
 }
+
 void SpineTrackEntry::set_delay(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setDelay(v);
 }
 
 float SpineTrackEntry::get_track_time() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getTrackTime();
 }
+
 void SpineTrackEntry::set_track_time(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setTrackTime(v);
 }
 
 float SpineTrackEntry::get_track_end() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getTrackEnd();
 }
+
 void SpineTrackEntry::set_track_end(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setTrackEnd(v);
 }
 
 float SpineTrackEntry::get_animation_start() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getAnimationStart();
 }
+
 void SpineTrackEntry::set_animation_start(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setAnimationStart(v);
 }
 
+float SpineTrackEntry::get_animation_end() {
+	SPINE_CHECK(track_entry, 0)
+	return track_entry->getAnimationEnd();
+}
+
+void SpineTrackEntry::set_animation_end(float v) {
+	SPINE_CHECK(track_entry,)
+	track_entry->setAnimationEnd(v);
+}
+
 float SpineTrackEntry::get_animation_last() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getAnimationLast();
 }
+
 void SpineTrackEntry::set_animation_last(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setAnimationLast(v);
 }
 
 float SpineTrackEntry::get_animation_time() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getAnimationTime();
 }
 
 float SpineTrackEntry::get_time_scale() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getTimeScale();
 }
+
 void SpineTrackEntry::set_time_scale(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setTimeScale(v);
 }
 
 float SpineTrackEntry::get_alpha() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getAlpha();
 }
+
 void SpineTrackEntry::set_alpha(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setAlpha(v);
 }
 
 float SpineTrackEntry::get_event_threshold() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getEventThreshold();
 }
+
 void SpineTrackEntry::set_event_threshold(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setEventThreshold(v);
 }
 
 float SpineTrackEntry::get_attachment_threshold() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getAttachmentThreshold();
 }
+
 void SpineTrackEntry::set_attachment_threshold(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setAttachmentThreshold(v);
 }
 
 float SpineTrackEntry::get_draw_order_threshold() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getDrawOrderThreshold();
 }
+
 void SpineTrackEntry::set_draw_order_threshold(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setDrawOrderThreshold(v);
 }
 
 Ref<SpineTrackEntry> SpineTrackEntry::get_next() {
-	Ref<SpineTrackEntry> gd_entry(memnew(SpineTrackEntry));
-	auto entry = track_entry->getNext();
-	if (entry == NULL) return NULL;
-	gd_entry->set_spine_object(entry);
-	return gd_entry;
+	SPINE_CHECK(track_entry, nullptr)
+	auto next = track_entry->getNext();
+	if (!next) return nullptr;
+	Ref<SpineTrackEntry> next_ref(memnew(SpineTrackEntry));
+	next_ref->set_spine_object(next);
+	return next_ref;
 }
 
 bool SpineTrackEntry::is_complete() {
+	SPINE_CHECK(track_entry, false)
 	return track_entry->isComplete();
 }
 
 float SpineTrackEntry::get_mix_time() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getMixTime();
 }
+
 void SpineTrackEntry::set_mix_time(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setMixTime(v);
 }
 
 float SpineTrackEntry::get_mix_duration() {
+	SPINE_CHECK(track_entry, 0)
 	return track_entry->getMixDuration();
 }
+
 void SpineTrackEntry::set_mix_duration(float v) {
+	SPINE_CHECK(track_entry,)
 	track_entry->setMixDuration(v);
 }
 
-SpineTrackEntry::MixBlend SpineTrackEntry::get_mix_blend() {
-	int mb = track_entry->getMixBlend();
-	return (MixBlend) mb;
+SpineConstant::MixBlend SpineTrackEntry::get_mix_blend() {
+	SPINE_CHECK(track_entry, SpineConstant::MixBlend_Setup)
+	return (SpineConstant::MixBlend)track_entry->getMixBlend();
 }
-void SpineTrackEntry::set_mix_blend(SpineTrackEntry::MixBlend v) {
-	int mb = (int) v;
-	track_entry->setMixBlend((spine::MixBlend) mb);
+
+void SpineTrackEntry::set_mix_blend(SpineConstant::MixBlend v) {
+	SPINE_CHECK(track_entry,)
+	track_entry->setMixBlend((spine::MixBlend) v);
 }
 
 Ref<SpineTrackEntry> SpineTrackEntry::get_mixing_from() {
-	Ref<SpineTrackEntry> gd_entry(memnew(SpineTrackEntry));
-	auto entry = track_entry->getMixingFrom();
-	if (entry == NULL) return NULL;
-	gd_entry->set_spine_object(entry);
-	return gd_entry;
+	SPINE_CHECK(track_entry, nullptr)
+	auto mixing_from = track_entry->getMixingFrom();
+	if (!mixing_from) return nullptr;
+	Ref<SpineTrackEntry> mixing_from_ref(memnew(SpineTrackEntry));
+	mixing_from_ref->set_spine_object(mixing_from);
+	return mixing_from_ref;
 }
 Ref<SpineTrackEntry> SpineTrackEntry::get_mixing_to() {
-	Ref<SpineTrackEntry> gd_entry(memnew(SpineTrackEntry));
-	auto entry = track_entry->getMixingTo();
-	if (entry == NULL) return NULL;
-	gd_entry->set_spine_object(entry);
-	return gd_entry;
+	SPINE_CHECK(track_entry, nullptr)
+	auto mixing_to = track_entry->getMixingTo();
+	if (!mixing_to) return nullptr;
+	Ref<SpineTrackEntry> mixing_to_ref(memnew(SpineTrackEntry));
+	mixing_to_ref->set_spine_object(mixing_to);
+	return mixing_to_ref;
 }
 
 void SpineTrackEntry::reset_rotation_directions() {
+	SPINE_CHECK(track_entry,)
 	track_entry->resetRotationDirections();
 }
 
-bool SpineTrackEntry::get_reverse() {
-	return track_entry->getReverse();
-}
-
-void SpineTrackEntry::set_reverse(bool v) {
-	track_entry->setReverse(v);
+float SpineTrackEntry::get_track_complete() {
+	SPINE_CHECK(track_entry, 0)
+	return track_entry->getTrackComplete();
 }

+ 39 - 24
spine-godot/spine_godot/SpineTrackEntry.h

@@ -30,14 +30,13 @@
 #ifndef GODOT_SPINETRACKENTRY_H
 #define GODOT_SPINETRACKENTRY_H
 
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
-
+#include "SpineCommon.h"
 #include "SpineAnimation.h"
+#include "SpineConstant.h"
+#include <spine/AnimationState.h>
 
-class SpineTrackEntry : public Reference {
-	GDCLASS(SpineTrackEntry, Reference);
+class SpineTrackEntry : public REFCOUNTED {
+	GDCLASS(SpineTrackEntry, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -47,65 +46,76 @@ private:
 
 public:
 	SpineTrackEntry();
-	~SpineTrackEntry();
-
-	inline void set_spine_object(spine::TrackEntry *t) {
-		track_entry = t;
-	}
-	inline spine::TrackEntry *get_spine_object() {
-		return track_entry;
-	}
-
-	enum MixBlend {
-		MIXBLEND_SETUP = 0,
-		MIXBLEND_FIRST,
-		MIXBLEND_REPLACE,
-		MIXBLEND_ADD
-	};
+
+	void set_spine_object(spine::TrackEntry *_track_entry) { this->track_entry = _track_entry; }
+	spine::TrackEntry *get_spine_object() { return track_entry; }
 
 	int get_track_index();
 
 	Ref<SpineAnimation> get_animation();
 
+	Ref<SpineTrackEntry> get_previous();
+
 	bool get_loop();
+
 	void set_loop(bool v);
 
 	bool get_hold_previous();
+
 	void set_hold_previous(bool v);
 
 	bool get_reverse();
+
 	void set_reverse(bool v);
 
+	bool get_shortest_rotation();
+
+	void set_shortest_rotation(bool v);
+
 	float get_delay();
+
 	void set_delay(float v);
 
 	float get_track_time();
+
 	void set_track_time(float v);
 
 	float get_track_end();
+
 	void set_track_end(float v);
 
 	float get_animation_start();
+
 	void set_animation_start(float v);
 
+	float get_animation_end();
+
+	void set_animation_end(float v);
+
 	float get_animation_last();
+
 	void set_animation_last(float v);
 
 	float get_animation_time();
 
 	float get_time_scale();
+
 	void set_time_scale(float v);
 
 	float get_alpha();
+
 	void set_alpha(float v);
 
 	float get_event_threshold();
+
 	void set_event_threshold(float v);
 
 	float get_attachment_threshold();
+
 	void set_attachment_threshold(float v);
 
 	float get_draw_order_threshold();
+
 	void set_draw_order_threshold(float v);
 
 	Ref<SpineTrackEntry> get_next();
@@ -113,19 +123,24 @@ public:
 	bool is_complete();
 
 	float get_mix_time();
+
 	void set_mix_time(float v);
 
 	float get_mix_duration();
+
 	void set_mix_duration(float v);
 
-	MixBlend get_mix_blend();
-	void set_mix_blend(MixBlend v);
+	SpineConstant::MixBlend get_mix_blend();
+
+	void set_mix_blend(SpineConstant::MixBlend v);
 
 	Ref<SpineTrackEntry> get_mixing_from();
+
 	Ref<SpineTrackEntry> get_mixing_to();
 
 	void reset_rotation_directions();
+
+	float get_track_complete();
 };
 
-VARIANT_ENUM_CAST(SpineTrackEntry::MixBlend);
 #endif//GODOT_SPINETRACKENTRY_H

+ 51 - 27
spine-godot/spine_godot/SpineTransformConstraint.cpp

@@ -28,6 +28,7 @@
  *****************************************************************************/
 
 #include "SpineTransformConstraint.h"
+#include "SpineCommon.h"
 
 void SpineTransformConstraint::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("update"), &SpineTransformConstraint::update);
@@ -51,98 +52,121 @@ void SpineTransformConstraint::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineTransformConstraint::set_active);
 }
 
-SpineTransformConstraint::SpineTransformConstraint() : transform_constraint(NULL) {}
-SpineTransformConstraint::~SpineTransformConstraint() {}
+SpineTransformConstraint::SpineTransformConstraint() : transform_constraint(nullptr) {
+}
 
 void SpineTransformConstraint::update() {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->update();
 }
 
 int SpineTransformConstraint::get_order() {
+	SPINE_CHECK(transform_constraint, 0)
 	return transform_constraint->getOrder();
 }
 
 Ref<SpineTransformConstraintData> SpineTransformConstraint::get_data() {
-	auto &d = transform_constraint->getData();
-	Ref<SpineTransformConstraintData> gd_d(memnew(SpineTransformConstraintData));
-	gd_d->set_spine_object(&d);
-	return gd_d;
+	SPINE_CHECK(transform_constraint, nullptr)
+	auto &data = transform_constraint->getData();
+	Ref<SpineTransformConstraintData> data_ref(memnew(SpineTransformConstraintData));
+	data_ref->set_spine_object(&data);
+	return data_ref;
 }
 
 Array SpineTransformConstraint::get_bones() {
-	auto &bs = transform_constraint->getBones();
-	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<SpineBone>(NULL);
-		Ref<SpineBone> gd_b(memnew(SpineBone));
-		gd_b->set_spine_object(b);
-		gd_bs[i] = gd_b;
+	Array result;
+	SPINE_CHECK(transform_constraint, result)
+	auto &bones = transform_constraint->getBones();
+	result.resize((int)bones.size());
+	for (int i = 0; i < bones.size(); ++i) {
+		auto bone = bones[i];
+		Ref<SpineBone> bone_ref(memnew(SpineBone));
+		bone_ref->set_spine_object(bone);
+		result[i] = bone_ref;
 	}
-	return gd_bs;
+	return result;
 }
 
 Ref<SpineBone> SpineTransformConstraint::get_target() {
-	auto b = transform_constraint->getTarget();
-	if (b == NULL) return NULL;
-	Ref<SpineBone> gd_b(memnew(SpineBone));
-	gd_b->set_spine_object(b);
-	return gd_b;
+	SPINE_CHECK(transform_constraint, nullptr)
+	auto target = transform_constraint->getTarget();
+	if (!target) return nullptr;
+	Ref<SpineBone> target_ref(memnew(SpineBone));
+	target_ref->set_spine_object(target);
+	return target_ref;
 }
+
 void SpineTransformConstraint::set_target(Ref<SpineBone> v) {
-	if (v.is_valid()) {
-		transform_constraint->setTarget(v->get_spine_object());
-	} else {
-		transform_constraint->setTarget(NULL);
-	}
+	SPINE_CHECK(transform_constraint,)
+	transform_constraint->setTarget(v.is_valid() ? v->get_spine_object() : nullptr);
 }
 
 float SpineTransformConstraint::get_mix_rotate() {
+	SPINE_CHECK(transform_constraint, 0)
 	return transform_constraint->getMixRotate();
 }
+
 void SpineTransformConstraint::set_mix_rotate(float v) {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->setMixRotate(v);
 }
 
 float SpineTransformConstraint::get_mix_x() {
+	SPINE_CHECK(transform_constraint, 0)
 	return transform_constraint->getMixX();
 }
+
 void SpineTransformConstraint::set_mix_x(float v) {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->setMixX(v);
 }
 
 float SpineTransformConstraint::get_mix_y() {
+	SPINE_CHECK(transform_constraint, 0)
 	return transform_constraint->getMixY();
 }
+
 void SpineTransformConstraint::set_mix_y(float v) {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->setMixY(v);
 }
 
 float SpineTransformConstraint::get_mix_scale_x() {
+	SPINE_CHECK(transform_constraint, 0)
 	return transform_constraint->getMixScaleX();
 }
+
 void SpineTransformConstraint::set_mix_scale_x(float v) {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->setMixScaleX(v);
 }
 
 float SpineTransformConstraint::get_mix_scale_y() {
+	SPINE_CHECK(transform_constraint, 0)
 	return transform_constraint->getMixScaleY();
 }
+
 void SpineTransformConstraint::set_mix_scale_y(float v) {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->setMixScaleY(v);
 }
 
 float SpineTransformConstraint::get_mix_shear_y() {
+	SPINE_CHECK(transform_constraint, 0)
 	return transform_constraint->getMixShearY();
 }
+
 void SpineTransformConstraint::set_mix_shear_y(float v) {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->setMixShearY(v);
 }
 
 bool SpineTransformConstraint::is_active() {
+	SPINE_CHECK(transform_constraint, false)
 	return transform_constraint->isActive();
 }
+
 void SpineTransformConstraint::set_active(bool v) {
+	SPINE_CHECK(transform_constraint,)
 	transform_constraint->setActive(v);
-}
+}

+ 14 - 13
spine-godot/spine_godot/SpineTransformConstraint.h

@@ -30,15 +30,13 @@
 #ifndef GODOT_SPINETRANSFORMCONSTRAINT_H
 #define GODOT_SPINETRANSFORMCONSTRAINT_H
 
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
-
+#include "SpineCommon.h"
 #include "SpineTransformConstraintData.h"
 #include "SpineBone.h"
+#include <spine/TransformConstraint.h>
 
-class SpineTransformConstraint : public Reference {
-	GDCLASS(SpineTransformConstraint, Reference);
+class SpineTransformConstraint : public REFCOUNTED {
+	GDCLASS(SpineTransformConstraint, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -48,14 +46,9 @@ private:
 
 public:
 	SpineTransformConstraint();
-	~SpineTransformConstraint();
 
-	inline void set_spine_object(spine::TransformConstraint *tc) {
-		transform_constraint = tc;
-	}
-	inline spine::TransformConstraint *get_spine_object() {
-		return transform_constraint;
-	}
+	void set_spine_object(spine::TransformConstraint *tc) { transform_constraint = tc; }
+	spine::TransformConstraint *get_spine_object() { return transform_constraint; }
 
 	void update();
 
@@ -66,27 +59,35 @@ public:
 	Array get_bones();
 
 	Ref<SpineBone> get_target();
+
 	void set_target(Ref<SpineBone> v);
 
 	float get_mix_rotate();
+
 	void set_mix_rotate(float v);
 
 	float get_mix_x();
+
 	void set_mix_x(float v);
 
 	float get_mix_y();
+
 	void set_mix_y(float v);
 
 	float get_mix_scale_x();
+
 	void set_mix_scale_x(float v);
 
 	float get_mix_scale_y();
+
 	void set_mix_scale_y(float v);
 
 	float get_mix_shear_y();
+
 	void set_mix_shear_y(float v);
 
 	bool is_active();
+
 	void set_active(bool v);
 };
 

+ 59 - 35
spine-godot/spine_godot/SpineTransformConstraintData.cpp

@@ -28,9 +28,10 @@
  *****************************************************************************/
 
 #include "SpineTransformConstraintData.h"
+#include "SpineCommon.h"
 
 void SpineTransformConstraintData::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("get_all_bone_data"), &SpineTransformConstraintData::get_bones);
+	ClassDB::bind_method(D_METHOD("get_bones"), &SpineTransformConstraintData::get_bones);
 	ClassDB::bind_method(D_METHOD("get_target"), &SpineTransformConstraintData::get_target);
 	ClassDB::bind_method(D_METHOD("get_mix_rotate"), &SpineTransformConstraintData::get_mix_rotate);
 	ClassDB::bind_method(D_METHOD("get_mix_x"), &SpineTransformConstraintData::get_mix_x);
@@ -48,71 +49,94 @@ void SpineTransformConstraintData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("is_local"), &SpineTransformConstraintData::is_local);
 }
 
-SpineTransformConstraintData::SpineTransformConstraintData() {}
-SpineTransformConstraintData::~SpineTransformConstraintData() {}
-
 Array SpineTransformConstraintData::get_bones() {
-	auto bs = get_spine_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;
-		}
+	Array result;
+	SPINE_CHECK(get_spine_constraint_data(), result)
+	auto bones = get_spine_constraint_data()->getBones();
+	result.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]);
+		result[i] = bone_ref;
 	}
-	return gd_bs;
+	return result;
 }
+
 Ref<SpineBoneData> SpineTransformConstraintData::get_target() {
-	auto b = get_spine_data()->getTarget();
-	if (b == NULL) return NULL;
-	Ref<SpineBoneData> gd_b(memnew(SpineBoneData));
-	gd_b->set_spine_object(b);
-	return gd_b;
+	SPINE_CHECK(get_spine_constraint_data(), nullptr)
+	auto bone = get_spine_constraint_data()->getTarget();
+	if (!bone) return nullptr;
+	Ref<SpineBoneData> slot_ref(memnew(SpineBoneData));
+	slot_ref->set_spine_object(bone);
+	return slot_ref;
 }
+
 float SpineTransformConstraintData::get_mix_rotate() {
-	return get_spine_data()->getMixRotate();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMixRotate();
 }
+
 float SpineTransformConstraintData::get_mix_x() {
-	return get_spine_data()->getMixX();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMixX();
 }
+
 float SpineTransformConstraintData::get_mix_y() {
-	return get_spine_data()->getMixY();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMixY();
 }
+
 float SpineTransformConstraintData::get_mix_scale_x() {
-	return get_spine_data()->getMixScaleX();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMixScaleX();
 }
+
 float SpineTransformConstraintData::get_mix_scale_y() {
-	return get_spine_data()->getMixScaleY();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMixScaleY();
 }
+
 float SpineTransformConstraintData::get_mix_shear_y() {
-	return get_spine_data()->getMixShearY();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMixShearY();
 }
 
 float SpineTransformConstraintData::get_offset_rotation() {
-	return get_spine_data()->getOffsetRotation();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getOffsetRotation();
 }
+
 float SpineTransformConstraintData::get_offset_x() {
-	return get_spine_data()->getOffsetX();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getOffsetX();
 }
+
 float SpineTransformConstraintData::get_offset_y() {
-	return get_spine_data()->getOffsetY();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getOffsetY();
 }
+
 float SpineTransformConstraintData::get_offset_scale_x() {
-	return get_spine_data()->getOffsetScaleX();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getOffsetScaleX();
 }
+
 float SpineTransformConstraintData::get_offset_scale_y() {
-	return get_spine_data()->getOffsetScaleY();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getOffsetScaleY();
 }
+
 float SpineTransformConstraintData::get_offset_shear_y() {
-	return get_spine_data()->getOffsetShearY();
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getOffsetShearY();
 }
 
 bool SpineTransformConstraintData::is_relative() {
-	return get_spine_data()->isRelative();
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isRelative();
 }
+
 bool SpineTransformConstraintData::is_local() {
-	return get_spine_data()->isLocal();
-}
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isLocal();
+}

+ 16 - 11
spine-godot/spine_godot/SpineTransformConstraintData.h

@@ -30,44 +30,49 @@
 #ifndef GODOT_SPINETRANSFORMCONSTRAINTDATA_H
 #define GODOT_SPINETRANSFORMCONSTRAINTDATA_H
 
-#include "core/variant_parser.h"
-
-#include <spine/spine.h>
-
 #include "SpineConstraintData.h"
 #include "SpineBoneData.h"
+#include <spine/TransformConstraintData.h>
 
 class SpineTransformConstraintData : public SpineConstraintData {
 	GDCLASS(SpineTransformConstraintData, SpineConstraintData);
 
+	spine::TransformConstraintData *get_spine_constraint_data() { return (spine::TransformConstraintData *) SpineConstraintData::get_spine_object(); }
+
 protected:
 	static void _bind_methods();
 
 public:
-	SpineTransformConstraintData();
-	~SpineTransformConstraintData();
-
-	virtual inline spine::TransformConstraintData *get_spine_data() {
-		return (spine::TransformConstraintData *) SpineConstraintData::get_spine_object();
-	}
-
 	Array get_bones();
+
 	Ref<SpineBoneData> get_target();
+
 	float get_mix_rotate();
+
 	float get_mix_x();
+
 	float get_mix_y();
+
 	float get_mix_scale_x();
+
 	float get_mix_scale_y();
+
 	float get_mix_shear_y();
 
 	float get_offset_rotation();
+
 	float get_offset_x();
+
 	float get_offset_y();
+
 	float get_offset_scale_x();
+
 	float get_offset_scale_y();
+
 	float get_offset_shear_y();
 
 	bool is_relative();
+
 	bool is_local();
 };
 

+ 16 - 7
spine-godot/spine_godot/register_types.cpp

@@ -27,8 +27,8 @@
  * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
+#include "SpineCommon.h"
 #include "register_types.h"
-#include "core/class_db.h"
 #include "SpineAtlasResource.h"
 #include "SpineSkeletonFileResource.h"
 #include "SpineSkeletonDataResource.h"
@@ -41,7 +41,6 @@
 #include "SpineBoneData.h"
 #include "SpineSlotData.h"
 #include "SpineAttachment.h"
-#include "SpineSkinAttachmentMapEntries.h"
 #include "SpineConstraintData.h"
 #include "SpineSkin.h"
 #include "SpineIkConstraintData.h"
@@ -57,11 +56,8 @@ static Ref<SpineSkeletonFileResourceFormatLoader> skeleton_file_loader;
 static Ref<SpineSkeletonFileResourceFormatSaver> skeleton_file_saver;
 
 #ifdef TOOLS_ENABLED
-#include "editor/editor_export.h"
 #include "editor/editor_node.h"
 #include "SpineEditorPlugin.h"
-#include "SpineSkeletonDataResource.h"
-#include "SpineSprite.h"
 
 static void editor_init_callback() {
 	EditorNode::get_singleton()->add_editor_plugin(memnew(SpineEditorPlugin(EditorNode::get_singleton())));
@@ -88,8 +84,7 @@ void register_spine_godot_types() {
 	ClassDB::register_class<SpineBoneData>();
 	ClassDB::register_class<SpineSlotData>();
 	ClassDB::register_class<SpineAttachment>();
-	ClassDB::register_class<SpineSkinAttachmentMapEntry>();
-	ClassDB::register_class<SpineSkinAttachmentMapEntries>();
+	ClassDB::register_class<SpineSkinEntry>();
 	ClassDB::register_class<SpineConstraintData>();
 	ClassDB::register_class<SpineSkin>();
 	ClassDB::register_class<SpineIkConstraintData>();
@@ -104,6 +99,19 @@ void register_spine_godot_types() {
 	ClassDB::register_class<SpineConstant>();
 	ClassDB::register_class<SpineCollisionShapeProxy>();
 
+#if VERSION_MAJOR > 3
+	atlas_loader.instantiate();
+	ResourceLoader::add_resource_format_loader(atlas_loader);
+
+	atlas_saver.instantiate();
+	ResourceSaver::add_resource_format_saver(atlas_saver);
+
+	skeleton_file_loader.instantiate();
+	ResourceLoader::add_resource_format_loader(skeleton_file_loader);
+
+	skeleton_file_saver.instantiate();
+	ResourceSaver::add_resource_format_saver(skeleton_file_saver);
+#else
 	atlas_loader.instance();
 	ResourceLoader::add_resource_format_loader(atlas_loader);
 
@@ -115,6 +123,7 @@ void register_spine_godot_types() {
 
 	skeleton_file_saver.instance();
 	ResourceSaver::add_resource_format_saver(skeleton_file_saver);
+#endif
 }
 
 void unregister_spine_godot_types() {