Pārlūkot izejas kodu

[godot] 4.x compatibility.

Mario Zechner 3 gadi atpakaļ
vecāks
revīzija
ccc43a3864
37 mainītis faili ar 318 papildinājumiem un 91 dzēšanām
  1. 1 0
      .gitignore
  2. 16 1
      spine-godot/setup.sh
  3. 5 0
      spine-godot/spine_godot/GodotSpineExtension.cpp
  4. 2 1
      spine-godot/spine_godot/SpineAnimation.cpp
  5. 3 3
      spine-godot/spine_godot/SpineAnimation.h
  6. 0 1
      spine-godot/spine_godot/SpineAnimationState.cpp
  7. 3 2
      spine-godot/spine_godot/SpineAnimationState.h
  8. 29 3
      spine-godot/spine_godot/SpineAtlasResource.cpp
  9. 6 0
      spine-godot/spine_godot/SpineAtlasResource.h
  10. 4 3
      spine-godot/spine_godot/SpineAttachment.h
  11. 2 3
      spine-godot/spine_godot/SpineBone.cpp
  12. 4 3
      spine-godot/spine_godot/SpineBone.h
  13. 3 3
      spine-godot/spine_godot/SpineBoneData.h
  14. 2 2
      spine-godot/spine_godot/SpineCollisionShapeProxy.cpp
  15. 18 0
      spine-godot/spine_godot/SpineCommon.h
  16. 1 1
      spine-godot/spine_godot/SpineConstant.h
  17. 4 7
      spine-godot/spine_godot/SpineConstraintData.h
  18. 33 1
      spine-godot/spine_godot/SpineEditorPlugin.cpp
  19. 32 5
      spine-godot/spine_godot/SpineEditorPlugin.h
  20. 3 3
      spine-godot/spine_godot/SpineEvent.h
  21. 3 3
      spine-godot/spine_godot/SpineEventData.h
  22. 2 2
      spine-godot/spine_godot/SpineIkConstraint.h
  23. 2 2
      spine-godot/spine_godot/SpinePathConstraint.h
  24. 5 6
      spine-godot/spine_godot/SpineSkeleton.cpp
  25. 3 2
      spine-godot/spine_godot/SpineSkeleton.h
  26. 19 11
      spine-godot/spine_godot/SpineSkeletonDataResource.cpp
  27. 18 1
      spine-godot/spine_godot/SpineSkeletonFileResource.cpp
  28. 6 1
      spine-godot/spine_godot/SpineSkeletonFileResource.h
  29. 5 4
      spine-godot/spine_godot/SpineSkin.h
  30. 3 2
      spine-godot/spine_godot/SpineSlot.h
  31. 3 3
      spine-godot/spine_godot/SpineSlotData.h
  32. 52 2
      spine-godot/spine_godot/SpineSprite.cpp
  33. 2 1
      spine-godot/spine_godot/SpineTimeline.cpp
  34. 3 3
      spine-godot/spine_godot/SpineTimeline.h
  35. 3 2
      spine-godot/spine_godot/SpineTrackEntry.h
  36. 3 2
      spine-godot/spine_godot/SpineTransformConstraint.h
  37. 15 2
      spine-godot/spine_godot/register_types.cpp

+ 1 - 0
.gitignore

@@ -171,3 +171,4 @@ spine-godot/spine_godot/__pycache__
 spine-godot/example/.import
 spine-godot/spine_godot/*.obj
 *.bc
+spine-godot/example/.godot

+ 16 - 1
spine-godot/setup.sh

@@ -1,8 +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
+rm -rf example/.import
+rm -rf example/.godot
 ./build.sh

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

@@ -29,7 +29,12 @@
 
 #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() {

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

@@ -31,8 +31,9 @@
 #include "SpineSkeleton.h"
 #include "SpineEvent.h"
 #include "SpineTimeline.h"
-#include "SpineCommon.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);

+ 3 - 3
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;

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

@@ -28,7 +28,6 @@
  *****************************************************************************/
 
 #include "SpineAnimationState.h"
-#include "SpineCommon.h"
 
 void SpineAnimationState::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("update", "delta"), &SpineAnimationState::update, DEFVAL(0));

+ 3 - 2
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();

+ 29 - 3
spine-godot/spine_godot/SpineAtlasResource.cpp

@@ -51,7 +51,7 @@ public:
 		if (sub_str_pos < 0) return path;
 		auto res = path.substr(sub_str_pos);
 
-		if (!res.empty()) {
+		if (!EMPTY(res)) {
 			if (res[0] != '/') {
 				return prefix + "/" + res;
 			} else {
@@ -65,8 +65,12 @@ public:
 		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);
@@ -162,11 +166,18 @@ Error SpineAtlasResource::load_from_file(const String &path) {
 	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;
 	Variant result;
 	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"];
@@ -184,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;
@@ -221,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);
 }
 

+ 6 - 0
spine-godot/spine_godot/SpineAtlasResource.h

@@ -30,11 +30,13 @@
 #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 {
@@ -80,7 +82,11 @@ class SpineAtlasResourceFormatLoader : public ResourceFormatLoader {
 	GDCLASS(SpineAtlasResourceFormatLoader, ResourceFormatLoader)
 
 public:
+#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;
 

+ 4 - 3
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();

+ 2 - 3
spine-godot/spine_godot/SpineBone.cpp

@@ -430,9 +430,8 @@ void SpineBone::set_active(bool v) {
 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(),

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

@@ -30,15 +30,16 @@
 #ifndef GODOT_SPINEBONE_H
 #define GODOT_SPINEBONE_H
 
+#include "SpineCommon.h"
 #include "SpineBoneData.h"
-#include <scene/2d/node_2d.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();

+ 3 - 3
spine-godot/spine_godot/SpineBoneData.h

@@ -30,12 +30,12 @@
 #ifndef GODOT_SPINEBONEDATA_H
 #define GODOT_SPINEBONEDATA_H
 
+#include "SpineCommon.h"
 #include "SpineConstant.h"
-#include "core/reference.h"
 #include <spine/BoneData.h>
 
-class SpineBoneData : public Reference {
-	GDCLASS(SpineBoneData, Reference);
+class SpineBoneData : public REFCOUNTED {
+	GDCLASS(SpineBoneData, REFCOUNTED);
 
 protected:
 	static void _bind_methods();

+ 2 - 2
spine-godot/spine_godot/SpineCollisionShapeProxy.cpp

@@ -99,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()));
@@ -155,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;

+ 18 - 0
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)) { \

+ 1 - 1
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);

+ 4 - 7
spine-godot/spine_godot/SpineConstraintData.h

@@ -30,14 +30,11 @@
 #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();

+ 33 - 1
spine-godot/spine_godot/SpineEditorPlugin.cpp

@@ -42,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";
@@ -82,8 +86,12 @@ 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;
@@ -96,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() {
@@ -124,7 +132,11 @@ 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();
+#if VERSION_MAJOR > 3
+	mixes.remove_at((int)idx);
+#else
 	mixes.remove((int)idx);
+#endif
 	emit_changed(get_edited_property(), mixes);
 }
 
@@ -180,12 +192,20 @@ void SpineEditorPropertyAnimationMixes::update_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;
@@ -256,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);
@@ -266,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);
@@ -276,7 +304,11 @@ 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;

+ 32 - 5
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 "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;
 };
 
@@ -127,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;

+ 3 - 3
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();

+ 3 - 3
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();

+ 2 - 2
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();

+ 2 - 2
spine-godot/spine_godot/SpinePathConstraint.h

@@ -34,8 +34,8 @@
 #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();

+ 5 - 6
spine-godot/spine_godot/SpineSkeleton.cpp

@@ -113,7 +113,7 @@ void SpineSkeleton::set_slots_to_setup_pose() {
 
 Ref<SpineBone> SpineSkeleton::find_bone(const String &name) {
 	SPINE_CHECK(skeleton, nullptr)
-	if (name.empty()) return nullptr;
+	if (EMPTY(name)) return nullptr;
 	auto bone = skeleton->findBone(SPINE_STRING(name));
 	if (!bone) return nullptr;
 	Ref<SpineBone> bone_ref(memnew(SpineBone));
@@ -124,7 +124,7 @@ Ref<SpineBone> SpineSkeleton::find_bone(const String &name) {
 
 Ref<SpineSlot> SpineSkeleton::find_slot(const String &name) {
 	SPINE_CHECK(skeleton, nullptr)
-	if (name.empty()) return nullptr;
+	if (EMPTY(name)) return nullptr;
 	auto slot = skeleton->findSlot(SPINE_STRING(name));
 	if (!slot) return nullptr;
 	Ref<SpineSlot> slot_ref(memnew(SpineSlot));
@@ -162,13 +162,12 @@ Ref<SpineAttachment> SpineSkeleton::get_attachment_by_slot_index(int slot_index,
 
 void SpineSkeleton::set_attachment(const String &slot_name, const String &attachment_name) {
 	SPINE_CHECK(skeleton,)
-	ERR_FAIL_COND(slot_name.empty());
 	skeleton->setAttachment(SPINE_STRING(slot_name), SPINE_STRING(attachment_name));
 }
 
 Ref<SpineIkConstraint> SpineSkeleton::find_ik_constraint(const String &constraint_name) {
 	SPINE_CHECK(skeleton, nullptr)
-	if (constraint_name.empty()) return 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));
@@ -178,7 +177,7 @@ Ref<SpineIkConstraint> SpineSkeleton::find_ik_constraint(const String &constrain
 
 Ref<SpineTransformConstraint> SpineSkeleton::find_transform_constraint(const String &constraint_name) {
 	SPINE_CHECK(skeleton, nullptr)
-	if (constraint_name.empty()) return 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));
@@ -188,7 +187,7 @@ Ref<SpineTransformConstraint> SpineSkeleton::find_transform_constraint(const Str
 
 Ref<SpinePathConstraint> SpineSkeleton::find_path_constraint(const String &constraint_name) {
 	SPINE_CHECK(skeleton, nullptr)
-	if (constraint_name.empty()) return 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));

+ 3 - 2
spine-godot/spine_godot/SpineSkeleton.h

@@ -30,6 +30,7 @@
 #ifndef GODOT_SPINESKELETON_H
 #define GODOT_SPINESKELETON_H
 
+#include "SpineCommon.h"
 #include "SpineSkeletonDataResource.h"
 #include "SpineBone.h"
 #include "SpineSlot.h"
@@ -39,8 +40,8 @@
 
 class SpineSprite;
 
-class SpineSkeleton : public Reference {
-	GDCLASS(SpineSkeleton, Reference);
+class SpineSkeleton : public REFCOUNTED {
+	GDCLASS(SpineSkeleton, REFCOUNTED);
 
 	friend class SpineBone;
 	friend class SpineSlot;

+ 19 - 11
spine-godot/spine_godot/SpineSkeletonDataResource.cpp

@@ -41,7 +41,11 @@ 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) {
@@ -116,7 +120,11 @@ 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");
 }
 
@@ -143,15 +151,15 @@ void SpineSkeletonDataResource::update_skeleton_data() {
 	}
 	emit_signal("skeleton_data_changed");
 #ifdef TOOLS_ENABLED
-	property_list_changed_notify();
+	NOTIFY_PROPERTY_LIST_CHANGED();
 #endif
 }
 
 void SpineSkeletonDataResource::load_resources(spine::Atlas *atlas, const String &json, const Vector<uint8_t> &binary) {
-	if ((json.empty() && binary.empty()) || atlas == nullptr) return;
+	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) {
@@ -263,7 +271,7 @@ void SpineSkeletonDataResource::update_mixes() {
 
 Ref<SpineAnimation> SpineSkeletonDataResource::find_animation(const String &animation_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (animation_name.empty()) return 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));
@@ -273,7 +281,7 @@ Ref<SpineAnimation> SpineSkeletonDataResource::find_animation(const String &anim
 
 Ref<SpineBoneData> SpineSkeletonDataResource::find_bone(const String &bone_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (bone_name.empty()) return 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));
@@ -283,7 +291,7 @@ Ref<SpineBoneData> SpineSkeletonDataResource::find_bone(const String &bone_name)
 
 Ref<SpineSlotData> SpineSkeletonDataResource::find_slot(const String &slot_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (slot_name.empty()) return 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));
@@ -293,7 +301,7 @@ Ref<SpineSlotData> SpineSkeletonDataResource::find_slot(const String &slot_name)
 
 Ref<SpineSkin> SpineSkeletonDataResource::find_skin(const String &skin_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (skin_name.empty()) return 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));
@@ -303,7 +311,7 @@ Ref<SpineSkin> SpineSkeletonDataResource::find_skin(const String &skin_name) con
 
 Ref<SpineEventData> SpineSkeletonDataResource::find_event(const String &event_data_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (event_data_name.empty()) return 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));
@@ -313,7 +321,7 @@ Ref<SpineEventData> SpineSkeletonDataResource::find_event(const String &event_da
 
 Ref<SpineIkConstraintData> SpineSkeletonDataResource::find_ik_constraint(const String &constraint_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (constraint_name.empty()) return 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));
@@ -323,7 +331,7 @@ Ref<SpineIkConstraintData> SpineSkeletonDataResource::find_ik_constraint(const S
 
 Ref<SpineTransformConstraintData> SpineSkeletonDataResource::find_transform_constraint(const String &constraint_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (constraint_name.empty()) return 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));
@@ -332,7 +340,7 @@ Ref<SpineTransformConstraintData> SpineSkeletonDataResource::find_transform_cons
 }
 Ref<SpinePathConstraintData> SpineSkeletonDataResource::find_path_constraint(const String &constraint_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
-	if (constraint_name.empty()) return 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));

+ 18 - 1
spine-godot/spine_godot/SpineSkeletonFileResource.cpp

@@ -28,7 +28,11 @@
  *****************************************************************************/
 
 #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() {
 }
@@ -44,20 +48,33 @@ Error SpineSkeletonFileResource::load_from_file(const String &path) {
 
 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 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;
 }
 
+#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;
@@ -78,7 +95,7 @@ bool SpineSkeletonFileResourceFormatLoader::handles_type(const String &type) con
 }
 
 Error SpineSkeletonFileResourceFormatSaver::save(const String &path, const RES &resource, uint32_t flags) {
-	Ref<SpineSkeletonFileResource> res = resource.get_ref_ptr();
+	Ref<SpineSkeletonFileResource> res = resource;
 	Error error = res->save_to_file(path);
 	return error;
 }

+ 6 - 1
spine-godot/spine_godot/SpineSkeletonFileResource.h

@@ -30,6 +30,7 @@
 #ifndef GODOT_SPINESKELETONFILERESOURCE_H
 #define GODOT_SPINESKELETONFILERESOURCE_H
 
+#include "SpineCommon.h"
 #include "core/io/resource_loader.h"
 #include "core/io/resource_saver.h"
 
@@ -43,7 +44,7 @@ protected:
 	Vector<uint8_t> binary;
 
 public:
-	bool is_binary() { return !binary.empty(); }
+	bool is_binary() { return binary.size() > 0; }
 
 	const Vector<uint8_t> &get_binary() { return binary; }
 
@@ -58,7 +59,11 @@ class SpineSkeletonFileResourceFormatLoader : public ResourceFormatLoader {
 	GDCLASS(SpineSkeletonFileResourceFormatLoader, ResourceFormatLoader);
 
 public:
+#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;
 

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

@@ -30,10 +30,11 @@
 #ifndef GODOT_SPINESKIN_H
 #define GODOT_SPINESKIN_H
 
+#include "SpineCommon.h"
 #include "SpineAttachment.h"
 
-class SpineSkin : public Reference {
-	GDCLASS(SpineSkin, Reference);
+class SpineSkin : public REFCOUNTED {
+	GDCLASS(SpineSkin, REFCOUNTED);
 
 protected:
 	static void _bind_methods();
@@ -74,8 +75,8 @@ public:
 	Array get_constraints();
 };
 
-class SpineSkinEntry : public Reference {
-GDCLASS(SpineSkinEntry, Reference);
+class SpineSkinEntry : public REFCOUNTED {
+GDCLASS(SpineSkinEntry, REFCOUNTED);
 
 	friend class SpineSkin;
 

+ 3 - 2
spine-godot/spine_godot/SpineSlot.h

@@ -30,6 +30,7 @@
 #ifndef GODOT_SPINESLOT_H
 #define GODOT_SPINESLOT_H
 
+#include "SpineCommon.h"
 #include "SpineSlotData.h"
 #include "SpineAttachment.h"
 #include "SpineBone.h"
@@ -37,8 +38,8 @@
 // Breaks cyclic dependency.
 class SpineSkeleton;
 
-class SpineSlot : public Reference {
-	GDCLASS(SpineSlot, Reference);
+class SpineSlot : public REFCOUNTED {
+	GDCLASS(SpineSlot, REFCOUNTED);
 
 protected:
 	static void _bind_methods();

+ 3 - 3
spine-godot/spine_godot/SpineSlotData.h

@@ -30,12 +30,12 @@
 #ifndef GODOT_SPINESLOTDATA_H
 #define GODOT_SPINESLOTDATA_H
 
+#include "SpineCommon.h"
 #include "SpineBoneData.h"
-#include "core/object.h"
 #include <spine/SlotData.h>
 
-class SpineSlotData : public Reference {
-	GDCLASS(SpineSlotData, Reference);
+class SpineSlotData : public REFCOUNTED {
+	GDCLASS(SpineSlotData, REFCOUNTED);
 
 protected:
 	static void _bind_methods();

+ 52 - 2
spine-godot/spine_godot/SpineSprite.cpp

@@ -117,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()) {
@@ -142,7 +147,7 @@ void SpineSprite::_on_skeleton_data_changed() {
 		}
 	}
 
-	property_list_changed_notify();
+	NOTIFY_PROPERTY_LIST_CHANGED();
 }
 
 Ref<SpineSkeleton> SpineSprite::get_skeleton() {
@@ -176,7 +181,7 @@ void SpineSprite::_notification(int p_what) {
 }
 
 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);
@@ -238,6 +243,21 @@ void SpineSprite::update_bind_slot_nodes() {
 }
 
 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();
@@ -248,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;
@@ -368,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);
@@ -400,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,
@@ -410,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) {
@@ -429,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,
@@ -439,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);

+ 2 - 1
spine-godot/spine_godot/SpineTimeline.cpp

@@ -30,8 +30,9 @@
 #include "SpineTimeline.h"
 #include "SpineSkeleton.h"
 #include "SpineEvent.h"
-#include "SpineCommon.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);

+ 3 - 3
spine-godot/spine_godot/SpineTimeline.h

@@ -30,15 +30,15 @@
 #ifndef GODOT_SPINETIMELINE_H
 #define GODOT_SPINETIMELINE_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();

+ 3 - 2
spine-godot/spine_godot/SpineTrackEntry.h

@@ -30,12 +30,13 @@
 #ifndef GODOT_SPINETRACKENTRY_H
 #define GODOT_SPINETRACKENTRY_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();

+ 3 - 2
spine-godot/spine_godot/SpineTransformConstraint.h

@@ -30,12 +30,13 @@
 #ifndef GODOT_SPINETRANSFORMCONSTRAINT_H
 #define GODOT_SPINETRANSFORMCONSTRAINT_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();

+ 15 - 2
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"
@@ -56,7 +56,6 @@ 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"
 
@@ -100,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);
 
@@ -111,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() {