Browse Source

Merge branch '4.1' into 4.2-beta

badlogic 1 year ago
parent
commit
c99535ed85
75 changed files with 5528 additions and 22 deletions
  1. 2 2
      .github/workflows/spine-godot-v4.yml
  2. 1 0
      .gitignore
  3. 4 3
      spine-godot/.vscode/settings.json
  4. 2 5
      spine-godot/build/build-v4.sh
  5. 1 1
      spine-godot/build/install-macos-vulkan-sdk.sh
  6. 11 11
      spine-godot/build/setup.sh
  7. BIN
      spine-godot/example-v4-csharp/assets/footstep.ogg
  8. 19 0
      spine-godot/example-v4-csharp/assets/footstep.ogg.import
  9. 10 0
      spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match-data.tres
  10. 1285 0
      spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match-pro.spine-json
  11. 14 0
      spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match-pro.spine-json.import
  12. 362 0
      spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.atlas
  13. 15 0
      spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.atlas.import
  14. BIN
      spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.png
  15. 34 0
      spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.png.import
  16. 15 0
      spine-godot/example-v4-csharp/assets/raggedyspineboy/Raggedy Spineboy.atlas.import
  17. 34 0
      spine-godot/example-v4-csharp/assets/raggedyspineboy/Raggedy Spineboy.png.import
  18. 8 0
      spine-godot/example-v4-csharp/assets/raggedyspineboy/raggedy spineboy-res.tres
  19. 46 0
      spine-godot/example-v4-csharp/assets/raggedyspineboy/raggedy spineboy.spine-json
  20. 14 0
      spine-godot/example-v4-csharp/assets/raggedyspineboy/raggedy spineboy.spine-json.import
  21. BIN
      spine-godot/example-v4-csharp/assets/raptor/light-sprite.png
  22. 34 0
      spine-godot/example-v4-csharp/assets/raptor/light-sprite.png.import
  23. BIN
      spine-godot/example-v4-csharp/assets/raptor/n_raptor.png
  24. 34 0
      spine-godot/example-v4-csharp/assets/raptor/n_raptor.png.import
  25. 9 0
      spine-godot/example-v4-csharp/assets/raptor/raptor-data.tres
  26. BIN
      spine-godot/example-v4-csharp/assets/raptor/raptor-pro.skel
  27. 14 0
      spine-godot/example-v4-csharp/assets/raptor/raptor-pro.skel.import
  28. 100 0
      spine-godot/example-v4-csharp/assets/raptor/raptor.atlas
  29. 15 0
      spine-godot/example-v4-csharp/assets/raptor/raptor.atlas.import
  30. BIN
      spine-godot/example-v4-csharp/assets/raptor/raptor.png
  31. 34 0
      spine-godot/example-v4-csharp/assets/raptor/raptor.png.import
  32. 20 0
      spine-godot/example-v4-csharp/assets/spineboy/spineboy-data-res.tres
  33. BIN
      spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.skel
  34. 14 0
      spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.skel.import
  35. 541 0
      spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.spine-json
  36. 14 0
      spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.spine-json.import
  37. 101 0
      spine-godot/example-v4-csharp/assets/spineboy/spineboy.atlas
  38. 15 0
      spine-godot/example-v4-csharp/assets/spineboy/spineboy.atlas.import
  39. BIN
      spine-godot/example-v4-csharp/assets/spineboy/spineboy.png
  40. 34 0
      spine-godot/example-v4-csharp/assets/spineboy/spineboy.png.import
  41. 7 0
      spine-godot/example-v4-csharp/default_env.tres
  42. 8 0
      spine-godot/example-v4-csharp/examples/01-helloworld/Spineboy.cs
  43. 19 0
      spine-godot/example-v4-csharp/examples/01-helloworld/helloworld.tscn
  44. 43 0
      spine-godot/example-v4-csharp/examples/02-animation-state-listeners/AnimationStateListener.cs
  45. 20 0
      spine-godot/example-v4-csharp/examples/02-animation-state-listeners/animation-state-listeners.tscn
  46. 29 0
      spine-godot/example-v4-csharp/examples/03-mix-and-match/MixAndMatch.cs
  47. 16 0
      spine-godot/example-v4-csharp/examples/03-mix-and-match/mix-and-match.tscn
  48. 33 0
      spine-godot/example-v4-csharp/examples/04-simple-input/SpineboyInput.cs
  49. 16 0
      spine-godot/example-v4-csharp/examples/04-simple-input/simple-input.tscn
  50. 22 0
      spine-godot/example-v4-csharp/examples/05-mouse-following/MouseFollowing.cs
  51. 23 0
      spine-godot/example-v4-csharp/examples/05-mouse-following/mouse-following.tscn
  52. 10 0
      spine-godot/example-v4-csharp/examples/06-bone-following/BoneFollowing.cs
  53. 27 0
      spine-godot/example-v4-csharp/examples/06-bone-following/bone-following.tscn
  54. 17 0
      spine-godot/example-v4-csharp/examples/07-slot-node/SlotNode.cs
  55. 62 0
      spine-godot/example-v4-csharp/examples/07-slot-node/slot-node.tscn
  56. 52 0
      spine-godot/example-v4-csharp/examples/08-animation-player/PlayCutscene.cs
  57. 1944 0
      spine-godot/example-v4-csharp/examples/08-animation-player/animation-player.tscn
  58. 45 0
      spine-godot/example-v4-csharp/examples/09-custom-material/custom-material.tscn
  59. 27 0
      spine-godot/example-v4-csharp/examples/10-2d-lighting/2d-lighting.tscn
  60. 10 0
      spine-godot/example-v4-csharp/examples/10-2d-lighting/Lighting.cs
  61. 54 0
      spine-godot/example-v4-csharp/examples/11-bone-node/BoneNode.cs
  62. 53 0
      spine-godot/example-v4-csharp/examples/11-bone-node/bone-node.tscn
  63. BIN
      spine-godot/example-v4-csharp/godot-nuget/Godot.NET.Sdk.4.1.1.nupkg
  64. BIN
      spine-godot/example-v4-csharp/godot-nuget/Godot.SourceGenerators.4.1.1.nupkg
  65. BIN
      spine-godot/example-v4-csharp/godot-nuget/GodotSharp.4.1.1.nupkg
  66. BIN
      spine-godot/example-v4-csharp/godot-nuget/GodotSharp.4.1.1.snupkg
  67. BIN
      spine-godot/example-v4-csharp/godot-nuget/GodotSharpEditor.4.1.1.nupkg
  68. BIN
      spine-godot/example-v4-csharp/godot-nuget/GodotSharpEditor.4.1.1.snupkg
  69. BIN
      spine-godot/example-v4-csharp/icon.png
  70. 34 0
      spine-godot/example-v4-csharp/icon.png.import
  71. 6 0
      spine-godot/example-v4-csharp/nuget.config
  72. 39 0
      spine-godot/example-v4-csharp/project.godot
  73. 7 0
      spine-godot/example-v4-csharp/spine-godot-examples.csproj
  74. 19 0
      spine-godot/example-v4-csharp/spine-godot-examples.sln
  75. 30 0
      spine-godot/spine_godot/SpineSprite.cpp

+ 2 - 2
.github/workflows/spine-godot-v4.yml

@@ -451,8 +451,8 @@ jobs:
           ls -lahR
           mv godot.windows.editor.x86_64.mono.exe godot-$BRANCH-$GODOT_TAG-mono.exe
           mv godot.linuxbsd.editor.x86_64.mono godot-$BRANCH-$GODOT_TAG-mono
-          zip godot-editor-windows-mono.zip godot-$BRANCH-$GODOT_TAG-mono.exe GodotSharp
-          zip godot-editor-linux-mono.zip godot-$BRANCH-$GODOT_TAG-mono GodotSharp
+          zip -r godot-editor-windows-mono.zip godot-$BRANCH-$GODOT_TAG-mono.exe GodotSharp
+          zip -r godot-editor-linux-mono.zip godot-$BRANCH-$GODOT_TAG-mono GodotSharp
           mv godot-editor-macos.zip godot-editor-macos-mono.zip
           aws s3 cp godot-editor-windows-mono.zip s3://spine-godot/$BRANCH/$GODOT_TAG/
           aws s3 cp godot-editor-linux-mono.zip s3://spine-godot/$BRANCH/$GODOT_TAG/

+ 1 - 0
.gitignore

@@ -199,3 +199,4 @@ spine-godot/godot-nuget
 spine-godot/godot-spine-csharp
 spine-ue4/Plugins/Developer
 spine-haxe/export
+spine-godot/example-v4-csharp/.godot

+ 4 - 3
spine-godot/.vscode/settings.json

@@ -1,4 +1,5 @@
 {
-    "cmake.configureOnOpen": false,
-    "C_Cpp.intelliSenseEngine": "disabled",
-}
+  "cmake.configureOnOpen": false,
+  "C_Cpp.intelliSenseEngine": "disabled",
+  "dotnet.defaultSolution": "disable"
+}

+ 2 - 5
spine-godot/build/build-v4.sh

@@ -29,10 +29,7 @@ fi
 
 if [ -f "../godot/custom.py" ]; then
 	dev="true"
-fi
-
-if [ -f "../godot/custom.py" ]; then
-	dev="true"
+	echo "DEV build"
 fi
 
 mono_module=""
@@ -55,7 +52,7 @@ cpus=2
 if [ "$OSTYPE" == "msys" ]; then
 	os="windows"
 	cpus=$NUMBER_OF_PROCESSORS
-	target="vsproj=yes livepp=$LIVEPP"
+	target="$target vsproj=yes livepp=$LIVEPP"
 	godot_exe="godot.windows.editor$dev_extension.x86_64$mono_extension.exe"
 	godot_exe_host=$godot_exe
 elif [[ "$OSTYPE" == "darwin"* ]]; then

+ 1 - 1
spine-godot/build/install-macos-vulkan-sdk.sh

@@ -2,7 +2,7 @@ set -euo pipefail
 IFS=$'\n\t'
 
 # Download and install the Vulkan SDK.
-curl -L "https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.dmg" -o /tmp/vulkan-sdk.dmg
+curl -L "https://sdk.lunarg.com/sdk/download/1.3.250.1/mac/vulkansdk-macos-1.3.250.1.dmg" -o /tmp/vulkan-sdk.dmg
 hdiutil attach /tmp/vulkan-sdk.dmg -mountpoint /Volumes/vulkan-sdk
 /Volumes/vulkan-sdk/InstallVulkan.app/Contents/MacOS/InstallVulkan \
     --accept-licenses --default-answer --confirm-command install

+ 11 - 11
spine-godot/build/setup.sh

@@ -49,17 +49,17 @@ if [ $dev = "true" ]; then
 	rm -rf example/.import
 	rm -rf example/.godot
 
-	if [ "$OSTYPE" = "msys" ]; then
-		pushd godot
-		if [[ $branch == 3* ]]; then
-			echo "Applying V3 Live++ patch"
-			git apply ../build/livepp.patch
-		else
-			echo "Applying V4 Live++ patch"
-			git apply ../build/livepp-v4.patch
-		fi
-		popd
-	fi
+	#if [ "$OSTYPE" = "msys" ]; then
+	#	pushd godot
+	#	if [[ $branch == 3* ]]; then
+	#		echo "Applying V3 Live++ patch"
+	#		git apply ../build/livepp.patch
+	#	else
+	#		echo "Applying V4 Live++ patch"
+	#		git apply ../build/livepp-v4.patch
+	#	fi
+	#	popd
+	#fi
 
 	if [ `uname` == 'Darwin' ] && [ ! -d "$HOME/VulkanSDK" ]; then
 		./build/install-macos-vulkan-sdk.sh

BIN
spine-godot/example-v4-csharp/assets/footstep.ogg


+ 19 - 0
spine-godot/example-v4-csharp/assets/footstep.ogg.import

@@ -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

+ 10 - 0
spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match-data.tres

@@ -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

File diff suppressed because it is too large
+ 1285 - 0
spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match-pro.spine-json


+ 14 - 0
spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match-pro.spine-json.import

@@ -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]
+

+ 362 - 0
spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.atlas

@@ -0,0 +1,362 @@
+mix-and-match.png
+	size: 1024, 512
+	filter: Linear, Linear
+	scale: 0.5
+base-head
+	bounds: 587, 2, 95, 73
+boy/arm-front
+	bounds: 558, 271, 36, 115
+boy/backpack
+	bounds: 235, 109, 119, 153
+boy/backpack-pocket
+	bounds: 328, 73, 34, 62
+	rotate: 90
+boy/backpack-strap-front
+	bounds: 665, 79, 38, 88
+boy/backpack-up
+	bounds: 395, 364, 21, 70
+	rotate: 90
+boy/body
+	bounds: 251, 264, 97, 132
+	rotate: 90
+boy/boot-ribbon-front
+	bounds: 648, 131, 9, 11
+boy/collar
+	bounds: 744, 4, 73, 29
+	rotate: 90
+boy/ear
+	bounds: 383, 109, 19, 23
+	rotate: 90
+boy/eye-back-low-eyelid
+	bounds: 739, 284, 17, 6
+	rotate: 90
+boy/eye-back-pupil
+	bounds: 832, 443, 8, 9
+	rotate: 90
+boy/eye-back-up-eyelid
+	bounds: 558, 264, 23, 5
+boy/eye-back-up-eyelid-back
+	bounds: 802, 491, 19, 10
+	rotate: 90
+boy/eye-front-low-eyelid
+	bounds: 386, 363, 22, 7
+	rotate: 90
+boy/eye-front-pupil
+	bounds: 816, 389, 9, 9
+boy/eye-front-up-eyelid
+	bounds: 160, 71, 31, 6
+	rotate: 90
+boy/eye-front-up-eyelid-back
+	bounds: 801, 434, 26, 9
+	rotate: 90
+boy/eye-iris-back
+	bounds: 618, 264, 17, 17
+boy/eye-iris-front
+	bounds: 727, 264, 18, 18
+boy/eye-white-back
+	bounds: 580, 131, 20, 12
+boy/eye-white-front
+	bounds: 510, 130, 27, 13
+boy/eyebrow-back
+	bounds: 751, 88, 20, 11
+	rotate: 90
+boy/eyebrow-front
+	bounds: 483, 130, 25, 11
+boy/hair-back
+	bounds: 494, 388, 122, 81
+	rotate: 90
+boy/hair-bangs
+	bounds: 667, 284, 70, 37
+boy/hair-side
+	bounds: 789, 374, 25, 43
+boy/hand-backfingers
+	bounds: 467, 364, 19, 21
+boy/hand-front-fingers
+	bounds: 488, 364, 19, 21
+boy/hat
+	bounds: 615, 417, 93, 56
+	rotate: 90
+boy/leg-front
+	bounds: 138, 104, 31, 158
+boy/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+girl-blue-cape/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+girl-spring-dress/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+girl/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+boy/mouth-smile
+	bounds: 705, 79, 29, 7
+boy/nose
+	bounds: 836, 473, 17, 10
+	rotate: 90
+boy/pompom
+	bounds: 747, 273, 48, 43
+	rotate: 90
+boy/zip
+	bounds: 648, 144, 14, 23
+girl-blue-cape/back-eyebrow
+	bounds: 602, 131, 18, 12
+girl-blue-cape/body-dress
+	bounds: 2, 264, 109, 246
+girl-blue-cape/body-ribbon
+	bounds: 615, 283, 50, 38
+girl-blue-cape/cape-back
+	bounds: 2, 69, 134, 193
+girl-blue-cape/cape-back-up
+	bounds: 386, 387, 123, 106
+	rotate: 90
+girl-blue-cape/cape-ribbon
+	bounds: 675, 264, 50, 18
+girl-blue-cape/cape-shoulder-back
+	bounds: 751, 110, 49, 59
+girl-blue-cape/cape-shoulder-front
+	bounds: 113, 264, 62, 76
+	rotate: 90
+girl-blue-cape/cape-up-front
+	bounds: 399, 264, 98, 117
+	rotate: 90
+girl-blue-cape/ear
+	bounds: 775, 2, 19, 23
+girl-spring-dress/ear
+	bounds: 775, 2, 19, 23
+girl/ear
+	bounds: 775, 2, 19, 23
+girl-blue-cape/eye-back-low-eyelid
+	bounds: 802, 463, 17, 6
+girl-spring-dress/eye-back-low-eyelid
+	bounds: 802, 463, 17, 6
+girl/eye-back-low-eyelid
+	bounds: 802, 463, 17, 6
+girl-blue-cape/eye-back-pupil
+	bounds: 816, 367, 8, 9
+girl-spring-dress/eye-back-pupil
+	bounds: 816, 367, 8, 9
+girl/eye-back-pupil
+	bounds: 816, 367, 8, 9
+girl-blue-cape/eye-back-up-eyelid
+	bounds: 554, 131, 24, 12
+girl-spring-dress/eye-back-up-eyelid
+	bounds: 554, 131, 24, 12
+girl/eye-back-up-eyelid
+	bounds: 554, 131, 24, 12
+girl-blue-cape/eye-back-up-eyelid-back
+	bounds: 832, 453, 17, 11
+	rotate: 90
+girl-spring-dress/eye-back-up-eyelid-back
+	bounds: 832, 453, 17, 11
+	rotate: 90
+girl/eye-back-up-eyelid-back
+	bounds: 832, 453, 17, 11
+	rotate: 90
+girl-blue-cape/eye-front-low-eyelid
+	bounds: 739, 303, 18, 6
+	rotate: 90
+girl-spring-dress/eye-front-low-eyelid
+	bounds: 739, 303, 18, 6
+	rotate: 90
+girl/eye-front-low-eyelid
+	bounds: 739, 303, 18, 6
+	rotate: 90
+girl-blue-cape/eye-front-pupil
+	bounds: 816, 378, 9, 9
+girl-spring-dress/eye-front-pupil
+	bounds: 816, 378, 9, 9
+girl/eye-front-pupil
+	bounds: 816, 378, 9, 9
+girl-blue-cape/eye-front-up-eyelid
+	bounds: 392, 77, 30, 14
+	rotate: 90
+girl-spring-dress/eye-front-up-eyelid
+	bounds: 392, 77, 30, 14
+	rotate: 90
+girl/eye-front-up-eyelid
+	bounds: 392, 77, 30, 14
+	rotate: 90
+girl-blue-cape/eye-front-up-eyelid-back
+	bounds: 455, 130, 26, 11
+girl-spring-dress/eye-front-up-eyelid-back
+	bounds: 455, 130, 26, 11
+girl/eye-front-up-eyelid-back
+	bounds: 455, 130, 26, 11
+girl-blue-cape/eye-iris-back
+	bounds: 637, 264, 17, 17
+girl-blue-cape/eye-iris-front
+	bounds: 802, 471, 18, 18
+girl-blue-cape/eye-white-back
+	bounds: 596, 264, 20, 16
+girl-spring-dress/eye-white-back
+	bounds: 596, 264, 20, 16
+girl-blue-cape/eye-white-front
+	bounds: 796, 5, 20, 16
+	rotate: 90
+girl-spring-dress/eye-white-front
+	bounds: 796, 5, 20, 16
+	rotate: 90
+girl/eye-white-front
+	bounds: 796, 5, 20, 16
+	rotate: 90
+girl-blue-cape/front-eyebrow
+	bounds: 608, 149, 18, 12
+	rotate: 90
+girl-blue-cape/hair-back
+	bounds: 508, 145, 117, 98
+	rotate: 90
+girl-blue-cape/hair-bangs
+	bounds: 673, 419, 91, 40
+	rotate: 90
+girl-blue-cape/hair-head-side-back
+	bounds: 196, 331, 30, 52
+	rotate: 90
+girl-blue-cape/hair-head-side-front
+	bounds: 738, 323, 41, 42
+girl-blue-cape/hair-side
+	bounds: 473, 3, 36, 71
+girl-blue-cape/hand-front-fingers
+	bounds: 509, 365, 19, 21
+girl-spring-dress/hand-front-fingers
+	bounds: 509, 365, 19, 21
+girl-blue-cape/leg-front
+	bounds: 168, 72, 30, 158
+	rotate: 90
+girl-blue-cape/mouth-smile
+	bounds: 736, 79, 29, 7
+girl-spring-dress/mouth-smile
+	bounds: 736, 79, 29, 7
+girl/mouth-smile
+	bounds: 736, 79, 29, 7
+girl-blue-cape/nose
+	bounds: 747, 264, 11, 7
+girl-spring-dress/nose
+	bounds: 747, 264, 11, 7
+girl/nose
+	bounds: 747, 264, 11, 7
+girl-blue-cape/sleeve-back
+	bounds: 767, 79, 42, 29
+girl-blue-cape/sleeve-front
+	bounds: 408, 76, 52, 119
+	rotate: 90
+girl-spring-dress/arm-front
+	bounds: 596, 282, 17, 111
+girl-spring-dress/back-eyebrow
+	bounds: 801, 420, 18, 12
+girl-spring-dress/body-up
+	bounds: 179, 4, 64, 66
+girl-spring-dress/cloak-down
+	bounds: 775, 27, 50, 50
+girl-spring-dress/cloak-up
+	bounds: 360, 7, 64, 58
+	rotate: 90
+girl-spring-dress/eye-iris-back
+	bounds: 656, 264, 17, 17
+girl-spring-dress/eye-iris-front
+	bounds: 814, 492, 18, 18
+girl-spring-dress/front-eyebrow
+	bounds: 822, 472, 18, 12
+	rotate: 90
+girl-spring-dress/hair-back
+	bounds: 196, 363, 147, 93
+	rotate: 90
+girl-spring-dress/hair-bangs
+	bounds: 696, 326, 91, 40
+	rotate: 90
+girl-spring-dress/hair-head-side-back
+	bounds: 529, 76, 30, 52
+girl-spring-dress/hair-head-side-front
+	bounds: 781, 323, 41, 42
+girl-spring-dress/hair-side
+	bounds: 511, 3, 36, 71
+girl-spring-dress/leg-front
+	bounds: 171, 104, 30, 158
+girl-spring-dress/neck
+	bounds: 138, 70, 20, 32
+girl-spring-dress/shoulder-ribbon
+	bounds: 622, 131, 36, 24
+	rotate: 90
+girl-spring-dress/skirt
+	bounds: 113, 328, 182, 81
+	rotate: 90
+girl-spring-dress/underskirt
+	bounds: 2, 2, 175, 65
+girl/arm-front
+	bounds: 577, 395, 36, 115
+girl/back-eyebrow
+	bounds: 834, 492, 18, 12
+	rotate: 90
+girl/bag-base
+	bounds: 191, 264, 62, 58
+	rotate: 90
+girl/bag-strap-front
+	bounds: 385, 265, 12, 96
+girl/bag-top
+	bounds: 738, 367, 49, 50
+girl/body
+	bounds: 356, 130, 97, 132
+girl/boot-ribbon-front
+	bounds: 539, 130, 13, 13
+girl/eye-iris-back
+	bounds: 821, 424, 17, 17
+girl/eye-iris-front
+	bounds: 812, 443, 18, 18
+girl/eye-white-back
+	bounds: 814, 5, 20, 16
+	rotate: 90
+girl/front-eyebrow
+	bounds: 816, 400, 18, 12
+	rotate: 90
+girl/hair-back
+	bounds: 291, 363, 147, 93
+	rotate: 90
+girl/hair-bangs
+	bounds: 715, 419, 91, 40
+	rotate: 90
+girl/hair-flap-down-front
+	bounds: 288, 5, 70, 65
+girl/hair-head-side-back
+	bounds: 561, 77, 30, 52
+girl/hair-head-side-front
+	bounds: 757, 419, 41, 42
+	rotate: 90
+girl/hair-patch
+	bounds: 245, 4, 66, 41
+	rotate: 90
+girl/hair-side
+	bounds: 549, 3, 36, 71
+girl/hair-strand-back-1
+	bounds: 684, 3, 58, 74
+girl/hair-strand-back-2
+	bounds: 692, 171, 91, 58
+	rotate: 90
+girl/hair-strand-back-3
+	bounds: 615, 323, 92, 79
+	rotate: 90
+girl/hair-strand-front-1
+	bounds: 518, 269, 38, 94
+girl/hair-strand-front-2
+	bounds: 593, 79, 70, 50
+girl/hair-strand-front-3
+	bounds: 705, 88, 44, 81
+girl/hand-front-fingers
+	bounds: 530, 365, 19, 21
+girl/hat
+	bounds: 608, 169, 93, 82
+	rotate: 90
+girl/leg-front
+	bounds: 203, 104, 30, 158
+girl/pompom
+	bounds: 757, 462, 48, 43
+	rotate: 90
+girl/scarf
+	bounds: 455, 143, 119, 51
+	rotate: 90
+girl/scarf-back
+	bounds: 420, 2, 72, 51
+	rotate: 90
+girl/zip
+	bounds: 356, 109, 19, 25
+	rotate: 90

+ 15 - 0
spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.atlas.import

@@ -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"

BIN
spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.png


+ 34 - 0
spine-godot/example-v4-csharp/assets/mix-and-match/mix-and-match.png.import

@@ -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

+ 15 - 0
spine-godot/example-v4-csharp/assets/raggedyspineboy/Raggedy Spineboy.atlas.import

@@ -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"

+ 34 - 0
spine-godot/example-v4-csharp/assets/raggedyspineboy/Raggedy Spineboy.png.import

@@ -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

+ 8 - 0
spine-godot/example-v4-csharp/assets/raggedyspineboy/raggedy spineboy-res.tres

@@ -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 )

File diff suppressed because it is too large
+ 46 - 0
spine-godot/example-v4-csharp/assets/raggedyspineboy/raggedy spineboy.spine-json


+ 14 - 0
spine-godot/example-v4-csharp/assets/raggedyspineboy/raggedy spineboy.spine-json.import

@@ -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]
+

BIN
spine-godot/example-v4-csharp/assets/raptor/light-sprite.png


+ 34 - 0
spine-godot/example-v4-csharp/assets/raptor/light-sprite.png.import

@@ -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

BIN
spine-godot/example-v4-csharp/assets/raptor/n_raptor.png


+ 34 - 0
spine-godot/example-v4-csharp/assets/raptor/n_raptor.png.import

@@ -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

+ 9 - 0
spine-godot/example-v4-csharp/assets/raptor/raptor-data.tres

@@ -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

BIN
spine-godot/example-v4-csharp/assets/raptor/raptor-pro.skel


+ 14 - 0
spine-godot/example-v4-csharp/assets/raptor/raptor-pro.skel.import

@@ -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]
+

+ 100 - 0
spine-godot/example-v4-csharp/assets/raptor/raptor.atlas

@@ -0,0 +1,100 @@
+raptor.png
+	size: 1024, 512
+	filter: Linear, Linear
+	scale: 0.5
+back-arm
+	bounds: 829, 88, 46, 25
+	rotate: 90
+back-bracer
+	bounds: 195, 238, 39, 28
+	rotate: 90
+back-hand
+	bounds: 724, 140, 36, 34
+	rotate: 90
+back-knee
+	bounds: 760, 131, 49, 67
+	rotate: 90
+back-thigh
+	bounds: 225, 238, 39, 24
+	rotate: 90
+eyes-open
+	bounds: 975, 204, 47, 45
+front-arm
+	bounds: 969, 112, 48, 26
+front-bracer
+	bounds: 724, 97, 41, 29
+	rotate: 90
+front-hand
+	bounds: 251, 239, 41, 38
+front-open-hand
+	bounds: 856, 76, 43, 44
+	rotate: 90
+front-thigh
+	bounds: 729, 178, 57, 29
+	rotate: 90
+gun
+	bounds: 894, 251, 107, 103
+gun-nohand
+	bounds: 764, 241, 105, 102
+head
+	bounds: 756, 345, 136, 149
+lower-leg
+	bounds: 475, 237, 73, 98
+	rotate: 90
+mouth-grind
+	bounds: 975, 172, 47, 30
+mouth-smile
+	bounds: 975, 140, 47, 30
+neck
+	bounds: 366, 282, 18, 21
+raptor-back-arm
+	bounds: 636, 97, 82, 86
+	rotate: 90
+raptor-body
+	bounds: 2, 2, 632, 233
+raptor-front-arm
+	bounds: 871, 168, 81, 102
+	rotate: 90
+raptor-front-leg
+	bounds: 2, 237, 191, 257
+raptor-hindleg-back
+	bounds: 195, 279, 169, 215
+raptor-horn
+	bounds: 431, 312, 182, 80
+	rotate: 90
+raptor-horn-back
+	bounds: 513, 318, 176, 77
+	rotate: 90
+raptor-jaw
+	bounds: 894, 356, 126, 138
+raptor-jaw-tooth
+	bounds: 294, 240, 37, 48
+	rotate: 90
+raptor-mouth-inside
+	bounds: 344, 241, 36, 41
+	rotate: 90
+raptor-saddle-strap-back
+	bounds: 575, 242, 54, 74
+raptor-saddle-strap-front
+	bounds: 764, 182, 57, 95
+	rotate: 90
+raptor-saddle-w-shadow
+	bounds: 592, 323, 162, 171
+raptor-tail-shadow
+	bounds: 366, 305, 189, 63
+	rotate: 90
+raptor-tongue
+	bounds: 387, 239, 86, 64
+stirrup-back
+	bounds: 829, 136, 44, 35
+	rotate: 90
+stirrup-front
+	bounds: 866, 121, 45, 50
+	rotate: 90
+stirrup-strap
+	bounds: 918, 120, 49, 46
+torso
+	bounds: 636, 181, 54, 91
+	rotate: 90
+visor
+	bounds: 631, 237, 131, 84

+ 15 - 0
spine-godot/example-v4-csharp/assets/raptor/raptor.atlas.import

@@ -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"

BIN
spine-godot/example-v4-csharp/assets/raptor/raptor.png


+ 34 - 0
spine-godot/example-v4-csharp/assets/raptor/raptor.png.import

@@ -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

+ 20 - 0
spine-godot/example-v4-csharp/assets/spineboy/spineboy-data-res.tres

@@ -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")]

BIN
spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.skel


+ 14 - 0
spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.skel.import

@@ -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
+ 541 - 0
spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.spine-json


+ 14 - 0
spine-godot/example-v4-csharp/assets/spineboy/spineboy-pro.spine-json.import

@@ -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]
+

+ 101 - 0
spine-godot/example-v4-csharp/assets/spineboy/spineboy.atlas

@@ -0,0 +1,101 @@
+spineboy.png
+	size: 1024, 256
+	filter: Linear, Linear
+	scale: 0.5
+crosshair
+	bounds: 813, 160, 45, 45
+eye-indifferent
+	bounds: 569, 2, 47, 45
+eye-surprised
+	bounds: 643, 7, 47, 45
+	rotate: 90
+front-bracer
+	bounds: 811, 51, 29, 40
+front-fist-closed
+	bounds: 807, 93, 38, 41
+front-fist-open
+	bounds: 815, 210, 43, 44
+front-foot
+	bounds: 706, 64, 63, 35
+	rotate: 90
+front-shin
+	bounds: 80, 11, 41, 92
+front-thigh
+	bounds: 754, 12, 23, 56
+front-upper-arm
+	bounds: 618, 5, 23, 49
+goggles
+	bounds: 214, 20, 131, 83
+gun
+	bounds: 347, 14, 105, 102
+	rotate: 90
+head
+	bounds: 80, 105, 136, 149
+hoverboard-board
+	bounds: 2, 8, 246, 76
+	rotate: 90
+hoverboard-thruster
+	bounds: 478, 2, 30, 32
+hoverglow-small
+	bounds: 218, 117, 137, 38
+	rotate: 90
+mouth-grind
+	bounds: 775, 80, 47, 30
+	rotate: 90
+mouth-oooo
+	bounds: 779, 31, 47, 30
+	rotate: 90
+mouth-smile
+	bounds: 783, 207, 47, 30
+	rotate: 90
+muzzle-glow
+	bounds: 779, 4, 25, 25
+muzzle-ring
+	bounds: 451, 14, 25, 105
+muzzle01
+	bounds: 664, 60, 67, 40
+	rotate: 90
+muzzle02
+	bounds: 580, 56, 68, 42
+	rotate: 90
+muzzle03
+	bounds: 478, 36, 83, 53
+	rotate: 90
+muzzle04
+	bounds: 533, 49, 75, 45
+	rotate: 90
+muzzle05
+	bounds: 624, 56, 68, 38
+	rotate: 90
+neck
+	bounds: 806, 8, 18, 21
+portal-bg
+	bounds: 258, 121, 133, 133
+portal-flare1
+	bounds: 690, 2, 56, 30
+	rotate: 90
+portal-flare2
+	bounds: 510, 3, 57, 31
+portal-flare3
+	bounds: 722, 4, 58, 30
+	rotate: 90
+portal-shade
+	bounds: 393, 121, 133, 133
+portal-streaks1
+	bounds: 528, 126, 126, 128
+portal-streaks2
+	bounds: 656, 129, 125, 125
+rear-bracer
+	bounds: 826, 13, 28, 36
+rear-foot
+	bounds: 743, 70, 57, 30
+	rotate: 90
+rear-shin
+	bounds: 174, 14, 38, 89
+rear-thigh
+	bounds: 783, 158, 28, 47
+rear-upper-arm
+	bounds: 783, 136, 20, 44
+	rotate: 90
+torso
+	bounds: 123, 13, 49, 90

+ 15 - 0
spine-godot/example-v4-csharp/assets/spineboy/spineboy.atlas.import

@@ -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"

BIN
spine-godot/example-v4-csharp/assets/spineboy/spineboy.png


+ 34 - 0
spine-godot/example-v4-csharp/assets/spineboy/spineboy.png.import

@@ -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

+ 7 - 0
spine-godot/example-v4-csharp/default_env.tres

@@ -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 )

+ 8 - 0
spine-godot/example-v4-csharp/examples/01-helloworld/Spineboy.cs

@@ -0,0 +1,8 @@
+using Godot;
+using System;
+
+public partial class Spineboy : SpineSprite {
+	public override void _Ready() {
+		GetAnimationState().SetAnimation("run", true, 0);
+	}
+}

+ 19 - 0
spine-godot/example-v4-csharp/examples/01-helloworld/helloworld.tscn

@@ -0,0 +1,19 @@
+[gd_scene load_steps=3 format=3 uid="uid://d0v5rhv2ysej8"]
+
+[ext_resource type="Script" path="res://examples/01-helloworld/Spineboy.cs" id="2_2c2a7"]
+[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("2_2c2a7")

+ 43 - 0
spine-godot/example-v4-csharp/examples/02-animation-state-listeners/AnimationStateListener.cs

@@ -0,0 +1,43 @@
+using Godot;
+using System;
+
+public partial class AnimationStateListener : Node2D
+{
+	public override void _Ready()
+	{
+		var footStepAudio = GetNode<AudioStreamPlayer>("FootstepAudio");
+		var spineboy = GetNode<SpineSprite>("Spineboy");
+		spineboy.AnimationStarted += (sprite, animationState, trackEntry) =>
+		{
+			var spineTrackEntry = trackEntry as SpineTrackEntry;
+			Console.WriteLine("Animation started: " + spineTrackEntry.GetAnimation().GetName());
+		};
+		spineboy.AnimationInterrupted += (sprite, animationState, trackEntry) =>
+		{
+			var spineTrackEntry = trackEntry as SpineTrackEntry;
+			Console.WriteLine("Animation interrupted: " + spineTrackEntry.GetAnimation().GetName());
+		};
+		spineboy.AnimationCompleted += (sprite, animationState, trackEntry) =>
+		{
+			var spineTrackEntry = trackEntry as SpineTrackEntry;
+			Console.WriteLine("Animation completed: " + spineTrackEntry.GetAnimation().GetName());
+		};
+		spineboy.AnimationDisposed += (sprite, animationState, trackEntry) =>
+		{
+			var spineTrackEntry = trackEntry as SpineTrackEntry;
+			Console.WriteLine("Animation disposed: " + spineTrackEntry.GetAnimation().GetName());
+		};
+		spineboy.AnimationEvent += (sprite, animationState, trackEntry, eventObject) =>
+		{
+			var spineTrackEntry = trackEntry as SpineTrackEntry;
+			var spineEvent = eventObject as SpineEvent;
+			Console.WriteLine("Animation event: " + spineTrackEntry.GetAnimation().GetName() + ", " + spineEvent.GetData().GetEventName());
+			if (spineEvent.GetData().GetEventName() == "footstep")
+				footStepAudio.Play();
+		};
+		var animationState = spineboy.GetAnimationState();
+		animationState.SetAnimation("jump", false, 0);
+		animationState.AddAnimation("walk", 0, true, 0);
+		animationState.AddAnimation("run", 2, true, 0);
+	}
+}

+ 20 - 0
spine-godot/example-v4-csharp/examples/02-animation-state-listeners/animation-state-listeners.tscn

@@ -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/AnimationStateListener.cs" id="1_cedgs"]
+[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_cedgs")
+
+[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")

+ 29 - 0
spine-godot/example-v4-csharp/examples/03-mix-and-match/MixAndMatch.cs

@@ -0,0 +1,29 @@
+using Godot;
+using System;
+
+public partial class MixAndMatch : SpineSprite
+{
+	public override void _Ready()
+	{
+		var data = GetSkeleton().GetData();
+		var custom_skin = NewSkin("custom-skin");
+		var skin_base = data.FindSkin("skin-base");
+		custom_skin.AddSkin(skin_base);
+		custom_skin.AddSkin(data.FindSkin("nose/short"));
+		custom_skin.AddSkin(data.FindSkin("eyelids/girly"));
+		custom_skin.AddSkin(data.FindSkin("eyes/violet"));
+		custom_skin.AddSkin(data.FindSkin("hair/brown"));
+		custom_skin.AddSkin(data.FindSkin("clothes/hoodie-orange"));
+		custom_skin.AddSkin(data.FindSkin("legs/pants-jeans"));
+		custom_skin.AddSkin(data.FindSkin("accessories/bag"));
+		custom_skin.AddSkin(data.FindSkin("accessories/hat-red-yellow"));
+		GetSkeleton().SetSkin(custom_skin);
+
+		foreach (SpineSkinEntry entry in custom_skin.GetAttachments())
+		{
+			Console.WriteLine(entry.GetSlotIndex() + " " + entry.GetName());
+		}
+
+		GetAnimationState().SetAnimation("dance", true, 0);
+	}
+}

+ 16 - 0
spine-godot/example-v4-csharp/examples/03-mix-and-match/mix-and-match.tscn

@@ -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/MixAndMatch.cs" id="2_80tsf"]
+
+[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_80tsf")

+ 33 - 0
spine-godot/example-v4-csharp/examples/04-simple-input/SpineboyInput.cs

@@ -0,0 +1,33 @@
+using Godot;
+using System;
+
+public partial class SpineboyInput : SpineSprite
+{
+	// Called when the node enters the scene tree for the first time.
+	public override void _Ready()
+	{
+		GetAnimationState().SetAnimation("idle", true, 0);
+	}
+
+	// Called every frame. 'delta' is the elapsed time since the previous frame.
+	public override void _Process(double delta)
+	{
+		if (Input.IsActionJustPressed("ui_left"))
+		{
+			GetAnimationState().SetAnimation("run", true, 0);
+			GetSkeleton().SetScaleX(-1);
+		}
+
+		if (Input.IsActionJustReleased("ui_left"))
+			GetAnimationState().SetAnimation("idle", true, 0);
+
+		if (Input.IsActionJustPressed("ui_right"))
+		{
+			GetAnimationState().SetAnimation("run", true, 0);
+			GetSkeleton().SetScaleX(1);
+		}
+
+		if (Input.IsActionJustReleased("ui_right"))
+			GetAnimationState().SetAnimation("idle", true, 0);
+	}
+}

+ 16 - 0
spine-godot/example-v4-csharp/examples/04-simple-input/simple-input.tscn

@@ -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/SpineboyInput.cs" id="2_4ryek"]
+
+[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_4ryek")

+ 22 - 0
spine-godot/example-v4-csharp/examples/05-mouse-following/MouseFollowing.cs

@@ -0,0 +1,22 @@
+using Godot;
+using System;
+
+public partial class MouseFollowing : Node2D
+{
+	private SpineSprite spineboy;
+
+	private SpineBoneNode crosshairBonne;
+	
+	public override void _Ready()
+	{
+		spineboy = GetNode<SpineSprite>("Spineboy");
+		crosshairBonne = spineboy.GetNode<SpineBoneNode>("CrosshairBone");
+		spineboy.GetAnimationState().SetAnimation("walk", true, 0);
+		spineboy.GetAnimationState().SetAnimation("aim", true, 1);
+	}
+	
+	public override void _Process(double delta)
+	{
+		crosshairBonne.GlobalPosition = GetViewport().GetMousePosition();
+	}
+}

+ 23 - 0
spine-godot/example-v4-csharp/examples/05-mouse-following/mouse-following.tscn

@@ -0,0 +1,23 @@
+[gd_scene load_steps=3 format=3 uid="uid://borp2l17n5xw1"]
+
+[ext_resource type="Script" path="res://examples/05-mouse-following/MouseFollowing.cs" id="1_sgiuf"]
+[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_sgiuf")
+
+[node name="Spineboy" type="SpineSprite" parent="."]
+position = Vector2(481, 457)
+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

+ 10 - 0
spine-godot/example-v4-csharp/examples/06-bone-following/BoneFollowing.cs

@@ -0,0 +1,10 @@
+using Godot;
+using System;
+
+public partial class BoneFollowing : Node2D
+{
+	public override void _Ready()
+	{
+		GetNode<SpineSprite>("Spineboy").GetAnimationState().SetAnimation("walk", true, 0);
+	}
+}

+ 27 - 0
spine-godot/example-v4-csharp/examples/06-bone-following/bone-following.tscn

@@ -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/BoneFollowing.cs" id="1_2vlen"]
+[ext_resource type="Texture2D" uid="uid://8ud5n2ywp5ba" path="res://icon.png" id="3"]
+
+[node name="Node2D" type="Node2D"]
+script = ExtResource("1_2vlen")
+
+[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")

+ 17 - 0
spine-godot/example-v4-csharp/examples/07-slot-node/SlotNode.cs

@@ -0,0 +1,17 @@
+using Godot;
+using System;
+
+public partial class SlotNode : Node2D
+{
+	public override void _Ready()
+	{
+		SpineSprite spineboy = GetNode<SpineSprite>("Spineboy");
+		SpineSprite raptor = GetNode<SpineSprite>("Spineboy/GunSlot/Raptor");
+		SpineSprite tinySpineboy = GetNode<SpineSprite>("Spineboy/FrontFirstSlot/TinySpineboy");
+
+		var entry = spineboy.GetAnimationState().SetAnimation("run", true, 0);
+		entry.SetTimeScale(0.1f);
+		raptor.GetAnimationState().SetAnimation("walk", true, 0);
+		tinySpineboy.GetAnimationState().SetAnimation("walk", true, 0);
+	}
+}

+ 62 - 0
spine-godot/example-v4-csharp/examples/07-slot-node/slot-node.tscn

@@ -0,0 +1,62 @@
+[gd_scene load_steps=5 format=3 uid="uid://bhht8dees2pyq"]
+
+[ext_resource type="Script" path="res://examples/07-slot-node/SlotNode.cs" id="1_8cn0r"]
+[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_8cn0r")
+
+[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.8753, -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
+scale = Vector2(1, 1)
+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

+ 52 - 0
spine-godot/example-v4-csharp/examples/08-animation-player/PlayCutscene.cs

@@ -0,0 +1,52 @@
+using Godot;
+using System;
+
+public partial class PlayCutscene : Node2D
+{
+	AnimationPlayer player;
+	SpineSprite spineboy;
+	float speed = 400;
+	float velocityX = 0;
+		
+	public override void _Ready()
+	{
+		player = GetNode<AnimationPlayer>("AnimationPlayer");
+		player.Play("cutscene");
+		spineboy = GetNode<SpineSprite>("Spineboy");
+	}
+	
+	public override void _Process(double delta)
+	{
+		if (player.IsPlaying()) return;
+		
+		if (Input.IsActionJustPressed("ui_left"))
+		{
+			spineboy.GetAnimationState().SetAnimation("run", true, 0);
+			spineboy.GetSkeleton().SetScaleX(-1);
+			velocityX = -1;
+		}
+
+		if (Input.IsActionJustReleased("ui_left"))
+		{
+			spineboy.GetAnimationState().SetAnimation("idle", true, 0);
+			velocityX = 0;
+		}
+
+		if (Input.IsActionJustPressed("ui_right"))
+		{
+			spineboy.GetAnimationState().SetAnimation("run", true, 0);
+			spineboy.GetSkeleton().SetScaleX(1);
+			velocityX = 1;
+		}
+
+		if (Input.IsActionJustReleased("ui_right"))
+		{
+			spineboy.GetAnimationState().SetAnimation("idle", true, 0);
+			velocityX = 0;
+		}
+
+		var newPosition = spineboy.Position;
+		newPosition.X += velocityX * speed * (float)delta;
+		spineboy.Position = newPosition;
+	}
+}

+ 1944 - 0
spine-godot/example-v4-csharp/examples/08-animation-player/animation-player.tscn

@@ -0,0 +1,1944 @@
+[gd_scene load_steps=68 format=3 uid="uid://dmddd1ll1y0bm"]
+
+[ext_resource type="SpineSkeletonDataResource" uid="uid://cb6rn6vonqbx0" path="res://assets/spineboy/spineboy-data-res.tres" id="1"]
+[ext_resource type="Script" path="res://examples/08-animation-player/PlayCutscene.cs" id="1_sfb8c"]
+[ext_resource type="SpineSkeletonDataResource" path="res://assets/raptor/raptor-data.tres" id="3"]
+
+[sub_resource type="Animation" id="Animation_0w4l6"]
+resource_name = "aim_looped"
+length = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["aim"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_ypp0f"]
+resource_name = "aim"
+length = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["aim"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_ro717"]
+resource_name = "death_looped"
+length = 4.9333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["death"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_eu7ym"]
+resource_name = "death"
+length = 4.9333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["death"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_0b0od"]
+resource_name = "hoverboard_looped"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["hoverboard"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_ere4j"]
+resource_name = "hoverboard"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["hoverboard"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_3t75h"]
+resource_name = "idle_looped"
+length = 1.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_0medg"]
+resource_name = "idle"
+length = 1.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_08xgr"]
+resource_name = "idle-turn_looped"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle-turn"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_srxvc"]
+resource_name = "idle-turn"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle-turn"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_dr83r"]
+resource_name = "jump_looped"
+length = 1.3333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["jump"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_4fl4p"]
+resource_name = "jump"
+length = 1.3333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["jump"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_jjgv6"]
+resource_name = "portal_looped"
+length = 3.1667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["portal"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_wjuhv"]
+resource_name = "portal"
+length = 3.1667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["portal"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_gkssb"]
+resource_name = "run_looped"
+length = 0.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_66ili"]
+resource_name = "run"
+length = 0.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_fntjy"]
+resource_name = "run-to-idle_looped"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run-to-idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_g7jj5"]
+resource_name = "run-to-idle"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run-to-idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_eoc38"]
+resource_name = "shoot_looped"
+length = 0.6333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["shoot"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_y5wex"]
+resource_name = "shoot"
+length = 0.6333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["shoot"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_mlycr"]
+resource_name = "walk_looped"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["walk"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_0dh1n"]
+resource_name = "walk"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["walk"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_caogd"]
+resource_name = "RESET"
+length = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [""]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_foxls"]
+_data = {
+"-- Empty --": SubResource("Animation_caogd"),
+"RESET": SubResource("Animation_caogd"),
+"aim": SubResource("Animation_ypp0f"),
+"aim_looped": SubResource("Animation_0w4l6"),
+"death": SubResource("Animation_eu7ym"),
+"death_looped": SubResource("Animation_ro717"),
+"hoverboard": SubResource("Animation_ere4j"),
+"hoverboard_looped": SubResource("Animation_0b0od"),
+"idle": SubResource("Animation_0medg"),
+"idle-turn": SubResource("Animation_srxvc"),
+"idle-turn_looped": SubResource("Animation_08xgr"),
+"idle_looped": SubResource("Animation_3t75h"),
+"jump": SubResource("Animation_4fl4p"),
+"jump_looped": SubResource("Animation_dr83r"),
+"portal": SubResource("Animation_wjuhv"),
+"portal_looped": SubResource("Animation_jjgv6"),
+"run": SubResource("Animation_66ili"),
+"run-to-idle": SubResource("Animation_g7jj5"),
+"run-to-idle_looped": SubResource("Animation_fntjy"),
+"run_looped": SubResource("Animation_gkssb"),
+"shoot": SubResource("Animation_y5wex"),
+"shoot_looped": SubResource("Animation_eoc38"),
+"walk": SubResource("Animation_0dh1n"),
+"walk_looped": SubResource("Animation_mlycr")
+}
+
+[sub_resource type="Animation" id="Animation_8oucm"]
+resource_name = "aim_looped"
+length = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["aim"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_awb25"]
+resource_name = "aim"
+length = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["aim"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_ua7q4"]
+resource_name = "death_looped"
+length = 4.9333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["death"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_qkjth"]
+resource_name = "death"
+length = 4.9333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["death"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_nk1ja"]
+resource_name = "hoverboard_looped"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["hoverboard"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_5ump1"]
+resource_name = "hoverboard"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["hoverboard"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_r65d1"]
+resource_name = "idle_looped"
+length = 1.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_v5cis"]
+resource_name = "idle"
+length = 1.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_ekfrt"]
+resource_name = "idle-turn_looped"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle-turn"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_i7uvx"]
+resource_name = "idle-turn"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["idle-turn"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_h7d1m"]
+resource_name = "jump_looped"
+length = 1.3333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["jump"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_p00wv"]
+resource_name = "jump"
+length = 1.3333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["jump"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_h28vd"]
+resource_name = "portal_looped"
+length = 3.1667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["portal"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_7n3cr"]
+resource_name = "portal"
+length = 3.1667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["portal"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_narkj"]
+resource_name = "run_looped"
+length = 0.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_f0l7r"]
+resource_name = "run"
+length = 0.6667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_tqo2u"]
+resource_name = "run-to-idle_looped"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run-to-idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_s4idr"]
+resource_name = "run-to-idle"
+length = 0.2667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["run-to-idle"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_u87bq"]
+resource_name = "shoot_looped"
+length = 0.6333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["shoot"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_p08dp"]
+resource_name = "shoot"
+length = 0.6333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["shoot"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_mras8"]
+resource_name = "walk_looped"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["walk"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_1kvym"]
+resource_name = "walk"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["walk"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_1epbr"]
+resource_name = "RESET"
+length = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [""]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_x5gja"]
+_data = {
+"-- Empty --": SubResource("Animation_1epbr"),
+"RESET": SubResource("Animation_1epbr"),
+"aim": SubResource("Animation_awb25"),
+"aim_looped": SubResource("Animation_8oucm"),
+"death": SubResource("Animation_qkjth"),
+"death_looped": SubResource("Animation_ua7q4"),
+"hoverboard": SubResource("Animation_5ump1"),
+"hoverboard_looped": SubResource("Animation_nk1ja"),
+"idle": SubResource("Animation_v5cis"),
+"idle-turn": SubResource("Animation_i7uvx"),
+"idle-turn_looped": SubResource("Animation_ekfrt"),
+"idle_looped": SubResource("Animation_r65d1"),
+"jump": SubResource("Animation_p00wv"),
+"jump_looped": SubResource("Animation_h7d1m"),
+"portal": SubResource("Animation_7n3cr"),
+"portal_looped": SubResource("Animation_h28vd"),
+"run": SubResource("Animation_f0l7r"),
+"run-to-idle": SubResource("Animation_s4idr"),
+"run-to-idle_looped": SubResource("Animation_tqo2u"),
+"run_looped": SubResource("Animation_narkj"),
+"shoot": SubResource("Animation_p08dp"),
+"shoot_looped": SubResource("Animation_u87bq"),
+"walk": SubResource("Animation_1kvym"),
+"walk_looped": SubResource("Animation_mras8")
+}
+
+[sub_resource type="Animation" id="Animation_7c84c"]
+resource_name = "gun-grab_looped"
+length = 0.666667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["gun-grab"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_fb0wh"]
+resource_name = "gun-grab"
+length = 0.666667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["gun-grab"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_h2sun"]
+resource_name = "gun-holster_looped"
+length = 0.666667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["gun-holster"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_jllc7"]
+resource_name = "gun-holster"
+length = 0.666667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["gun-holster"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_d0xy4"]
+resource_name = "jump_looped"
+length = 1.53333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["jump"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_junop"]
+resource_name = "jump"
+length = 1.53333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["jump"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_g8fnf"]
+resource_name = "roar_looped"
+length = 2.13333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["roar"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_wujnd"]
+resource_name = "roar"
+length = 2.13333
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["roar"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_q37yj"]
+resource_name = "walk_looped"
+length = 1.26667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["walk"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [true]
+}
+
+[sub_resource type="Animation" id="Animation_kv7gf"]
+resource_name = "walk"
+length = 1.26667
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": ["walk"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="Animation" id="Animation_3x4j7"]
+resource_name = "RESET"
+length = 0.5
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:animation_name")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [""]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath(".:loop")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [false]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_i0k7e"]
+_data = {
+"-- Empty --": SubResource("Animation_3x4j7"),
+"RESET": SubResource("Animation_3x4j7"),
+"gun-grab": SubResource("Animation_fb0wh"),
+"gun-grab_looped": SubResource("Animation_7c84c"),
+"gun-holster": SubResource("Animation_jllc7"),
+"gun-holster_looped": SubResource("Animation_h2sun"),
+"jump": SubResource("Animation_junop"),
+"jump_looped": SubResource("Animation_d0xy4"),
+"roar": SubResource("Animation_wujnd"),
+"roar_looped": SubResource("Animation_g8fnf"),
+"walk": SubResource("Animation_kv7gf"),
+"walk_looped": SubResource("Animation_q37yj")
+}
+
+[sub_resource type="Animation" id="25"]
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("Spineboy:position")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(72.0001, 520)]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Raptor:position")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(1284, 520)]
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Spineboy/SpineAnimationTrack:mix_duration")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [-1.0]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("Spineboy/SpineAnimationTrack:reverse")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [false]
+}
+tracks/4/type = "value"
+tracks/4/imported = false
+tracks/4/enabled = true
+tracks/4/path = NodePath("Raptor/SpineAnimationTrack:mix_duration")
+tracks/4/interp = 1
+tracks/4/loop_wrap = true
+tracks/4/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [-1.0]
+}
+tracks/5/type = "value"
+tracks/5/imported = false
+tracks/5/enabled = true
+tracks/5/path = NodePath("Spineboy/SpineAnimationTrack:time_scale")
+tracks/5/interp = 1
+tracks/5/loop_wrap = true
+tracks/5/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [1.0]
+}
+
+[sub_resource type="Animation" id="1"]
+resource_name = "cutscene"
+length = 10.0
+step = 0.02
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("Spineboy:position")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 4, 10),
+"transitions": PackedFloat32Array(1, 1, 1),
+"update": 0,
+"values": [Vector2(72.0001, 520), Vector2(500, 520), Vector2(500, 520)]
+}
+tracks/1/type = "animation"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Spineboy/SpineAnimationTrack/Spineboy Track 0")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"clips": PackedStringArray("walk_looped", "idle", "death", "idle"),
+"times": PackedFloat32Array(0, 4, 4.34, 8.86)
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Spineboy/SpineAnimationTrack2:mix_duration")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [0.1]
+}
+tracks/3/type = "animation"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("Spineboy/SpineAnimationTrack2/Spineboy Track 1")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"clips": PackedStringArray("-- Empty --", "aim", "-- Empty --"),
+"times": PackedFloat32Array(0.14, 2.5, 3.94)
+}
+tracks/4/type = "value"
+tracks/4/imported = false
+tracks/4/enabled = true
+tracks/4/path = NodePath("Raptor:position")
+tracks/4/interp = 1
+tracks/4/loop_wrap = true
+tracks/4/keys = {
+"times": PackedFloat32Array(0, 2.02, 3.7, 10),
+"transitions": PackedFloat32Array(1, 1, 1, 1),
+"update": 0,
+"values": [Vector2(1284, 520), Vector2(1284, 520), Vector2(750, 520), Vector2(750, 520)]
+}
+tracks/5/type = "animation"
+tracks/5/imported = false
+tracks/5/enabled = true
+tracks/5/path = NodePath("Raptor/SpineAnimationTrack/Raptor Track 0")
+tracks/5/interp = 1
+tracks/5/loop_wrap = true
+tracks/5/keys = {
+"clips": PackedStringArray("walk_looped", "roar_looped", "-- Empty --"),
+"times": PackedFloat32Array(0.46, 3.7, 9.64)
+}
+tracks/6/type = "value"
+tracks/6/imported = false
+tracks/6/enabled = true
+tracks/6/path = NodePath("Spineboy/SpineAnimationTrack:mix_duration")
+tracks/6/interp = 1
+tracks/6/loop_wrap = true
+tracks/6/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [0.2]
+}
+tracks/7/type = "value"
+tracks/7/imported = false
+tracks/7/enabled = true
+tracks/7/path = NodePath("Raptor/SpineAnimationTrack:mix_duration")
+tracks/7/interp = 1
+tracks/7/loop_wrap = true
+tracks/7/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [0.2]
+}
+
+[sub_resource type="Animation" id="83"]
+resource_name = "slow-moonwalk"
+length = 5.0
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("Spineboy:position")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 5),
+"transitions": PackedFloat32Array(1, 1),
+"update": 0,
+"values": [Vector2(905, 565), Vector2(70, 565)]
+}
+tracks/1/type = "animation"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("Spineboy/SpineAnimationTrack/Spineboy Track 0")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"clips": PackedStringArray("walk_looped"),
+"times": PackedFloat32Array(0)
+}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("Spineboy/SpineAnimationTrack:reverse")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [true]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("Spineboy/SpineAnimationTrack:time_scale")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [0.5]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_3lgey"]
+_data = {
+"RESET": SubResource("25"),
+"cutscene": SubResource("1"),
+"slow-moonwalk": SubResource("83")
+}
+
+[node name="Node2D2" type="Node2D"]
+script = ExtResource("1_sfb8c")
+
+[node name="Spineboy" type="SpineSprite" parent="."]
+position = Vector2(72.0001, 520)
+scale = Vector2(0.323942, 0.323942)
+skeleton_data_res = ExtResource("1")
+preview_skin = "Default"
+preview_animation = "-- Empty --"
+preview_frame = false
+preview_time = 0.0
+
+[node name="SpineAnimationTrack" type="SpineAnimationTrack" parent="Spineboy"]
+track_index = 0
+debug = true
+
+[node name="Spineboy Track 0" type="AnimationPlayer" parent="Spineboy/SpineAnimationTrack"]
+libraries = {
+"": SubResource("AnimationLibrary_foxls")
+}
+
+[node name="SpineAnimationTrack2" type="SpineAnimationTrack" parent="Spineboy"]
+track_index = 1
+mix_duration = 0.1
+debug = true
+
+[node name="Spineboy Track 1" type="AnimationPlayer" parent="Spineboy/SpineAnimationTrack2"]
+libraries = {
+"": SubResource("AnimationLibrary_x5gja")
+}
+
+[node name="Raptor" type="SpineSprite" parent="."]
+position = Vector2(1284, 520)
+scale = Vector2(-0.328761, 0.328761)
+skeleton_data_res = ExtResource("3")
+preview_skin = "Default"
+preview_animation = "-- Empty --"
+preview_frame = false
+preview_time = 0.0
+
+[node name="SpineAnimationTrack" type="SpineAnimationTrack" parent="Raptor"]
+track_index = 0
+
+[node name="Raptor Track 0" type="AnimationPlayer" parent="Raptor/SpineAnimationTrack"]
+libraries = {
+"": SubResource("AnimationLibrary_i0k7e")
+}
+
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
+libraries = {
+"": SubResource("AnimationLibrary_3lgey")
+}

+ 45 - 0
spine-godot/example-v4-csharp/examples/09-custom-material/custom-material.tscn

@@ -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")

+ 27 - 0
spine-godot/example-v4-csharp/examples/10-2d-lighting/2d-lighting.tscn

@@ -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="Script" path="res://examples/10-2d-lighting/Lighting.cs" id="1_cdnty"]
+[ext_resource type="Texture2D" uid="uid://cggfs567rn1ay" path="res://assets/raptor/light-sprite.png" id="2"]
+
+[node name="Node2D" type="Node2D"]
+script = ExtResource("1_cdnty")
+
+[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)

+ 10 - 0
spine-godot/example-v4-csharp/examples/10-2d-lighting/Lighting.cs

@@ -0,0 +1,10 @@
+using Godot;
+using System;
+
+public partial class Lighting : Node2D
+{	
+	public override void _Ready()
+	{
+		GetNode<SpineSprite>("SpineSprite").GetAnimationState().SetAnimation("walk", true, 0);
+	}
+}

+ 54 - 0
spine-godot/example-v4-csharp/examples/11-bone-node/BoneNode.cs

@@ -0,0 +1,54 @@
+using Godot;
+using System;
+
+public partial class BoneNode : Node2D
+{
+	private SpineSprite spineboy;
+	private SpineBoneNode centerBone;
+	private RayCast2D centerRay;
+	private SpineBoneNode targetBone;
+	private RayCast2D targetRay;
+	private SpineBoneNode hipBone;
+	private float centerHipDistance = 0;
+	
+	public override void _Ready()
+	{
+		spineboy = GetNode<SpineSprite>("SpineSprite");
+		centerBone = GetNode<SpineBoneNode>("SpineSprite/HoverboardCenterBone");
+		centerRay = GetNode<RayCast2D>("SpineSprite/HoverboardCenterBone/CenterRay");
+		targetBone = GetNode<SpineBoneNode>("SpineSprite/HoverboardTargetBone");
+		targetRay = GetNode<RayCast2D>("SpineSprite/HoverboardTargetBone/TargetRay");
+		hipBone = GetNode<SpineBoneNode>("SpineSprite/HipBone");
+		spineboy.GetAnimationState().SetAnimation("hoverboard", true, 0);
+		spineboy.UpdateSkeleton(0);
+		centerHipDistance = hipBone.GlobalPosition.Y - centerBone.GlobalPosition.Y;
+	}
+	
+	public override void _Process(double delta) 
+	{
+		if (targetRay.IsColliding())
+		{
+			var newPosition = targetBone.GlobalPosition;
+			newPosition.Y = targetRay.GetCollisionPoint().Y - 30;
+			targetBone.Position = newPosition;
+		}
+		
+		if (centerRay.IsColliding())
+		{
+			var newPosition = centerBone.GlobalPosition;
+			newPosition.Y = centerRay.GetCollisionPoint().Y - 30;
+			centerBone.Position = newPosition;
+		}
+
+		if (Math.Abs(hipBone.GlobalPosition.Y - centerBone.GlobalPosition.Y) - Math.Abs(centerHipDistance) < 20)
+		{
+			var newPosition = hipBone.GlobalPosition;
+			newPosition.Y = centerBone.GlobalPosition.Y + centerHipDistance;
+			hipBone.Position = newPosition;
+		}
+
+		var position = spineboy.GlobalPosition;
+		position.X += (float)delta * 150;
+		spineboy.GlobalPosition = position;
+	}
+}

+ 53 - 0
spine-godot/example-v4-csharp/examples/11-bone-node/bone-node.tscn

@@ -0,0 +1,53 @@
+[gd_scene load_steps=3 format=3 uid="uid://chrw4i0nksphn"]
+
+[ext_resource type="Script" path="res://examples/11-bone-node/BoneNode.cs" id="1_sspn4"]
+[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_sspn4")
+
+[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)

BIN
spine-godot/example-v4-csharp/godot-nuget/Godot.NET.Sdk.4.1.1.nupkg


BIN
spine-godot/example-v4-csharp/godot-nuget/Godot.SourceGenerators.4.1.1.nupkg


BIN
spine-godot/example-v4-csharp/godot-nuget/GodotSharp.4.1.1.nupkg


BIN
spine-godot/example-v4-csharp/godot-nuget/GodotSharp.4.1.1.snupkg


BIN
spine-godot/example-v4-csharp/godot-nuget/GodotSharpEditor.4.1.1.nupkg


BIN
spine-godot/example-v4-csharp/godot-nuget/GodotSharpEditor.4.1.1.snupkg


BIN
spine-godot/example-v4-csharp/icon.png


+ 34 - 0
spine-godot/example-v4-csharp/icon.png.import

@@ -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

+ 6 - 0
spine-godot/example-v4-csharp/nuget.config

@@ -0,0 +1,6 @@
+<configuration>
+   <packageSources>
+      <!-- package source is additive -->
+      <add key="godot-nuget" value="./godot-nuget" />
+   </packageSources>
+</configuration>

+ 39 - 0
spine-godot/example-v4-csharp/project.godot

@@ -0,0 +1,39 @@
+; 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/04-simple-input/simple-input.tscn"
+config/features=PackedStringArray("4.1", "C#")
+run/low_processor_mode=true
+config/icon="res://icon.png"
+
+[dotnet]
+
+project/assembly_name="spine-godot-examples"
+
+[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"

+ 7 - 0
spine-godot/example-v4-csharp/spine-godot-examples.csproj

@@ -0,0 +1,7 @@
+<Project Sdk="Godot.NET.Sdk/4.1.1">
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <EnableDynamicLoading>true</EnableDynamicLoading>
+    <RootNamespace>spinegodotexamples</RootNamespace>
+  </PropertyGroup>
+</Project>

+ 19 - 0
spine-godot/example-v4-csharp/spine-godot-examples.sln

@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-godot-examples", "spine-godot-examples.csproj", "{B21498ED-66AD-4BA6-9E10-71D7C93549C9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+	Debug|Any CPU = Debug|Any CPU
+	ExportDebug|Any CPU = ExportDebug|Any CPU
+	ExportRelease|Any CPU = ExportRelease|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B21498ED-66AD-4BA6-9E10-71D7C93549C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B21498ED-66AD-4BA6-9E10-71D7C93549C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B21498ED-66AD-4BA6-9E10-71D7C93549C9}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
+		{B21498ED-66AD-4BA6-9E10-71D7C93549C9}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
+		{B21498ED-66AD-4BA6-9E10-71D7C93549C9}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
+		{B21498ED-66AD-4BA6-9E10-71D7C93549C9}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
+	EndGlobalSection
+EndGlobal

+ 30 - 0
spine-godot/spine_godot/SpineSprite.cpp

@@ -831,6 +831,24 @@ void SpineSprite::update_meshes(Ref<SpineSkeleton> skeleton_ref) {
 	skeleton_clipper->clipEnd();
 }
 
+void createLinesFromMesh(Vector<Vector2> &scratch_points, spine::Vector<unsigned short> &triangles, spine::Vector<float> *vertices) {
+	scratch_points.resize(0);
+	for (int i = 0; i < triangles.size(); i += 3) {
+		int i1 = triangles[i];
+		int i2 = triangles[i + 1];
+		int i3 = triangles[i + 2];
+		Vector2 v1(vertices->buffer()[i1 * 2], vertices->buffer()[i1 * 2 + 1]);
+		Vector2 v2(vertices->buffer()[i2 * 2], vertices->buffer()[i2 * 2 + 1]);
+		Vector2 v3(vertices->buffer()[i3 * 2], vertices->buffer()[i3 * 2 + 1]);
+		scratch_points.push_back(v1);
+		scratch_points.push_back(v2);
+		scratch_points.push_back(v2);
+		scratch_points.push_back(v3);
+		scratch_points.push_back(v3);
+		scratch_points.push_back(v1);
+	}
+}
+
 void SpineSprite::draw() {
 	if (!animation_state.is_valid() && !skeleton.is_valid()) return;
 	if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) return;
@@ -857,6 +875,12 @@ void SpineSprite::draw() {
 			auto *vertices = &scratch_vertices;
 			vertices->setSize(8, 0);
 			region->computeWorldVertices(*slot, *vertices, 0);
+
+			// Render triangles.
+			createLinesFromMesh(scratch_points, quad_indices, vertices);
+			draw_polyline(scratch_points, debug_regions_color);
+
+			// Render hull.
 			scratch_points.resize(0);
 			for (int i = 0, j = 0; i < 4; i++, j += 2) {
 				float x = vertices->buffer()[j];
@@ -888,6 +912,12 @@ void SpineSprite::draw() {
 			auto *vertices = &scratch_vertices;
 			vertices->setSize(mesh->getWorldVerticesLength(), 0);
 			mesh->computeWorldVertices(*slot, *vertices);
+
+			// Render triangles.
+			createLinesFromMesh(scratch_points, mesh->getTriangles(), vertices);
+			draw_polyline(scratch_points, debug_meshes_color);
+
+			// Render hull
 			scratch_points.resize(0);
 			for (int i = 0, j = 0; i < mesh->getHullLength(); i++, j += 2) {
 				float x = vertices->buffer()[j];

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