[godot] More GDExtension work. SpineAnimationTrack, animation mixes editor plugin and SpineMesh2D are non-functional due to missing APIs in godot-cpp

This commit is contained in:
Mario Zechner 2024-10-07 13:54:58 +02:00
parent f8a0b5b6f7
commit e9b43f9c73
101 changed files with 20604 additions and 41 deletions

7
.gitignore vendored
View File

@ -205,3 +205,10 @@ spine-sdl/.vs
spine-ts/spine-canvaskit/dist
spine-ts/output.png
spine-godot/godot-cpp
spine-godot/__pycache__
*.os
spine-godot/.sconsign.dblite
spine-godot/example-v4-extension/.godot
spine-godot/src
spine-godot/compile_commands.json
spine-godot/bin

View File

@ -1,5 +1,20 @@
{
"cmake.configureOnOpen": false,
"C_Cpp.intelliSenseEngine": "default",
"dotnet.defaultSolution": "disable"
"dotnet.defaultSolution": "disable",
"files.associations": {
"__bit_reference": "cpp",
"__hash_table": "cpp",
"__tree": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"string_view": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"__split_buffer": "cpp",
"deque": "cpp",
"list": "cpp"
}
}

99
spine-godot/SConstruct Normal file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env python
import os
import sys
from methods import print_error
def normalize_path(val, env):
return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val)
def validate_parent_dir(key, val, env):
if not os.path.isdir(normalize_path(os.path.dirname(val), env)):
raise UserError("'%s' is not a directory: %s" % (key, os.path.dirname(val)))
libname = "spine_godot"
projectdir = "example-v4-extension"
localEnv = Environment(tools=["default"], PLATFORM="")
customs = ["custom.py"]
customs = [os.path.abspath(path) for path in customs]
opts = Variables(customs, ARGUMENTS)
opts.Add(
BoolVariable(
key="compiledb",
help="Generate compilation DB (`compile_commands.json`) for external tools",
default=localEnv.get("compiledb", False),
)
)
opts.Add(
PathVariable(
key="compiledb_file",
help="Path to a custom `compile_commands.json` file",
default=localEnv.get("compiledb_file", "compile_commands.json"),
validator=validate_parent_dir,
)
)
opts.Update(localEnv)
Help(opts.GenerateHelpText(localEnv))
env = localEnv.Clone()
env["compiledb"] = False
env.Tool("compilation_db")
compilation_db = env.CompilationDatabase(
normalize_path(localEnv["compiledb_file"], localEnv)
)
env.Alias("compiledb", compilation_db)
submodule_initialized = False
dir_name = 'godot-cpp'
if os.path.isdir(dir_name):
if os.listdir(dir_name):
submodule_initialized = True
if not submodule_initialized:
print_error("""godot-cpp is not available within this folder, as Git submodules haven't been initialized.
Run the following command to download godot-cpp:
git submodule update --init --recursive""")
sys.exit(1)
env = SConscript("godot-cpp/SConstruct", {"env": env, "customs": customs})
env.Append(CPPDEFINES=["SPINE_GODOT_EXTENSION"])
env.Append(CPPPATH=["spine_godot/", "spine_godot/spine-cpp/include"])
sources = Glob("spine_godot/*.cpp") + Glob("spine_godot/spine-cpp/src/spine/*.cpp")
if env["target"] in ["editor", "template_debug"]:
try:
doc_data = env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=Glob("spine_godot/docs/*.xml"))
sources.append(doc_data)
except AttributeError:
print("Not including class reference as we're targeting a pre-4.3 baseline.")
file = "{}{}{}".format(libname, env["suffix"], env["SHLIBSUFFIX"])
filepath = ""
if env["platform"] == "macos" or env["platform"] == "ios":
filepath = "{}.framework/".format(env["platform"])
file = "{}.{}.{}".format(libname, env["platform"], env["target"])
libraryfile = "bin/{}/{}{}".format(env["platform"], filepath, file)
library = env.SharedLibrary(
libraryfile,
source=sources,
)
copy = env.InstallAs("{}/bin/{}/{}lib{}".format(projectdir, env["platform"], filepath, file), library)
default_args = [library, copy]
if localEnv.get("compiledb", False):
default_args += [compilation_db]
Default(*default_args)

View File

@ -0,0 +1,8 @@
[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=3 uid="uid://d1ordmjpe5kt7"]
[ext_resource type="SpineAtlasResource" uid="uid://syvy0bxbnwgi" path="res://assets/celestial-circus/celestial-circus.atlas" id="1_fs1an"]
[ext_resource type="SpineSkeletonFileResource" uid="uid://doan7yl2by7vm" path="res://assets/celestial-circus/celestial-circus.skel" id="2_sbom4"]
[resource]
atlas_res = ExtResource("1_fs1an")
skeleton_file_res = ExtResource("2_sbom4")

View File

@ -0,0 +1,173 @@
celestial-circus.png
size: 1024, 1024
filter: Linear, Linear
scale: 0.4
arm-back-down
bounds: 324, 401, 38, 82
rotate: 90
arm-back-up
bounds: 290, 44, 83, 116
rotate: 90
arm-front-down
bounds: 706, 2, 36, 78
rotate: 90
arm-front-up
bounds: 860, 138, 77, 116
bench
bounds: 725, 256, 189, 48
body-bottom
bounds: 879, 868, 154, 124
rotate: 90
body-top
bounds: 725, 128, 126, 133
rotate: 90
chest
bounds: 408, 26, 104, 93
cloud-back
bounds: 752, 378, 202, 165
cloud-front
bounds: 2, 2, 325, 196
rotate: 90
collar
bounds: 786, 13, 47, 26
ear
bounds: 1002, 643, 20, 28
eye-back-shadow
bounds: 428, 395, 14, 10
eye-front-shadow
bounds: 704, 529, 24, 14
eye-reflex-back
bounds: 860, 128, 8, 7
rotate: 90
eye-reflex-front
bounds: 726, 386, 10, 7
eye-white-back
bounds: 835, 23, 13, 16
eye-white-front
bounds: 1005, 1000, 22, 17
rotate: 90
eyelashes-down-back
bounds: 232, 329, 11, 6
rotate: 90
eyelashes-down-front
bounds: 913, 851, 15, 6
rotate: 90
eyelashes-top-back
bounds: 408, 395, 18, 10
eyelashes-top-front
bounds: 702, 179, 30, 16
rotate: 90
face
bounds: 514, 26, 93, 102
rotate: 90
feathers-back
bounds: 954, 625, 46, 46
feathers-front
bounds: 706, 40, 72, 86
fringe-middle-back
bounds: 200, 6, 33, 52
rotate: 90
fringe-middle-front
bounds: 878, 76, 60, 50
rotate: 90
fringe-side-back
bounds: 780, 41, 27, 94
rotate: 90
fringe-side-front
bounds: 939, 161, 26, 93
glove-bottom-back
bounds: 954, 572, 51, 41
rotate: 90
glove-bottom-front
bounds: 916, 256, 47, 48
hair-back-1
bounds: 444, 395, 132, 306
rotate: 90
hair-back-2
bounds: 438, 211, 80, 285
rotate: 90
hair-back-3
bounds: 719, 306, 70, 268
rotate: 90
hair-back-4
bounds: 438, 121, 88, 262
rotate: 90
hair-back-5
bounds: 438, 293, 88, 279
rotate: 90
hair-back-6
bounds: 200, 41, 88, 286
hair-hat-shadow
bounds: 232, 398, 90, 41
hand-back
bounds: 954, 673, 60, 47
rotate: 90
hand-front
bounds: 967, 172, 53, 60
hat-back
bounds: 954, 802, 64, 45
rotate: 90
hat-front
bounds: 780, 70, 96, 56
head-back
bounds: 618, 17, 102, 86
rotate: 90
jabot
bounds: 967, 234, 70, 55
rotate: 90
leg-back
bounds: 232, 441, 210, 333
leg-front
bounds: 444, 529, 258, 320
logo-brooch
bounds: 954, 545, 16, 25
mouth
bounds: 408, 121, 22, 6
neck
bounds: 232, 342, 39, 56
rotate: 90
nose
bounds: 742, 529, 6, 7
rotate: 90
nose-highlight
bounds: 719, 300, 4, 4
nose-shadow
bounds: 869, 128, 7, 8
pupil-back
bounds: 730, 529, 10, 14
pupil-front
bounds: 254, 21, 12, 18
rope-back
bounds: 232, 383, 10, 492
rotate: 90
rope-front
bounds: 232, 383, 10, 492
rotate: 90
rope-front-bottom
bounds: 954, 735, 42, 65
skirt
bounds: 2, 776, 440, 246
sock-bow
bounds: 408, 407, 33, 32
spine-logo-body
bounds: 879, 853, 13, 32
rotate: 90
star-big
bounds: 939, 141, 18, 24
rotate: 90
star-medium
bounds: 742, 537, 6, 8
rotate: 90
star-small
bounds: 719, 378, 3, 4
rotate: 90
underskirt
bounds: 2, 329, 445, 228
rotate: 90
underskirt-back
bounds: 444, 851, 433, 171
wing-back
bounds: 290, 129, 146, 252
wing-front
bounds: 704, 545, 304, 248
rotate: 90

View File

@ -0,0 +1,15 @@
[remap]
importer="spine.atlas"
type="SpineAtlasResource"
uid="uid://syvy0bxbnwgi"
path="res://.godot/imported/celestial-circus.atlas-8277f39286d729eed930dc8584632c9d.spatlas"
[deps]
source_file="res://assets/celestial-circus/celestial-circus.atlas"
dest_files=["res://.godot/imported/celestial-circus.atlas-8277f39286d729eed930dc8584632c9d.spatlas"]
[params]
normal_map_prefix="n"

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d27f2nxof5i18"
path="res://.godot/imported/celestial-circus.png-362082edc9ee92c57423ee448ab8be8a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/celestial-circus/celestial-circus.png"
dest_files=["res://.godot/imported/celestial-circus.png-362082edc9ee92c57423ee448ab8be8a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,14 @@
[remap]
importer="spine.skel"
type="SpineSkeletonFileResource"
uid="uid://doan7yl2by7vm"
path="res://.godot/imported/celestial-circus.skel-57e15df02c4ab2ec1bbb6a38273235f3.spskel"
[deps]
source_file="res://assets/celestial-circus/celestial-circus.skel"
dest_files=["res://.godot/imported/celestial-circus.skel-57e15df02c4ab2ec1bbb6a38273235f3.spskel"]
[params]

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://baym8211e1as0"
path="res://.godot/imported/celestial-circus_2.png-10ce6d37d52bd6e8495aa1b68f8b3576.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/celestial-circus/celestial-circus_2.png"
dest_files=["res://.godot/imported/celestial-circus_2.png-10ce6d37d52bd6e8495aa1b68f8b3576.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

View File

@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://can7k84o8svum"
path="res://.godot/imported/footstep.ogg-789c3f1e3c4e0ca3bebcb13f1160f623.oggvorbisstr"
[deps]
source_file="res://assets/footstep.ogg"
dest_files=["res://.godot/imported/footstep.ogg-789c3f1e3c4e0ca3bebcb13f1160f623.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4

View File

@ -0,0 +1,10 @@
[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=2]
[ext_resource path="res://assets/mix-and-match/mix-and-match.atlas" type="SpineAtlasResource" id=1]
[ext_resource path="res://assets/mix-and-match/mix-and-match-pro.spine-json" type="SpineSkeletonFileResource" id=2]
[resource]
atlas_res = ExtResource( 1 )
skeleton_file_res = ExtResource( 2 )
animations = null
skins = null

View File

@ -0,0 +1,14 @@
[remap]
importer="spine.json"
type="SpineSkeletonFileResource"
uid="uid://ckitsrtfxmo2w"
path="res://.godot/imported/mix-and-match-pro.spine-json-3655503b0d08b0b0590c6310da1ac47b.spjson"
[deps]
source_file="res://assets/mix-and-match/mix-and-match-pro.spine-json"
dest_files=["res://.godot/imported/mix-and-match-pro.spine-json-3655503b0d08b0b0590c6310da1ac47b.spjson"]
[params]

View File

@ -0,0 +1,358 @@
mix-and-match.png
size: 1024, 512
filter: Linear, Linear
scale: 0.5
base-head
bounds: 118, 70, 95, 73
boy/arm-front
bounds: 831, 311, 36, 115
rotate: 90
boy/backpack
bounds: 249, 357, 119, 153
boy/backpack-pocket
bounds: 628, 193, 34, 62
rotate: 90
boy/backpack-strap-front
bounds: 330, 263, 38, 88
rotate: 90
boy/backpack-up
bounds: 482, 171, 21, 70
boy/body
bounds: 845, 413, 97, 132
rotate: 90
boy/boot-ribbon-front
bounds: 234, 304, 9, 11
boy/collar
bounds: 471, 243, 73, 29
rotate: 90
boy/ear
bounds: 991, 352, 19, 23
rotate: 90
boy/eye-back-low-eyelid
bounds: 66, 72, 17, 6
boy/eye-back-pupil
bounds: 694, 279, 8, 9
rotate: 90
boy/eye-back-up-eyelid
bounds: 460, 101, 23, 5
rotate: 90
boy/eye-back-up-eyelid-back
bounds: 979, 414, 19, 10
rotate: 90
boy/eye-front-low-eyelid
bounds: 1015, 203, 22, 7
rotate: 90
boy/eye-front-pupil
bounds: 309, 50, 9, 9
boy/eye-front-up-eyelid
bounds: 991, 373, 31, 6
boy/eye-front-up-eyelid-back
bounds: 107, 76, 26, 9
rotate: 90
boy/eye-iris-back
bounds: 810, 260, 17, 17
boy/eye-iris-front
bounds: 902, 230, 18, 18
boy/eye-white-back
bounds: 599, 179, 20, 12
boy/eye-white-front
bounds: 544, 183, 27, 13
boy/eyebrow-back
bounds: 1002, 225, 20, 11
rotate: 90
boy/eyebrow-front
bounds: 975, 234, 25, 11
boy/hair-back
bounds: 629, 289, 122, 81
rotate: 90
boy/hair-bangs
bounds: 505, 180, 70, 37
rotate: 90
boy/hair-side
bounds: 979, 435, 25, 43
rotate: 90
boy/hand-backfingers
bounds: 858, 183, 19, 21
boy/hand-front-fingers
bounds: 879, 183, 19, 21
boy/hat
bounds: 218, 121, 93, 56
boy/leg-front
bounds: 85, 104, 31, 158
boy/mouth-close
bounds: 467, 100, 21, 5
girl-blue-cape/mouth-close
bounds: 467, 100, 21, 5
girl-spring-dress/mouth-close
bounds: 467, 100, 21, 5
girl/mouth-close
bounds: 467, 100, 21, 5
boy/mouth-smile
bounds: 1015, 258, 29, 7
rotate: 90
boy/nose
bounds: 323, 79, 17, 10
boy/pompom
bounds: 979, 462, 48, 43
rotate: 90
boy/zip
bounds: 922, 231, 14, 23
rotate: 90
girl-blue-cape/back-eyebrow
bounds: 527, 106, 18, 12
rotate: 90
girl-blue-cape/body-dress
bounds: 2, 264, 109, 246
girl-blue-cape/body-ribbon
bounds: 576, 193, 50, 38
girl-blue-cape/cape-back
bounds: 113, 317, 134, 193
girl-blue-cape/cape-back-up
bounds: 504, 305, 123, 106
girl-blue-cape/cape-ribbon
bounds: 396, 118, 50, 18
rotate: 90
girl-blue-cape/cape-shoulder-back
bounds: 420, 243, 49, 59
girl-blue-cape/cape-shoulder-front
bounds: 2, 2, 62, 76
girl-blue-cape/cape-up-front
bounds: 118, 145, 98, 117
girl-blue-cape/ear
bounds: 837, 181, 19, 23
girl-spring-dress/ear
bounds: 837, 181, 19, 23
girl/ear
bounds: 837, 181, 19, 23
girl-blue-cape/eye-back-low-eyelid
bounds: 810, 252, 17, 6
girl-spring-dress/eye-back-low-eyelid
bounds: 810, 252, 17, 6
girl/eye-back-low-eyelid
bounds: 810, 252, 17, 6
girl-blue-cape/eye-back-pupil
bounds: 309, 40, 8, 9
rotate: 90
girl-spring-dress/eye-back-pupil
bounds: 309, 40, 8, 9
rotate: 90
girl/eye-back-pupil
bounds: 309, 40, 8, 9
rotate: 90
girl-blue-cape/eye-back-up-eyelid
bounds: 573, 179, 24, 12
girl-spring-dress/eye-back-up-eyelid
bounds: 573, 179, 24, 12
girl/eye-back-up-eyelid
bounds: 573, 179, 24, 12
girl-blue-cape/eye-back-up-eyelid-back
bounds: 380, 105, 17, 11
rotate: 90
girl-spring-dress/eye-back-up-eyelid-back
bounds: 380, 105, 17, 11
rotate: 90
girl/eye-back-up-eyelid-back
bounds: 380, 105, 17, 11
rotate: 90
girl-blue-cape/eye-front-low-eyelid
bounds: 1016, 353, 18, 6
rotate: 90
girl-spring-dress/eye-front-low-eyelid
bounds: 1016, 353, 18, 6
rotate: 90
girl/eye-front-low-eyelid
bounds: 1016, 353, 18, 6
rotate: 90
girl-blue-cape/eye-front-pupil
bounds: 363, 94, 9, 9
girl-spring-dress/eye-front-pupil
bounds: 363, 94, 9, 9
girl/eye-front-pupil
bounds: 363, 94, 9, 9
girl-blue-cape/eye-front-up-eyelid
bounds: 679, 413, 30, 14
rotate: 90
girl-spring-dress/eye-front-up-eyelid
bounds: 679, 413, 30, 14
rotate: 90
girl/eye-front-up-eyelid
bounds: 679, 413, 30, 14
rotate: 90
girl-blue-cape/eye-front-up-eyelid-back
bounds: 947, 234, 26, 11
girl-spring-dress/eye-front-up-eyelid-back
bounds: 947, 234, 26, 11
girl/eye-front-up-eyelid-back
bounds: 947, 234, 26, 11
girl-blue-cape/eye-iris-back
bounds: 323, 105, 17, 17
girl-blue-cape/eye-iris-front
bounds: 467, 107, 18, 18
girl-blue-cape/eye-white-back
bounds: 621, 175, 20, 16
girl-spring-dress/eye-white-back
bounds: 621, 175, 20, 16
girl-blue-cape/eye-white-front
bounds: 643, 175, 20, 16
girl-spring-dress/eye-white-front
bounds: 643, 175, 20, 16
girl/eye-white-front
bounds: 643, 175, 20, 16
girl-blue-cape/front-eyebrow
bounds: 309, 101, 18, 12
rotate: 90
girl-blue-cape/hair-back
bounds: 712, 317, 117, 98
girl-blue-cape/hair-bangs
bounds: 313, 170, 91, 40
rotate: 90
girl-blue-cape/hair-head-side-back
bounds: 544, 198, 30, 52
girl-blue-cape/hair-head-side-front
bounds: 466, 127, 41, 42
girl-blue-cape/hair-side
bounds: 175, 2, 36, 71
rotate: 90
girl-blue-cape/hand-front-fingers
bounds: 902, 207, 19, 21
girl-spring-dress/hand-front-fingers
bounds: 902, 207, 19, 21
girl-blue-cape/leg-front
bounds: 519, 413, 30, 158
rotate: 90
girl-blue-cape/mouth-smile
bounds: 1015, 227, 29, 7
rotate: 90
girl-spring-dress/mouth-smile
bounds: 1015, 227, 29, 7
rotate: 90
girl/mouth-smile
bounds: 1015, 227, 29, 7
rotate: 90
girl-blue-cape/nose
bounds: 342, 82, 11, 7
girl-spring-dress/nose
bounds: 342, 82, 11, 7
girl/nose
bounds: 342, 82, 11, 7
girl-blue-cape/sleeve-back
bounds: 416, 95, 42, 29
girl-blue-cape/sleeve-front
bounds: 249, 303, 52, 119
rotate: 90
girl-spring-dress/arm-front
bounds: 829, 292, 17, 111
rotate: 90
girl-spring-dress/back-eyebrow
bounds: 309, 81, 18, 12
rotate: 90
girl-spring-dress/body-up
bounds: 66, 2, 64, 66
girl-spring-dress/cloak-down
bounds: 758, 227, 50, 50
girl-spring-dress/cloak-up
bounds: 628, 229, 64, 58
girl-spring-dress/eye-iris-back
bounds: 342, 105, 17, 17
girl-spring-dress/eye-iris-front
bounds: 487, 107, 18, 18
girl-spring-dress/front-eyebrow
bounds: 323, 91, 18, 12
girl-spring-dress/hair-back
bounds: 370, 417, 147, 93
girl-spring-dress/hair-bangs
bounds: 829, 250, 91, 40
girl-spring-dress/hair-head-side-back
bounds: 509, 126, 30, 52
girl-spring-dress/hair-head-side-front
bounds: 816, 206, 41, 42
girl-spring-dress/hair-side
bounds: 248, 2, 36, 71
rotate: 90
girl-spring-dress/leg-front
bounds: 831, 381, 30, 158
rotate: 90
girl-spring-dress/neck
bounds: 85, 70, 20, 32
girl-spring-dress/shoulder-ribbon
bounds: 175, 44, 36, 24
girl-spring-dress/skirt
bounds: 2, 80, 182, 81
rotate: 90
girl-spring-dress/underskirt
bounds: 519, 445, 175, 65
girl/arm-front
bounds: 712, 279, 36, 115
rotate: 90
girl/back-eyebrow
bounds: 309, 61, 18, 12
rotate: 90
girl/bag-base
bounds: 694, 219, 62, 58
girl/bag-strap-front
bounds: 370, 304, 12, 96
rotate: 90
girl/bag-top
bounds: 765, 175, 49, 50
girl/body
bounds: 370, 318, 97, 132
rotate: 90
girl/boot-ribbon-front
bounds: 323, 64, 13, 13
girl/eye-iris-back
bounds: 361, 105, 17, 17
girl/eye-iris-front
bounds: 507, 106, 18, 18
girl/eye-white-back
bounds: 665, 175, 20, 16
girl/front-eyebrow
bounds: 343, 91, 18, 12
girl/hair-back
bounds: 696, 417, 147, 93
girl/hair-bangs
bounds: 922, 247, 91, 40
girl/hair-flap-down-front
bounds: 415, 171, 70, 65
rotate: 90
girl/hair-head-side-back
bounds: 991, 381, 30, 52
girl/hair-head-side-front
bounds: 859, 206, 41, 42
girl/hair-patch
bounds: 132, 2, 66, 41
rotate: 90
girl/hair-side
bounds: 692, 181, 36, 71
rotate: 90
girl/hair-strand-back-1
bounds: 948, 289, 58, 74
rotate: 90
girl/hair-strand-back-2
bounds: 355, 170, 91, 58
rotate: 90
girl/hair-strand-back-3
bounds: 215, 40, 92, 79
girl/hair-strand-front-1
bounds: 234, 263, 38, 94
rotate: 90
girl/hair-strand-front-2
bounds: 576, 233, 70, 50
rotate: 90
girl/hair-strand-front-3
bounds: 313, 124, 44, 81
rotate: 90
girl/hand-front-fingers
bounds: 923, 208, 19, 21
girl/hat
bounds: 218, 179, 93, 82
girl/leg-front
bounds: 831, 349, 30, 158
rotate: 90
girl/pompom
bounds: 416, 126, 48, 43
girl/scarf
bounds: 113, 264, 119, 51
girl/scarf-back
bounds: 502, 252, 72, 51
girl/zip
bounds: 816, 179, 19, 25

View File

@ -0,0 +1,15 @@
[remap]
importer="spine.atlas"
type="SpineAtlasResource"
uid="uid://cvu8lycjkd245"
path="res://.godot/imported/mix-and-match.atlas-3d349b543ecdcc01fb29033adaef0841.spatlas"
[deps]
source_file="res://assets/mix-and-match/mix-and-match.atlas"
dest_files=["res://.godot/imported/mix-and-match.atlas-3d349b543ecdcc01fb29033adaef0841.spatlas"]
[params]
normal_map_prefix="n"

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dkpeve6qcxa70"
path="res://.godot/imported/mix-and-match.png-c2d8e28d9f2efc380ff8b95a22dadcc3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/mix-and-match/mix-and-match.png"
dest_files=["res://.godot/imported/mix-and-match.png-c2d8e28d9f2efc380ff8b95a22dadcc3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,15 @@
[remap]
importer="spine.atlas"
type="SpineAtlasResource"
uid="uid://c75mtwn6dnkwp"
path="res://.godot/imported/Raggedy Spineboy.atlas-07f7c6b30431397bcf472b18d48851e0.spatlas"
[deps]
source_file="res://assets/raggedyspineboy/Raggedy Spineboy.atlas"
dest_files=["res://.godot/imported/Raggedy Spineboy.atlas-07f7c6b30431397bcf472b18d48851e0.spatlas"]
[params]
normal_map_prefix="n"

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://couyrsq850nh6"
path="res://.godot/imported/Raggedy Spineboy.png-8982b59aad5b612b7ed1a5da8b447d00.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/raggedyspineboy/Raggedy Spineboy.png"
dest_files=["res://.godot/imported/Raggedy Spineboy.png-8982b59aad5b612b7ed1a5da8b447d00.ctex"]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,8 @@
[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=2]
[ext_resource path="res://assets/raggedyspineboy/Raggedy Spineboy.atlas" type="SpineAtlasResource" id=1]
[ext_resource path="res://assets/raggedyspineboy/raggedy spineboy.spine-json" type="SpineSkeletonFileResource" id=2]
[resource]
atlas_res = ExtResource( 1 )
skeleton_file_res = ExtResource( 2 )

View File

@ -0,0 +1,14 @@
[remap]
importer="spine.json"
type="SpineSkeletonFileResource"
uid="uid://2iqykoiop2tc"
path="res://.godot/imported/raggedy spineboy.spine-json-d90ee4b829503274afa3dbf64c369460.spjson"
[deps]
source_file="res://assets/raggedyspineboy/raggedy spineboy.spine-json"
dest_files=["res://.godot/imported/raggedy spineboy.spine-json-d90ee4b829503274afa3dbf64c369460.spjson"]
[params]

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cggfs567rn1ay"
path="res://.godot/imported/light-sprite.png-346e910021b52658f1de723e4c80e05e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/raptor/light-sprite.png"
dest_files=["res://.godot/imported/light-sprite.png-346e910021b52658f1de723e4c80e05e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dnjt8gyvsw0l8"
path="res://.godot/imported/n_raptor.png-d9af68b4a56af2b4319bb485e366dc90.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/raptor/n_raptor.png"
dest_files=["res://.godot/imported/n_raptor.png-d9af68b4a56af2b4319bb485e366dc90.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,9 @@
[gd_resource type="SpineSkeletonDataResource" load_steps=3 format=2]
[ext_resource path="res://assets/raptor/raptor.atlas" type="SpineAtlasResource" id=1]
[ext_resource path="res://assets/raptor/raptor-pro.skel" type="SpineSkeletonFileResource" id=2]
[resource]
atlas_res = ExtResource( 1 )
skeleton_file_res = ExtResource( 2 )
default_mix = 0.2

View File

@ -0,0 +1,14 @@
[remap]
importer="spine.skel"
type="SpineSkeletonFileResource"
uid="uid://dor8huwld4f84"
path="res://.godot/imported/raptor-pro.skel-022e23a5f5581547a2d7faa9fb2c54e3.spskel"
[deps]
source_file="res://assets/raptor/raptor-pro.skel"
dest_files=["res://.godot/imported/raptor-pro.skel-022e23a5f5581547a2d7faa9fb2c54e3.spskel"]
[params]

View File

@ -0,0 +1,93 @@
raptor.png
size: 1024, 512
filter: Linear, Linear
scale: 0.5
back-arm
bounds: 895, 295, 46, 25
back-bracer
bounds: 992, 216, 39, 28
rotate: 90
back-hand
bounds: 594, 58, 36, 34
back-knee
bounds: 729, 86, 49, 67
rotate: 90
back-thigh
bounds: 379, 2, 39, 24
eyes-open
bounds: 902, 194, 47, 45
rotate: 90
front-arm
bounds: 945, 306, 48, 26
front-bracer
bounds: 949, 197, 41, 29
front-hand
bounds: 949, 266, 41, 38
front-open-hand
bounds: 875, 148, 43, 44
front-thigh
bounds: 793, 171, 57, 29
rotate: 90
gun
bounds: 379, 28, 107, 103
rotate: 90
gun-nohand
bounds: 487, 87, 105, 102
head
bounds: 807, 361, 136, 149
lower-leg
bounds: 827, 195, 73, 98
mouth-grind
bounds: 920, 145, 47, 30
rotate: 90
mouth-smile
bounds: 992, 257, 47, 30
rotate: 90
neck
bounds: 359, 114, 18, 21
raptor-back-arm
bounds: 653, 142, 82, 86
raptor-body
bounds: 2, 277, 632, 233
raptor-front-arm
bounds: 484, 4, 81, 102
rotate: 90
raptor-front-leg
bounds: 2, 18, 191, 257
raptor-hindleg-back
bounds: 636, 295, 169, 215
raptor-horn
bounds: 195, 22, 182, 80
raptor-horn-back
bounds: 945, 334, 176, 77
rotate: 90
raptor-jaw
bounds: 359, 137, 126, 138
raptor-jaw-tooth
bounds: 895, 322, 37, 48
rotate: 90
raptor-mouth-inside
bounds: 949, 228, 36, 41
rotate: 90
raptor-saddle-strap-back
bounds: 653, 86, 54, 74
rotate: 90
raptor-saddle-strap-front
bounds: 594, 94, 57, 95
raptor-saddle-w-shadow
bounds: 195, 104, 162, 171
raptor-tail-shadow
bounds: 636, 230, 189, 63
raptor-tongue
bounds: 807, 295, 86, 64
stirrup-back
bounds: 952, 151, 44, 35
rotate: 90
stirrup-front
bounds: 902, 243, 45, 50
stirrup-strap
bounds: 824, 147, 49, 46
torso
bounds: 737, 137, 54, 91
visor
bounds: 487, 191, 131, 84

View File

@ -0,0 +1,15 @@
[remap]
importer="spine.atlas"
type="SpineAtlasResource"
uid="uid://dhtyf5vltqsjg"
path="res://.godot/imported/raptor.atlas-66da4b831eebf404341993162ba3ddb8.spatlas"
[deps]
source_file="res://assets/raptor/raptor.atlas"
dest_files=["res://.godot/imported/raptor.atlas-66da4b831eebf404341993162ba3ddb8.spatlas"]
[params]
normal_map_prefix="n"

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ucvdpil67hul"
path="res://.godot/imported/raptor.png-505be50f63fd1d0fb9175a9efbb9776c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/raptor/raptor.png"
dest_files=["res://.godot/imported/raptor.png-505be50f63fd1d0fb9175a9efbb9776c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,20 @@
[gd_resource type="SpineSkeletonDataResource" load_steps=5 format=3 uid="uid://cb6rn6vonqbx0"]
[ext_resource type="SpineAtlasResource" uid="uid://dt2kctrit34y0" path="res://assets/spineboy/spineboy.atlas" id="1"]
[ext_resource type="SpineSkeletonFileResource" uid="uid://bngulrxfavqyn" path="res://assets/spineboy/spineboy-pro.spine-json" 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")
default_mix = 0.1
animation_mixes = [SubResource("1"), SubResource("2")]

View File

@ -0,0 +1,14 @@
[remap]
importer="spine.skel"
type="SpineSkeletonFileResource"
uid="uid://cth0eypg16cgi"
path="res://.godot/imported/spineboy-pro.skel-52781a88227740d2a80cb8d7636ea22e.spskel"
[deps]
source_file="res://assets/spineboy/spineboy-pro.skel"
dest_files=["res://.godot/imported/spineboy-pro.skel-52781a88227740d2a80cb8d7636ea22e.spskel"]
[params]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
[remap]
importer="spine.json"
type="SpineSkeletonFileResource"
uid="uid://bngulrxfavqyn"
path="res://.godot/imported/spineboy-pro.spine-json-f9f3900b0187b1b6e5b1abca50f5f02a.spjson"
[deps]
source_file="res://assets/spineboy/spineboy-pro.spine-json"
dest_files=["res://.godot/imported/spineboy-pro.spine-json-f9f3900b0187b1b6e5b1abca50f5f02a.spjson"]
[params]

View File

@ -0,0 +1,94 @@
spineboy.png
size: 1024, 256
filter: Linear, Linear
scale: 0.5
crosshair
bounds: 352, 7, 45, 45
eye-indifferent
bounds: 862, 105, 47, 45
eye-surprised
bounds: 505, 79, 47, 45
front-bracer
bounds: 826, 66, 29, 40
front-fist-closed
bounds: 786, 65, 38, 41
front-fist-open
bounds: 710, 51, 43, 44
rotate: 90
front-foot
bounds: 210, 6, 63, 35
front-shin
bounds: 665, 128, 41, 92
rotate: 90
front-thigh
bounds: 2, 2, 23, 56
rotate: 90
front-upper-arm
bounds: 250, 205, 23, 49
goggles
bounds: 665, 171, 131, 83
gun
bounds: 798, 152, 105, 102
head
bounds: 2, 27, 136, 149
hoverboard-board
bounds: 2, 178, 246, 76
hoverboard-thruster
bounds: 722, 96, 30, 32
rotate: 90
hoverglow-small
bounds: 275, 81, 137, 38
mouth-grind
bounds: 614, 97, 47, 30
mouth-oooo
bounds: 612, 65, 47, 30
mouth-smile
bounds: 661, 64, 47, 30
muzzle-glow
bounds: 382, 54, 25, 25
muzzle-ring
bounds: 275, 54, 25, 105
rotate: 90
muzzle01
bounds: 911, 95, 67, 40
rotate: 90
muzzle02
bounds: 792, 108, 68, 42
muzzle03
bounds: 956, 171, 83, 53
rotate: 90
muzzle04
bounds: 275, 7, 75, 45
muzzle05
bounds: 140, 3, 68, 38
neck
bounds: 250, 182, 18, 21
portal-bg
bounds: 140, 43, 133, 133
portal-flare1
bounds: 554, 65, 56, 30
portal-flare2
bounds: 759, 112, 57, 31
rotate: 90
portal-flare3
bounds: 554, 97, 58, 30
portal-shade
bounds: 275, 121, 133, 133
portal-streaks1
bounds: 410, 126, 126, 128
portal-streaks2
bounds: 538, 129, 125, 125
rear-bracer
bounds: 857, 67, 28, 36
rear-foot
bounds: 663, 96, 57, 30
rear-shin
bounds: 414, 86, 38, 89
rotate: 90
rear-thigh
bounds: 756, 63, 28, 47
rear-upper-arm
bounds: 60, 5, 20, 44
rotate: 90
torso
bounds: 905, 164, 49, 90

View File

@ -0,0 +1,15 @@
[remap]
importer="spine.atlas"
type="SpineAtlasResource"
uid="uid://dt2kctrit34y0"
path="res://.godot/imported/spineboy.atlas-54c12b5ff1cdaaa1b4e452a7d0d868c9.spatlas"
[deps]
source_file="res://assets/spineboy/spineboy.atlas"
dest_files=["res://.godot/imported/spineboy.atlas-54c12b5ff1cdaaa1b4e452a7d0d868c9.spatlas"]
[params]
normal_map_prefix="n"

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bh5imhdfuc6m0"
path="res://.godot/imported/spineboy.png-436dbd6da2b707b6828ede17b7871f43.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/spineboy/spineboy.png"
dest_files=["res://.godot/imported/spineboy.png-436dbd6da2b707b6828ede17b7871f43.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,25 @@
[configuration]
entry_symbol = "spine_godot_library_init"
compatibility_minimum = "4.1"
[libraries]
macos.debug = "res://bin/macos/macos.framework/libspine_godot.macos.template_debug"
macos.release = "res://bin/macos/macos.framework/libspine_godot.macos.template_release"
ios.debug = "res://bin/ios/ios.framework/libspine_godot.ios.template_debug"
ios.release = "res://bin/ios/ios.framework/libspine_godot.ios.template_release"
windows.debug.x86_32 = "res://bin/windows/libspine_godot.windows.template_debug.x86_32.dll"
windows.release.x86_32 = "res://bin/windows/libspine_godot.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "res://bin/windows/libspine_godot.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://bin/windows/libspine_godot.windows.template_release.x86_64.dll"
linux.debug.x86_64 = "res://bin/linux/libspine_godot.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://bin/linux/libspine_godot.linux.template_release.x86_64.so"
linux.debug.arm64 = "res://bin/linux/libspine_godot.linux.template_debug.arm64.so"
linux.release.arm64 = "res://bin/linux/libspine_godot.linux.template_release.arm64.so"
linux.debug.rv64 = "res://bin/linux/libspine_godot.linux.template_debug.rv64.so"
linux.release.rv64 = "res://bin/linux/libspine_godot.linux.template_release.rv64.so"
android.debug.x86_64 = "res://bin/android/libspine_godot.android.template_debug.x86_64.so"
android.release.x86_64 = "res://bin/android/libspine_godot.android.template_release.x86_64.so"
android.debug.arm64 = "res://bin/android/libspine_godot.android.template_debug.arm64.so"
android.release.arm64 = "res://bin/android/libspine_godot.android.template_release.arm64.so"

View File

@ -0,0 +1,7 @@
[gd_resource type="Environment" load_steps=2 format=2]
[sub_resource type="ProceduralSky" id=1]
[resource]
background_mode = 2
background_sky = SubResource( 1 )

View File

@ -0,0 +1,19 @@
[gd_scene load_steps=3 format=3 uid="uid://d0v5rhv2ysej8"]
[ext_resource type="Script" path="res://examples/01-helloworld/spineboy-helloworld.gd" id="1"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="3"]
[node name="Node2D" type="Node2D"]
[node name="Spineboy" type="SpineSprite" parent="."]
position = Vector2(505, 466)
scale = Vector2(0.466832, 0.466832)
skeleton_data_res = ExtResource("3")
bones_color = Color(0.968627, 1, 0, 0.501961)
paths_color = Color(1, 0.498039, 0, 0.466667)
paths_clipping = Color(0.8, 0, 0, 0.5)
preview_skin = "Default"
preview_animation = "run"
preview_frame = true
preview_time = 0.24
script = ExtResource("1")

View File

@ -0,0 +1,4 @@
extends SpineSprite
func _ready():
get_animation_state().set_animation("walk", true, 0)

View File

@ -0,0 +1,39 @@
extends Node2D
@onready var footstep_audio: AudioStreamPlayer = $FootstepAudio
func _animation_started(sprite: SpineSprite, animation_state: SpineAnimationState, track_entry: SpineTrackEntry):
print("Animation started: " + track_entry.get_animation().get_name())
func _animation_interrupted(sprite: SpineSprite, animation_state: SpineAnimationState, track_entry: SpineTrackEntry):
print("Animation interrupted: " + track_entry.get_animation().get_name())
func _animation_ended(sprite: SpineSprite, animation_state: SpineAnimationState, track_entry: SpineTrackEntry):
print("Animation ended: " + track_entry.get_animation().get_name())
func _animation_completed(sprite: SpineSprite, animation_state: SpineAnimationState, track_entry: SpineTrackEntry):
print("Animation completed: " + track_entry.get_animation().get_name())
func _animation_disposed(sprite: SpineSprite, animation_state: SpineAnimationState, track_entry: SpineTrackEntry):
print("Animation disposed: " + track_entry.get_animation().get_name())
func _animation_event(sprite: SpineSprite, animation_state: SpineAnimationState, track_entry: SpineTrackEntry, event: SpineEvent):
print("Animation event: " + track_entry.get_animation().get_name() + ", " + event.get_data().get_event_name())
if (event.get_data().get_event_name() == "footstep"):
footstep_audio.play()
func _ready():
var spineboy = $Spineboy
spineboy.animation_started.connect(_animation_started)
spineboy.animation_interrupted.connect(_animation_interrupted)
spineboy.animation_ended.connect(_animation_ended)
spineboy.animation_completed.connect(_animation_completed)
spineboy.animation_disposed.connect(_animation_disposed)
spineboy.animation_event.connect(_animation_event)
var animation_state = spineboy.get_animation_state()
animation_state.set_animation("jump", false, 0)
animation_state.add_animation("walk", 0, true, 0)
animation_state.add_animation("run", 2, true, 0)
pass

View File

@ -0,0 +1,20 @@
[gd_scene load_steps=4 format=3 uid="uid://c738i3nbdkn0h"]
[ext_resource type="Script" path="res://examples/02-animation-state-listeners/animation-state-listeners.gd" id="1"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="2"]
[ext_resource type="AudioStream" uid="uid://can7k84o8svum" path="res://assets/footstep.ogg" id="3"]
[node name="Node2D" type="Node2D"]
script = ExtResource("1")
[node name="Spineboy" type="SpineSprite" parent="."]
position = Vector2(473, 487)
scale = Vector2(0.575051, 0.575051)
skeleton_data_res = ExtResource("2")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
[node name="FootstepAudio" type="AudioStreamPlayer" parent="."]
stream = ExtResource("3")

View File

@ -0,0 +1,22 @@
extends SpineSprite
func _ready():
var data = get_skeleton().get_data()
var custom_skin = new_skin("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)

View File

@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://dodvuj07fsynd"]
[ext_resource type="SpineSkeletonDataResource" path="res://assets/mix-and-match/mix-and-match-data.tres" id="1"]
[ext_resource type="Script" path="res://examples/03-mix-and-match/mix-and-match.gd" id="2"]
[node name="Node2D" type="Node2D"]
[node name="MixAndMatch" type="SpineSprite" parent="."]
position = Vector2(532.982, 480.287)
scale = Vector2(0.441932, 0.441932)
skeleton_data_res = ExtResource("1")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
script = ExtResource("2")

View File

@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://bgdpghp11j3kg"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="1"]
[ext_resource type="Script" path="res://examples/04-simple-input/spineboy-simple-input.gd" id="2"]
[node name="Node2D" type="Node2D"]
[node name="Spineboy" type="SpineSprite" parent="."]
position = Vector2(501.503, 472.035)
scale = Vector2(0.518624, 0.518624)
skeleton_data_res = ExtResource("1")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
script = ExtResource("2")

View File

@ -0,0 +1,19 @@
extends SpineSprite
func _ready():
get_animation_state().set_animation("idle", true, 0)
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)
if Input.is_action_just_released("ui_left"):
get_animation_state().set_animation("idle", true, 0)
if (Input.is_action_just_pressed("ui_right")):
get_animation_state().set_animation("run", true, 0)
get_skeleton().set_scale_x(1)
if Input.is_action_just_released("ui_right"):
get_animation_state().set_animation("idle", true, 0)

View File

@ -0,0 +1,11 @@
extends Node2D
@onready var spineboy: SpineSprite = $Spineboy
@onready var crosshair_bone: SpineBoneNode = $Spineboy/CrosshairBone
func _ready():
spineboy.get_animation_state().set_animation("walk", true, 0)
spineboy.get_animation_state().set_animation("aim", true, 1)
func _process(_delta):
crosshair_bone.global_position = get_viewport().get_mouse_position()

View File

@ -0,0 +1,23 @@
[gd_scene load_steps=3 format=3 uid="uid://borp2l17n5xw1"]
[ext_resource type="Script" path="res://examples/05-mouse-following/mouse-following.gd" id="1"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="2"]
[node name="Node2D" type="Node2D"]
script = ExtResource("1")
[node name="Spineboy" type="SpineSprite" parent="."]
position = Vector2(147, 493)
scale = Vector2(0.5, 0.5)
skeleton_data_res = ExtResource("2")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
[node name="CrosshairBone" type="SpineBoneNode" parent="Spineboy"]
show_behind_parent = true
position = Vector2(302.333, -569.714)
rotation = -0.000872665
bone_name = "crosshair"
bone_mode = 1

View File

@ -0,0 +1,5 @@
extends Node2D
func _ready():
var spineboy: SpineSprite = $Spineboy
spineboy.get_animation_state().set_animation("walk", true, 0)

View File

@ -0,0 +1,27 @@
[gd_scene load_steps=4 format=3 uid="uid://bir7yvf0qwdge"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="1"]
[ext_resource type="Script" path="res://examples/06-bone-following/bone-following.gd" id="2"]
[ext_resource type="Texture2D" uid="uid://8ud5n2ywp5ba" path="res://icon.png" id="3"]
[node name="Node2D" type="Node2D"]
script = ExtResource("2")
[node name="Spineboy" type="SpineSprite" parent="."]
position = Vector2(478, 483)
scale = Vector2(0.58461, 0.58461)
skeleton_data_res = ExtResource("1")
preview_skin = "Default"
preview_animation = ""
preview_frame = false
preview_time = 0.0
[node name="GunTipBone" type="SpineBoneNode" parent="Spineboy"]
show_behind_parent = true
position = Vector2(214.298, -162.047)
rotation = 0.713316
scale = Vector2(1, 1)
bone_name = "gun-tip"
[node name="Sprite" type="Sprite2D" parent="Spineboy/GunTipBone"]
texture = ExtResource("3")

View File

@ -0,0 +1,11 @@
extends Node2D
@onready var spineboy: SpineSprite = $Spineboy
@onready var raptor: SpineSprite = $Spineboy/GunSlot/Raptor
@onready var tiny_spineboy: SpineSprite = $Spineboy/FrontFistSlot/TinySpineboy
func _ready():
var entry = spineboy.get_animation_state().set_animation("run", true, 0)
entry.set_time_scale(0.1)
raptor.get_animation_state().set_animation("walk", true, 0)
tiny_spineboy.get_animation_state().set_animation("walk", true, 0)

View File

@ -0,0 +1,61 @@
[gd_scene load_steps=5 format=3 uid="uid://bhht8dees2pyq"]
[ext_resource type="Script" path="res://examples/07-slot-node/slot-node.gd" id="1"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="2"]
[ext_resource type="SpineSkeletonDataResource" path="res://assets/raptor/raptor-data.tres" id="3"]
[ext_resource type="Texture2D" uid="uid://8ud5n2ywp5ba" path="res://icon.png" id="4"]
[node name="Node2D" type="Node2D"]
script = ExtResource("1")
[node name="Spineboy" type="SpineSprite" parent="."]
position = Vector2(474, 506)
scale = Vector2(0.560712, 0.560712)
skeleton_data_res = ExtResource("2")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
[node name="GunSlot" type="SpineSlotNode" parent="Spineboy"]
show_behind_parent = true
position = Vector2(40.8752, -276.036)
rotation = 0.837234
scale = Vector2(1, 1)
slot_name = "gun"
[node name="Raptor" type="SpineSprite" parent="Spineboy/GunSlot"]
position = Vector2(84.6909, -67.9174)
scale = Vector2(0.193472, 0.193472)
skeleton_data_res = ExtResource("3")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
[node name="EyeSlot" type="SpineSlotNode" parent="Spineboy"]
show_behind_parent = true
position = Vector2(-23.4598, -402.301)
rotation = -1.71793
scale = Vector2(1, 1)
slot_name = "eye"
[node name="Sprite" type="Sprite2D" parent="Spineboy/EyeSlot"]
position = Vector2(84.4734, 43.4469)
rotation = 1.66344
texture = ExtResource("4")
[node name="FrontFistSlot" type="SpineSlotNode" parent="Spineboy"]
show_behind_parent = true
position = Vector2(-29.0298, -241.577)
rotation = 0.995187
slot_name = "front-fist"
[node name="TinySpineboy" type="SpineSprite" parent="Spineboy/FrontFistSlot"]
position = Vector2(-2.64624, -10.8111)
scale = Vector2(0.193389, 0.193389)
skeleton_data_res = ExtResource("2")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0

View File

@ -0,0 +1,45 @@
[gd_scene load_steps=6 format=3 uid="uid://b4p2vn7bwm52a"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="1"]
[sub_resource type="Shader" id="1"]
code = "shader_type canvas_item;
void fragment() {
COLOR = texture(TEXTURE, UV);
COLOR.r = 0.0;
}"
[sub_resource type="ShaderMaterial" id="2"]
shader = SubResource("1")
[sub_resource type="Shader" id="3"]
code = "shader_type canvas_item;
void fragment() {
COLOR = texture(TEXTURE, UV);
COLOR.b = 0.0;
}"
[sub_resource type="ShaderMaterial" id="4"]
shader = SubResource("3")
[node name="Node2D" type="Node2D"]
[node name="SpineSprite" type="SpineSprite" parent="."]
position = Vector2(501, 507)
scale = Vector2(0.546374, 0.546373)
skeleton_data_res = ExtResource("1")
normal_material = SubResource("2")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
[node name="GunSlot" type="SpineSlotNode" parent="SpineSprite"]
show_behind_parent = true
position = Vector2(40.8753, -276.036)
rotation = 0.837234
scale = Vector2(1, 1)
slot_name = "gun"
normal_material = SubResource("4")

View File

@ -0,0 +1,4 @@
extends Node2D
func _ready():
$SpineSprite.get_animation_state().set_animation("walk");

View File

@ -0,0 +1,27 @@
[gd_scene load_steps=4 format=3 uid="uid://rt2llskmx7xm"]
[ext_resource type="SpineSkeletonDataResource" path="res://assets/raptor/raptor-data.tres" id="1"]
[ext_resource type="Texture2D" uid="uid://cggfs567rn1ay" path="res://assets/raptor/light-sprite.png" id="2"]
[ext_resource type="Script" path="res://examples/10-2d-lighting/2d-lighting.gd" id="3"]
[node name="Node2D" type="Node2D"]
script = ExtResource("3")
[node name="SpineSprite" type="SpineSprite" parent="."]
position = Vector2(576, 506)
scale = Vector2(0.458967, 0.458967)
skeleton_data_res = ExtResource("1")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
[node name="Light2D" type="PointLight2D" parent="."]
position = Vector2(691, 283)
scale = Vector2(1.51563, 1.51563)
color = Color(1, 0.0117647, 0.0117647, 1)
texture = ExtResource("2")
height = 100.0
[node name="CanvasModulate" type="CanvasModulate" parent="."]
color = Color(0.223529, 0.160784, 0.160784, 1)

View File

@ -0,0 +1,26 @@
extends Node2D
@onready var spineboy = $SpineSprite
@onready var center_bone = $SpineSprite/HoverboardCenterBone
@onready var center_ray = $SpineSprite/HoverboardCenterBone/CenterRay
@onready var target_bone = $SpineSprite/HoverboardTargetBone
@onready var target_ray = $SpineSprite/HoverboardTargetBone/TargetRay
@onready var hip_bone = $SpineSprite/HipBone
var center_hip_distance = 0
func _ready():
spineboy.get_animation_state().set_animation("hoverboard", true, 0)
spineboy.update_skeleton(0);
center_hip_distance = hip_bone.global_position.y - center_bone.global_position.y
func _physics_process(delta):
if target_ray.is_colliding():
target_bone.global_position.y = target_ray.get_collision_point().y - 30
if center_ray.is_colliding():
center_bone.global_position.y = center_ray.get_collision_point().y - 30
if abs(hip_bone.global_position.y - center_bone.global_position.y) - abs(center_hip_distance) < 20:
hip_bone.global_position.y = center_bone.global_position.y + center_hip_distance
spineboy.global_position.x += delta * 150;

View File

@ -0,0 +1,53 @@
[gd_scene load_steps=3 format=3 uid="uid://chrw4i0nksphn"]
[ext_resource type="Script" path="res://examples/11-bone-node/bone-node.gd" id="1"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="2"]
[node name="Node2D" type="Node2D"]
script = ExtResource("1")
[node name="SpineSprite" type="SpineSprite" parent="."]
position = Vector2(13, 569)
scale = Vector2(0.278096, 0.278096)
skeleton_data_res = ExtResource("2")
update_mode = 1
preview_skin = "Default"
preview_animation = "hoverboard"
preview_frame = true
preview_time = 0.0
[node name="HoverboardCenterBone" type="SpineBoneNode" parent="SpineSprite"]
show_behind_parent = true
position = Vector2(-10.1996, -68.2213)
rotation = -0.00403465
bone_name = "hoverboard-controller"
bone_mode = 1
[node name="CenterRay" type="RayCast2D" parent="SpineSprite/HoverboardCenterBone"]
target_position = Vector2(0, 10000)
[node name="HoverboardTargetBone" type="SpineBoneNode" parent="SpineSprite"]
show_behind_parent = true
position = Vector2(258.903, -71.9176)
rotation = -0.000872665
bone_name = "board-ik"
bone_mode = 1
[node name="TargetRay" type="RayCast2D" parent="SpineSprite/HoverboardTargetBone"]
position = Vector2(-3.59872, 3.59277)
target_position = Vector2(0, 10000)
[node name="HipBone" type="SpineBoneNode" parent="SpineSprite"]
show_behind_parent = true
position = Vector2(-53.7338, -279.363)
rotation = -0.000872665
bone_name = "hip"
bone_mode = 1
[node name="Polygon2D" type="Polygon2D" parent="."]
polygon = PackedVector2Array(0, 596, 309, 471, 516, 515, 762, 447, 984, 504, 1023, 505, 1024, 596)
[node name="StaticBody2D" type="StaticBody2D" parent="Polygon2D"]
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Polygon2D/StaticBody2D"]
polygon = PackedVector2Array(3, 592, 304, 469, 516, 514, 762, 443, 984, 499, 1252, 498, 1280, 596)

View File

@ -0,0 +1,32 @@
extends Node2D
@onready var celestial_circus: SpineSprite = $"celestial-circus"
var last_x = -1
var last_y = -1
var isMouseOver = false
func _ready():
celestial_circus.get_animation_state().set_animation("wind-idle", true, 0)
celestial_circus.get_animation_state().set_animation("eyeblink-long", true, 1)
celestial_circus.get_animation_state().set_animation("stars", true, 2)
func _process(_delta):
if (Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) and isMouseOver):
var pos = get_viewport().get_mouse_position()
if (last_x != -1):
var dx = pos.x - last_x
var dy = pos.y - last_y
celestial_circus.global_position += Vector2(dx, dy)
celestial_circus.get_skeleton().physics_translate(dx * 1 / celestial_circus.scale.x, dy * 1 / celestial_circus.scale.y)
last_x = pos.x
last_y = pos.y
else:
last_x = -1
last_y = -1
func _on_area_2d_mouse_entered():
isMouseOver = true
func _on_area_2d_mouse_exited():
isMouseOver = false

View File

@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=3 uid="uid://re2mg31p3vln"]
[ext_resource type="Script" path="res://examples/12-physics/physics.gd" id="1_7guqn"]
[ext_resource type="SpineSkeletonDataResource" uid="uid://d1ordmjpe5kt7" path="res://assets/celestial-circus/celestial-circus-data.tres" id="2_t2blj"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_do8w3"]
size = Vector2(270, 573)
[node name="Node2D" type="Node2D"]
script = ExtResource("1_7guqn")
[node name="celestial-circus" type="SpineSprite" parent="."]
position = Vector2(600, 485)
scale = Vector2(0.25, 0.25)
skeleton_data_res = ExtResource("2_t2blj")
preview_skin = "Default"
preview_animation = "-- Empty --"
preview_frame = false
preview_time = 0.0
[node name="Area2D" type="Area2D" parent="celestial-circus"]
show_behind_parent = true
scale = Vector2(4, 4)
[node name="CollisionShape2D" type="CollisionShape2D" parent="celestial-circus/Area2D"]
show_behind_parent = true
position = Vector2(0, -158.5)
shape = SubResource("RectangleShape2D_do8w3")
[connection signal="mouse_entered" from="celestial-circus/Area2D" to="." method="_on_area_2d_mouse_entered"]
[connection signal="mouse_exited" from="celestial-circus/Area2D" to="." method="_on_area_2d_mouse_exited"]

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dr1u7vj8mm6ed"]
[ext_resource type="Script" path="res://examples/13-load-from-disk/load_from_disk.gd" id="1_krs2n"]
[node name="Load-from-disk" type="Node2D"]
script = ExtResource("1_krs2n")

View File

@ -0,0 +1,24 @@
extends Node2D
func _ready():
# Load the skeleton file
var skeleton_file_res = SpineSkeletonFileResource.new();
skeleton_file_res.load_from_file("/Users/badlogic/workspaces/spine-runtimes/examples/coin/export/coin-pro.skel");
# Load the atlas file
var atlas_res = SpineAtlasResource.new();
atlas_res.load_from_atlas_file("/Users/badlogic/workspaces/spine-runtimes/examples/coin/export/coin.atlas");
# Create a skeleton data resource, you can share this across multiple sprites
var skeleton_data_res = SpineSkeletonDataResource.new();
skeleton_data_res.skeleton_file_res = skeleton_file_res;
skeleton_data_res.atlas_res = atlas_res
# Create a sprite from the skeleton data and add it as a child
var sprite = SpineSprite.new();
sprite.skeleton_data_res = skeleton_data_res;
sprite.position.x = 200;
sprite.position.y = 200;
sprite.get_animation_state().set_animation("animation", true, 0);
self.add_child(sprite)
pass

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://8ud5n2ywp5ba"
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.png"
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,35 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="spine-godot-examples"
run/main_scene="res://examples/08-animation-player/animation-player.tscn"
config/features=PackedStringArray("4.3")
run/low_processor_mode=true
config/icon="res://icon.png"
[global]
batch=false
[physics]
common/enable_pause_aware_picking=true
[rendering]
batching/parameters/max_join_item_commands=100
batching/parameters/batch_buffer_size=65535
batching/parameters/item_reordering_lookahead=100
quality/driver/driver_name="GLES2"
vram_compression/import_etc=true
vram_compression/import_etc2=false
environment/default_environment="res://default_env.tres"

View File

@ -0,0 +1,4 @@
extends SpineSprite
func _ready():
get_animation_state().set_animation("walk", true)

View File

@ -0,0 +1,871 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://assets/spineboy/spineboy-data-res.tres" type="SpineSkeletonDataResource" id=1]
[ext_resource path="res://tests/batch-test.gd" type="Script" id=2]
[node name="Node2D" type="Node2D"]
rotation = -3.67884e-05
[node name="SpineSprite" type="SpineSprite" parent="."]
position = Vector2( 53.8037, 119.483 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite2" type="SpineSprite" parent="."]
position = Vector2( 111.488, 119.485 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite3" type="SpineSprite" parent="."]
position = Vector2( 164.678, 119.487 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = true
preview_time = 2.36477e-39
script = ExtResource( 2 )
[node name="SpineSprite4" type="SpineSprite" parent="."]
position = Vector2( 217.119, 121.736 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = true
preview_time = 6.85235e-43
script = ExtResource( 2 )
[node name="SpineSprite5" type="SpineSprite" parent="."]
position = Vector2( 277.051, 120.989 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite6" type="SpineSprite" parent="."]
position = Vector2( 337.733, 118.744 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite7" type="SpineSprite" parent="."]
position = Vector2( 403.658, 120.994 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite8" type="SpineSprite" parent="."]
position = Vector2( 464.34, 120.996 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite9" type="SpineSprite" parent="."]
position = Vector2( 525.021, 120.998 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 51.0
script = ExtResource( 2 )
[node name="SpineSprite10" type="SpineSprite" parent="."]
position = Vector2( 589.448, 121.001 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite11" type="SpineSprite" parent="."]
position = Vector2( 649.381, 121.752 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite12" type="SpineSprite" parent="."]
position = Vector2( 709.313, 123.253 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite13" type="SpineSprite" parent="."]
position = Vector2( 769.245, 119.509 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite14" type="SpineSprite" parent="."]
position = Vector2( 830.676, 119.511 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite15" type="SpineSprite" parent="."]
position = Vector2( 892.106, 121.761 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite16" type="SpineSprite" parent="."]
position = Vector2( 953.537, 121.763 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite17" type="SpineSprite" parent="."]
position = Vector2( 56.0478, 207.883 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite18" type="SpineSprite" parent="."]
position = Vector2( 113.733, 207.885 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite19" type="SpineSprite" parent="."]
position = Vector2( 166.923, 207.887 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite20" type="SpineSprite" parent="."]
position = Vector2( 219.363, 210.136 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite21" type="SpineSprite" parent="."]
position = Vector2( 279.295, 209.389 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite22" type="SpineSprite" parent="."]
position = Vector2( 339.977, 207.144 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite23" type="SpineSprite" parent="."]
position = Vector2( 405.902, 209.394 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite24" type="SpineSprite" parent="."]
position = Vector2( 466.584, 209.396 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite25" type="SpineSprite" parent="."]
position = Vector2( 527.265, 209.399 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite26" type="SpineSprite" parent="."]
position = Vector2( 591.692, 209.401 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite27" type="SpineSprite" parent="."]
position = Vector2( 651.625, 210.152 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite28" type="SpineSprite" parent="."]
position = Vector2( 711.557, 211.653 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite29" type="SpineSprite" parent="."]
position = Vector2( 771.489, 207.909 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite30" type="SpineSprite" parent="."]
position = Vector2( 832.92, 207.911 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite31" type="SpineSprite" parent="."]
position = Vector2( 894.351, 210.161 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite32" type="SpineSprite" parent="."]
position = Vector2( 955.781, 210.163 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite33" type="SpineSprite" parent="."]
position = Vector2( 60.5394, 300.778 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite34" type="SpineSprite" parent="."]
position = Vector2( 118.224, 300.78 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite35" type="SpineSprite" parent="."]
position = Vector2( 171.414, 300.782 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite36" type="SpineSprite" parent="."]
position = Vector2( 223.855, 303.032 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite37" type="SpineSprite" parent="."]
position = Vector2( 283.787, 302.285 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite38" type="SpineSprite" parent="."]
position = Vector2( 344.468, 300.039 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite39" type="SpineSprite" parent="."]
position = Vector2( 410.394, 302.289 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite40" type="SpineSprite" parent="."]
position = Vector2( 471.075, 302.292 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite41" type="SpineSprite" parent="."]
position = Vector2( 531.757, 302.294 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite42" type="SpineSprite" parent="."]
position = Vector2( 596.184, 302.296 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite43" type="SpineSprite" parent="."]
position = Vector2( 656.116, 303.047 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite44" type="SpineSprite" parent="."]
position = Vector2( 716.048, 304.548 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite45" type="SpineSprite" parent="."]
position = Vector2( 775.981, 300.804 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite46" type="SpineSprite" parent="."]
position = Vector2( 837.411, 300.807 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite47" type="SpineSprite" parent="."]
position = Vector2( 898.842, 303.056 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite48" type="SpineSprite" parent="."]
position = Vector2( 960.273, 303.059 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite49" type="SpineSprite" parent="."]
position = Vector2( 60.5361, 389.178 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite50" type="SpineSprite" parent="."]
position = Vector2( 118.221, 389.18 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite51" type="SpineSprite" parent="."]
position = Vector2( 171.411, 389.182 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite52" type="SpineSprite" parent="."]
position = Vector2( 223.851, 391.432 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite53" type="SpineSprite" parent="."]
position = Vector2( 283.784, 390.685 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite54" type="SpineSprite" parent="."]
position = Vector2( 344.465, 388.44 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite55" type="SpineSprite" parent="."]
position = Vector2( 410.391, 390.689 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite56" type="SpineSprite" parent="."]
position = Vector2( 471.072, 390.692 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite57" type="SpineSprite" parent="."]
position = Vector2( 531.753, 390.694 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite58" type="SpineSprite" parent="."]
position = Vector2( 596.181, 390.696 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite59" type="SpineSprite" parent="."]
position = Vector2( 656.113, 391.448 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite60" type="SpineSprite" parent="."]
position = Vector2( 716.045, 392.948 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite61" type="SpineSprite" parent="."]
position = Vector2( 775.978, 389.204 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite62" type="SpineSprite" parent="."]
position = Vector2( 837.408, 389.207 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite63" type="SpineSprite" parent="."]
position = Vector2( 898.839, 391.456 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite64" type="SpineSprite" parent="."]
position = Vector2( 960.269, 391.459 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite65" type="SpineSprite" parent="."]
position = Vector2( 62.0311, 477.578 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite66" type="SpineSprite" parent="."]
position = Vector2( 119.716, 477.581 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite67" type="SpineSprite" parent="."]
position = Vector2( 172.906, 477.583 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite68" type="SpineSprite" parent="."]
position = Vector2( 225.346, 479.832 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite69" type="SpineSprite" parent="."]
position = Vector2( 285.279, 479.085 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite70" type="SpineSprite" parent="."]
position = Vector2( 345.96, 476.84 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite71" type="SpineSprite" parent="."]
position = Vector2( 411.886, 479.09 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite72" type="SpineSprite" parent="."]
position = Vector2( 472.567, 479.092 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite73" type="SpineSprite" parent="."]
position = Vector2( 533.248, 479.094 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite74" type="SpineSprite" parent="."]
position = Vector2( 597.676, 479.096 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite75" type="SpineSprite" parent="."]
position = Vector2( 657.608, 479.848 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite76" type="SpineSprite" parent="."]
position = Vector2( 717.54, 481.348 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite77" type="SpineSprite" parent="."]
position = Vector2( 777.473, 477.605 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite78" type="SpineSprite" parent="."]
position = Vector2( 838.903, 477.607 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite79" type="SpineSprite" parent="."]
position = Vector2( 900.334, 479.857 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite80" type="SpineSprite" parent="."]
position = Vector2( 961.765, 479.859 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite81" type="SpineSprite" parent="."]
position = Vector2( 66.5229, 562.233 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite82" type="SpineSprite" parent="."]
position = Vector2( 124.208, 562.235 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite83" type="SpineSprite" parent="."]
position = Vector2( 177.398, 562.237 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite84" type="SpineSprite" parent="."]
position = Vector2( 229.838, 564.486 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite85" type="SpineSprite" parent="."]
position = Vector2( 289.77, 563.74 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite86" type="SpineSprite" parent="."]
position = Vector2( 350.452, 561.494 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite87" type="SpineSprite" parent="."]
position = Vector2( 416.377, 563.744 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite88" type="SpineSprite" parent="."]
position = Vector2( 477.059, 563.746 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite89" type="SpineSprite" parent="."]
position = Vector2( 537.74, 563.749 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite90" type="SpineSprite" parent="."]
position = Vector2( 602.167, 563.751 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite91" type="SpineSprite" parent="."]
position = Vector2( 662.1, 564.502 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite92" type="SpineSprite" parent="."]
position = Vector2( 722.032, 566.003 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite93" type="SpineSprite" parent="."]
position = Vector2( 781.964, 562.259 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite94" type="SpineSprite" parent="."]
position = Vector2( 843.395, 562.261 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite95" type="SpineSprite" parent="."]
position = Vector2( 904.826, 564.511 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )
[node name="SpineSprite96" type="SpineSprite" parent="."]
position = Vector2( 966.256, 564.513 )
scale = Vector2( 0.1, 0.1 )
skeleton_data_res = ExtResource( 1 )
preview_animation = ""
preview_frame = false
preview_time = 0.0
script = ExtResource( 2 )

View File

@ -0,0 +1,53 @@
[gd_scene format=2]
[node name="Node2D" type="Node2D"]
[node name="A" type="RigidBody2D" parent="."]
position = Vector2( 483, 158 )
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="A"]
position = Vector2( 6, 17 )
polygon = PoolVector2Array( -38, 6, 28, 6, 28, -45, -40, -45 )
__meta__ = {
"_edit_lock_": true
}
[node name="B" type="RigidBody2D" parent="."]
position = Vector2( 484, 228 )
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="B"]
position = Vector2( 6, 17 )
polygon = PoolVector2Array( -38, 6, 28, 6, 28, -45, -40, -45 )
__meta__ = {
"_edit_lock_": true
}
[node name="C" type="RigidBody2D" parent="."]
position = Vector2( 485, 296 )
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="C"]
position = Vector2( 6, 17 )
polygon = PoolVector2Array( -38, 6, 28, 6, 28, -45, -40, -45 )
__meta__ = {
"_edit_lock_": true
}
[node name="PinJoint2D" type="PinJoint2D" parent="."]
position = Vector2( 484, 189 )
node_a = NodePath("../A")
node_b = NodePath("../B")
bias = 0.9
disable_collision = false
[node name="PinJoint2D2" type="PinJoint2D" parent="."]
position = Vector2( 486, 257 )
node_a = NodePath("../B")
node_b = NodePath("../C")
bias = 0.9
disable_collision = false
[node name="Ground" type="StaticBody2D" parent="."]
position = Vector2( 489, 478 )
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Ground"]
polygon = PoolVector2Array( -116, -4, 128, -100, 204, 34, -156, 48 )

View File

@ -0,0 +1,26 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://assets/spineboy/spineboy-data-res.tres" type="SpineSkeletonDataResource" id=1]
[ext_resource path="res://icon.png" type="Texture" id=2]
[node name="Node2D" type="Node2D"]
[node name="SpineSprite" type="SpineSprite" parent="."]
position = Vector2( 459.397, 501.236 )
scale = Vector2( 0.742335, 0.742335 )
skeleton_data_res = ExtResource( 1 )
preview_animation = "aim"
preview_frame = true
preview_time = 0.0
[node name="SpineBoneNode" type="SpineBoneNode" parent="SpineSprite"]
position = Vector2( 40.8752, -276.036 )
rotation = 0.837234
bone_name = "gun"
bone_mode = 1
enabled = false
color = Color( 0, 1, 0.0627451, 0.466667 )
[node name="Sprite" type="Sprite" parent="SpineSprite/SpineBoneNode"]
visible = false
texture = ExtResource( 2 )

View File

@ -0,0 +1,39 @@
extends SpineSprite
func test_spine_animation():
var walkAnim: SpineAnimation = get_skeleton().get_data().find_animation("walk")
assert(walkAnim.get_name() == "walk")
var duration = walkAnim.get_duration()
walkAnim.set_duration(duration + 1)
assert(walkAnim.get_duration() == duration + 1)
assert(walkAnim.get_timelines().size() == 39)
var timeline: SpineTimeline = walkAnim.get_timelines()[0]
var propertyIds = timeline.get_property_ids()
assert(walkAnim.has_timeline(propertyIds))
assert(!walkAnim.has_timeline([0]))
func test_spine_timeline():
var walkAnim: SpineAnimation = get_skeleton().get_data().find_animation("walk")
var timeline: SpineTimeline = walkAnim.get_timelines()[0]
assert(timeline.get_duration() == 1)
assert(timeline.get_property_ids() == [4294967300])
assert(timeline.get_type() == "RotateTimeline")
func test_spine_object_invalidation():
var skeleton_data = get_skeleton().get_data()
var bone_data = skeleton_data.find_bone("gun");
var old_bone_data_x = bone_data.get_x();
var bone = get_skeleton().find_bone("gun")
var old_bone_x = bone.get_x()
skeleton_data_res = null
assert(old_bone_x != bone.get_x())
assert(old_bone_data_x == bone_data.get_x())
skeleton_data.atlas_res = null;
assert(old_bone_data_x != bone_data.get_x())
func _ready():
test_spine_animation()
test_spine_timeline()
test_spine_object_invalidation()
print("All tests passed")

View File

@ -0,0 +1,12 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://tests/unit-tests.gd" type="Script" id=1]
[ext_resource path="res://assets/spineboy/spineboy-data-res.tres" type="SpineSkeletonDataResource" id=2]
[node name="Node2D" type="Node2D"]
position = Vector2( 496.659, 431.634 )
scale = Vector2( 0.7, 0.7 )
[node name="SpineSprite" type="SpineSprite" parent="."]
skeleton_data_res = ExtResource( 2 )
script = ExtResource( 1 )

View File

@ -0,0 +1,25 @@
[configuration]
entry_symbol = "spine_godot_library_init"
compatibility_minimum = "4.1"
[libraries]
macos.debug = "res://bin/macos/macos.framework/libspine_godot.macos.template_debug"
macos.release = "res://bin/macos/macos.framework/libspine_godot.macos.template_release"
ios.debug = "res://bin/ios/ios.framework/libspine_godot.ios.template_debug"
ios.release = "res://bin/ios/ios.framework/libspine_godot.ios.template_release"
windows.debug.x86_32 = "res://bin/windows/libspine_godot.windows.template_debug.x86_32.dll"
windows.release.x86_32 = "res://bin/windows/libspine_godot.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "res://bin/windows/libspine_godot.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://bin/windows/libspine_godot.windows.template_release.x86_64.dll"
linux.debug.x86_64 = "res://bin/linux/libspine_godot.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://bin/linux/libspine_godot.linux.template_release.x86_64.so"
linux.debug.arm64 = "res://bin/linux/libspine_godot.linux.template_debug.arm64.so"
linux.release.arm64 = "res://bin/linux/libspine_godot.linux.template_release.arm64.so"
linux.debug.rv64 = "res://bin/linux/libspine_godot.linux.template_debug.rv64.so"
linux.release.rv64 = "res://bin/linux/libspine_godot.linux.template_release.rv64.so"
android.debug.x86_64 = "res://bin/android/libspine_godot.android.template_debug.x86_64.so"
android.release.x86_64 = "res://bin/android/libspine_godot.android.template_release.x86_64.so"
android.debug.arm64 = "res://bin/android/libspine_godot.android.template_debug.arm64.so"
android.release.arm64 = "res://bin/android/libspine_godot.android.template_release.arm64.so"

52
spine-godot/methods.py Normal file
View File

@ -0,0 +1,52 @@
import os
import sys
from enum import Enum
# Colors are disabled in non-TTY environments such as pipes. This means
# that if output is redirected to a file, it won't contain color codes.
# Colors are always enabled on continuous integration.
_colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
class ANSI(Enum):
"""
Enum class for adding ansi colorcodes directly into strings.
Automatically converts values to strings representing their
internal value, or an empty string in a non-colorized scope.
"""
RESET = "\x1b[0m"
BOLD = "\x1b[1m"
ITALIC = "\x1b[3m"
UNDERLINE = "\x1b[4m"
STRIKETHROUGH = "\x1b[9m"
REGULAR = "\x1b[22;23;24;29m"
BLACK = "\x1b[30m"
RED = "\x1b[31m"
GREEN = "\x1b[32m"
YELLOW = "\x1b[33m"
BLUE = "\x1b[34m"
MAGENTA = "\x1b[35m"
CYAN = "\x1b[36m"
WHITE = "\x1b[37m"
PURPLE = "\x1b[38;5;93m"
PINK = "\x1b[38;5;206m"
ORANGE = "\x1b[38;5;214m"
GRAY = "\x1b[38;5;244m"
def __str__(self) -> str:
global _colorize
return str(self.value) if _colorize else ""
def print_warning(*values: object) -> None:
"""Prints a warning message with formatting."""
print(f"{ANSI.YELLOW}{ANSI.BOLD}WARNING:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
def print_error(*values: object) -> None:
"""Prints an error message with formatting."""
print(f"{ANSI.RED}{ANSI.BOLD}ERROR:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)

View File

@ -82,7 +82,11 @@ Array SpineAnimation::get_timelines() {
for (int i = 0; i < (int) result.size(); ++i) {
auto timeline_ref = Ref<SpineTimeline>(memnew(SpineTimeline));
timeline_ref->set_spine_object(get_spine_owner(), timelines[i]);
#ifdef SPINE_GODOT_EXTENSION
result[i] = timeline_ref;
#else
result.set(i, timeline_ref);
#endif
}
return result;
}

View File

@ -27,6 +27,8 @@
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_GODOT_EXTENSION
#include "SpineAnimationTrack.h"
#if VERSION_MAJOR > 3
#include "core/config/engine.h"
@ -554,3 +556,5 @@ void SpineAnimationTrack::set_debug(bool _debug) {
bool SpineAnimationTrack::get_debug() {
return debug;
}
#endif

View File

@ -29,14 +29,10 @@
#pragma once
#ifndef SPINE_GODOT_EXTENSION
#include "SpineSprite.h"
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/animation_player.hpp>
#include <godot_cpp/classes/animation.hpp>
#else
#include "scene/animation/animation_player.h"
#include "scene/resources/animation.h"
#endif
class SpineAnimationTrack : public Node {
GDCLASS(SpineAnimationTrack, Node)
@ -138,3 +134,5 @@ public:
bool get_debug();
};
#endif

View File

@ -34,22 +34,28 @@
#include <godot_cpp/classes/json.hpp>
#include <godot_cpp/classes/texture.hpp>
#include <godot_cpp/classes/file_access.hpp>
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/image_texture.hpp>
#else
#include "core/io/json.h"
#include "scene/resources/texture.h"
#endif
#include <spine/TextureLoader.h>
#if VERSION_MAJOR > 3
#include "core/io/image.h"
#include "scene/resources/image_texture.h"
#else
#include "core/image.h"
#endif
#endif
#ifdef TOOLS_ENABLED
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/editor_file_system.hpp>
#else
#include "editor/editor_file_system.h"
#endif
#endif
#include <spine/TextureLoader.h>
class GodotSpineTextureLoader : public spine::TextureLoader {
@ -69,11 +75,11 @@ public:
return false;
}
auto sub_str_pos = i + prefix.size() - 1;
auto sub_str_pos = i + SSIZE(prefix) - 1;
auto res = path.substr(sub_str_pos);
if (!EMPTY(res)) {
if (res[0] != '/') {
path = prefix + "/" + res;
path = prefix + String("/") + res;
} else {
path = prefix + res;
}
@ -85,7 +91,11 @@ public:
Ref<Texture2D> get_texture_from_image(const String &path, bool is_resource) {
Error error = OK;
if (is_resource) {
#ifdef SPINE_GODOT_EXTENSION
return ResourceLoader::get_singleton()->load(path, "", ResourceLoader::CACHE_MODE_REUSE);
#else
return ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error);
#endif
} else {
Ref<Image> img;
img.instantiate();
@ -246,10 +256,15 @@ Error SpineAtlasResource::load_from_atlas_file(const String &path) {
}
Error SpineAtlasResource::load_from_atlas_file_internal(const String &path, bool is_importing) {
Error err;
source_path = path;
#ifdef SPINE_GODOT_EXTENSION
atlas_data = FileAccess::get_file_as_string(path);
if (SSIZE(atlas_data) == 0) return ERR_FILE_UNRECOGNIZED;
#else
Error err;
atlas_data = FileAccess::get_file_as_string(path, &err);
if (err != OK) return err;
#endif
clear();
texture_loader = new GodotSpineTextureLoader(&textures, &normal_maps, normal_map_prefix, is_importing);
@ -263,8 +278,13 @@ Error SpineAtlasResource::load_from_atlas_file_internal(const String &path, bool
Error SpineAtlasResource::load_from_file(const String &path) {
Error error;
#ifdef SPINE_GODOT_EXTENSION
String json_string = FileAccess::get_file_as_string(path);
if (SSIZE(json_string) == 0) return ERR_FILE_UNRECOGNIZED;
#else
String json_string = FileAccess::get_file_as_string(path, &error);
if (error != OK) return error;
#endif
#if VERSION_MAJOR > 3
JSON json;
@ -297,8 +317,13 @@ Error SpineAtlasResource::load_from_file(const String &path) {
Error SpineAtlasResource::save_to_file(const String &path) {
Error err;
#if VERSION_MAJOR > 3
#if SPINE_GODOT_EXTENSION
Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE);
if (file.is_null()) return ERR_FILE_UNRECOGNIZED;
#else
Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &err);
if (err != OK) return err;
#endif
#else
FileAccess *file = FileAccess::open(path, FileAccess::WRITE, &err);
if (err != OK) {
@ -322,6 +347,7 @@ Error SpineAtlasResource::save_to_file(const String &path) {
return OK;
}
#ifndef SPINE_GODOT_EXTENSION
#if VERSION_MAJOR > 3
Error SpineAtlasResource::copy_from(const Ref<Resource> &p_resource) {
auto error = Resource::copy_from(p_resource);
@ -343,7 +369,11 @@ Error SpineAtlasResource::copy_from(const Ref<Resource> &p_resource) {
return OK;
}
#endif
#endif
#ifdef SPINE_GODOT_EXTENSION
Variant SpineAtlasResourceFormatLoader::_load(const String &path, const String &original_path, bool use_sub_threads, int32_t cache_mode) {
#else
#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
@ -352,41 +382,79 @@ RES SpineAtlasResourceFormatLoader::load(const String &path, const String &origi
#else
RES SpineAtlasResourceFormatLoader::load(const String &path, const String &original_path, Error *error) {
#endif
#endif
#endif
Ref<SpineAtlasResource> atlas = memnew(SpineAtlasResource);
atlas->load_from_file(path);
#ifndef SPINE_GODOT_EXTENSION
if (error) *error = OK;
#endif
return atlas;
}
#ifdef SPINE_GODOT_EXTENSION
PackedStringArray SpineAtlasResourceFormatLoader::_get_recognized_extensions() {
PackedStringArray extensions;
extensions.push_back("spatlas");
return extensions;
}
#else
void SpineAtlasResourceFormatLoader::get_recognized_extensions(List<String> *extensions) const {
const char atlas_ext[] = "spatlas";
if (!extensions->find(atlas_ext))
extensions->push_back(atlas_ext);
}
#endif
#ifdef SPINE_GODOT_EXTENSION
String SpineAtlasResourceFormatLoader::_get_resource_type(const String &path) {
#else
String SpineAtlasResourceFormatLoader::get_resource_type(const String &path) const {
#endif
return path.ends_with("spatlas") || path.ends_with(".atlas") ? "SpineAtlasResource" : "";
}
#ifdef SPINE_GODOT_EXTENSION
bool SpineAtlasResourceFormatLoader::_handles_type(const StringName &type) {
#else
bool SpineAtlasResourceFormatLoader::handles_type(const String &type) const {
return type == "SpineAtlasResource" || ClassDB::is_parent_class(type, "SpineAtlasResource");
#endif
return type == StringName("SpineAtlasResource") || ClassDB::is_parent_class(type, "SpineAtlasResource");
}
#ifdef SPINE_GODOT_EXTENSION
Error SpineAtlasResourceFormatSaver::_save(const Ref<Resource> &resource, const String &path, uint32_t flags) {
#else
#if VERSION_MAJOR > 3
Error SpineAtlasResourceFormatSaver::save(const RES &resource, const String &path, uint32_t flags) {
#else
Error SpineAtlasResourceFormatSaver::save(const String &path, const RES &resource, uint32_t flags) {
#endif
#endif
Ref<SpineAtlasResource> res = resource;
return res->save_to_file(path);
}
#ifdef SPINE_GODOT_EXTENSION
PackedStringArray SpineAtlasResourceFormatSaver::_get_recognized_extensions(const Ref<Resource> &resource) {
PackedStringArray extensions;
if (Object::cast_to<SpineAtlasResource>(*resource)) {
extensions.push_back("spatlas");
}
return extensions;
}
#else
void SpineAtlasResourceFormatSaver::get_recognized_extensions(const RES &resource, List<String> *extensions) const {
if (Object::cast_to<SpineAtlasResource>(*resource))
extensions->push_back("spatlas");
}
#endif
#ifdef SPINE_GODOT_EXTENSION
bool SpineAtlasResourceFormatSaver::_recognize(const RES &resource) {
#else
bool SpineAtlasResourceFormatSaver::recognize(const RES &resource) const {
#endif
return Object::cast_to<SpineAtlasResource>(*resource) != nullptr;
}

View File

@ -80,8 +80,10 @@ public:
Error save_to_file(const String &path);// .spatlas
#ifndef SPINE_GODOT_EXTENSION
#if VERSION_MAJOR > 3
virtual Error copy_from(const Ref<Resource> &p_resource);
#endif
#endif
String get_source_path();

View File

@ -29,11 +29,16 @@
#include "SpineBoneNode.h"
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/classes/scene_tree.hpp>
#else
#if VERSION_MAJOR > 3
#include "core/config/engine.h"
#else
#include "core/engine.h"
#endif
#endif
void SpineBoneNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bone_mode"), &SpineBoneNode::set_bone_mode);
@ -102,7 +107,11 @@ void SpineBoneNode::_notification(int what) {
}
void SpineBoneNode::_get_property_list(List<PropertyInfo> *list) const {
#ifdef SPINE_GODOT_EXTENSION
PackedStringArray bone_names;
#else
Vector<String> bone_names;
#endif
SpineSprite *sprite = find_parent_sprite();
if (sprite) sprite->get_skeleton_data_res()->get_bone_names(bone_names);
else
@ -110,7 +119,7 @@ void SpineBoneNode::_get_property_list(List<PropertyInfo> *list) const {
auto element = list->front();
while (element) {
auto property_info = element->get();
if (property_info.name == "SpineBoneNode") break;
if (property_info.name == StringName("SpineBoneNode")) break;
element = element->next();
}
PropertyInfo slot_name_property;
@ -123,7 +132,7 @@ void SpineBoneNode::_get_property_list(List<PropertyInfo> *list) const {
}
bool SpineBoneNode::_get(const StringName &property, Variant &value) const {
if (property == "bone_name") {
if (property == StringName("bone_name")) {
value = bone_name;
return true;
}
@ -131,7 +140,7 @@ bool SpineBoneNode::_get(const StringName &property, Variant &value) const {
}
bool SpineBoneNode::_set(const StringName &property, const Variant &value) {
if (property == "bone_name") {
if (property == StringName("bone_name")) {
bone_name = value;
SpineSprite *sprite = find_parent_sprite();
init_transform(sprite);
@ -218,7 +227,11 @@ void SpineBoneNode::draw() {
if (bone_length == 0) {
draw_circle(Vector2(0, 0), debug_thickness, debug_color);
} else {
#ifdef SPINE_GODOT_EXTENSION
PackedVector2Array points;
#else
Vector<Vector2> points;
#endif
points.push_back(Vector2(-debug_thickness, 0));
points.push_back(Vector2(0, debug_thickness));
points.push_back(Vector2(bone_length, 0));

View File

@ -32,7 +32,11 @@
#include "SpineCommon.h"
#include "SpineSkeleton.h"
#include "SpineSprite.h"
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/node2d.hpp>
#else
#include "scene/2d/node_2d.h"
#endif
class SpineBoneNode : public Node2D {
GDCLASS(SpineBoneNode, Node2D)

View File

@ -46,8 +46,12 @@ using namespace godot;
#define RES Ref<Resource>
#define REF Ref<RefCounted>
#define GEOMETRY2D Geometry2D
#ifndef VERSION_MAJOR
#define VERSION_MAJOR GODOT_VERSION_MAJOR
#endif
#ifndef VERSION_MINOR
#define VERSION_MINOR GODOT_VERSION_MINOR
#endif
// FIXME this doesn't do the same as the engine SNAME in terms of caching
#define SNAME(name) StringName(name)
#define RS RenderingServer

View File

@ -34,8 +34,16 @@
#include "SpineSkeletonFileResource.h"
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/editor_undo_redo_manager.hpp>
#else
#include "editor/editor_undo_redo_manager.h"
#endif
#ifdef SPINE_GODOT_EXTENSION
Error SpineAtlasResourceImportPlugin::_import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray<String> &platform_variants, const TypedArray<String> &gen_files) const {
#else
Error SpineAtlasResourceImportPlugin::import(const String &source_file, const String &save_path, const HashMap<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) {
#endif
#else
Error SpineAtlasResourceImportPlugin::import(const String &source_file, const String &save_path, const Map<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) {
#endif
@ -43,15 +51,21 @@ Error SpineAtlasResourceImportPlugin::import(const String &source_file, const St
atlas->set_normal_texture_prefix(options["normal_map_prefix"]);
atlas->load_from_atlas_file_internal(source_file, true);
String file_name = vformat("%s.%s", save_path, get_save_extension());
String file_name = save_path + String(".") + _get_save_extension();
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
auto error = ResourceSaver::get_singleton()->save(atlas, file_name);
#else
auto error = ResourceSaver::save(atlas, file_name);
#endif
#else
auto error = ResourceSaver::save(file_name, atlas);
#endif
return error;
}
// FIXME get_import_options is not available in godot-cpp
#ifndef SPINE_GODOT_EXTENSION
#if VERSION_MAJOR > 3
void SpineAtlasResourceImportPlugin::get_import_options(const String &path, List<ImportOption> *options, int preset) const {
#else
@ -66,9 +80,14 @@ void SpineAtlasResourceImportPlugin::get_import_options(List<ImportOption> *opti
options->push_back(op);
}
}
#endif
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
Error SpineJsonResourceImportPlugin::_import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray<String> &platform_variants, const TypedArray<String> &gen_files) const {
#else
Error SpineJsonResourceImportPlugin::import(const String &source_file, const String &save_path, const HashMap<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) {
#endif
#else
Error SpineJsonResourceImportPlugin::import(const String &source_file, const String &save_path, const Map<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) {
#endif
@ -76,17 +95,27 @@ Error SpineJsonResourceImportPlugin::import(const String &source_file, const Str
Error error = skeleton_file_res->load_from_file(source_file);
if (error != OK) return error;
String file_name = vformat("%s.%s", save_path, get_save_extension());
#if VERSION_MAJOR > 3
error = ResourceSaver::save(skeleton_file_res, file_name);
#ifdef SPINE_GODOT_EXTENSION
String file_name = save_path + String(".") + _get_save_extension();
error = ResourceSaver::get_singleton()->save(skeleton_file_res, file_name);
#else
String file_name = save_path + String(".") + get_save_extension();
error = ResourceSaver::save(skeleton_file_res, file_name);
#endif
#else
String file_name = save_path + String(".") + get_save_extension();
error = ResourceSaver::save(file_name, skeleton_file_res);
#endif
return error;
}
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
Error SpineBinaryResourceImportPlugin::_import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray<String> &platform_variants, const TypedArray<String> &gen_files) const {
#else
Error SpineBinaryResourceImportPlugin::import(const String &source_file, const String &save_path, const HashMap<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) {
#endif
#else
Error SpineBinaryResourceImportPlugin::import(const String &source_file, const String &save_path, const Map<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) {
#endif
@ -94,15 +123,30 @@ Error SpineBinaryResourceImportPlugin::import(const String &source_file, const S
Error error = skeleton_file_res->load_from_file(source_file);
if (error != OK) return error;
String file_name = vformat("%s.%s", save_path, get_save_extension());
#if VERSION_MAJOR > 3
error = ResourceSaver::save(skeleton_file_res, file_name);
#ifdef SPINE_GODOT_EXTENSION
String file_name = save_path + String(".") + _get_save_extension();
error = ResourceSaver::get_singleton()->save(skeleton_file_res, file_name);
#else
String file_name = save_path + String(".") + get_save_extension();
error = ResourceSaver::save(skeleton_file_res, file_name);
#endif
#else
String file_name = save_path + String(".") + get_save_extension();
error = ResourceSaver::save(file_name, skeleton_file_res);
#endif
return error;
}
#ifdef SPINE_GODOT_EXTENSION
SpineEditorPlugin::SpineEditorPlugin() {
add_import_plugin(memnew(SpineAtlasResourceImportPlugin));
add_import_plugin(memnew(SpineJsonResourceImportPlugin));
add_import_plugin(memnew(SpineBinaryResourceImportPlugin));
add_inspector_plugin(memnew(SpineSkeletonDataResourceInspectorPlugin));
add_inspector_plugin(memnew(SpineSpriteInspectorPlugin));
}
#else
SpineEditorPlugin::SpineEditorPlugin(EditorNode *node) {
add_import_plugin(memnew(SpineAtlasResourceImportPlugin));
add_import_plugin(memnew(SpineJsonResourceImportPlugin));
@ -110,17 +154,28 @@ SpineEditorPlugin::SpineEditorPlugin(EditorNode *node) {
add_inspector_plugin(memnew(SpineSkeletonDataResourceInspectorPlugin));
add_inspector_plugin(memnew(SpineSpriteInspectorPlugin));
}
#endif
#ifdef SPINE_GODOT_EXTENSION
bool SpineSkeletonDataResourceInspectorPlugin::_can_handle(Object *object) const {
#else
bool SpineSkeletonDataResourceInspectorPlugin::can_handle(Object *object) {
#endif
return object->is_class("SpineSkeletonDataResource");
}
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
bool SpineSkeletonDataResourceInspectorPlugin::_parse_property(Object *object, Variant::Type type, const String &path, PropertyHint hint, const String &hint_text, const BitField<PropertyUsageFlags> p_usage, bool wide) {
#else
bool SpineSkeletonDataResourceInspectorPlugin::parse_property(Object *object, const Variant::Type type, const String &path, const PropertyHint hint, const String &hint_text, const BitField<PropertyUsageFlags> p_usage, const bool wide) {
#endif
#else
bool SpineSkeletonDataResourceInspectorPlugin::parse_property(Object *object, Variant::Type type, const String &path,
PropertyHint hint, const String &hint_text, int usage) {
#endif
// FIXME can't do this in godot-cpp
#ifndef SPINE_GODOT_EXTENSION
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;
@ -129,9 +184,12 @@ bool SpineSkeletonDataResourceInspectorPlugin::parse_property(Object *object, Va
add_property_editor(path, mixes_property);
return true;
}
#endif
return false;
}
// FIXME can't do this in godot-cpp
#ifndef SPINE_GODOT_EXTENSION
SpineEditorPropertyAnimationMixes::SpineEditorPropertyAnimationMixes() : skeleton_data(nullptr), container(nullptr), updating(false) {
INSTANTIATE(array_object);
}
@ -349,6 +407,7 @@ void SpineEditorPropertyAnimationMix::update_property() {
updating = false;
}
#endif
void SpineSpriteInspectorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("button_clicked"), &SpineSpriteInspectorPlugin::button_clicked);
@ -357,11 +416,19 @@ void SpineSpriteInspectorPlugin::_bind_methods() {
void SpineSpriteInspectorPlugin::button_clicked(const String &button_name) {
}
#ifdef SPINE_GODOT_EXTENSION
bool SpineSpriteInspectorPlugin::_can_handle(Object *object) const {
#else
bool SpineSpriteInspectorPlugin::can_handle(Object *object) {
#endif
return Object::cast_to<SpineSprite>(object) != nullptr;
}
#ifdef SPINE_GODOT_EXTENSION
void SpineSpriteInspectorPlugin::_parse_begin(Object *object) {
#else
void SpineSpriteInspectorPlugin::parse_begin(Object *object) {
#endif
sprite = Object::cast_to<SpineSprite>(object);
if (!sprite) return;
if (!sprite->get_skeleton_data_res().is_valid() || !sprite->get_skeleton_data_res()->is_skeleton_data_loaded()) return;

View File

@ -30,19 +30,47 @@
#pragma once
#ifdef TOOLS_ENABLED
#include "SpineCommon.h"
#include "SpineSprite.h"
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/editor_import_plugin.hpp>
#else
#include "editor/import/editor_import_plugin.h"
#endif
#endif
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/editor_plugin.hpp>
#include <godot_cpp/classes/editor_inspector_plugin.hpp>
#include <godot_cpp/classes/editor_property.hpp>
#else
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_properties_array_dict.h"
#endif
class SpineAtlasResourceImportPlugin : public EditorImportPlugin {
GDCLASS(SpineAtlasResourceImportPlugin, EditorImportPlugin)
public:
#ifdef SPINE_GODOT_EXTENSION
String _get_importer_name() const override { return "spine.atlas"; }
String _get_visible_name() const override { return "Spine Runtime Atlas"; }
PackedStringArray _get_recognized_extensions() const override {
PackedStringArray extensions;
extensions.push_back("atlas");
return extensions;
}
String _get_preset_name(int idx) const override { return idx == 0 ? "Default" : "Unknown"; }
int _get_preset_count() const override { return 1; }
String _get_save_extension() const override { return "spatlas"; }
String _get_resource_type() const override { return "SpineAtlasResource"; }
#else
String get_importer_name() const override { return "spine.atlas"; }
String get_visible_name() const override { return "Spine Runtime Atlas"; }
@ -56,8 +84,18 @@ public:
String get_save_extension() const override { return "spatlas"; }
String get_resource_type() const override { return "SpineAtlasResource"; }
#endif
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
virtual int _get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
virtual float _get_priority() const override { return 1; }
virtual bool _get_option_visibility(const String &p_path, const StringName &p_option_name, const Dictionary &p_options) const override { return true; };
virtual Error _import(const String &p_source_file, const String &p_save_path, const Dictionary &p_options, const TypedArray<String> &p_platform_variants, const TypedArray<String> &p_gen_files) const override;
#else
int get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
float get_priority() const override { return 1; }
@ -67,6 +105,7 @@ public:
virtual bool get_option_visibility(const String &path, const String &option, const HashMap<StringName, Variant> &options) const override { return true; }
Error import(const String &source_file, const String &save_path, const HashMap<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) override;
#endif
#else
void get_import_options(List<ImportOption> *options, int preset) const override;
@ -80,6 +119,25 @@ class SpineJsonResourceImportPlugin : public EditorImportPlugin {
GDCLASS(SpineJsonResourceImportPlugin, EditorImportPlugin)
public:
#ifdef SPINE_GODOT_EXTENSION
String _get_importer_name() const override { return "spine.json"; }
String _get_visible_name() const override { return "Spine Skeleton Json"; }
PackedStringArray _get_recognized_extensions() const override {
PackedStringArray extensions;
extensions.push_back("spine-json");
return extensions;
}
String _get_preset_name(int idx) const override { return idx == 0 ? "Default" : "Unknown"; }
int _get_preset_count() const override { return 1; }
String _get_save_extension() const override { return "spjson"; }
String _get_resource_type() const override { return "SpineSkeletonFileResource"; }
#else
String get_importer_name() const override { return "spine.json"; }
String get_visible_name() const override { return "Spine Skeleton Json"; }
@ -93,8 +151,18 @@ public:
String get_save_extension() const override { return "spjson"; }
String get_resource_type() const override { return "SpineSkeletonFileResource"; }
#endif
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
int _get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
float _get_priority() const override { return 1; }
virtual bool _get_option_visibility(const String &p_path, const StringName &p_option_name, const Dictionary &p_options) const override { return true; };
virtual Error _import(const String &p_source_file, const String &p_save_path, const Dictionary &p_options, const TypedArray<String> &p_platform_variants, const TypedArray<String> &p_gen_files) const override;
#else
int get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
float get_priority() const override { return 1; }
@ -104,6 +172,7 @@ public:
bool get_option_visibility(const String &path, const String &option, const HashMap<StringName, Variant> &options) const override { return true; }
Error import(const String &source_file, const String &save_path, const HashMap<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) override;
#endif
#else
void get_import_options(List<ImportOption> *options, int preset) const override {}
@ -117,6 +186,25 @@ class SpineBinaryResourceImportPlugin : public EditorImportPlugin {
GDCLASS(SpineBinaryResourceImportPlugin, EditorImportPlugin);
public:
#ifdef SPINE_GODOT_EXTENSION
String _get_importer_name() const override { return "spine.skel"; }
String _get_visible_name() const override { return "Spine Skeleton Binary"; }
PackedStringArray _get_recognized_extensions() const override {
PackedStringArray extensions;
extensions.push_back("skel");
return extensions;
}
String _get_preset_name(int idx) const override { return idx == 0 ? "Default" : "Unknown"; }
int _get_preset_count() const override { return 1; }
String _get_save_extension() const override { return "spskel"; }
String _get_resource_type() const override { return "SpineSkeletonFileResource"; }
#else
String get_importer_name() const override { return "spine.skel"; }
String get_visible_name() const override { return "Spine Skeleton Binary"; }
@ -130,8 +218,18 @@ public:
String get_save_extension() const override { return "spskel"; }
String get_resource_type() const override { return "SpineSkeletonFileResource"; }
#endif
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
int _get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
float _get_priority() const override { return 1; }
virtual bool _get_option_visibility(const String &p_path, const StringName &p_option_name, const Dictionary &p_options) const override { return true; };
virtual Error _import(const String &p_source_file, const String &p_save_path, const Dictionary &p_options, const TypedArray<String> &p_platform_variants, const TypedArray<String> &p_gen_files) const override;
#else
int get_import_order() const override { return IMPORT_ORDER_DEFAULT; }
float get_priority() const override { return 1; }
@ -141,6 +239,7 @@ public:
bool get_option_visibility(const String &path, const String &option, const HashMap<StringName, Variant> &options) const override { return true; }
Error import(const String &source_file, const String &save_path, const HashMap<StringName, Variant> &options, List<String> *platform_variants, List<String> *gen_files, Variant *metadata) override;
#endif
#else
void get_import_options(List<ImportOption> *options, int preset) const override {}
@ -153,24 +252,38 @@ public:
class SpineEditorPlugin : public EditorPlugin {
GDCLASS(SpineEditorPlugin, EditorPlugin)
static void _bind_methods() {}
public:
#ifdef SPINE_GODOT_EXTENSION
explicit SpineEditorPlugin();
String _get_plugin_name() const override { return "SpineEditorPlugin"; }
#else
explicit SpineEditorPlugin(EditorNode *node);
String get_name() const override { return "SpineEditorPlugin"; }
#endif
};
class SpineSkeletonDataResourceInspectorPlugin : public EditorInspectorPlugin {
GDCLASS(SpineSkeletonDataResourceInspectorPlugin, EditorInspectorPlugin)
public:
#ifdef SPINE_GODOT_EXTENSION
bool _can_handle(Object *p_object) const override;
bool _parse_property(Object *object, Variant::Type type, const String &path, PropertyHint hint, const String &hint_text, const BitField<PropertyUsageFlags> p_usage, bool wide) override;
#else
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, const BitField<PropertyUsageFlags> p_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
#endif
};
#ifndef SPINE_GODOT_EXTENSION
class SpineEditorPropertyAnimationMix;
class SpineEditorPropertyAnimationMixes : public EditorProperty {
@ -210,6 +323,7 @@ public:
void setup(SpineEditorPropertyAnimationMixes *mixes_property, const Ref<SpineSkeletonDataResource> &skeleton_data, int index);
void update_property() override;
};
#endif
class SpineSpriteInspectorPlugin : public EditorInspectorPlugin {
GDCLASS(SpineSpriteInspectorPlugin, EditorInspectorPlugin)
@ -220,8 +334,13 @@ class SpineSpriteInspectorPlugin : public EditorInspectorPlugin {
void button_clicked(const String &button_name);
public:
#ifdef SPINE_GODOT_EXTENSION
virtual bool _can_handle(Object *object) const override;
virtual void _parse_begin(Object *object) override;
#else
bool can_handle(Object *object) override;
void parse_begin(Object *object) override;
#endif
};
#endif

View File

@ -30,6 +30,10 @@
#include "SpineSkeletonDataResource.h"
#include "SpineCommon.h"
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/encoded_object_as_id.hpp>
#endif
void SpineAnimationMix::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_from", "from"),
&SpineAnimationMix::set_from);
@ -201,9 +205,15 @@ void SpineSkeletonDataResource::update_skeleton_data() {
#endif
}
#ifdef SPINE_GODOT_EXTENSION
void SpineSkeletonDataResource::load_resources(spine::Atlas *atlas,
const String &json,
const PackedByteArray &binary) {
#else
void SpineSkeletonDataResource::load_resources(spine::Atlas *atlas,
const String &json,
const Vector<uint8_t> &binary) {
#endif
if ((EMPTY(json) && EMPTY(binary)) || atlas == nullptr)
return;
@ -287,8 +297,13 @@ SpineSkeletonDataResource::get_skeleton_file_res() {
return skeleton_file_res;
}
#ifdef SPINE_GODOT_EXTENSION
void SpineSkeletonDataResource::get_animation_names(
PackedStringArray &animation_names) const {
#else
void SpineSkeletonDataResource::get_animation_names(
Vector<String> &animation_names) const {
#endif
animation_names.clear();
if (!is_skeleton_data_loaded())
return;
@ -299,8 +314,13 @@ void SpineSkeletonDataResource::get_animation_names(
}
}
#ifdef SPINE_GODOT_EXTENSION
void SpineSkeletonDataResource::get_skin_names(
PackedStringArray &skin_names) const {
#else
void SpineSkeletonDataResource::get_skin_names(
Vector<String> &skin_names) const {
#endif
skin_names.clear();
if (!is_skeleton_data_loaded())
return;
@ -311,7 +331,11 @@ void SpineSkeletonDataResource::get_skin_names(
}
}
#ifdef SPINE_GODOT_EXTENSION
void SpineSkeletonDataResource::get_slot_names(PackedStringArray &slot_names) {
#else
void SpineSkeletonDataResource::get_slot_names(Vector<String> &slot_names) {
#endif
slot_names.clear();
if (!is_skeleton_data_loaded())
return;
@ -322,7 +346,11 @@ void SpineSkeletonDataResource::get_slot_names(Vector<String> &slot_names) {
}
}
#ifdef SPINE_GODOT_EXTENSION
void SpineSkeletonDataResource::get_bone_names(PackedStringArray &bone_names) {
#else
void SpineSkeletonDataResource::get_bone_names(Vector<String> &bone_names) {
#endif
bone_names.clear();
if (!is_skeleton_data_loaded())
return;

View File

@ -84,8 +84,13 @@ private:
void update_skeleton_data();
#ifdef SPINE_GODOT_EXTENSION
void load_resources(spine::Atlas *atlas, const String &json,
const PackedByteArray &binary);
#else
void load_resources(spine::Atlas *atlas, const String &json,
const Vector<uint8_t> &binary);
#endif
public:
SpineSkeletonDataResource();
@ -106,6 +111,15 @@ public:
return animation_state_data;
}
#ifdef SPINE_GODOT_EXTENSION
void get_animation_names(PackedStringArray &animation_names) const;
void get_skin_names(PackedStringArray &l) const;
void get_slot_names(PackedStringArray &slot_names);
void get_bone_names(PackedStringArray &bone_names);
#else
void get_animation_names(Vector<String> &animation_names) const;
void get_skin_names(Vector<String> &l) const;
@ -113,6 +127,7 @@ public:
void get_slot_names(Vector<String> &slot_names);
void get_bone_names(Vector<String> &bone_names);
#endif
void set_default_mix(float default_mix);

View File

@ -129,16 +129,26 @@ static bool checkBinary(const char *binaryData, int length) {
Error SpineSkeletonFileResource::load_from_file(const String &path) {
Error error = OK;
if (path.ends_with(".spjson") || path.ends_with(".spine-json")) {
#ifdef SPINE_GODOT_EXTENSION
json = FileAccess::get_file_as_string(path);
if (SSIZE(json) == 0) return ERR_INVALID_DATA;
#else
json = FileAccess::get_file_as_string(path, &error);
if (error != OK) return error;
#endif
if (!checkJson(json.utf8())) return ERR_INVALID_DATA;
} else {
#ifdef SPINE_GODOT_EXTENSION
binary = FileAccess::get_file_as_bytes(path);
if (binary.size() == 0) return ERR_INVALID_DATA;
#else
#if VERSION_MAJOR > 3
binary = FileAccess::get_file_as_bytes(path, &error);
#else
binary = FileAccess::get_file_as_array(path, &error);
#endif
if (error != OK) return error;
#endif
if (!checkBinary((const char *) binary.ptr(), binary.size())) return ERR_INVALID_DATA;
}
return error;
@ -146,6 +156,10 @@ Error SpineSkeletonFileResource::load_from_file(const String &path) {
Error SpineSkeletonFileResource::save_to_file(const String &path) {
Error error;
#ifdef SPINE_GODOT_EXTENSION
Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE);
if (!file.is_valid()) return ERR_FILE_CANT_OPEN;
#else
#if VERSION_MAJOR > 3
Ref<FileAccess> file = FileAccess::open(path, FileAccess::WRITE, &error);
if (error != OK) return error;
@ -155,6 +169,7 @@ Error SpineSkeletonFileResource::save_to_file(const String &path) {
if (file) file->close();
return error;
}
#endif
#endif
if (!is_binary())
file->store_string(json);
@ -168,6 +183,7 @@ Error SpineSkeletonFileResource::save_to_file(const String &path) {
return OK;
}
#ifndef SPINE_GODOT_EXTENSION
#if VERSION_MAJOR > 3
Error SpineSkeletonFileResource::copy_from(const Ref<Resource> &p_resource) {
auto error = Resource::copy_from(p_resource);
@ -179,7 +195,11 @@ Error SpineSkeletonFileResource::copy_from(const Ref<Resource> &p_resource) {
return OK;
}
#endif
#endif
#ifdef SPINE_GODOT_EXTENSION
Variant SpineSkeletonFileResourceFormatLoader::_load(const String &path, const String &original_path, bool use_sub_threads, int32_t cache_mode) {
#else
#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
@ -188,43 +208,82 @@ RES SpineSkeletonFileResourceFormatLoader::load(const String &path, const String
#else
RES SpineSkeletonFileResourceFormatLoader::load(const String &path, const String &original_path, Error *error) {
#endif
#endif
#endif
Ref<SpineSkeletonFileResource> skeleton_file = memnew(SpineSkeletonFileResource);
skeleton_file->load_from_file(path);
#ifndef SPINE_GODOT_EXTENSION
if (error) *error = OK;
#endif
return skeleton_file;
}
#ifdef SPINE_GODOT_EXTENSION
PackedStringArray SpineSkeletonFileResourceFormatLoader::_get_recognized_extensions() {
PackedStringArray extensions;
extensions.push_back("spjson");
extensions.push_back("spskel");
return extensions;
}
#else
void SpineSkeletonFileResourceFormatLoader::get_recognized_extensions(List<String> *extensions) const {
extensions->push_back("spjson");
extensions->push_back("spskel");
}
#endif
#ifdef SPINE_GODOT_EXTENSION
String SpineSkeletonFileResourceFormatLoader::_get_resource_type(const String &path) {
#else
String SpineSkeletonFileResourceFormatLoader::get_resource_type(const String &path) const {
#endif
return path.ends_with(".spjson") || path.ends_with(".spskel") || path.ends_with(".spine-json") || path.ends_with(".skel") ? "SpineSkeletonFileResource" : "";
}
#ifdef SPINE_GODOT_EXTENSION
bool SpineSkeletonFileResourceFormatLoader::_handles_type(const StringName &type) {
#else
bool SpineSkeletonFileResourceFormatLoader::handles_type(const String &type) const {
return type == "SpineSkeletonFileResource" || ClassDB::is_parent_class(type, "SpineSkeletonFileResource");
#endif
return type == StringName("SpineSkeletonFileResource") || ClassDB::is_parent_class(type, "SpineSkeletonFileResource");
}
#ifdef SPINE_GODOT_EXTENSION
Error SpineSkeletonFileResourceFormatSaver::_save(const Ref<Resource> &resource, const String &path, uint32_t flags) {
#else
#if VERSION_MAJOR > 3
Error SpineSkeletonFileResourceFormatSaver::save(const RES &resource, const String &path, uint32_t flags) {
#else
Error SpineSkeletonFileResourceFormatSaver::save(const String &path, const RES &resource, uint32_t flags) {
#endif
#endif
Ref<SpineSkeletonFileResource> res = resource;
Error error = res->save_to_file(path);
return error;
}
#ifdef SPINE_GODOT_EXTENSION
PackedStringArray SpineSkeletonFileResourceFormatSaver::_get_recognized_extensions(const Ref<Resource> &resource) {
PackedStringArray extensions;
if (Object::cast_to<SpineSkeletonFileResource>(*resource)) {
extensions.push_back("spjson");
extensions.push_back("spskel");
}
return extensions;
}
#else
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");
}
}
#endif
bool SpineSkeletonFileResourceFormatSaver::recognize(const RES &p_resource) const {
return Object::cast_to<SpineSkeletonFileResource>(*p_resource) != nullptr;
#ifdef SPINE_GODOT_EXTENSION
bool SpineSkeletonFileResourceFormatSaver::_recognize(const Ref<Resource> &resource) {
#else
bool SpineSkeletonFileResourceFormatSaver::recognize(const RES &resource) const {
#endif
return Object::cast_to<SpineSkeletonFileResource>(*resource) != nullptr;
}

View File

@ -50,12 +50,20 @@ protected:
static void _bind_methods();
String json;
#ifdef SPINE_GODOT_EXTENSION
PackedByteArray binary;
#else
Vector<uint8_t> binary;
#endif
public:
bool is_binary() { return binary.size() > 0; }
#ifdef SPINE_GODOT_EXTENSION
const PackedByteArray &get_binary() { return binary; }
#else
const Vector<uint8_t> &get_binary() { return binary; }
#endif
const String &get_json() { return json; }
@ -63,9 +71,11 @@ public:
Error save_to_file(const String &path);
#ifndef SPINE_GODOT_EXTENSION
#if VERSION_MAJOR > 3
virtual Error copy_from(const Ref<Resource> &p_resource);
#endif
#endif
};
class SpineSkeletonFileResourceFormatLoader : public ResourceFormatLoader {

View File

@ -30,9 +30,17 @@
#include "SpineSlotNode.h"
#ifdef TOOLS_ENABLED
#ifdef SPINE_GODOT_EXTENSION
// FIXME
#else
#include "editor/editor_node.h"
#endif
#endif
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/viewport.hpp>
#else
#include "scene/main/viewport.h"
#endif
void SpineSlotNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_on_world_transforms_changed", "spine_sprite"), &SpineSlotNode::on_world_transforms_changed);
@ -99,7 +107,11 @@ void SpineSlotNode::_notification(int what) {
}
void SpineSlotNode::_get_property_list(List<PropertyInfo> *list) const {
#ifdef SPINE_GODOT_EXTENSION
PackedStringArray slot_names;
#else
Vector<String> slot_names;
#endif
SpineSprite *sprite = cast_to<SpineSprite>(get_parent());
if (sprite && sprite->get_skeleton_data_res().is_valid()) sprite->get_skeleton_data_res()->get_slot_names(slot_names);
else
@ -107,7 +119,7 @@ void SpineSlotNode::_get_property_list(List<PropertyInfo> *list) const {
auto element = list->front();
while (element) {
auto property_info = element->get();
if (property_info.name == "SpineSlotNode") break;
if (property_info.name == StringName("SpineSlotNode")) break;
element = element->next();
}
PropertyInfo slot_name_property;
@ -120,7 +132,7 @@ void SpineSlotNode::_get_property_list(List<PropertyInfo> *list) const {
}
bool SpineSlotNode::_get(const StringName &property, Variant &value) const {
if (property == "slot_name") {
if (property == StringName("slot_name")) {
value = slot_name;
return true;
}
@ -128,7 +140,7 @@ bool SpineSlotNode::_get(const StringName &property, Variant &value) const {
}
bool SpineSlotNode::_set(const StringName &property, const Variant &value) {
if (property == "slot_name") {
if (property == StringName("slot_name")) {
slot_name = value;
SpineSprite *sprite = cast_to<SpineSprite>(get_parent());
update_transform(sprite);

View File

@ -31,7 +31,11 @@
#include "SpineCommon.h"
#include "SpineSprite.h"
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/classes/node2d.hpp>
#else
#include "scene/2d/node_2d.h"
#endif
class SpineSlotNode : public Node2D {
GDCLASS(SpineSlotNode, Node2D)

View File

@ -33,6 +33,23 @@
#include "SpineSkeleton.h"
#include "SpineRendererObject.h"
#include "SpineSlotNode.h"
#ifdef SPINE_GODOT_EXTENSION
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/classes/geometry2d.hpp>
#include <godot_cpp/variant/array.hpp>
#include <godot_cpp/classes/mesh.hpp>
#include <godot_cpp/classes/rendering_server.hpp>
#include <godot_cpp/classes/editor_interface.hpp>
#include <godot_cpp/classes/control.hpp>
#include <godot_cpp/classes/viewport.hpp>
#include <godot_cpp/classes/scene_tree.hpp>
#if TOOLS_ENABLED
#include <godot_cpp/classes/editor_plugin.hpp>
#include <godot_cpp/classes/font.hpp>
#endif
#else
#include "core/os/memory.h"
#if VERSION_MAJOR > 3
@ -64,6 +81,7 @@
#include "editor/editor_plugin.h"
#endif
#endif
#endif
Ref<CanvasItemMaterial>
@ -71,7 +89,11 @@ Ref<CanvasItemMaterial>
static int sprite_count = 0;
static spine::Vector<unsigned short> quad_indices;
static spine::Vector<float> scratch_vertices;
#ifdef SPINE_GODOT_EXTENSION
static PackedVector2Array scratch_points;
#else
static Vector<Vector2> scratch_points;
#endif
static void clear_triangles(SpineMesh2D *mesh_instance) {
@ -82,12 +104,21 @@ static void clear_triangles(SpineMesh2D *mesh_instance) {
#endif
}
#ifdef SPINE_GODOT_EXTENSION
static void add_triangles(SpineMesh2D *mesh_instance,
const PackedVector2Array &vertices,
const PackedVector2Array &uvs,
const PackedColorArray &colors,
const PackedInt32Array &indices,
SpineRendererObject *renderer_object) {
#else
static void add_triangles(SpineMesh2D *mesh_instance,
const Vector<Point2> &vertices,
const Vector<Point2> &uvs,
const Vector<Color> &colors,
const Vector<int> &indices,
SpineRendererObject *renderer_object) {
#endif
#if VERSION_MAJOR > 3
mesh_instance->update_mesh(vertices, uvs, colors, indices, renderer_object);
#else
@ -137,15 +168,29 @@ void SpineMesh2D::_notification(int what) {
void SpineMesh2D::_bind_methods() {
}
#ifdef SPINE_GODOT_EXTENSION
void SpineMesh2D::update_mesh(const PackedVector2Array &vertices,
const PackedVector2Array &uvs,
const PackedColorArray &colors,
const PackedInt32Array &indices,
SpineRendererObject *renderer_object) {
#else
void SpineMesh2D::update_mesh(const Vector<Point2> &vertices,
const Vector<Point2> &uvs,
const Vector<Color> &colors,
const Vector<int> &indices,
SpineRendererObject *renderer_object) {
#endif
#if SPINE_GODOT_EXTENSION
#else
#if VERSION_MAJOR > 3
if (!mesh.is_valid() || vertices.size() != num_vertices || indices.size() != num_indices || indices_changed) {
if (mesh.is_valid()) {
#ifdef SPINE_GODOT_EXTENSION
RS::get_singleton()->free_rid(mesh);
#else
RS::get_singleton()->free(mesh);
#endif
}
mesh = RS::get_singleton()->mesh_create();
Array arrays;
@ -257,6 +302,7 @@ void SpineMesh2D::update_mesh(const Vector<Point2> &vertices,
renderer_object->texture.is_null() ? RID() : renderer_object->texture->get_rid(),
renderer_object->normal_map.is_null() ? RID() : renderer_object->normal_map->get_rid());
#endif
#endif
}
void SpineSprite::_bind_methods() {
@ -555,8 +601,13 @@ void SpineSprite::_notification(int what) {
void SpineSprite::_get_property_list(List<PropertyInfo> *list) const {
if (!skeleton_data_res.is_valid() || !skeleton_data_res->is_skeleton_data_loaded()) return;
#ifdef SPINE_GODOT_EXTENSION
PackedStringArray animation_names;
PackedStringArray skin_names;
#else
Vector<String> animation_names;
Vector<String> skin_names;
#endif
skeleton_data_res->get_animation_names(animation_names);
skeleton_data_res->get_skin_names(skin_names);
animation_names.insert(0, "-- Empty --");
@ -592,28 +643,32 @@ void SpineSprite::_get_property_list(List<PropertyInfo> *list) const {
auto animation = skeleton_data_res->find_animation(preview_animation);
if (animation.is_valid()) animation_duration = animation->get_duration();
}
#ifdef SPINE_GODOT_EXTENSION
preview_time_property.hint_string = String("0.0,") + String::num(animation_duration) + String(",0.01");
#else
preview_time_property.hint_string = String("0.0,{0},0.01").format(varray(animation_duration));
#endif
preview_time_property.hint = PROPERTY_HINT_RANGE;
list->push_back(preview_time_property);
}
bool SpineSprite::_get(const StringName &property, Variant &value) const {
if (property == "preview_skin") {
if (property == StringName("preview_skin")) {
value = preview_skin;
return true;
}
if (property == "preview_animation") {
if (property == StringName("preview_animation")) {
value = preview_animation;
return true;
}
if (property == "preview_frame") {
if (property == StringName("preview_frame")) {
value = preview_frame;
return true;
}
if (property == "preview_time") {
if (property == StringName("preview_time")) {
value = preview_time;
return true;
}
@ -644,27 +699,27 @@ static void update_preview_animation(SpineSprite *sprite, const String &skin, co
}
bool SpineSprite::_set(const StringName &property, const Variant &value) {
if (property == "preview_skin") {
if (property == StringName("preview_skin")) {
preview_skin = value;
update_preview_animation(this, preview_skin, preview_animation, preview_frame, preview_time);
NOTIFY_PROPERTY_LIST_CHANGED();
return true;
}
if (property == "preview_animation") {
if (property == StringName("preview_animation")) {
preview_animation = value;
update_preview_animation(this, preview_skin, preview_animation, preview_frame, preview_time);
NOTIFY_PROPERTY_LIST_CHANGED();
return true;
}
if (property == "preview_frame") {
if (property == StringName("preview_frame")) {
preview_frame = value;
update_preview_animation(this, preview_skin, preview_animation, preview_frame, preview_time);
return true;
}
if (property == "preview_time") {
if (property == StringName("preview_time")) {
preview_time = value;
update_preview_animation(this, preview_skin, preview_animation, preview_frame, preview_time);
return true;
@ -865,7 +920,11 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> skeleton_ref) {
skeleton_clipper->clipEnd();
}
#ifdef SPINE_GODOT_EXTENSION
void createLinesFromMesh(PackedVector2Array &scratch_points, spine::Vector<unsigned short> &triangles, spine::Vector<float> *vertices) {
#else
void createLinesFromMesh(Vector<Vector2> &scratch_points, spine::Vector<unsigned short> &triangles, spine::Vector<float> *vertices) {
#endif
scratch_points.resize(0);
for (int i = 0; i < triangles.size(); i += 3) {
int i1 = triangles[i];
@ -924,7 +983,11 @@ void SpineSprite::draw() {
scratch_points.push_back(Vector2(vertices->buffer()[0], vertices->buffer()[1]));
Color color = debug_regions_color;
#ifdef SPINE_GODOT_EXTENSION
if (GEOMETRY2D::get_singleton()->is_point_in_polygon(mouse_position, scratch_points)) {
#else
if (GEOMETRY2D::is_point_in_polygon(mouse_position, scratch_points)) {
#endif
hovered_slot = slot;
color = Color(1, 1, 1, 1);
}
@ -960,7 +1023,11 @@ void SpineSprite::draw() {
}
Color color = debug_meshes_color;
#ifdef SPINE_GODOT_EXTENSION
if (GEOMETRY2D::get_singleton()->is_point_in_polygon(mouse_position, scratch_points)) {
#else
if (GEOMETRY2D::is_point_in_polygon(mouse_position, scratch_points)) {
#endif
hovered_slot = slot;
color = Color(1, 1, 1, 1);
}
@ -1029,7 +1096,11 @@ void SpineSprite::draw() {
Transform2D bone_transform(spine::MathUtil::Deg_Rad * bone->getWorldRotationX(), Vector2(bone->getWorldX(), bone->getWorldY()));
bone_transform.scale_basis(Vector2(bone->getWorldScaleX(), bone->getWorldScaleY()));
auto mouse_local_position = bone_transform.affine_inverse().xform(mouse_position);
#ifdef SPINE_GODOT_EXTENSION
if (GEOMETRY2D::get_singleton()->is_point_in_polygon(mouse_local_position, scratch_points)) {
#else
if (GEOMETRY2D::is_point_in_polygon(mouse_local_position, scratch_points)) {
#endif
hovered_bone = bone;
}
}
@ -1053,7 +1124,11 @@ void SpineSprite::draw() {
Transform2D bone_transform(spine::MathUtil::Deg_Rad * bone->getWorldRotationX(), Vector2(bone->getWorldX(), bone->getWorldY()));
bone_transform.scale_basis(Vector2(bone->getWorldScaleX(), bone->getWorldScaleY()));
auto mouse_local_position = bone_transform.affine_inverse().xform(mouse_position);
#ifdef SPINE_GODOT_EXTENSION
if (GEOMETRY2D::get_singleton()->is_point_in_polygon(mouse_local_position, scratch_points)) {
#else
if (GEOMETRY2D::is_point_in_polygon(mouse_local_position, scratch_points)) {
#endif
hovered_bone = bone;
}
}
@ -1089,7 +1164,12 @@ void SpineSprite::draw() {
memdelete(control);
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
// FIXME possibly wrong
float line_height = default_font->get_height() + default_font->get_descent();
#else
float line_height = default_font->get_height(Font::DEFAULT_FONT_SIZE) + default_font->get_descent(Font::DEFAULT_FONT_SIZE);
#endif
#else
float line_height = default_font->get_height() + default_font->get_descent();
#endif
@ -1099,14 +1179,22 @@ void SpineSprite::draw() {
}
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
Rect2 background_rect(0, -default_font->get_height() - 5, rect_width + 20, line_height * hover_text_lines.size() + 10);
#else
Rect2 background_rect(0, -default_font->get_height(Font::DEFAULT_FONT_SIZE) - 5, rect_width + 20, line_height * hover_text_lines.size() + 10);
#endif
#else
Rect2 background_rect(0, -default_font->get_height() - 5, rect_width + 20, line_height * hover_text_lines.size() + 10);
#endif
if (hover_text_lines.size() > 0) draw_rect(background_rect, Color(0, 0, 0, 0.8));
for (int i = 0; i < hover_text_lines.size(); i++) {
#if VERSION_MAJOR > 3
#ifdef SPINE_GODOT_EXTENSION
draw_string(default_font, Vector2(10, 0 + i * default_font->get_height()), hover_text_lines[i], HORIZONTAL_ALIGNMENT_LEFT, -1, 16, Color(1, 1, 1, 1));
#else
draw_string(default_font, Vector2(10, 0 + i * default_font->get_height(Font::DEFAULT_FONT_SIZE)), hover_text_lines[i], HORIZONTAL_ALIGNMENT_LEFT, -1, Font::DEFAULT_FONT_SIZE, Color(1, 1, 1, 1));
#endif
#else
draw_string(default_font, Vector2(10, 0 + i * default_font->get_height()), hover_text_lines[i], Color(1, 1, 1, 1));
#endif
@ -1118,7 +1206,11 @@ void SpineSprite::draw_bone(spine::Bone *bone, const Color &color) {
draw_set_transform(Vector2(bone->getWorldX(), bone->getWorldY()), spine::MathUtil::Deg_Rad * bone->getWorldRotationX(), Vector2(bone->getWorldScaleX(), bone->getWorldScaleY()));
float bone_length = bone->getData().getLength();
if (bone_length == 0) bone_length = debug_bones_thickness * 2;
#ifdef SPINE_GODOT_EXTENSION
PackedVector2Array points;
#else
Vector<Vector2> points;
#endif
points.push_back(Vector2(-debug_bones_thickness, 0));
points.push_back(Vector2(0, debug_bones_thickness));
points.push_back(Vector2(bone_length, 0));
@ -1162,7 +1254,6 @@ Transform2D SpineSprite::get_global_bone_transform(const String &bone_name) {
if (!animation_state.is_valid() && !skeleton.is_valid()) return get_global_transform();
auto bone = skeleton->find_bone(bone_name);
if (!bone.is_valid()) {
print_error(vformat("Bone: '%s' not found.", bone_name));
return get_global_transform();
}
return bone->get_global_transform();
@ -1223,13 +1314,14 @@ void SpineSprite::set_screen_material(Ref<Material> material) {
screen_material = material;
}
#ifndef SPINE_GODOT_EXTENSION
// FIXME
#ifdef TOOLS_ENABLED
Rect2 SpineSprite::_edit_get_rect() const {
if (skeleton_data_res.is_valid() && skeleton_data_res->is_skeleton_data_loaded()) {
auto data = skeleton_data_res->get_skeleton_data();
return Rect2(data->getX(), -data->getY() - data->getHeight(), data->getWidth(), data->getHeight());
}
return Node2D::_edit_get_rect();
}
@ -1237,3 +1329,4 @@ bool SpineSprite::_edit_use_rect() const {
return skeleton_data_res.is_valid() && skeleton_data_res->is_skeleton_data_loaded();
}
#endif
#endif

View File

@ -58,10 +58,17 @@ protected:
void _notification(int what);
static void _bind_methods();
#ifdef SPINE_GODOT_EXTENSION
PackedVector2Array vertices;
PackedVector2Array uvs;
PackedColorArray colors;
PackedInt32Array indices;
#else
Vector<Vector2> vertices;
Vector<Vector2> uvs;
Vector<Color> colors;
Vector<int> indices;
#endif
SpineRendererObject *renderer_object;
bool indices_changed;
@ -89,7 +96,7 @@ protected:
public:
#if VERSION_MAJOR > 3
SpineMesh2D() : renderer_object(nullptr), indices_changed(true), num_vertices(0), num_indices(0), vertex_stride(0), normal_tangent_stride(0), attribute_stride(0){};
SpineMesh2D() : renderer_object(nullptr), indices_changed(true), num_vertices(0), num_indices(0), vertex_stride(0), normal_tangent_stride(0), attribute_stride(0) {};
~SpineMesh2D() {
if (mesh.is_valid()) {
#ifdef SPINE_GODOT_EXTENSION
@ -100,7 +107,7 @@ public:
}
}
#else
SpineMesh2D() : renderer_object(nullptr), indices_changed(true), num_vertices(0), num_indices(0){};
SpineMesh2D() : renderer_object(nullptr), indices_changed(true), num_vertices(0), num_indices(0) {};
~SpineMesh2D() {
if (mesh.is_valid()) {
VS::get_singleton()->free(mesh);
@ -108,11 +115,19 @@ public:
}
#endif
#ifdef SPINE_GODOT_EXTENSION
void update_mesh(const PackedVector2Array &vertices,
const PackedVector2Array &uvs,
const PackedColorArray &colors,
const PackedInt32Array &indices,
SpineRendererObject *renderer_object);
#else
void update_mesh(const Vector<Point2> &vertices,
const Vector<Point2> &uvs,
const Vector<Color> &colors,
const Vector<int> &indices,
SpineRendererObject *renderer_object);
#endif
};
class SpineSprite : public Node2D,
@ -276,8 +291,11 @@ public:
void set_debug_clipping_color(const Color &color) { debug_clipping_color = color; }
#ifndef SPINE_GODOT_EXTENSION
// FIXME
#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
#endif
#endif
};

Some files were not shown because too many files have changed in this diff Show More