Эх сурвалжийг харах

[csharp][unity] Port sequence attachment. See #1956. Also port of other 4.1-beta branch changes compared to 4.0.

Harald Csaszar 3 жил өмнө
parent
commit
3250e74e26
100 өөрчлөгдсөн 3957 нэмэгдсэн , 2413 устгасан
  1. 18 2
      CHANGELOG.md
  2. 95 4
      spine-csharp/src/Animation.cs
  3. 8 4
      spine-csharp/src/AnimationState.cs
  4. 11 3
      spine-csharp/src/Atlas.cs
  5. 27 26
      spine-csharp/src/Attachments/AtlasAttachmentLoader.cs
  6. 10 6
      spine-csharp/src/Attachments/Attachment.cs
  7. 2 2
      spine-csharp/src/Attachments/AttachmentLoader.cs
  8. 1 1
      spine-csharp/src/Attachments/AttachmentType.cs
  9. 6 3
      spine-csharp/src/Attachments/BoundingBoxAttachment.cs
  10. 7 4
      spine-csharp/src/Attachments/ClippingAttachment.cs
  11. 56 0
      spine-csharp/src/Attachments/IHasTextureRegion.cs
  12. 2 1
      spine-csharp/src/Attachments/IHasTextureRegion.cs.meta
  13. 125 126
      spine-csharp/src/Attachments/MeshAttachment.cs
  14. 12 7
      spine-csharp/src/Attachments/PathAttachment.cs
  15. 9 5
      spine-csharp/src/Attachments/PointAttachment.cs
  16. 89 70
      spine-csharp/src/Attachments/RegionAttachment.cs
  17. 95 0
      spine-csharp/src/Attachments/Sequence.cs
  18. 11 0
      spine-csharp/src/Attachments/Sequence.cs.meta
  19. 29 24
      spine-csharp/src/Attachments/VertexAttachment.cs
  20. 17 2
      spine-csharp/src/Bone.cs
  21. 4 4
      spine-csharp/src/IkConstraint.cs
  22. 14 10
      spine-csharp/src/PathConstraint.cs
  23. 149 40
      spine-csharp/src/Skeleton.cs
  24. 87 51
      spine-csharp/src/SkeletonBinary.cs
  25. 30 8
      spine-csharp/src/SkeletonData.cs
  26. 107 60
      spine-csharp/src/SkeletonJson.cs
  27. 3 3
      spine-csharp/src/SkeletonLoader.cs
  28. 12 13
      spine-csharp/src/Slot.cs
  29. 105 0
      spine-csharp/src/SpringConstraint.cs
  30. 11 0
      spine-csharp/src/SpringConstraint.cs.meta
  31. 59 0
      spine-csharp/src/SpringConstraintData.cs
  32. 11 0
      spine-csharp/src/SpringConstraintData.cs.meta
  33. 49 0
      spine-csharp/src/TextureRegion.cs
  34. 4 4
      spine-csharp/src/TransformConstraint.cs
  35. 1 1
      spine-csharp/src/package.json
  36. 2 3
      spine-csharp/tests/src/AnimationStateTests.cs
  37. 1 1
      spine-unity/Assets/Spine Examples/Scripts/Sample Components/RootMotionDeltaCompensation.cs.meta
  38. 0 1
      spine-unity/Assets/Spine Examples/Scripts/SpineGauge.cs
  39. 77 60
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.atlas.txt
  40. 49 69
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.json
  41. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.png
  42. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon2.png
  43. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon3.png
  44. 108 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon3.png.meta
  45. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon4.png
  46. 108 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon4.png.meta
  47. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon5.png
  48. 108 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon5.png.meta
  49. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon6.png
  50. 108 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon6.png.meta
  51. 39 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon3.mat
  52. 8 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon3.mat.meta
  53. 39 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon4.mat
  54. 8 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon4.mat.meta
  55. 39 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon5.mat
  56. 8 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon5.mat.meta
  57. 39 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon6.mat
  58. 8 0
      spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon6.mat.meta
  59. 2 2
      spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.json
  60. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.png
  61. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.png
  62. 2 2
      spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier.json
  63. 2 2
      spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.json
  64. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.png
  65. 304 282
      spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.json
  66. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.png
  67. 548 498
      spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.json
  68. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.png
  69. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.png
  70. 2 2
      spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/raggedy spineboy.json
  71. 43 39
      spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.json
  72. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.png
  73. 252 220
      spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.json
  74. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.png
  75. 140 136
      spine-unity/Assets/Spine Examples/Spine Skeletons/Stretchyman/stretchyman.json
  76. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/mix-and-match/mix-and-match-pma.png
  77. 20 20
      spine-unity/Assets/Spine Examples/Spine Skeletons/mix-and-match/mix-and-match-pro.json
  78. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/raptor-pro-and-mask/raptor-pma.png
  79. 4 4
      spine-unity/Assets/Spine Examples/Spine Skeletons/raptor-pro-and-mask/raptor-pro.json
  80. 482 430
      spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.json
  81. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.png
  82. 19 19
      spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity.json
  83. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.png
  84. 2 2
      spine-unity/Assets/Spine Examples/Spine Skeletons/whirlyblendmodes/whirlyblendmodes.json
  85. BIN
      spine-unity/Assets/Spine Examples/Spine Skeletons/whirlyblendmodes/whirlyblendmodes.png
  86. 2 2
      spine-unity/Assets/Spine Examples/package.json
  87. 38 8
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs
  88. 2 2
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/BlendModeMaterialsUtility.cs
  89. 3 2
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs
  90. 5 5
      spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterials.cs
  91. 4 4
      spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/RegionlessAttachmentLoader.cs
  92. 2 2
      spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/SkeletonDataCompatibility.cs
  93. 0 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs
  94. 0 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs
  95. 18 12
      spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs
  96. 3 2
      spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonDataModifierAssets/BlendModeMaterials/BlendModeMaterialsAsset.cs
  97. 17 25
      spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs
  98. 6 5
      spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs
  99. 8 64
      spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs
  100. 2 2
      spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs

+ 18 - 2
CHANGELOG.md

@@ -14,6 +14,22 @@
 
 ## C# ##
 
+* **Additions**
+  * Full support for sequences.
+  * `RegionAttachment` and `MeshAttachment` now provide a `Region` property. Use this property instead of the removed `RendererObject` property (see section *Breaking Changes* below).
+
+* **Breaking changes**
+  * Removed `RendererObject` property from `RegionAttachment` and `MeshAttachment`. Use `attachment.Region` property instead. Removed removed `IHasRendererObject` interface. Use `IHasTextureRegion` instead.
+  * Replaced `RegionAttachment.UpdateOffset` and `MeshAttachment.UpdateUVs` with `Attachment.UpdateRegion`. The caller must ensure that the attachment's region is not `null`.
+  * Removed `AttachmentRegionExtensions` methods `Attachment.SetRegion`, `MeshAttachment.SetRegion` and `RegionAttachment.SetRegion(region, update)`. Use `attachment.Region = region; if (update) attachment.UpdateRegion()` instead.
+  * `AttachmentLoader.NewRegionAttachment()` and `AttachmentLoader.NewMeshAttachment()` take an additional `Sequence` parameter.
+  * `VertexAttachment.DeformAttachment` property has been replaced with `VertexAttachment.TimelineAttachment`.
+  * `RegionAttachment.ComputeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument.
+  * Removed `Skeleton.Update(float deltaTime)` method.
+  * Removed `Slot.AttachmentTime` property.
+  * Removed extension method `AtlasRegion.GetSpineAtlasRect()` parameter `includeRotate` (with default value `true`). Most likely this method was never used with `includeRotate=false` in user code so no changes are required.
+  * `AtlasRegion.PackedWidth` and `AtlasRegion.PackedHeight` are swapped compared to 4.0 when packing rotation is equal to 90 degrees. Most likely this property was never accessed in user code so no changes are required.
+
 ### Unity
 
 * **Officially supported Unity versions are 2017.1-2021.1**.
@@ -34,7 +50,7 @@
 * **Breaking change**: `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter.
 * **Breaking change**: `Slot#setAttachmentTime()` and `Slot#getAttachmentTime()` have been removed.
 * **Breaking change**: `VertexAttachment#setDeformAttachment()` and `VertexAttachment#getDeformAttachment()` have been replaced with `VertexAttachment#setTimelineAttachment()` and `VertexAttachment#getTimelineAttachment()`.
-* **Breaking change**: `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The called must ensure that the attachment's region is not `null`.
+* **Breaking change**: `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`.
 * **Breaking change**: `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument.
 * **Addition**: full support for sequences.
 
@@ -45,7 +61,7 @@
 * **Breaking change**: `AttachmentLoader#newRegionAttachment()` and `AttachmentLoader#newMeshAttachment()` take an additional `Sequence` parameter.
 * **Breaking change**: `Slot#attachmentTime` and has been removed.
 * **Breaking change**: `VertexAttachment#deformAttachment` has been replaced with `VertexAttachment#timelineAttachment`.
-* **Breaking change**: `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The called must ensure that the attachment's region is not `null`.
+* **Breaking change**: `RegionAttachment#updateOffset()` has been renamed to `RegionAttachment#updateRegion()`. The caller must ensure that the attachment's region is not `null`.
 * **Breaking change**: `RegionAttachment#computeWorldVertices()` takes a `Slot` instead of a `Bone` as the first argument.
 * **Addition**: full support for sequences.
 

+ 95 - 4
spine-csharp/src/Animation.cs

@@ -181,7 +181,8 @@ namespace Spine {
 		Attachment, Deform, //
 		Event, DrawOrder, //
 		IkConstraint, TransformConstraint, //
-		PathConstraintPosition, PathConstraintSpacing, PathConstraintMix
+		PathConstraintPosition, PathConstraintSpacing, PathConstraintMix, //
+		Sequence
 	}
 
 	/// <summary>
@@ -1786,7 +1787,7 @@ namespace Spine {
 			}
 		}
 		/// <summary>The attachment that will be deformed.</summary>
-		/// <seealso cref="VertexAttachment.DeformAttachment"/>
+		/// <seealso cref="VertexAttachment.TimelineAttachment"/>
 		public VertexAttachment Attachment {
 			get {
 				return attachment;
@@ -1869,9 +1870,9 @@ namespace Spine {
 			Slot slot = skeleton.slots.Items[slotIndex];
 			if (!slot.bone.active) return;
 			var vertexAttachment = slot.attachment as VertexAttachment;
-			if (vertexAttachment == null || vertexAttachment.DeformAttachment != attachment) return;
+			if (vertexAttachment == null || vertexAttachment.TimelineAttachment != attachment) return;
 
-			var deformArray = slot.Deform;
+			var deformArray = slot.deform;
 			if (deformArray.Count == 0) blend = MixBlend.Setup;
 
 			float[][] vertices = this.vertices;
@@ -2583,4 +2584,94 @@ namespace Spine {
 			}
 		}
 	}
+
+	/// <summary>Changes a slot's <see cref="Slot.SequenceIndex"/> for an attachment's <see cref="Sequence"/>.</summary>
+	public class SequenceTimeline : Timeline, ISlotTimeline {
+		public const int ENTRIES = 3;
+		private const int MODE = 1, DELAY = 2;
+
+		readonly int slotIndex;
+		readonly IHasTextureRegion attachment;
+
+		public SequenceTimeline (int frameCount, int slotIndex, Attachment attachment)
+			: base(frameCount, (int)Property.Sequence + "|" + slotIndex + "|" + ((IHasTextureRegion)attachment).Sequence.Id) {
+			this.slotIndex = slotIndex;
+			this.attachment = (IHasTextureRegion)attachment;
+		}
+
+		public override int FrameEntries {
+			get { return ENTRIES; }
+		}
+
+		public int SlotIndex {
+			get {
+				return slotIndex;
+			}
+		}
+		public Attachment Attachment {
+			get {
+				return (Attachment)attachment;
+			}
+		}
+
+		/// <summary>Sets the time, mode, index, and frame time for the specified frame.</summary>
+		/// <param name="frame">Between 0 and <code>frameCount</code>, inclusive.</param>
+		/// <param name="time">Seconds between frames.</param>
+		public void SetFrame (int frame, float time, SequenceMode mode, int index, float delay) {
+			frame *= ENTRIES;
+			frames[frame] = time;
+			frames[frame + MODE] = (int)mode | (index << 4);
+			frames[frame + DELAY] = delay;
+		}
+
+		override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList<Event> firedEvents, float alpha, MixBlend blend,
+			MixDirection direction) {
+
+			Slot slot = skeleton.slots.Items[slotIndex];
+			if (!slot.bone.active) return;
+			Attachment slotAttachment = slot.attachment;
+			if (slotAttachment != attachment) {
+				VertexAttachment vertexAttachment = slotAttachment as VertexAttachment;
+				if ((vertexAttachment == null)
+					|| vertexAttachment.TimelineAttachment != attachment) return;
+			}
+
+			float[] frames = this.frames;
+			if (time < frames[0]) { // Time is before first frame.
+				if (blend == MixBlend.Setup || blend == MixBlend.First) slot.SequenceIndex = -1;
+				return;
+			}
+
+			int i = Search(frames, time, ENTRIES);
+			float before = frames[i];
+			int modeAndIndex = (int)frames[i + MODE];
+			float delay = frames[i + DELAY];
+
+			int index = modeAndIndex >> 4, count = attachment.Sequence.Regions.Length;
+			SequenceMode mode = (SequenceMode)(modeAndIndex & 0xf);
+			if (mode != SequenceMode.Hold) {
+				index += (int)((time - before) / delay + 0.00001f);
+				switch (mode) {
+				case SequenceMode.Once:
+					index = Math.Min(count - 1, index);
+					break;
+				case SequenceMode.Loop:
+					index %= count;
+					break;
+				case SequenceMode.Pingpong:
+					int n = (count << 1) - 2;
+					index %= n;
+					if (index >= count) index = n - index;
+					break;
+				case SequenceMode.OnceReverse:
+					index = Math.Max(count - 1 - index, 0);
+					break;
+				case SequenceMode.LoopReverse:
+					index = count - 1 - (index % count);
+					break;
+				}
+			}
+			slot.SequenceIndex = index;
+		}
+	}
 }

+ 8 - 4
spine-csharp/src/AnimationState.cs

@@ -1107,9 +1107,12 @@ namespace Spine {
 		}
 
 		/// <summary>
-		/// Uses <see cref="TrackEntry.TrackTime"/> to compute the <code>AnimationTime</code>, which is between <see cref="TrackEntry.AnimationStart"/>
-		/// and <see cref="TrackEntry.AnimationEnd"/>. When the <code>TrackTime</code> is 0, the <code>AnimationTime</code> is equal to the
-		/// <code>AnimationStart</code> time.
+		/// Uses <see cref="TrackEntry.TrackTime"/> to compute the <code>AnimationTime</code>. When the <code>TrackTime</code> is 0, the
+		/// <code>AnimationTime</code> is equal to the <code>AnimationStart</code> time.
+		/// <para>
+		/// The <code>animationTime</code> is between <see cref="AnimationStart"/> and <see cref="AnimationEnd"/>, except if this
+		/// track entry is non-looping and <see cref="AnimationEnd"/> is >= to the animation <see cref="Animation.Duration"/>, then
+		/// <code>animationTime</code> continues to increase past <see cref="AnimationEnd"/>.</para>
 		/// </summary>
 		public float AnimationTime {
 			get {
@@ -1118,7 +1121,8 @@ namespace Spine {
 					if (duration == 0) return animationStart;
 					return (trackTime % duration) + animationStart;
 				}
-				return Math.Min(trackTime + animationStart, animationEnd);
+				float animationTime = trackTime + animationStart;
+				return animationEnd >= animation.duration ? animationTime : Math.Min(animationTime, animationEnd);
 			}
 		}
 

+ 11 - 3
spine-csharp/src/Atlas.cs

@@ -245,6 +245,10 @@ namespace Spine {
 					if (region.degrees == 90) {
 						region.u2 = (region.x + region.height) / (float)page.width;
 						region.v2 = (region.y + region.width) / (float)page.height;
+
+						var tempSwap = region.packedWidth;
+						region.packedWidth = region.packedHeight;
+						region.packedHeight = tempSwap;
 					} else {
 						region.u2 = (region.x + region.width) / (float)page.width;
 						region.v2 = (region.y + region.height) / (float)page.height;
@@ -339,19 +343,23 @@ namespace Spine {
 		}
 	}
 
-	public class AtlasRegion {
+	public class AtlasRegion : TextureRegion {
 		public AtlasPage page;
 		public string name;
-		public int x, y, width, height;
-		public float u, v, u2, v2;
+		public int x, y;
 		public float offsetX, offsetY;
 		public int originalWidth, originalHeight;
+		public int packedWidth { get { return width; } set { width = value; } }
+		public int packedHeight { get { return height; } set { height = value; } }
 		public int degrees;
 		public bool rotate;
 		public int index;
 		public string[] names;
 		public int[][] values;
 
+		override public int OriginalWidth { get { return originalWidth; } }
+		override public int OriginalHeight { get { return originalHeight; } }
+
 		public AtlasRegion Clone () {
 			return MemberwiseClone() as AtlasRegion;
 		}

+ 27 - 26
spine-csharp/src/Attachments/AtlasAttachmentLoader.cs

@@ -43,37 +43,38 @@ namespace Spine {
 			this.atlasArray = atlasArray;
 		}
 
-		public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
-			AtlasRegion region = FindRegion(path);
-			if (region == null) throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
+		private void LoadSequence (string name, string basePath, Sequence sequence) {
+			TextureRegion[] regions = sequence.Regions;
+			for (int i = 0, n = regions.Length; i < n; i++) {
+				string path = sequence.GetPath(basePath, i);
+				regions[i] = FindRegion(path);
+				if (regions[i] == null) throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
+			}
+		}
+
+		public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
 			RegionAttachment attachment = new RegionAttachment(name);
-			attachment.RendererObject = region;
-			attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.degrees);
-			attachment.regionOffsetX = region.offsetX;
-			attachment.regionOffsetY = region.offsetY;
-			attachment.regionWidth = region.width;
-			attachment.regionHeight = region.height;
-			attachment.regionOriginalWidth = region.originalWidth;
-			attachment.regionOriginalHeight = region.originalHeight;
+			if (sequence != null)
+				LoadSequence(name, path, sequence);
+			else {
+				AtlasRegion region = FindRegion(path);
+				if (region == null)
+					throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
+				attachment.Region = region;
+			}
 			return attachment;
 		}
 
-		public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
-			AtlasRegion region = FindRegion(path);
-			if (region == null) throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
+		public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
 			MeshAttachment attachment = new MeshAttachment(name);
-			attachment.RendererObject = region;
-			attachment.RegionU = region.u;
-			attachment.RegionV = region.v;
-			attachment.RegionU2 = region.u2;
-			attachment.RegionV2 = region.v2;
-			attachment.RegionDegrees = region.degrees;
-			attachment.regionOffsetX = region.offsetX;
-			attachment.regionOffsetY = region.offsetY;
-			attachment.regionWidth = region.width;
-			attachment.regionHeight = region.height;
-			attachment.regionOriginalWidth = region.originalWidth;
-			attachment.regionOriginalHeight = region.originalHeight;
+			if (sequence != null)
+				LoadSequence(name, path, sequence);
+			else {
+				AtlasRegion region = FindRegion(path);
+				if (region == null)
+					throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
+				attachment.Region = region;
+			}
 			return attachment;
 		}
 

+ 10 - 6
spine-csharp/src/Attachments/Attachment.cs

@@ -30,12 +30,20 @@
 using System;
 
 namespace Spine {
+
+	/// <summary>The base class for all attachments.</summary>
 	abstract public class Attachment {
-		public string Name { get; private set; }
+		/// <summary>The attachment's name.</summary>
+		public string Name { get; }
 
 		protected Attachment (string name) {
 			if (name == null) throw new ArgumentNullException("name", "name cannot be null");
-			Name = name;
+			this.Name = name;
+		}
+
+		/// <summary>Copy constructor.</summary>
+		protected Attachment (Attachment other) {
+			Name = other.Name;
 		}
 
 		override public string ToString () {
@@ -45,8 +53,4 @@ namespace Spine {
 		///<summary>Returns a copy of the attachment.</summary>
 		public abstract Attachment Copy ();
 	}
-
-	public interface IHasRendererObject {
-		object RendererObject { get; set; }
-	}
 }

+ 2 - 2
spine-csharp/src/Attachments/AttachmentLoader.cs

@@ -30,10 +30,10 @@
 namespace Spine {
 	public interface AttachmentLoader {
 		/// <return>May be null to not load any attachment.</return>
-		RegionAttachment NewRegionAttachment (Skin skin, string name, string path);
+		RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence);
 
 		/// <return>May be null to not load any attachment.</return>
-		MeshAttachment NewMeshAttachment (Skin skin, string name, string path);
+		MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence);
 
 		/// <return>May be null to not load any attachment.</return>
 		BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name);

+ 1 - 1
spine-csharp/src/Attachments/AttachmentType.cs

@@ -29,6 +29,6 @@
 
 namespace Spine {
 	public enum AttachmentType {
-		Region, Boundingbox, Mesh, Linkedmesh, Path, Point, Clipping
+		Region, Boundingbox, Mesh, Linkedmesh, Path, Point, Clipping, Sequence
 	}
 }

+ 6 - 3
spine-csharp/src/Attachments/BoundingBoxAttachment.cs

@@ -36,10 +36,13 @@ namespace Spine {
 			: base(name) {
 		}
 
+		/// <summary>Copy constructor.</summary>
+		protected BoundingBoxAttachment (BoundingBoxAttachment other)
+			: base(other) {
+		}
+
 		public override Attachment Copy () {
-			BoundingBoxAttachment copy = new BoundingBoxAttachment(this.Name);
-			CopyTo(copy);
-			return copy;
+			return new BoundingBoxAttachment(this);
 		}
 	}
 }

+ 7 - 4
spine-csharp/src/Attachments/ClippingAttachment.cs

@@ -38,11 +38,14 @@ namespace Spine {
 		public ClippingAttachment (string name) : base(name) {
 		}
 
+		/// <summary>Copy constructor.</summary>
+		protected ClippingAttachment (ClippingAttachment other)
+			: base(other) {
+			endSlot = other.endSlot;
+		}
+
 		public override Attachment Copy () {
-			ClippingAttachment copy = new ClippingAttachment(this.Name);
-			CopyTo(copy);
-			copy.endSlot = endSlot;
-			return copy;
+			return new ClippingAttachment(this);
 		}
 	}
 }

+ 56 - 0
spine-csharp/src/Attachments/IHasTextureRegion.cs

@@ -0,0 +1,56 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated September 24, 2021. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2021, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+using System;
+using System.Text;
+
+namespace Spine {
+	public interface IHasTextureRegion {
+		/// <summary>The name used to find the <see cref="Region"/></summary>
+		public string Path { get; set; }
+		/// <summary>
+		/// Sets the region used to draw the attachment. After setting the region or if the region's properties are changed,
+		/// <see cref="UpdateRegion()"/> must be called.
+		/// </summary>
+		public TextureRegion Region { get; set; }
+
+		/// <summary>
+		/// Updates any values the attachment calculates using the <see cref="Region"/>. Must be called after setting the
+		/// <see cref="Region"/> or if the region's properties are changed.
+		/// </summary>
+		public void UpdateRegion ();
+
+		public float R { get; set; }
+		public float G { get; set; }
+		public float B { get; set; }
+		public float A { get; set; }
+
+		public Sequence Sequence { get; set; }
+	}
+}

+ 2 - 1
spine-unity/Assets/Spine Examples/Scripts/Sample Components/Legacy/CustomSkin.cs.meta → spine-csharp/src/Attachments/IHasTextureRegion.cs.meta

@@ -1,6 +1,7 @@
 fileFormatVersion: 2
-guid: 6e55c8477eccddc4cb5c3551a3945ca7
+guid: d0e8b0a33cae75d498aa8c328787cafb
 MonoImporter:
+  externalObjects: {}
   serializedVersion: 2
   defaultReferences: []
   executionOrder: 0

+ 125 - 126
spine-csharp/src/Attachments/MeshAttachment.cs

@@ -31,17 +31,27 @@ using System;
 
 namespace Spine {
 	/// <summary>Attachment that displays a texture region using a mesh.</summary>
-	public class MeshAttachment : VertexAttachment, IHasRendererObject {
-		internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
-		private MeshAttachment parentMesh;
-		internal float[] uvs, regionUVs;
+	public class MeshAttachment : VertexAttachment, IHasTextureRegion {
+		internal TextureRegion region;
+		internal string path;
+		internal float[] regionUVs, uvs;
 		internal int[] triangles;
 		internal float r = 1, g = 1, b = 1, a = 1;
-		internal int hulllength;
+		internal int hullLength;
+		private MeshAttachment parentMesh;
+		private Sequence sequence;
 
-		public int HullLength { get { return hulllength; } set { hulllength = value; } }
+		public TextureRegion Region {
+			get { return region; }
+			set {
+				if (value == null) throw new ArgumentNullException("region", "region cannot be null.");
+				region = value;
+			}
+		}
+		public int HullLength { get { return hullLength; } set { hullLength = value; } }
 		public float[] RegionUVs { get { return regionUVs; } set { regionUVs = value; } }
-		/// <summary>The UV pair for each vertex, normalized within the entire texture. <seealso cref="MeshAttachment.UpdateUVs"/></summary>
+		/// <summary>The UV pair for each vertex, normalized within the entire texture.
+		/// <seealso cref="MeshAttachment.UpdateRegion"/></summary>
 		public float[] UVs { get { return uvs; } set { uvs = value; } }
 		public int[] Triangles { get { return triangles; } set { triangles = value; } }
 
@@ -50,19 +60,8 @@ namespace Spine {
 		public float B { get { return b; } set { b = value; } }
 		public float A { get { return a; } set { a = value; } }
 
-		public string Path { get; set; }
-		public object RendererObject { get; set; }
-		public float RegionU { get; set; }
-		public float RegionV { get; set; }
-		public float RegionU2 { get; set; }
-		public float RegionV2 { get; set; }
-		public int RegionDegrees { get; set; }
-		public float RegionOffsetX { get { return regionOffsetX; } set { regionOffsetX = value; } }
-		public float RegionOffsetY { get { return regionOffsetY; } set { regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
-		public float RegionWidth { get { return regionWidth; } set { regionWidth = value; } }
-		public float RegionHeight { get { return regionHeight; } set { regionHeight = value; } } // Unrotated, stripped size.
-		public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
-		public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
+		public string Path { get { return path; } set { path = value; } }
+		public Sequence Sequence { get { return sequence; } set { sequence = value; } }
 
 		public MeshAttachment ParentMesh {
 			get { return parentMesh; }
@@ -91,131 +90,131 @@ namespace Spine {
 			: base(name) {
 		}
 
-		public void UpdateUVs () {
+		/// <summary>Copy constructor. Use <see cref="NewLinkedMesh"/> if the other mesh is a linked mesh.</summary>
+		protected MeshAttachment (MeshAttachment other)
+			: base(other) {
+
+			if (parentMesh != null) throw new ArgumentException("Use newLinkedMesh to copy a linked mesh.");
+
+			region = other.region;
+			path = other.path;
+			r = other.r;
+			g = other.g;
+			b = other.b;
+			a = other.a;
+
+			regionUVs = new float[other.regionUVs.Length];
+			Array.Copy(other.regionUVs, 0, regionUVs, 0, regionUVs.Length);
+
+			uvs = new float[other.uvs.Length];
+			Array.Copy(other.uvs, 0, uvs, 0, uvs.Length);
+
+			triangles = new int[other.triangles.Length];
+			Array.Copy(other.triangles, 0, triangles, 0, triangles.Length);
+
+			hullLength = other.hullLength;
+			sequence = other.sequence == null ? null : new Sequence(other.sequence);
+
+			// Nonessential.
+			if (other.Edges != null) {
+				Edges = new int[other.Edges.Length];
+				Array.Copy(other.Edges, 0, Edges, 0, Edges.Length);
+			}
+			Width = other.Width;
+			Height = other.Height;
+		}
+
+
+		public void UpdateRegion () {
 			float[] regionUVs = this.regionUVs;
 			if (this.uvs == null || this.uvs.Length != regionUVs.Length) this.uvs = new float[regionUVs.Length];
 			float[] uvs = this.uvs;
-			float u = RegionU, v = RegionV, width = 0, height = 0;
-
-			if (RegionDegrees == 90) {
-				float textureHeight = this.regionWidth / (RegionV2 - RegionV);
-				float textureWidth = this.regionHeight / (RegionU2 - RegionU);
-				u -= (RegionOriginalHeight - RegionOffsetY - RegionHeight) / textureWidth;
-				v -= (RegionOriginalWidth - RegionOffsetX - RegionWidth) / textureHeight;
-				width = RegionOriginalHeight / textureWidth;
-				height = RegionOriginalWidth / textureHeight;
-
-				for (int i = 0, n = uvs.Length; i < n; i += 2) {
-					uvs[i] = u + regionUVs[i + 1] * width;
-					uvs[i + 1] = v + (1 - regionUVs[i]) * height;
-				}
-			} else if (RegionDegrees == 180) {
-				float textureWidth = this.regionWidth / (RegionU2 - RegionU);
-				float textureHeight = this.regionHeight / (RegionV2 - RegionV);
-				u -= (RegionOriginalWidth - RegionOffsetX - RegionWidth) / textureWidth;
-				v -= RegionOffsetY / textureHeight;
-				width = RegionOriginalWidth / textureWidth;
-				height = RegionOriginalHeight / textureHeight;
-
-				for (int i = 0, n = uvs.Length; i < n; i += 2) {
-					uvs[i] = u + (1 - regionUVs[i]) * width;
-					uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;
-				}
-			} else if (RegionDegrees == 270) {
-				float textureWidth = this.regionWidth / (RegionU2 - RegionU);
-				float textureHeight = this.regionHeight / (RegionV2 - RegionV);
-				u -= RegionOffsetY / textureWidth;
-				v -= RegionOffsetX / textureHeight;
-				width = RegionOriginalHeight / textureWidth;
-				height = RegionOriginalWidth / textureHeight;
-
-				for (int i = 0, n = uvs.Length; i < n; i += 2) {
-					uvs[i] = u + (1 - regionUVs[i + 1]) * width;
-					uvs[i + 1] = v + regionUVs[i] * height;
+			int n = uvs.Length;
+			float u, v, width, height;
+
+			if (region is AtlasRegion) {
+				u = this.region.u;
+				v = this.region.v;
+				AtlasRegion region = (AtlasRegion)this.region;
+				// Note: difference from reference implementation.
+				// Covers rotation since region.width and height are already setup accordingly.
+				float textureWidth = this.region.width / (region.u2 - region.u);
+				float textureHeight = this.region.height / (region.v2 - region.v);
+				switch (region.degrees) {
+				case 90:
+					u -= (region.originalHeight - region.offsetY - region.packedWidth) / textureWidth;
+					v -= (region.originalWidth - region.offsetX - region.packedHeight) / textureHeight;
+					width = region.originalHeight / textureWidth;
+					height = region.originalWidth / textureHeight;
+					for (int i = 0; i < n; i += 2) {
+						uvs[i] = u + regionUVs[i + 1] * width;
+						uvs[i + 1] = v + (1 - regionUVs[i]) * height;
+					}
+					return;
+				case 180:
+					u -= (region.originalWidth - region.offsetX - region.packedWidth) / textureWidth;
+					v -= region.offsetY / textureHeight;
+					width = region.originalWidth / textureWidth;
+					height = region.originalHeight / textureHeight;
+					for (int i = 0; i < n; i += 2) {
+						uvs[i] = u + (1 - regionUVs[i]) * width;
+						uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;
+					}
+					return;
+				case 270:
+					u -= region.offsetY / textureWidth;
+					v -= region.offsetX / textureHeight;
+					width = region.originalHeight / textureWidth;
+					height = region.originalWidth / textureHeight;
+					for (int i = 0; i < n; i += 2) {
+						uvs[i] = u + (1 - regionUVs[i + 1]) * width;
+						uvs[i + 1] = v + regionUVs[i] * height;
+					}
+					return;
 				}
+				u -= region.offsetX / textureWidth;
+				v -= (region.originalHeight - region.offsetY - region.packedHeight) / textureHeight;
+				width = region.originalWidth / textureWidth;
+				height = region.originalHeight / textureHeight;
+			} else if (region == null) {
+				u = v = 0;
+				width = height = 1;
 			} else {
-				float textureWidth = this.regionWidth / (RegionU2 - RegionU);
-				float textureHeight = this.regionHeight / (RegionV2 - RegionV);
-				u -= RegionOffsetX / textureWidth;
-				v -= (RegionOriginalHeight - RegionOffsetY - RegionHeight) / textureHeight;
-				width = RegionOriginalWidth / textureWidth;
-				height = RegionOriginalHeight / textureHeight;
-
-				for (int i = 0, n = uvs.Length; i < n; i += 2) {
-					uvs[i] = u + regionUVs[i] * width;
-					uvs[i + 1] = v + regionUVs[i + 1] * height;
-				}
+				u = region.u;
+				v = region.v;
+				width = region.u2 - u;
+				height = region.v2 - v;
+			}
+			for (int i = 0; i < n; i += 2) {
+				uvs[i] = u + regionUVs[i] * width;
+				uvs[i + 1] = v + regionUVs[i + 1] * height;
 			}
 		}
 
-		public override Attachment Copy () {
-			if (parentMesh != null) return NewLinkedMesh();
-
-			MeshAttachment copy = new MeshAttachment(this.Name);
-			copy.RendererObject = RendererObject;
-			copy.regionOffsetX = regionOffsetX;
-			copy.regionOffsetY = regionOffsetY;
-			copy.regionWidth = regionWidth;
-			copy.regionHeight = regionHeight;
-			copy.regionOriginalWidth = regionOriginalWidth;
-			copy.regionOriginalHeight = regionOriginalHeight;
-			copy.RegionDegrees = RegionDegrees;
-			copy.RegionU = RegionU;
-			copy.RegionV = RegionV;
-			copy.RegionU2 = RegionU2;
-			copy.RegionV2 = RegionV2;
-
-			copy.Path = Path;
-			copy.r = r;
-			copy.g = g;
-			copy.b = b;
-			copy.a = a;
-
-			CopyTo(copy);
-			copy.regionUVs = new float[regionUVs.Length];
-			Array.Copy(regionUVs, 0, copy.regionUVs, 0, regionUVs.Length);
-			copy.uvs = new float[uvs.Length];
-			Array.Copy(uvs, 0, copy.uvs, 0, uvs.Length);
-			copy.triangles = new int[triangles.Length];
-			Array.Copy(triangles, 0, copy.triangles, 0, triangles.Length);
-			copy.HullLength = HullLength;
-
-			// Nonessential.
-			if (Edges != null) {
-				copy.Edges = new int[Edges.Length];
-				Array.Copy(Edges, 0, copy.Edges, 0, Edges.Length);
-			}
-			copy.Width = Width;
-			copy.Height = Height;
-			return copy;
+		/// <summary>If the attachment has a <see cref="Sequence"/>, the region may be changed.</summary>
+		override public void ComputeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset, int stride = 2) {
+			if (sequence != null) sequence.Apply(slot, this);
+			base.ComputeWorldVertices(slot, start, count, worldVertices, offset, stride);
 		}
 
 		///<summary>Returns a new mesh with this mesh set as the <see cref="ParentMesh"/>.
 		public MeshAttachment NewLinkedMesh () {
 			MeshAttachment mesh = new MeshAttachment(Name);
-			mesh.RendererObject = RendererObject;
-			mesh.regionOffsetX = regionOffsetX;
-			mesh.regionOffsetY = regionOffsetY;
-			mesh.regionWidth = regionWidth;
-			mesh.regionHeight = regionHeight;
-			mesh.regionOriginalWidth = regionOriginalWidth;
-			mesh.regionOriginalHeight = regionOriginalHeight;
-			mesh.RegionDegrees = RegionDegrees;
-			mesh.RegionU = RegionU;
-			mesh.RegionV = RegionV;
-			mesh.RegionU2 = RegionU2;
-			mesh.RegionV2 = RegionV2;
-
-			mesh.Path = Path;
+
+			mesh.timelineAttachment = timelineAttachment;
+			mesh.region = region;
+			mesh.path = path;
 			mesh.r = r;
 			mesh.g = g;
 			mesh.b = b;
 			mesh.a = a;
-
-			mesh.deformAttachment = deformAttachment;
 			mesh.ParentMesh = parentMesh != null ? parentMesh : this;
-			mesh.UpdateUVs();
+			if (mesh.Region != null) mesh.UpdateRegion();
 			return mesh;
 		}
+
+		public override Attachment Copy () {
+			return parentMesh != null ? NewLinkedMesh() : new MeshAttachment(this);
+		}
 	}
 }

+ 12 - 7
spine-csharp/src/Attachments/PathAttachment.cs

@@ -47,14 +47,19 @@ namespace Spine {
 			: base(name) {
 		}
 
+		/// <summary>Copy constructor.</summary>
+		protected PathAttachment (PathAttachment other)
+			: base(other) {
+
+			lengths = new float[other.lengths.Length];
+			Array.Copy(other.lengths, 0, lengths, 0, lengths.Length);
+
+			closed = other.closed;
+			constantSpeed = other.constantSpeed;
+		}
+
 		public override Attachment Copy () {
-			PathAttachment copy = new PathAttachment(this.Name);
-			CopyTo(copy);
-			copy.lengths = new float[lengths.Length];
-			Array.Copy(lengths, 0, copy.lengths, 0, lengths.Length);
-			copy.closed = closed;
-			copy.constantSpeed = constantSpeed;
-			return copy;
+			return new PathAttachment(this);
 		}
 	}
 }

+ 9 - 5
spine-csharp/src/Attachments/PointAttachment.cs

@@ -45,6 +45,14 @@ namespace Spine {
 			: base(name) {
 		}
 
+		/** Copy constructor. */
+		protected PointAttachment (PointAttachment other)
+			: base(other) {
+			x = other.x;
+			y = other.y;
+			rotation = other.rotation;
+		}
+
 		public void ComputeWorldPosition (Bone bone, out float ox, out float oy) {
 			bone.LocalToWorld(this.x, this.y, out ox, out oy);
 		}
@@ -57,11 +65,7 @@ namespace Spine {
 		}
 
 		public override Attachment Copy () {
-			PointAttachment copy = new PointAttachment(this.Name);
-			copy.x = x;
-			copy.y = y;
-			copy.rotation = rotation;
-			return copy;
+			return new PointAttachment(this);
 		}
 	}
 }

+ 89 - 70
spine-csharp/src/Attachments/RegionAttachment.cs

@@ -31,20 +31,17 @@ using System;
 
 namespace Spine {
 	/// <summary>Attachment that displays a texture region.</summary>
-	public class RegionAttachment : Attachment, IHasRendererObject {
-		public const int BLX = 0;
-		public const int BLY = 1;
-		public const int ULX = 2;
-		public const int ULY = 3;
-		public const int URX = 4;
-		public const int URY = 5;
-		public const int BRX = 6;
-		public const int BRY = 7;
+	public class RegionAttachment : Attachment, IHasTextureRegion {
+		public const int BLX = 0, BLY = 1;
+		public const int ULX = 2, ULY = 3;
+		public const int URX = 4, URY = 5;
+		public const int BRX = 6, BRY = 7;
 
+		internal TextureRegion region;
 		internal float x, y, rotation, scaleX = 1, scaleY = 1, width, height;
-		internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
 		internal float[] offset = new float[8], uvs = new float[8];
 		internal float r = 1, g = 1, b = 1, a = 1;
+		internal Sequence sequence;
 
 		public float X { get { return x; } set { x = value; } }
 		public float Y { get { return y; } set { y = value; } }
@@ -60,31 +57,73 @@ namespace Spine {
 		public float A { get { return a; } set { a = value; } }
 
 		public string Path { get; set; }
-		public object RendererObject { get; set; }
-		public float RegionOffsetX { get { return regionOffsetX; } set { regionOffsetX = value; } }
-		public float RegionOffsetY { get { return regionOffsetY; } set { regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
-		public float RegionWidth { get { return regionWidth; } set { regionWidth = value; } }
-		public float RegionHeight { get { return regionHeight; } set { regionHeight = value; } } // Unrotated, stripped size.
-		public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
-		public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
+		public TextureRegion Region { get { return region; } set { region = value; } }
 
+		/// <summary>For each of the 4 vertices, a pair of <code>x,y</code> values that is the local position of the vertex.</summary>
+		/// <seealso cref="UpdateRegion"/>
 		public float[] Offset { get { return offset; } }
 		public float[] UVs { get { return uvs; } }
+		public Sequence Sequence { get { return sequence; } set { sequence = value; } }
 
 		public RegionAttachment (string name)
 			: base(name) {
 		}
 
-		public void UpdateOffset () {
-			float regionScaleX = width / regionOriginalWidth * scaleX;
-			float regionScaleY = height / regionOriginalHeight * scaleY;
-			float localX = -width / 2 * scaleX + regionOffsetX * regionScaleX;
-			float localY = -height / 2 * scaleY + regionOffsetY * regionScaleY;
-			float localX2 = localX + regionWidth * regionScaleX;
-			float localY2 = localY + regionHeight * regionScaleY;
+		/// <summary>Copy constructor.</summary>
+		public RegionAttachment (RegionAttachment other)
+			: base(other) {
+			region = other.region;
+			Path = other.Path;
+			x = other.x;
+			y = other.y;
+			scaleX = other.scaleX;
+			scaleY = other.scaleY;
+			rotation = other.rotation;
+			width = other.width;
+			height = other.height;
+			Array.Copy(other.uvs, 0, uvs, 0, 8);
+			Array.Copy(other.offset, 0, offset, 0, 8);
+			r = other.r;
+			g = other.g;
+			b = other.b;
+			a = other.a;
+			sequence = other.sequence == null ? null : new Sequence(other.sequence);
+		}
+
+		/// <summary>Calculates the <see cref="Offset"/> and <see cref="UVs"/> using the region and the attachment's transform. Must be called if the
+		/// region, the region's properties, or the transform are changed.</summary>
+		public void UpdateRegion () {
+			float width = Width;
+			float height = Height;
+			float localX2 = width / 2;
+			float localY2 = height / 2;
+			float localX = -localX2;
+			float localY = -localY2;
+			bool rotated = false;
+			if (region is AtlasRegion) {
+				AtlasRegion region = (AtlasRegion)this.region;
+				localX += region.offsetX / region.originalWidth * width;
+				localY += region.offsetY / region.originalHeight * height;
+				if (region.degrees == 90) {
+					rotated = true;
+					localX2 -= (region.originalWidth - region.offsetX - region.packedHeight) / region.originalWidth * width;
+					localY2 -= (region.originalHeight - region.offsetY - region.packedWidth) / region.originalHeight * height;
+				} else {
+					localX2 -= (region.originalWidth - region.offsetX - region.packedWidth) / region.originalWidth * width;
+					localY2 -= (region.originalHeight - region.offsetY - region.packedHeight) / region.originalHeight * height;
+				}
+			}
+			float scaleX = ScaleX;
+			float scaleY = ScaleY;
+			localX *= scaleX;
+			localY *= scaleY;
+			localX2 *= scaleX;
+			localY2 *= scaleY;
+			float rotation = Rotation;
 			float cos = MathUtils.CosDeg(this.rotation);
 			float sin = MathUtils.SinDeg(this.rotation);
-			float x = this.x, y = this.y;
+			float x = X;
+			float y = Y;
 			float localXCos = localX * cos + x;
 			float localXSin = localX * sin;
 			float localYCos = localY * cos + y;
@@ -102,39 +141,41 @@ namespace Spine {
 			offset[URY] = localY2Cos + localX2Sin;
 			offset[BRX] = localX2Cos - localYSin;
 			offset[BRY] = localYCos + localX2Sin;
-		}
 
-		public void SetUVs (float u, float v, float u2, float v2, int degrees) {
 			float[] uvs = this.uvs;
-			// UV values differ from spine-libgdx.
-			if (degrees == 90) {
-				uvs[URX] = u;
-				uvs[URY] = v2;
-				uvs[BRX] = u;
-				uvs[BRY] = v;
-				uvs[BLX] = u2;
-				uvs[BLY] = v;
-				uvs[ULX] = u2;
-				uvs[ULY] = v2;
+			if (rotated) {
+				uvs[URX] = region.u;
+				uvs[URY] = region.v2;
+				uvs[BRX] = region.u;
+				uvs[BRY] = region.v;
+				uvs[BLX] = region.u2;
+				uvs[BLY] = region.v;
+				uvs[ULX] = region.u2;
+				uvs[ULY] = region.v2;
 			} else {
-				uvs[ULX] = u;
-				uvs[ULY] = v2;
-				uvs[URX] = u;
-				uvs[URY] = v;
-				uvs[BRX] = u2;
-				uvs[BRY] = v;
-				uvs[BLX] = u2;
-				uvs[BLY] = v2;
+				uvs[ULX] = region.u;
+				uvs[ULY] = region.v2;
+				uvs[URX] = region.u;
+				uvs[URY] = region.v;
+				uvs[BRX] = region.u2;
+				uvs[BRY] = region.v;
+				uvs[BLX] = region.u2;
+				uvs[BLY] = region.v2;
 			}
 		}
 
-		/// <summary>Transforms the attachment's four vertices to world coordinates.</summary>
+		/// <summary>
+		/// Transforms the attachment's four vertices to world coordinates. If the attachment has a <see cref="Sequence"/> the region may
+		/// be changed.</summary>
 		/// <param name="bone">The parent bone.</param>
 		/// <param name="worldVertices">The output world vertices. Must have a length greater than or equal to offset + 8.</param>
 		/// <param name="offset">The worldVertices index to begin writing values.</param>
 		/// <param name="stride">The number of worldVertices entries between the value pairs written.</param>
-		public void ComputeWorldVertices (Bone bone, float[] worldVertices, int offset, int stride = 2) {
+		public void ComputeWorldVertices (Slot slot, float[] worldVertices, int offset, int stride = 2) {
+			if (sequence != null) sequence.Apply(slot, this);
+
 			float[] vertexOffset = this.offset;
+			Bone bone = slot.Bone;
 			float bwx = bone.worldX, bwy = bone.worldY;
 			float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
 			float offsetX, offsetY;
@@ -166,29 +207,7 @@ namespace Spine {
 		}
 
 		public override Attachment Copy () {
-			RegionAttachment copy = new RegionAttachment(this.Name);
-			copy.RendererObject = RendererObject;
-			copy.regionOffsetX = regionOffsetX;
-			copy.regionOffsetY = regionOffsetY;
-			copy.regionWidth = regionWidth;
-			copy.regionHeight = regionHeight;
-			copy.regionOriginalWidth = regionOriginalWidth;
-			copy.regionOriginalHeight = regionOriginalHeight;
-			copy.Path = Path;
-			copy.x = x;
-			copy.y = y;
-			copy.scaleX = scaleX;
-			copy.scaleY = scaleY;
-			copy.rotation = rotation;
-			copy.width = width;
-			copy.height = height;
-			Array.Copy(uvs, 0, copy.uvs, 0, 8);
-			Array.Copy(offset, 0, copy.offset, 0, 8);
-			copy.r = r;
-			copy.g = g;
-			copy.b = b;
-			copy.a = a;
-			return copy;
+			return new RegionAttachment(this);
 		}
 	}
 }

+ 95 - 0
spine-csharp/src/Attachments/Sequence.cs

@@ -0,0 +1,95 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated September 24, 2021. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2021, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+using System;
+using System.Text;
+
+namespace Spine {
+	public class Sequence {
+		static int nextID = 0;
+		static readonly Object nextIdLock = new Object();
+
+		internal readonly int id;
+		internal readonly TextureRegion[] regions;
+		internal int start, digits, setupIndex;
+
+		public int Start { get { return start; } set { start = value; } }
+		public int Digits { get { return digits; } set { digits = value; } }
+		/// <summary>The index of the region to show for the setup pose.</summary>
+		public int SetupIndex { get { return setupIndex; } set { setupIndex = value; } }
+		public TextureRegion[] Regions { get { return regions; } }
+		/// <summary>Returns a unique ID for this attachment.</summary>
+		public int Id { get { return id; } }
+
+		public Sequence (int count) {
+			lock (Sequence.nextIdLock) {
+				id = Sequence.nextID++;
+			}
+			regions = new TextureRegion[count];
+		}
+
+		/// <summary>Copy constructor.</summary>
+		public Sequence (Sequence other) {
+			lock (Sequence.nextIdLock) {
+				id = Sequence.nextID++;
+			}
+			regions = new TextureRegion[other.regions.Length];
+			Array.Copy(other.regions, 0, regions, 0, regions.Length);
+
+			start = other.start;
+			digits = other.digits;
+			setupIndex = other.setupIndex;
+		}
+
+		public void Apply (Slot slot, IHasTextureRegion attachment) {
+			int index = slot.SequenceIndex;
+			if (index == -1) index = setupIndex;
+			if (index >= regions.Length) index = regions.Length - 1;
+			TextureRegion region = regions[index];
+			if (attachment.Region != region) {
+				attachment.Region = region;
+				attachment.UpdateRegion();
+			}
+		}
+
+		public string GetPath (string basePath, int index) {
+			StringBuilder buffer = new StringBuilder(basePath.Length + digits);
+			buffer.Append(basePath);
+			string frame = (start + index).ToString();
+			for (int i = digits - frame.Length; i > 0; i--)
+				buffer.Append('0');
+			buffer.Append(frame);
+			return buffer.ToString();
+		}
+	}
+
+	public enum SequenceMode {
+		Hold, Once, Loop, Pingpong, OnceReverse, LoopReverse, PingpongReverse
+	}
+}

+ 11 - 0
spine-csharp/src/Attachments/Sequence.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 522632bd4e297fe47acf78100bfd8689
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 29 - 24
spine-csharp/src/Attachments/VertexAttachment.cs

@@ -37,27 +37,50 @@ namespace Spine {
 		static readonly Object nextIdLock = new Object();
 
 		internal readonly int id;
+		internal VertexAttachment timelineAttachment;
 		internal int[] bones;
 		internal float[] vertices;
 		internal int worldVerticesLength;
-		internal VertexAttachment deformAttachment;
 
 		/// <summary>Gets a unique ID for this attachment.</summary>
 		public int Id { get { return id; } }
 		public int[] Bones { get { return bones; } set { bones = value; } }
 		public float[] Vertices { get { return vertices; } set { vertices = value; } }
 		public int WorldVerticesLength { get { return worldVerticesLength; } set { worldVerticesLength = value; } }
-		///<summary>Deform keys for the deform attachment are also applied to this attachment.
-		/// May be null if no deform keys should be applied.</summary>
-		public VertexAttachment DeformAttachment { get { return deformAttachment; } set { deformAttachment = value; } }
+		///<summary>Timelines for the timeline attachment are also applied to this attachment.
+		/// May be null if no attachment-specific timelines should be applied.</summary>
+		public VertexAttachment TimelineAttachment { get { return timelineAttachment; } set { timelineAttachment = value; } }
 
 		public VertexAttachment (string name)
 			: base(name) {
 
-			deformAttachment = this;
 			lock (VertexAttachment.nextIdLock) {
 				id = VertexAttachment.nextID++;
 			}
+			timelineAttachment = this;
+		}
+
+		/// <summary>Copy constructor.</summary>
+		public VertexAttachment (VertexAttachment other)
+			: base(other) {
+
+			lock (VertexAttachment.nextIdLock) {
+				id = VertexAttachment.nextID++;
+			}
+			timelineAttachment = other.timelineAttachment;
+			if (other.bones != null) {
+				bones = new int[other.bones.Length];
+				Array.Copy(other.bones, 0, bones, 0, bones.Length);
+			} else
+				bones = null;
+
+			if (other.vertices != null) {
+				vertices = new float[other.vertices.Length];
+				Array.Copy(other.vertices, 0, vertices, 0, vertices.Length);
+			} else
+				vertices = null;
+
+			worldVerticesLength = other.worldVerticesLength;
 		}
 
 		public void ComputeWorldVertices (Slot slot, float[] worldVertices) {
@@ -76,7 +99,7 @@ namespace Spine {
 		/// <param name="worldVertices">The output world vertices. Must have a length greater than or equal to <paramref name="offset"/> + <paramref name="count"/>.</param>
 		/// <param name="offset">The <paramref name="worldVertices"/> index to begin writing values.</param>
 		/// <param name="stride">The number of <paramref name="worldVertices"/> entries between the value pairs written.</param>
-		public void ComputeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset, int stride = 2) {
+		public virtual void ComputeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset, int stride = 2) {
 			count = offset + (count >> 1) * stride;
 			ExposedList<float> deformArray = slot.deform;
 			float[] vertices = this.vertices;
@@ -131,23 +154,5 @@ namespace Spine {
 				}
 			}
 		}
-
-		///<summary>Does not copy id (generated) or name (set on construction).</summary>
-		internal void CopyTo (VertexAttachment attachment) {
-			if (bones != null) {
-				attachment.bones = new int[bones.Length];
-				Array.Copy(bones, 0, attachment.bones, 0, bones.Length);
-			} else
-				attachment.bones = null;
-
-			if (vertices != null) {
-				attachment.vertices = new float[vertices.Length];
-				Array.Copy(vertices, 0, attachment.vertices, 0, vertices.Length);
-			} else
-				attachment.vertices = null;
-
-			attachment.worldVerticesLength = worldVerticesLength;
-			attachment.deformAttachment = deformAttachment;
-		}
 	}
 }

+ 17 - 2
spine-csharp/src/Bone.cs

@@ -121,8 +121,6 @@ namespace Spine {
 		/// <summary>Returns the magnitide (always positive) of the world scale Y.</summary>
 		public float WorldScaleY { get { return (float)Math.Sqrt(b * b + d * d); } }
 
-		/// <summary>Copy constructor. Does not copy the <see cref="Children"/> bones.</summary>
-		/// <param name="parent">May be null.</param>
 		public Bone (BoneData data, Skeleton skeleton, Bone parent) {
 			if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
 			if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
@@ -132,6 +130,23 @@ namespace Spine {
 			SetToSetupPose();
 		}
 
+		/// <summary>Copy constructor. Does not copy the <see cref="Children"/> bones.</summary>
+		/// <param name="parent">May be null.</param>
+		public Bone (Bone bone, Skeleton skeleton, Bone parent) {
+			if (bone == null) throw new ArgumentNullException("bone", "bone cannot be null.");
+			if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
+			this.skeleton = skeleton;
+			this.parent = parent;
+			data = bone.data;
+			x = bone.x;
+			y = bone.y;
+			rotation = bone.rotation;
+			scaleX = bone.scaleX;
+			scaleY = bone.scaleY;
+			shearX = bone.shearX;
+			shearY = bone.shearY;
+		}
+
 		/// <summary>Computes the world transform using the parent bone and this bone's local applied transform.</summary>
 		public void Update () {
 			UpdateWorldTransform(ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY);

+ 4 - 4
spine-csharp/src/IkConstraint.cs

@@ -38,8 +38,8 @@ namespace Spine {
 	/// See <a href="http://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide.</para>
 	/// </summary>
 	public class IkConstraint : IUpdatable {
-		internal IkConstraintData data;
-		internal ExposedList<Bone> bones = new ExposedList<Bone>();
+		internal readonly IkConstraintData data;
+		internal readonly ExposedList<Bone> bones = new ExposedList<Bone>();
 		internal Bone target;
 		internal int bendDirection;
 		internal bool compress, stretch;
@@ -59,8 +59,8 @@ namespace Spine {
 
 			bones = new ExposedList<Bone>(data.bones.Count);
 			foreach (BoneData boneData in data.bones)
-				bones.Add(skeleton.FindBone(boneData.name));
-			target = skeleton.FindBone(data.target.name);
+				bones.Add(skeleton.bones.Items[boneData.index]);
+			target = skeleton.bones.Items[data.target.index];
 		}
 
 		/// <summary>Copy constructor.</summary>

+ 14 - 10
spine-csharp/src/PathConstraint.cs

@@ -42,16 +42,16 @@ namespace Spine {
 		const int NONE = -1, BEFORE = -2, AFTER = -3;
 		const float Epsilon = 0.00001f;
 
-		internal PathConstraintData data;
-		internal ExposedList<Bone> bones;
+		internal readonly PathConstraintData data;
+		internal readonly ExposedList<Bone> bones;
 		internal Slot target;
 		internal float position, spacing, mixRotate, mixX, mixY;
 
 		internal bool active;
 
-		internal ExposedList<float> spaces = new ExposedList<float>(), positions = new ExposedList<float>();
-		internal ExposedList<float> world = new ExposedList<float>(), curves = new ExposedList<float>(), lengths = new ExposedList<float>();
-		internal float[] segments = new float[10];
+		internal readonly ExposedList<float> spaces = new ExposedList<float>(), positions = new ExposedList<float>();
+		internal readonly ExposedList<float> world = new ExposedList<float>(), curves = new ExposedList<float>(), lengths = new ExposedList<float>();
+		internal readonly float[] segments = new float[10];
 
 		public PathConstraint (PathConstraintData data, Skeleton skeleton) {
 			if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
@@ -59,8 +59,8 @@ namespace Spine {
 			this.data = data;
 			bones = new ExposedList<Bone>(data.Bones.Count);
 			foreach (BoneData boneData in data.bones)
-				bones.Add(skeleton.FindBone(boneData.name));
-			target = skeleton.FindSlot(data.target.name);
+				bones.Add(skeleton.bones.Items[boneData.index]);
+			target = skeleton.slots.Items[data.target.index];
 			position = data.position;
 			spacing = data.spacing;
 			mixRotate = data.mixRotate;
@@ -73,9 +73,9 @@ namespace Spine {
 			if (constraint == null) throw new ArgumentNullException("constraint cannot be null.");
 			if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null.");
 			data = constraint.data;
-			bones = new ExposedList<Bone>(constraint.Bones.Count);
-			foreach (Bone bone in constraint.Bones)
-				bones.Add(skeleton.Bones.Items[bone.data.index]);
+			bones = new ExposedList<Bone>(constraint.bones.Count);
+			foreach (Bone bone in constraint.bones)
+				bones.Add(skeleton.bones.Items[bone.data.index]);
 			target = skeleton.slots.Items[constraint.target.data.index];
 			position = constraint.position;
 			spacing = constraint.spacing;
@@ -506,5 +506,9 @@ namespace Spine {
 		public bool Active { get { return active; } }
 		/// <summary>The path constraint's setup pose data.</summary>
 		public PathConstraintData Data { get { return data; } }
+
+		override public string ToString () {
+			return data.name;
+		}
 	}
 }

+ 149 - 40
spine-csharp/src/Skeleton.cs

@@ -39,10 +39,10 @@ namespace Spine {
 		internal ExposedList<IkConstraint> ikConstraints;
 		internal ExposedList<TransformConstraint> transformConstraints;
 		internal ExposedList<PathConstraint> pathConstraints;
+		internal ExposedList<SpringConstraint> springConstraints;
 		internal ExposedList<IUpdatable> updateCache = new ExposedList<IUpdatable>();
 		internal Skin skin;
 		internal float r = 1, g = 1, b = 1, a = 1;
-		internal float time;
 		private float scaleX = 1, scaleY = 1;
 		internal float x, y;
 
@@ -53,6 +53,7 @@ namespace Spine {
 		public ExposedList<Slot> DrawOrder { get { return drawOrder; } }
 		public ExposedList<IkConstraint> IkConstraints { get { return ikConstraints; } }
 		public ExposedList<PathConstraint> PathConstraints { get { return pathConstraints; } }
+		public ExposedList<SpringConstraint> SpringConstraints { get { return SpringConstraints; } }
 		public ExposedList<TransformConstraint> TransformConstraints { get { return transformConstraints; } }
 
 		public Skin Skin {
@@ -65,7 +66,6 @@ namespace Spine {
 		public float G { get { return g; } set { g = value; } }
 		public float B { get { return b; } set { b = value; } }
 		public float A { get { return a; } set { a = value; } }
-		public float Time { get { return time; } set { time = value; } }
 		public float X { get { return x; } set { x = value; } }
 		public float Y { get { return y; } set { y = value; } }
 		public float ScaleX { get { return scaleX; } set { scaleX = value; } }
@@ -121,8 +121,68 @@ namespace Spine {
 			foreach (PathConstraintData pathConstraintData in data.pathConstraints)
 				pathConstraints.Add(new PathConstraint(pathConstraintData, this));
 
+			springConstraints = new ExposedList<SpringConstraint>(data.springConstraints.Count);
+			foreach (SpringConstraintData springConstraintData in data.springConstraints)
+				springConstraints.Add(new SpringConstraint(springConstraintData, this));
+
+			UpdateCache();
+		}
+
+		/// <summary>Copy constructor.</summary>
+		public Skeleton (Skeleton skeleton) {
+			if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
+			data = skeleton.data;
+
+			bones = new ExposedList<Bone>(skeleton.bones.Count);
+			foreach (Bone bone in skeleton.bones) {
+				Bone newBone;
+				if (bone.parent == null)
+					newBone = new Bone(bone, this, null);
+				else {
+					Bone parent = bones.Items[bone.parent.data.index];
+					newBone = new Bone(bone, this, parent);
+					parent.children.Add(newBone);
+				}
+				bones.Add(newBone);
+			}
+
+			slots = new ExposedList<Slot>(skeleton.slots.Count);
+			Bone[] bonesItems = bones.Items;
+			foreach (Slot slot in skeleton.slots) {
+				Bone bone = bonesItems[slot.bone.data.index];
+				slots.Add(new Slot(slot, bone));
+			}
+
+			drawOrder = new ExposedList<Slot>(slots.Count);
+			Slot[] slotsItems = slots.Items;
+			foreach (Slot slot in skeleton.drawOrder)
+				drawOrder.Add(slotsItems[slot.data.index]);
+
+			ikConstraints = new ExposedList<IkConstraint>(skeleton.ikConstraints.Count);
+			foreach (IkConstraint ikConstraint in skeleton.ikConstraints)
+				ikConstraints.Add(new IkConstraint(ikConstraint, this));
+
+			transformConstraints = new ExposedList<TransformConstraint>(skeleton.transformConstraints.Count);
+			foreach (TransformConstraint transformConstraint in skeleton.transformConstraints)
+				transformConstraints.Add(new TransformConstraint(transformConstraint, this));
+
+			pathConstraints = new ExposedList<PathConstraint>(skeleton.pathConstraints.Count);
+			foreach (PathConstraint pathConstraint in skeleton.pathConstraints)
+				pathConstraints.Add(new PathConstraint(pathConstraint, this));
+
+			springConstraints = new ExposedList<SpringConstraint>(skeleton.springConstraints.Count);
+			foreach (SpringConstraint springConstraint in skeleton.springConstraints)
+				springConstraints.Add(new SpringConstraint(springConstraint, this));
+
+			skin = skeleton.skin;
+			r = skeleton.r;
+			g = skeleton.g;
+			b = skeleton.b;
+			a = skeleton.a;
+			scaleX = skeleton.scaleX;
+			scaleY = skeleton.scaleY;
+
 			UpdateCache();
-			//UpdateWorldTransform();
 		}
 
 		/// <summary>Caches information about bones and constraints. Must be called if the <see cref="Skin"/> is modified or if bones, constraints, or
@@ -150,11 +210,13 @@ namespace Spine {
 				}
 			}
 
-			int ikCount = this.ikConstraints.Count, transformCount = this.transformConstraints.Count, pathCount = this.pathConstraints.Count;
+			int ikCount = this.ikConstraints.Count, transformCount = this.transformConstraints.Count, pathCount = this.pathConstraints.Count,
+				springCount = this.springConstraints.Count;
 			IkConstraint[] ikConstraints = this.ikConstraints.Items;
 			TransformConstraint[] transformConstraints = this.transformConstraints.Items;
 			PathConstraint[] pathConstraints = this.pathConstraints.Items;
-			int constraintCount = ikCount + transformCount + pathCount;
+			SpringConstraint[] springConstraints = this.springConstraints.Items;
+			int constraintCount = ikCount + transformCount + pathCount + springCount;
 			for (int i = 0; i < constraintCount; i++) {
 				for (int ii = 0; ii < ikCount; ii++) {
 					IkConstraint constraint = ikConstraints[ii];
@@ -177,6 +239,13 @@ namespace Spine {
 						goto continue_outer;
 					}
 				}
+				for (int ii = 0; ii < springCount; ii++) {
+					SpringConstraint constraint = springConstraints[ii];
+					if (constraint.data.order == i) {
+						SortSpringConstraint(constraint);
+						goto continue_outer;
+					}
+				}
 				continue_outer: { }
 			}
 
@@ -210,25 +279,25 @@ namespace Spine {
 			}
 		}
 
-		private void SortPathConstraint (PathConstraint constraint) {
-			constraint.active = constraint.target.bone.active
+		private void SortTransformConstraint (TransformConstraint constraint) {
+			constraint.active = constraint.target.active
 				&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
 			if (!constraint.active) return;
 
-			Slot slot = constraint.target;
-			int slotIndex = slot.data.index;
-			Bone slotBone = slot.bone;
-			if (skin != null) SortPathConstraintAttachment(skin, slotIndex, slotBone);
-			if (data.defaultSkin != null && data.defaultSkin != skin)
-				SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
-
-			Attachment attachment = slot.attachment;
-			if (attachment is PathAttachment) SortPathConstraintAttachment(attachment, slotBone);
+			SortBone(constraint.target);
 
 			var constrained = constraint.bones.Items;
 			int boneCount = constraint.bones.Count;
-			for (int i = 0; i < boneCount; i++)
-				SortBone(constrained[i]);
+			if (constraint.data.local) {
+				for (int i = 0; i < boneCount; i++) {
+					Bone child = constrained[i];
+					SortBone(child.parent);
+					SortBone(child);
+				}
+			} else {
+				for (int i = 0; i < boneCount; i++)
+					SortBone(constrained[i]);
+			}
 
 			updateCache.Add(constraint);
 
@@ -238,25 +307,25 @@ namespace Spine {
 				constrained[i].sorted = true;
 		}
 
-		private void SortTransformConstraint (TransformConstraint constraint) {
-			constraint.active = constraint.target.active
+		private void SortPathConstraint (PathConstraint constraint) {
+			constraint.active = constraint.target.bone.active
 				&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
 			if (!constraint.active) return;
 
-			SortBone(constraint.target);
+			Slot slot = constraint.target;
+			int slotIndex = slot.data.index;
+			Bone slotBone = slot.bone;
+			if (skin != null) SortPathConstraintAttachment(skin, slotIndex, slotBone);
+			if (data.defaultSkin != null && data.defaultSkin != skin)
+				SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
+
+			Attachment attachment = slot.attachment;
+			if (attachment is PathAttachment) SortPathConstraintAttachment(attachment, slotBone);
 
 			var constrained = constraint.bones.Items;
 			int boneCount = constraint.bones.Count;
-			if (constraint.data.local) {
-				for (int i = 0; i < boneCount; i++) {
-					Bone child = constrained[i];
-					SortBone(child.parent);
-					SortBone(child);
-				}
-			} else {
-				for (int i = 0; i < boneCount; i++)
-					SortBone(constrained[i]);
-			}
+			for (int i = 0; i < boneCount; i++)
+				SortBone(constrained[i]);
 
 			updateCache.Add(constraint);
 
@@ -287,6 +356,23 @@ namespace Spine {
 			}
 		}
 
+		private void SortSpringConstraint (SpringConstraint constraint) {
+			constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data));
+			if (!constraint.active) return;
+
+			Object[] constrained = constraint.bones.Items;
+			int boneCount = constraint.bones.Count;
+			for (int i = 0; i < boneCount; i++)
+				SortBone((Bone)constrained[i]);
+
+			updateCache.Add(constraint);
+
+			for (int i = 0; i < boneCount; i++)
+				SortReset(((Bone)constrained[i]).children);
+			for (int i = 0; i < boneCount; i++)
+				((Bone)constrained[i]).sorted = true;
+		}
+
 		private void SortBone (Bone bone) {
 			if (bone.sorted) return;
 			Bone parent = bone.parent;
@@ -372,7 +458,7 @@ namespace Spine {
 			for (int i = 0, n = this.bones.Count; i < n; i++)
 				bones[i].SetToSetupPose();
 
-			var ikConstraints = this.ikConstraints.Items;
+			IkConstraint[] ikConstraints = this.ikConstraints.Items;
 			for (int i = 0, n = this.ikConstraints.Count; i < n; i++) {
 				IkConstraint constraint = ikConstraints[i];
 				IkConstraintData data = constraint.data;
@@ -383,7 +469,7 @@ namespace Spine {
 				constraint.stretch = data.stretch;
 			}
 
-			var transformConstraints = this.transformConstraints.Items;
+			TransformConstraint[] transformConstraints = this.transformConstraints.Items;
 			for (int i = 0, n = this.transformConstraints.Count; i < n; i++) {
 				TransformConstraint constraint = transformConstraints[i];
 				TransformConstraintData data = constraint.data;
@@ -395,7 +481,7 @@ namespace Spine {
 				constraint.mixShearY = data.mixShearY;
 			}
 
-			var pathConstraints = this.pathConstraints.Items;
+			PathConstraint[] pathConstraints = this.pathConstraints.Items;
 			for (int i = 0, n = this.pathConstraints.Count; i < n; i++) {
 				PathConstraint constraint = pathConstraints[i];
 				PathConstraintData data = constraint.data;
@@ -405,6 +491,20 @@ namespace Spine {
 				constraint.mixX = data.mixX;
 				constraint.mixY = data.mixY;
 			}
+
+			SpringConstraint[] springConstraints = this.springConstraints.Items;
+			for (int i = 0, n = this.springConstraints.Count; i < n; i++) {
+				SpringConstraint constraint = springConstraints[i];
+				SpringConstraintData data = constraint.data;
+				constraint.mix = data.mix;
+				constraint.friction = data.friction;
+				constraint.gravity = data.gravity;
+				constraint.wind = data.wind;
+				constraint.stiffness = data.stiffness;
+				constraint.damping = data.damping;
+				constraint.rope = data.rope;
+				constraint.stretch = data.stretch;
+			}
 		}
 
 		public void SetSlotsToSetupPose () {
@@ -558,8 +658,17 @@ namespace Spine {
 			return null;
 		}
 
-		public void Update (float delta) {
-			time += delta;
+		/// <summary>Finds a spring constraint by comparing each spring constraint's name. It is more efficient to cache the results of this
+		/// method than to call it repeatedly.</summary>
+		/// <returns>May be null.</returns>
+		public SpringConstraint FindSpringConstraint (String constraintName) {
+			if (constraintName == null) throw new ArgumentNullException("constraintName", "constraintName cannot be null.");
+			SpringConstraint[] springConstraints = this.springConstraints.Items;
+			for (int i = 0, n = this.springConstraints.Count; i < n; i++) {
+				SpringConstraint constraint = springConstraints[i];
+				if (constraint.data.name.Equals(constraintName)) return constraint;
+			}
+			return null;
 		}
 
 		/// <summary>Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.</summary>
@@ -579,12 +688,12 @@ namespace Spine {
 				int verticesLength = 0;
 				float[] vertices = null;
 				Attachment attachment = slot.attachment;
-				var regionAttachment = attachment as RegionAttachment;
-				if (regionAttachment != null) {
+				RegionAttachment region = attachment as RegionAttachment;
+				if (region != null) {
 					verticesLength = 8;
 					vertices = temp;
 					if (vertices.Length < 8) vertices = temp = new float[8];
-					regionAttachment.ComputeWorldVertices(slot.bone, temp, 0);
+					region.ComputeWorldVertices(slot, temp, 0, 2);
 				} else {
 					var meshAttachment = attachment as MeshAttachment;
 					if (meshAttachment != null) {
@@ -592,7 +701,7 @@ namespace Spine {
 						verticesLength = mesh.WorldVerticesLength;
 						vertices = temp;
 						if (vertices.Length < verticesLength) vertices = temp = new float[verticesLength];
-						mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0);
+						mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0, 2);
 					}
 				}
 

+ 87 - 51
spine-csharp/src/SkeletonBinary.cs

@@ -61,6 +61,9 @@ namespace Spine {
 		public const int SLOT_RGB2 = 4;
 		public const int SLOT_ALPHA = 5;
 
+		public const int ATTACHMENT_DEFORM = 0;
+		public const int ATTACHMENT_SEQUENCE = 1;
+
 		public const int PATH_POSITION = 0;
 		public const int PATH_SPACING = 1;
 		public const int PATH_MIX = 2;
@@ -296,9 +299,9 @@ namespace Spine {
 				if (skin == null) throw new Exception("Skin not found: " + linkedMesh.skin);
 				Attachment parent = skin.GetAttachment(linkedMesh.slotIndex, linkedMesh.parent);
 				if (parent == null) throw new Exception("Parent mesh not found: " + linkedMesh.parent);
-				linkedMesh.mesh.DeformAttachment = linkedMesh.inheritDeform ? (VertexAttachment)parent : linkedMesh.mesh;
+				linkedMesh.mesh.TimelineAttachment = linkedMesh.inheritTimelines ? (VertexAttachment)parent : linkedMesh.mesh;
 				linkedMesh.mesh.ParentMesh = (MeshAttachment)parent;
-				linkedMesh.mesh.UpdateUVs();
+				if (linkedMesh.mesh.Sequence == null) linkedMesh.mesh.UpdateRegion();
 			}
 			linkedMeshes.Clear();
 
@@ -384,9 +387,10 @@ namespace Spine {
 				float width = input.ReadFloat();
 				float height = input.ReadFloat();
 				int color = input.ReadInt();
+				Sequence sequence = ReadSequence(input);
 
 				if (path == null) path = name;
-				RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
+				RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path, sequence);
 				if (region == null) return null;
 				region.Path = path;
 				region.x = x * scale;
@@ -400,7 +404,8 @@ namespace Spine {
 				region.g = ((color & 0x00ff0000) >> 16) / 255f;
 				region.b = ((color & 0x0000ff00) >> 8) / 255f;
 				region.a = ((color & 0x000000ff)) / 255f;
-				region.UpdateOffset();
+				region.sequence = sequence;
+				if (sequence == null) region.UpdateRegion();
 				return region;
 			}
 			case AttachmentType.Boundingbox: {
@@ -424,6 +429,7 @@ namespace Spine {
 				int[] triangles = ReadShortArray(input);
 				Vertices vertices = ReadVertices(input, vertexCount);
 				int hullLength = input.ReadInt(true);
+				Sequence sequence = ReadSequence(input);
 				int[] edges = null;
 				float width = 0, height = 0;
 				if (nonessential) {
@@ -433,7 +439,7 @@ namespace Spine {
 				}
 
 				if (path == null) path = name;
-				MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
+				MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path, sequence);
 				if (mesh == null) return null;
 				mesh.Path = path;
 				mesh.r = ((color & 0xff000000) >> 24) / 255f;
@@ -445,8 +451,9 @@ namespace Spine {
 				mesh.WorldVerticesLength = vertexCount << 1;
 				mesh.triangles = triangles;
 				mesh.regionUVs = uvs;
-				mesh.UpdateUVs();
+				if (sequence == null) mesh.UpdateRegion();
 				mesh.HullLength = hullLength << 1;
+				mesh.Sequence = sequence;
 				if (nonessential) {
 					mesh.Edges = edges;
 					mesh.Width = width * scale;
@@ -459,7 +466,8 @@ namespace Spine {
 				int color = input.ReadInt();
 				String skinName = input.ReadStringRef();
 				String parent = input.ReadStringRef();
-				bool inheritDeform = input.ReadBoolean();
+				bool inheritTimelines = input.ReadBoolean();
+				Sequence sequence = ReadSequence(input);
 				float width = 0, height = 0;
 				if (nonessential) {
 					width = input.ReadFloat();
@@ -467,18 +475,19 @@ namespace Spine {
 				}
 
 				if (path == null) path = name;
-				MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
+				MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path, sequence);
 				if (mesh == null) return null;
 				mesh.Path = path;
 				mesh.r = ((color & 0xff000000) >> 24) / 255f;
 				mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
 				mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
 				mesh.a = ((color & 0x000000ff)) / 255f;
+				mesh.Sequence = sequence;
 				if (nonessential) {
 					mesh.Width = width * scale;
 					mesh.Height = height * scale;
 				}
-				linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent, inheritDeform));
+				linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent, inheritTimelines));
 				return mesh;
 			}
 			case AttachmentType.Path: {
@@ -535,6 +544,15 @@ namespace Spine {
 			return null;
 		}
 
+		private Sequence ReadSequence (SkeletonInput input) {
+			if (!input.ReadBoolean()) return null;
+			Sequence sequence = new Sequence(input.ReadInt(true));
+			sequence.Start = input.ReadInt(true);
+			sequence.Digits = input.ReadInt(true);
+			sequence.SetupIndex = input.ReadInt(true);
+			return sequence;
+		}
+
 		private Vertices ReadVertices (SkeletonInput input, int vertexCount) {
 			float scale = this.scale;
 			int verticesLength = vertexCount << 1;
@@ -904,58 +922,76 @@ namespace Spine {
 				}
 			}
 
-			// Deform timelines.
+			// Attachment timelines.
 			for (int i = 0, n = input.ReadInt(true); i < n; i++) {
 				Skin skin = skeletonData.skins.Items[input.ReadInt(true)];
 				for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
 					int slotIndex = input.ReadInt(true);
 					for (int iii = 0, nnn = input.ReadInt(true); iii < nnn; iii++) {
 						String attachmentName = input.ReadStringRef();
-						VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, attachmentName);
-						if (attachment == null) throw new SerializationException("Vertex attachment not found: " + attachmentName);
-						bool weighted = attachment.Bones != null;
-						float[] vertices = attachment.Vertices;
-						int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
-
-						int frameCount = input.ReadInt(true), frameLast = frameCount - 1;
-						DeformTimeline timeline = new DeformTimeline(frameCount, input.ReadInt(true), slotIndex, attachment);
-
-						float time = input.ReadFloat();
-						for (int frame = 0, bezier = 0; ; frame++) {
-							float[] deform;
-							int end = input.ReadInt(true);
-							if (end == 0)
-								deform = weighted ? new float[deformLength] : vertices;
-							else {
-								deform = new float[deformLength];
-								int start = input.ReadInt(true);
-								end += start;
-								if (scale == 1) {
-									for (int v = start; v < end; v++)
-										deform[v] = input.ReadFloat();
-								} else {
-									for (int v = start; v < end; v++)
-										deform[v] = input.ReadFloat() * scale;
+						Attachment attachment = skin.GetAttachment(slotIndex, attachmentName);
+						if (attachment == null) throw new SerializationException("Timeline attachment not found: " + attachmentName);
+
+						int timelineType = input.ReadByte(), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
+						switch (timelineType) {
+						case ATTACHMENT_DEFORM: {
+							VertexAttachment vertexAttachment = (VertexAttachment)attachment;
+							bool weighted = vertexAttachment.Bones != null;
+							float[] vertices = vertexAttachment.Vertices;
+							int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
+
+							DeformTimeline timeline = new DeformTimeline(frameCount, input.ReadInt(true), slotIndex, vertexAttachment);
+
+							float time = input.ReadFloat();
+							for (int frame = 0, bezier = 0; ; frame++) {
+								float[] deform;
+								int end = input.ReadInt(true);
+								if (end == 0)
+									deform = weighted ? new float[deformLength] : vertices;
+								else {
+									deform = new float[deformLength];
+									int start = input.ReadInt(true);
+									end += start;
+									if (scale == 1) {
+										for (int v = start; v < end; v++)
+											deform[v] = input.ReadFloat();
+									} else {
+										for (int v = start; v < end; v++)
+											deform[v] = input.ReadFloat() * scale;
+									}
+									if (!weighted) {
+										for (int v = 0, vn = deform.Length; v < vn; v++)
+											deform[v] += vertices[v];
+									}
 								}
-								if (!weighted) {
-									for (int v = 0, vn = deform.Length; v < vn; v++)
-										deform[v] += vertices[v];
+								timeline.SetFrame(frame, time, deform);
+								if (frame == frameLast) break;
+								float time2 = input.ReadFloat();
+								switch (input.ReadByte()) {
+								case CURVE_STEPPED:
+									timeline.SetStepped(frame);
+									break;
+								case CURVE_BEZIER:
+									SetBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
+									break;
 								}
+								time = time2;
 							}
-							timeline.SetFrame(frame, time, deform);
-							if (frame == frameLast) break;
-							float time2 = input.ReadFloat();
-							switch (input.ReadByte()) {
-							case CURVE_STEPPED:
-								timeline.SetStepped(frame);
-								break;
-							case CURVE_BEZIER:
-								SetBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
-								break;
-							}
-							time = time2;
+							timelines.Add(timeline);
+							break;
 						}
-						timelines.Add(timeline);
+						case ATTACHMENT_SEQUENCE: {
+							SequenceTimeline timeline = new SequenceTimeline(frameCount, slotIndex, attachment);
+							for (int frame = 0; frame < frameCount; frame++) {
+								float time = input.ReadFloat();
+								int modeAndIndex = input.ReadInt();
+								timeline.SetFrame(frame, time, (SequenceMode)(modeAndIndex & 0xf), modeAndIndex >> 4,
+									input.ReadFloat());
+							}
+							timelines.Add(timeline);
+							break;
+						} // end case
+						} // end switch
 					}
 				}
 			}

+ 30 - 8
spine-csharp/src/SkeletonData.cs

@@ -43,6 +43,7 @@ namespace Spine {
 		internal ExposedList<IkConstraintData> ikConstraints = new ExposedList<IkConstraintData>();
 		internal ExposedList<TransformConstraintData> transformConstraints = new ExposedList<TransformConstraintData>();
 		internal ExposedList<PathConstraintData> pathConstraints = new ExposedList<PathConstraintData>();
+		internal ExposedList<SpringConstraintData> springConstraints = new ExposedList<SpringConstraintData>();
 		internal float x, y, width, height;
 		internal string version, hash;
 
@@ -95,7 +96,7 @@ namespace Spine {
 		/// <summary>The dopesheet FPS in Spine, or zero if nonessential data was not exported.</summary>
 		public float Fps { get { return fps; } set { fps = value; } }
 
-		// --- Bones.
+		// --- Bones
 
 		/// <summary>
 		/// Finds a bone by comparing each bone's name.
@@ -111,7 +112,7 @@ namespace Spine {
 			return null;
 		}
 
-		// --- Slots.
+		// --- Slots
 
 		/// <returns>May be null.</returns>
 		public SlotData FindSlot (string slotName) {
@@ -124,7 +125,7 @@ namespace Spine {
 			return null;
 		}
 
-		// --- Skins.
+		// --- Skins
 
 		/// <returns>May be null.</returns>
 		public Skin FindSkin (string skinName) {
@@ -134,7 +135,7 @@ namespace Spine {
 			return null;
 		}
 
-		// --- Events.
+		// --- Events
 
 		/// <returns>May be null.</returns>
 		public EventData FindEvent (string eventDataName) {
@@ -144,7 +145,7 @@ namespace Spine {
 			return null;
 		}
 
-		// --- Animations.
+		// --- Animations
 
 		/// <returns>May be null.</returns>
 		public Animation FindAnimation (string animationName) {
@@ -157,7 +158,7 @@ namespace Spine {
 			return null;
 		}
 
-		// --- IK constraints.
+		// --- IK constraints
 
 		/// <returns>May be null.</returns>
 		public IkConstraintData FindIkConstraint (string constraintName) {
@@ -170,7 +171,7 @@ namespace Spine {
 			return null;
 		}
 
-		// --- Transform constraints.
+		// --- Transform constraints
 
 		/// <returns>May be null.</returns>
 		public TransformConstraintData FindTransformConstraint (string constraintName) {
@@ -183,8 +184,12 @@ namespace Spine {
 			return null;
 		}
 
-		// --- Path constraints.
+		// --- Path constraints
 
+		/// <summary>
+		/// Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method
+		/// than to call it multiple times.
+		/// </summary>
 		/// <returns>May be null.</returns>
 		public PathConstraintData FindPathConstraint (string constraintName) {
 			if (constraintName == null) throw new ArgumentNullException("constraintName", "constraintName cannot be null.");
@@ -196,6 +201,23 @@ namespace Spine {
 			return null;
 		}
 
+		// --- Spring constraints
+
+		/// <summary>
+		/// Finds a spring constraint by comparing each spring constraint's name. It is more efficient to cache the results of this
+		/// method than to call it multiple times.
+		/// </summary>
+		/// <returns>May be null.</returns>
+		public SpringConstraintData FindSpringConstraint (String constraintName) {
+			if (constraintName == null) throw new ArgumentNullException("constraintName", "constraintName cannot be null.");
+			Object[] springConstraints = this.springConstraints.Items;
+			for (int i = 0, n = this.springConstraints.Count; i < n; i++) {
+				SpringConstraintData constraint = (SpringConstraintData)springConstraints[i];
+				if (constraint.name.Equals(constraintName)) return constraint;
+			}
+			return null;
+		}
+
 		// ---
 
 		override public string ToString () {

+ 107 - 60
spine-csharp/src/SkeletonJson.cs

@@ -336,9 +336,9 @@ namespace Spine {
 				if (skin == null) throw new Exception("Slot not found: " + linkedMesh.skin);
 				Attachment parent = skin.GetAttachment(linkedMesh.slotIndex, linkedMesh.parent);
 				if (parent == null) throw new Exception("Parent mesh not found: " + linkedMesh.parent);
-				linkedMesh.mesh.DeformAttachment = linkedMesh.inheritDeform ? (VertexAttachment)parent : linkedMesh.mesh;
+				linkedMesh.mesh.TimelineAttachment = linkedMesh.inheritTimelines ? (VertexAttachment)parent : linkedMesh.mesh;
 				linkedMesh.mesh.ParentMesh = (MeshAttachment)parent;
-				linkedMesh.mesh.UpdateUVs();
+				if (linkedMesh.mesh.Region != null) linkedMesh.mesh.UpdateRegion();
 			}
 			linkedMeshes.Clear();
 
@@ -386,11 +386,13 @@ namespace Spine {
 			var typeName = GetString(map, "type", "region");
 			var type = (AttachmentType)Enum.Parse(typeof(AttachmentType), typeName, true);
 
-			string path = GetString(map, "path", name);
-
 			switch (type) {
-			case AttachmentType.Region:
-				RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
+			case AttachmentType.Region: {
+				string path = GetString(map, "path", name);
+				object sequenceJson;
+				map.TryGetValue("sequence", out sequenceJson);
+				Sequence sequence = ReadSequence(sequenceJson);
+				RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path, sequence);
 				if (region == null) return null;
 				region.Path = path;
 				region.x = GetFloat(map, "x", 0) * scale;
@@ -400,6 +402,7 @@ namespace Spine {
 				region.rotation = GetFloat(map, "rotation", 0);
 				region.width = GetFloat(map, "width", 32) * scale;
 				region.height = GetFloat(map, "height", 32) * scale;
+				region.sequence = sequence;
 
 				if (map.ContainsKey("color")) {
 					var color = (string)map["color"];
@@ -409,8 +412,9 @@ namespace Spine {
 					region.a = ToColor(color, 3);
 				}
 
-				region.UpdateOffset();
+				if (region.Region != null) region.UpdateRegion();
 				return region;
+			}
 			case AttachmentType.Boundingbox:
 				BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name);
 				if (box == null) return null;
@@ -418,7 +422,11 @@ namespace Spine {
 				return box;
 			case AttachmentType.Mesh:
 			case AttachmentType.Linkedmesh: {
-				MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
+				string path = GetString(map, "path", name);
+				object sequenceJson;
+				map.TryGetValue("sequence", out sequenceJson);
+				Sequence sequence = ReadSequence(sequenceJson);
+				MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path, sequence);
 				if (mesh == null) return null;
 				mesh.Path = path;
 
@@ -432,10 +440,11 @@ namespace Spine {
 
 				mesh.Width = GetFloat(map, "width", 0) * scale;
 				mesh.Height = GetFloat(map, "height", 0) * scale;
+				mesh.Sequence = sequence;
 
 				string parent = GetString(map, "parent", null);
 				if (parent != null) {
-					linkedMeshes.Add(new LinkedMesh(mesh, GetString(map, "skin", null), slotIndex, parent, GetBoolean(map, "deform", true)));
+					linkedMeshes.Add(new LinkedMesh(mesh, GetString(map, "skin", null), slotIndex, parent, GetBoolean(map, "timelines", true)));
 					return mesh;
 				}
 
@@ -443,7 +452,7 @@ namespace Spine {
 				ReadVertices(map, mesh, uvs.Length);
 				mesh.triangles = GetIntArray(map, "triangles");
 				mesh.regionUVs = uvs;
-				mesh.UpdateUVs();
+				if (mesh.Region != null) mesh.UpdateRegion();
 
 				if (map.ContainsKey("hull")) mesh.HullLength = GetInt(map, "hull", 0) << 1;
 				if (map.ContainsKey("edges")) mesh.Edges = GetIntArray(map, "edges");
@@ -494,6 +503,16 @@ namespace Spine {
 			return null;
 		}
 
+		public static Sequence ReadSequence (object sequenceJson) {
+			var map = sequenceJson as Dictionary<string, Object>;
+			if (map == null) return null;
+			Sequence sequence = new Sequence(GetInt(map, "count"));
+			sequence.start = GetInt(map, "start", 1);
+			sequence.digits = GetInt(map, "digits", 0);
+			sequence.setupIndex = GetInt(map, "setup", 0);
+			return sequence;
+		}
+
 		private void ReadVertices (Dictionary<string, Object> map, VertexAttachment attachment, int verticesLength) {
 			attachment.WorldVerticesLength = verticesLength;
 			float[] vertices = GetFloatArray(map, "vertices", 1);
@@ -549,7 +568,7 @@ namespace Spine {
 							var timeline = new AttachmentTimeline(frames, slotIndex);
 							int frame = 0;
 							foreach (Dictionary<string, Object> keyMap in values) {
-								timeline.SetFrame(frame++, GetFloat(keyMap, "time", 0), (string)keyMap["name"]);
+								timeline.SetFrame(frame++, GetFloat(keyMap, "time", 0), GetString(keyMap, "name", null));
 							}
 							timelines.Add(timeline);
 
@@ -945,59 +964,82 @@ namespace Spine {
 				}
 			}
 
-			// Deform timelines.
-			if (map.ContainsKey("deform")) {
-				foreach (KeyValuePair<string, Object> deformMap in (Dictionary<string, Object>)map["deform"]) {
-					Skin skin = skeletonData.FindSkin(deformMap.Key);
-					foreach (KeyValuePair<string, Object> slotMap in (Dictionary<string, Object>)deformMap.Value) {
-						int slotIndex = FindSlotIndex(skeletonData, slotMap.Key);
-						foreach (KeyValuePair<string, Object> timelineMap in (Dictionary<string, Object>)slotMap.Value) {
-							var values = (List<Object>)timelineMap.Value;
-							var keyMapEnumerator = values.GetEnumerator();
-							if (!keyMapEnumerator.MoveNext()) continue;
-							var keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
-							VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, timelineMap.Key);
-							if (attachment == null) throw new Exception("Deform attachment not found: " + timelineMap.Key);
-							bool weighted = attachment.bones != null;
-							float[] vertices = attachment.vertices;
-							int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
-							DeformTimeline timeline = new DeformTimeline(values.Count, values.Count, slotIndex, attachment);
-							float time = GetFloat(keyMap, "time", 0);
-							for (int frame = 0, bezier = 0; ; frame++) {
-								float[] deform;
-								if (!keyMap.ContainsKey("vertices")) {
-									deform = weighted ? new float[deformLength] : vertices;
-								} else {
-									deform = new float[deformLength];
-									int start = GetInt(keyMap, "offset", 0);
-									float[] verticesValue = GetFloatArray(keyMap, "vertices", 1);
-									Array.Copy(verticesValue, 0, deform, start, verticesValue.Length);
-									if (scale != 1) {
-										for (int i = start, n = i + verticesValue.Length; i < n; i++)
-											deform[i] *= scale;
+			// Attachment timelines.
+			if (map.ContainsKey("attachments")) {
+				foreach (KeyValuePair<string, Object> attachmentsMap in (Dictionary<string, Object>)map["attachments"]) {
+					Skin skin = skeletonData.FindSkin(attachmentsMap.Key);
+					foreach (KeyValuePair<string, Object> slotMap in (Dictionary<string, Object>)attachmentsMap.Value) {
+						SlotData slot = skeletonData.FindSlot(slotMap.Key);
+						if (slot == null) throw new Exception("Slot not found: " + slotMap.Key);
+						foreach (KeyValuePair<string, Object> attachmentMap in (Dictionary<string, Object>)slotMap.Value) {
+							Attachment attachment = skin.GetAttachment(slot.index, attachmentMap.Key);
+							if (attachment == null) throw new Exception("Timeline attachment not found: " + attachmentMap.Key);
+							foreach (KeyValuePair<string, Object> timelineMap in (Dictionary<string, Object>)attachmentMap.Value) {
+								var values = (List<Object>)timelineMap.Value;
+								var keyMapEnumerator = values.GetEnumerator();
+								if (!keyMapEnumerator.MoveNext()) continue;
+								var keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
+								int frames = values.Count;
+								string timelineName = timelineMap.Key;
+								if (timelineName == "deform") {
+									VertexAttachment vertexAttachment = (VertexAttachment)attachment;
+									bool weighted = vertexAttachment.bones != null;
+									float[] vertices = vertexAttachment.vertices;
+									int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
+
+									DeformTimeline timeline = new DeformTimeline(frames, frames, slot.Index, vertexAttachment);
+									float time = GetFloat(keyMap, "time", 0);
+									for (int frame = 0, bezier = 0; ; frame++) {
+										float[] deform;
+										if (!keyMap.ContainsKey("vertices")) {
+											deform = weighted ? new float[deformLength] : vertices;
+										} else {
+											deform = new float[deformLength];
+											int start = GetInt(keyMap, "offset", 0);
+											float[] verticesValue = GetFloatArray(keyMap, "vertices", 1);
+											Array.Copy(verticesValue, 0, deform, start, verticesValue.Length);
+											if (scale != 1) {
+												for (int i = start, n = i + verticesValue.Length; i < n; i++)
+													deform[i] *= scale;
+											}
+
+											if (!weighted) {
+												for (int i = 0; i < deformLength; i++)
+													deform[i] += vertices[i];
+											}
+										}
+
+										timeline.SetFrame(frame, time, deform);
+										if (!keyMapEnumerator.MoveNext()) {
+											timeline.Shrink(bezier);
+											break;
+										}
+										var nextMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
+										float time2 = GetFloat(nextMap, "time", 0);
+										if (keyMap.ContainsKey("curve")) {
+											object curve = keyMap["curve"];
+											bezier = ReadCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
+										}
+										time = time2;
+										keyMap = nextMap;
 									}
-
-									if (!weighted) {
-										for (int i = 0; i < deformLength; i++)
-											deform[i] += vertices[i];
+									timelines.Add(timeline);
+								} else if (timelineName == "sequence") {
+									SequenceTimeline timeline = new SequenceTimeline(frames, slot.index, attachment);
+									float lastDelay = 0;
+									for (int frame = 0; keyMap != null;
+										keyMapEnumerator.MoveNext(), keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current, frame++) {
+
+										float delay = GetFloat(keyMap, "delay", lastDelay);
+										SequenceMode sequenceMode = (SequenceMode)Enum.Parse(typeof(SequenceMode),
+											GetString(keyMap, "mode", "hold"), true);
+										timeline.SetFrame(frame, GetFloat(keyMap, "time", 0),
+											sequenceMode, GetInt(keyMap, "index", 0), delay);
+										lastDelay = delay;
 									}
+									timelines.Add(timeline);
 								}
-
-								timeline.SetFrame(frame, time, deform);
-								if (!keyMapEnumerator.MoveNext()) {
-									timeline.Shrink(bezier);
-									break;
-								}
-								var nextMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
-								float time2 = GetFloat(nextMap, "time", 0);
-								if (keyMap.ContainsKey("curve")) {
-									object curve = keyMap["curve"];
-									bezier = ReadCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
-								}
-								time = time2;
-								keyMap = nextMap;
 							}
-							timelines.Add(timeline);
 						}
 					}
 				}
@@ -1174,6 +1216,11 @@ namespace Spine {
 			return (int)(float)map[name];
 		}
 
+		static int GetInt (Dictionary<string, Object> map, string name) {
+			if (!map.ContainsKey(name)) throw new ArgumentException("Named value not found: " + name);
+			return (int)(float)map[name];
+		}
+
 		static bool GetBoolean (Dictionary<string, Object> map, string name, bool defaultValue) {
 			if (!map.ContainsKey(name)) return defaultValue;
 			return (bool)map[name];

+ 3 - 3
spine-csharp/src/SkeletonLoader.cs

@@ -77,14 +77,14 @@ namespace Spine {
 			internal string parent, skin;
 			internal int slotIndex;
 			internal MeshAttachment mesh;
-			internal bool inheritDeform;
+			internal bool inheritTimelines;
 
-			public LinkedMesh (MeshAttachment mesh, string skin, int slotIndex, string parent, bool inheritDeform) {
+			public LinkedMesh (MeshAttachment mesh, string skin, int slotIndex, string parent, bool inheritTimelines) {
 				this.mesh = mesh;
 				this.skin = skin;
 				this.slotIndex = slotIndex;
 				this.parent = parent;
-				this.inheritDeform = inheritDeform;
+				this.inheritTimelines = inheritTimelines;
 			}
 		}
 

+ 12 - 13
spine-csharp/src/Slot.cs

@@ -43,7 +43,7 @@ namespace Spine {
 		internal float r2, g2, b2;
 		internal bool hasSecondColor;
 		internal Attachment attachment;
-		internal float attachmentTime;
+		internal int sequenceIndex;
 		internal ExposedList<float> deform = new ExposedList<float>();
 		internal int attachmentState;
 
@@ -83,7 +83,7 @@ namespace Spine {
 			hasSecondColor = slot.hasSecondColor;
 
 			attachment = slot.attachment;
-			attachmentTime = slot.attachmentTime;
+			sequenceIndex = slot.sequenceIndex;
 			deform.AddRange(slot.deform);
 		}
 
@@ -135,27 +135,26 @@ namespace Spine {
 			/// <summary>The current attachment for the slot, or null if the slot has no attachment.</summary>
 			get { return attachment; }
 			/// <summary>
-			/// Sets the slot's attachment and, if the attachment changed, resets <see cref="AttachmentTime"/> and clears the <see cref="Deform"/>.
-			/// The deform is not cleared if the old attachment has the same <see cref="VertexAttachment.DeformAttachment"/> as the specified
-			/// attachment.</summary>
+			/// Sets the slot's attachment and, if the attachment changed, resets <see cref="SequenceIndex"/> and clears the <see cref="Deform"/>.
+			/// The deform is not cleared if the old attachment has the same <see cref="VertexAttachment.TimelineAttachment"/> as the
+			/// specified attachment.</summary>
 			/// <param name="value">May be null.</param>
 			set {
 				if (attachment == value) return;
 				if (!(value is VertexAttachment) || !(this.attachment is VertexAttachment)
-					|| ((VertexAttachment)value).DeformAttachment != ((VertexAttachment)this.attachment).DeformAttachment) {
+					|| ((VertexAttachment)value).TimelineAttachment != ((VertexAttachment)this.attachment).TimelineAttachment) {
 					deform.Clear();
 				}
 				this.attachment = value;
-				attachmentTime = bone.skeleton.time;
+				sequenceIndex = -1;
 			}
 		}
 
-		/// <summary> The time that has elapsed since the last time the attachment was set or cleared. Relies on Skeleton
-		/// <see cref="Skeleton.Time"/></summary>
-		public float AttachmentTime {
-			get { return bone.skeleton.time - attachmentTime; }
-			set { attachmentTime = bone.skeleton.time - value; }
-		}
+		/// <summary>
+		/// The index of the texture region to display when the slot's attachment has a <see cref="Sequence"/>. -1 represents the
+		/// <see cref="Sequence.SetupIndex"/>.
+		/// </summary>
+		public int SequenceIndex { get { return sequenceIndex; } set { sequenceIndex = value; } }
 
 		/// <summary> Vertices to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a
 		/// weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions.

+ 105 - 0
spine-csharp/src/SpringConstraint.cs

@@ -0,0 +1,105 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated September 24, 2021. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2021, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+using System;
+
+namespace Spine {
+	/// <summary>
+	/// Stores the current pose for a spring constraint. A spring constraint applies physics to bones.
+	/// <para>
+	/// See <a href="http://esotericsoftware.com/spine-spring-constraints">Spring constraints</a> in the Spine User Guide.</para>
+	/// </summary>
+	public class SpringConstraint : IUpdatable {
+		internal readonly SpringConstraintData data;
+		internal readonly ExposedList<Bone> bones;
+		// BOZO! - stiffness -> strength. stiffness, damping, rope, stretch -> move to spring.
+		internal float mix, friction, gravity, wind, stiffness, damping;
+		internal bool rope, stretch;
+
+		internal bool active;
+
+		public SpringConstraint (SpringConstraintData data, Skeleton skeleton) {
+			if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
+			if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
+			this.data = data;
+			mix = data.mix;
+			friction = data.friction;
+			gravity = data.gravity;
+			wind = data.wind;
+			stiffness = data.stiffness;
+			damping = data.damping;
+			rope = data.rope;
+			stretch = data.stretch;
+
+			bones = new ExposedList<Bone>(data.Bones.Count);
+			foreach (BoneData boneData in data.bones)
+				bones.Add(skeleton.bones.Items[boneData.index]);
+		}
+
+		/// <summary>Copy constructor.</summary>
+		public SpringConstraint (SpringConstraint constraint, Skeleton skeleton) {
+			if (constraint == null) throw new ArgumentNullException("constraint", "constraint cannot be null.");
+			if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
+			data = constraint.data;
+			bones = new ExposedList<Bone>(constraint.bones.Count);
+			foreach (Bone bone in constraint.bones)
+				bones.Add(skeleton.bones.Items[bone.data.index]);
+			mix = constraint.mix;
+			friction = constraint.friction;
+			gravity = constraint.gravity;
+			wind = constraint.wind;
+			stiffness = constraint.stiffness;
+			damping = constraint.damping;
+			rope = constraint.rope;
+			stretch = constraint.stretch;
+		}
+
+		/// <summary>Applies the constraint to the constrained bones.</summary>
+		public void Update () {
+
+		}
+
+		/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained poses.</summary>
+		public float Mix { get { return mix; } set { mix = value; } }
+		public float Friction { get { return friction; } set { friction = value; } }
+		public float Gravity { get { return gravity; } set { gravity = value; } }
+		public float Wind { get { return wind; } set { wind = value; } }
+		public float Stiffness { get { return stiffness; } set { stiffness = value; } }
+		public float Damping { get { return damping; } set { damping = value; } }
+		public bool Rope { get { return rope; } set { rope = value; } }
+		public bool Stretch { get { return stretch; } set { stretch = value; } }
+		public bool Active { get { return active; } }
+		/// <summary>The spring constraint's setup pose data.</summary>
+		public SpringConstraintData Data { get { return data; } }
+
+		override public string ToString () {
+			return data.name;
+		}
+	}
+}

+ 11 - 0
spine-csharp/src/SpringConstraint.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e2816491d178b3b4986920107586ce55
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 59 - 0
spine-csharp/src/SpringConstraintData.cs

@@ -0,0 +1,59 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated September 24, 2021. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2021, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+using System;
+
+namespace Spine {
+	/// <summary>
+	/// Stores the setup pose for a <see cref="SpringConstraint"/>.
+	/// <para>
+	/// See <a href="http://esotericsoftware.com/spine-spring-constraints">Spring constraints</a> in the Spine User Guide.</para>
+	/// </summary>
+	public class SpringConstraintData : ConstraintData {
+		internal ExposedList<BoneData> bones = new ExposedList<BoneData>();
+		internal float mix, friction, gravity, wind, stiffness, damping;
+		internal bool rope, stretch;
+
+		public SpringConstraintData (string name) : base(name) {
+		}
+
+		/// <summary>The bones that are constrained by this spring constraint.</summary>
+		public ExposedList<BoneData> Bones { get { return bones; } }
+
+		/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained poses.</summary>
+		public float Mix { get { return mix; } set { mix = value; } }
+		public float Friction { get { return friction; } set { friction = value; } }
+		public float Gravity { get { return gravity; } set { gravity = value; } }
+		public float Wind { get { return wind; } set { wind = value; } }
+		public float Stiffness { get { return stiffness; } set { stiffness = value; } }
+		public float Damping { get { return damping; } set { damping = value; } }
+		public bool Rope { get { return rope; } set { rope = value; } }
+		public bool Stretch { get { return stretch; } set { stretch = value; } }
+	}
+}

+ 11 - 0
spine-csharp/src/SpringConstraintData.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 438688f6194e6dc40953a23d05d48e1a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 49 - 0
spine-csharp/src/TextureRegion.cs

@@ -0,0 +1,49 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated September 24, 2021. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2021, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software
+ * or otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#if (UNITY_5 || UNITY_5_3_OR_NEWER || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
+#define IS_UNITY
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+
+
+namespace Spine {
+	public class TextureRegion {
+		public int width, height;
+		public float u, v, u2, v2;
+
+		virtual public int OriginalWidth { get { return width; } }
+		virtual public int OriginalHeight { get { return height; } }
+	}
+}

+ 4 - 4
spine-csharp/src/TransformConstraint.cs

@@ -38,8 +38,8 @@ namespace Spine {
 	/// See <a href="http://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide.</para>
 	/// </summary>
 	public class TransformConstraint : IUpdatable {
-		internal TransformConstraintData data;
-		internal ExposedList<Bone> bones;
+		internal readonly TransformConstraintData data;
+		internal readonly ExposedList<Bone> bones;
 		internal Bone target;
 		internal float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
 
@@ -57,9 +57,9 @@ namespace Spine {
 			mixShearY = data.mixShearY;
 			bones = new ExposedList<Bone>();
 			foreach (BoneData boneData in data.bones)
-				bones.Add(skeleton.FindBone(boneData.name));
+				bones.Add(skeleton.bones.Items[boneData.index]);
 
-			target = skeleton.FindBone(data.target.name);
+			target = skeleton.bones.Items[data.target.index];
 		}
 
 		/// <summary>Copy constructor.</summary>

+ 1 - 1
spine-csharp/src/package.json

@@ -2,7 +2,7 @@
 	"name": "com.esotericsoftware.spine.spine-csharp",
 	"displayName": "spine-csharp Runtime",
 	"description": "This plugin provides the spine-csharp core runtime.",
-	"version": "4.0.0",
+	"version": "4.1.0",
 	"unity": "2018.3",
 	"author": {
 		"name": "Esoteric Software",

+ 2 - 3
spine-csharp/tests/src/AnimationStateTests.cs

@@ -44,11 +44,11 @@ namespace Spine {
 		}
 
 		class NullAttachmentLoader : AttachmentLoader {
-			public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
+			public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
 				return null;
 			}
 
-			public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
+			public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
 				return null;
 			}
 
@@ -851,7 +851,6 @@ namespace Spine {
 			state.Apply(skeleton);
 			while (time < endTime) {
 				time += incr;
-				skeleton.Update(incr);
 				state.Update(incr);
 
 				// Reduce float discrepancies for tests.

+ 1 - 1
spine-unity/Assets/Spine Examples/Scripts/Sample Components/RootMotionDeltaCompensation.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: e47cc991328826946a8c4efdd1885bf2
+guid: 1e002a2e05cd8a441801b685e426f6c8
 timeCreated: 1599066046
 licenseType: Pro
 MonoImporter:

+ 0 - 1
spine-unity/Assets/Spine Examples/Scripts/SpineGauge.cs

@@ -56,7 +56,6 @@ namespace Spine.Unity.Examples {
 			var skeleton = skeletonRenderer.skeleton; if (skeleton == null) return;
 
 			fillAnimation.Animation.Apply(skeleton, 0, percent, false, null, 1f, MixBlend.Setup, MixDirection.In);
-			skeleton.Update(Time.deltaTime);
 			skeleton.UpdateWorldTransform();
 		}
 	}

+ 77 - 60
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.atlas.txt

@@ -3,110 +3,127 @@ dragon.png
 	filter: Linear, Linear
 	pma: true
 back
-	bounds: 2, 334, 190, 185
+	bounds: 564, 534, 190, 185
 chest
-	bounds: 2, 697, 136, 122
+	bounds: 2, 645, 136, 122
 chin
-	bounds: 611, 613, 214, 146
+	bounds: 140, 619, 214, 146
 front-toe-a
-	bounds: 2, 914, 29, 50
+	bounds: 2, 862, 29, 50
 	rotate: 90
 front-toe-b
-	bounds: 467, 887, 56, 57
+	bounds: 467, 835, 56, 57
+	rotate: 90
+head
+	bounds: 756, 398, 296, 260
 	rotate: 90
 left-front-leg
-	bounds: 599, 886, 84, 57
+	bounds: 599, 834, 84, 57
 left-front-thigh
-	bounds: 782, 871, 84, 72
+	bounds: 782, 819, 84, 72
 left-rear-leg
-	bounds: 465, 434, 206, 177
+	bounds: 356, 558, 206, 177
 left-rear-thigh
-	bounds: 216, 819, 91, 149
+	bounds: 216, 767, 91, 149
 	rotate: 90
 left-wing01
-	bounds: 403, 241, 191, 256
+	bounds: 2, 268, 264, 589
 	rotate: 90
 left-wing02
-	bounds: 673, 401, 179, 269
-	rotate: 90
-left-wing03
-	bounds: 194, 286, 186, 207
-	rotate: 90
-left-wing04
-	bounds: 140, 682, 188, 135
-left-wing06
-	bounds: 661, 207, 192, 331
+	bounds: 2, 2, 264, 589
 	rotate: 90
-left-wing07
-	bounds: 2, 521, 159, 255
-	rotate: 90
-left-wing08
-	bounds: 827, 582, 164, 181
-	rotate: 90
-left-wing09
-	bounds: 259, 474, 204, 167
 right-front-leg
-	bounds: 113, 821, 101, 89
+	bounds: 113, 769, 101, 89
 right-front-thigh
-	bounds: 758, 761, 108, 108
+	bounds: 758, 709, 108, 108
 right-rear-leg
-	bounds: 640, 773, 116, 100
+	bounds: 640, 721, 116, 100
 right-rear-thigh
-	bounds: 367, 794, 91, 149
+	bounds: 367, 742, 91, 149
 	rotate: 90
 right-rear-toe
-	bounds: 2, 833, 109, 77
-right-wing02
-	bounds: 635, 2, 203, 305
-	rotate: 90
-right-wing04
-	bounds: 330, 643, 279, 144
-right-wing06
-	bounds: 2, 84, 200, 366
-	rotate: 90
-right-wing07
-	bounds: 370, 39, 200, 263
-	rotate: 90
+	bounds: 2, 781, 109, 77
 tail01
-	bounds: 868, 748, 120, 153
+	bounds: 868, 696, 120, 153
 	rotate: 90
 tail02
-	bounds: 518, 789, 95, 120
+	bounds: 518, 737, 95, 120
 	rotate: 90
 tail03
-	bounds: 868, 870, 73, 92
+	bounds: 868, 818, 73, 92
 	rotate: 90
 tail04
-	bounds: 526, 887, 56, 71
+	bounds: 526, 835, 56, 71
 	rotate: 90
 tail05
-	bounds: 406, 891, 52, 59
+	bounds: 406, 839, 52, 59
 	rotate: 90
 tail06
-	bounds: 685, 875, 95, 68
+	bounds: 685, 823, 95, 68
 thiagobrayner
-	bounds: 54, 912, 350, 31
+	bounds: 54, 860, 350, 31
 
 dragon2.png
-	size: 1024, 512
+	size: 1024, 1024
 	filter: Linear, Linear
 	pma: true
-head
-	bounds: 2, 214, 296, 260
+left-wing03
+	bounds: 2, 534, 264, 589
+	rotate: 90
+left-wing04
+	bounds: 2, 268, 264, 589
 	rotate: 90
 left-wing05
-	bounds: 741, 39, 218, 213
+	bounds: 593, 209, 264, 589
+left-wing06
+	bounds: 2, 2, 264, 589
+	rotate: 90
+
+dragon3.png
+	size: 1024, 1024
+	filter: Linear, Linear
+	pma: true
+left-wing07
+	bounds: 2, 694, 264, 589
+	rotate: 90
+left-wing08
+	bounds: 2, 428, 264, 589
 	rotate: 90
+left-wing09
+	bounds: 593, 369, 264, 589
 right-wing01
-	bounds: 264, 200, 219, 310
+	bounds: 2, 2, 365, 643
+	rotate: 90
+
+dragon4.png
+	size: 1024, 1024
+	filter: Linear, Linear
+	pma: true
+right-wing02
+	bounds: 2, 369, 365, 643
 right-wing03
-	bounds: 485, 238, 272, 247
+	bounds: 369, 369, 365, 643
+right-wing04
+	bounds: 2, 2, 365, 643
 	rotate: 90
+
+dragon5.png
+	size: 1024, 1024
+	filter: Linear, Linear
+	pma: true
 right-wing05
-	bounds: 734, 259, 251, 229
+	bounds: 2, 369, 365, 643
+right-wing06
+	bounds: 369, 369, 365, 643
+right-wing07
+	bounds: 2, 2, 365, 643
 	rotate: 90
+
+dragon6.png
+	size: 1024, 1024
+	filter: Linear, Linear
+	pma: true
 right-wing08
-	bounds: 485, 2, 234, 254
-	rotate: 90
+	bounds: 2, 2, 365, 643
 right-wing09
-	bounds: 2, 8, 248, 204
+	bounds: 369, 2, 365, 643

+ 49 - 69
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.json

@@ -1,13 +1,13 @@
 {
 "skeleton": {
-	"hash": "UIFpNNbbcQI",
-	"spine": "4.0.31",
+	"hash": "aPoA1GjXkVI",
+	"spine": "4.1.04-beta",
 	"x": -366.31,
-	"y": -286.62,
+	"y": -327.81,
 	"width": 660.39,
-	"height": 604.09,
+	"height": 643,
 	"images": "./images/",
-	"audio": ""
+	"audio": "././"
 },
 "bones": [
 	{ "name": "root", "y": -176.12 },
@@ -297,7 +297,7 @@
 "slots": [
 	{ "name": "left-rear-leg", "bone": "left-rear-leg", "attachment": "left-rear-leg" },
 	{ "name": "left-rear-thigh", "bone": "left-rear-thigh", "attachment": "left-rear-thigh" },
-	{ "name": "left-wing", "bone": "left-wing", "attachment": "left-wing01" },
+	{ "name": "left-wing", "bone": "left-wing", "attachment": "left-wing" },
 	{ "name": "tail6", "bone": "tail6", "attachment": "tail06" },
 	{ "name": "tail5", "bone": "tail5", "attachment": "tail05" },
 	{ "name": "tail4", "bone": "tail4", "attachment": "tail04" },
@@ -323,7 +323,7 @@
 	{ "name": "right-front-toe2", "bone": "right-front-toe2", "attachment": "front-toe-b" },
 	{ "name": "right-front-toe3", "bone": "right-front-toe3", "attachment": "front-toe-b" },
 	{ "name": "chin", "bone": "chin", "attachment": "chin" },
-	{ "name": "right-wing", "bone": "right-wing", "attachment": "right-wing01" },
+	{ "name": "right-wing", "bone": "right-wing", "attachment": "right-wing" },
 	{ "name": "head", "bone": "head", "attachment": "head" },
 	{ "name": "thiagobrayner", "bone": "root", "attachment": "thiagobrayner" }
 ],
@@ -376,15 +376,14 @@
 				"left-rear-thigh": { "x": 56.03, "y": 27.39, "rotation": 74.94, "width": 91, "height": 149 }
 			},
 			"left-wing": {
-				"left-wing01": { "x": 129.21, "y": -45.49, "rotation": -83.7, "width": 191, "height": 256 },
-				"left-wing02": { "x": 126.38, "y": -31.69, "rotation": -86.19, "width": 179, "height": 269 },
-				"left-wing03": { "x": 110.27, "y": -90.89, "rotation": -86.19, "width": 186, "height": 207 },
-				"left-wing04": { "x": -61.62, "y": -83.27, "rotation": -86.19, "width": 188, "height": 135 },
-				"left-wing05": { "x": -90.02, "y": -78.14, "rotation": -86.19, "width": 218, "height": 213 },
-				"left-wing06": { "x": -143.77, "y": -83.72, "rotation": -86.19, "width": 192, "height": 331 },
-				"left-wing07": { "x": -133.05, "y": -33.9, "rotation": -86.19, "width": 159, "height": 255 },
-				"left-wing08": { "x": 50.15, "y": -15.71, "rotation": -86.19, "width": 164, "height": 181 },
-				"left-wing09": { "x": 85.94, "y": -11.33, "rotation": -86.19, "width": 204, "height": 167 }
+				"left-wing": {
+					"x": -36.32,
+					"y": -44.53,
+					"rotation": -83.7,
+					"width": 264,
+					"height": 589,
+					"sequence": { "count": 9, "digits": 2 }
+				}
 			},
 			"right-front-leg": {
 				"right-front-leg": { "x": 17.8, "y": 4.23, "rotation": 37.63, "width": 101, "height": 89 }
@@ -417,15 +416,14 @@
 				"right-rear-toe": { "x": 47.46, "y": -7.64, "rotation": 134.34, "width": 109, "height": 77 }
 			},
 			"right-wing": {
-				"right-wing01": { "x": 170.08, "y": -23.68, "rotation": -130.34, "width": 219, "height": 310 },
-				"right-wing02": { "x": 171.15, "y": -19.33, "rotation": -130.34, "width": 203, "height": 305 },
-				"right-wing03": { "x": 166.46, "y": 29.24, "rotation": -130.34, "width": 272, "height": 247 },
-				"right-wing04": { "x": 42.94, "y": 134.06, "rotation": -130.34, "width": 279, "height": 144 },
-				"right-wing05": { "x": -8.84, "y": 142.59, "rotation": -130.34, "width": 251, "height": 229 },
-				"right-wing06": { "x": -123.33, "y": 111.22, "rotation": -130.34, "width": 200, "height": 366 },
-				"right-wing07": { "x": -40.17, "y": 118.03, "rotation": -130.34, "width": 200, "height": 263 },
-				"right-wing08": { "x": 48.02, "y": 28.76, "rotation": -130.34, "width": 234, "height": 254 },
-				"right-wing09": { "x": 128.1, "y": 21.13, "rotation": -130.34, "width": 248, "height": 204 }
+				"right-wing": {
+					"x": 35.09,
+					"y": 78.11,
+					"rotation": -130.34,
+					"width": 365,
+					"height": 643,
+					"sequence": { "count": 9, "digits": 2 }
+				}
 			},
 			"tail1": {
 				"tail01": { "x": 22.6, "y": -4.5, "rotation": 163.85, "width": 120, "height": 153 }
@@ -453,50 +451,6 @@
 ],
 "animations": {
 	"flying": {
-		"slots": {
-			"left-wing": {
-				"attachment": [
-					{ "time": 0.0667, "name": "left-wing02" },
-					{ "time": 0.1333, "name": "left-wing03" },
-					{ "time": 0.2, "name": "left-wing04" },
-					{ "time": 0.2667, "name": "left-wing05" },
-					{ "time": 0.3333, "name": "left-wing06" },
-					{ "time": 0.4, "name": "left-wing07" },
-					{ "time": 0.4667, "name": "left-wing08" },
-					{ "time": 0.5333, "name": "left-wing09" },
-					{ "time": 0.6, "name": "left-wing01" },
-					{ "time": 0.7333, "name": "left-wing02" },
-					{ "time": 0.8, "name": "left-wing03" },
-					{ "time": 0.8333, "name": "left-wing04" },
-					{ "time": 0.8667, "name": "left-wing05" },
-					{ "time": 0.9, "name": "left-wing06" },
-					{ "time": 0.9333, "name": "left-wing07" },
-					{ "time": 0.9667, "name": "left-wing08" },
-					{ "time": 1, "name": "left-wing01" }
-				]
-			},
-			"right-wing": {
-				"attachment": [
-					{ "time": 0.0667, "name": "right-wing02" },
-					{ "time": 0.1333, "name": "right-wing03" },
-					{ "time": 0.2, "name": "right-wing04" },
-					{ "time": 0.2667, "name": "right-wing05" },
-					{ "time": 0.3333, "name": "right-wing06" },
-					{ "time": 0.4, "name": "right-wing07" },
-					{ "time": 0.4667, "name": "right-wing08" },
-					{ "time": 0.5333, "name": "right-wing09" },
-					{ "time": 0.6, "name": "right-wing01" },
-					{ "time": 0.7333, "name": "right-wing02" },
-					{ "time": 0.8, "name": "right-wing03" },
-					{ "time": 0.8333, "name": "right-wing04" },
-					{ "time": 0.8667, "name": "right-wing05" },
-					{ "time": 0.9, "name": "right-wing06" },
-					{ "time": 0.9333, "name": "right-wing07" },
-					{ "time": 0.9667, "name": "right-wing08" },
-					{ "time": 1, "name": "right-wing01" }
-				]
-			}
-		},
 		"bones": {
 			"back": {
 				"rotate": [
@@ -1093,6 +1047,32 @@
 					{ "time": 1 }
 				]
 			}
+		},
+		"attachments": {
+			"default": {
+				"left-wing": {
+					"left-wing": {
+						"sequence": [
+							{ "mode": "loop", "delay": 0.0667 },
+							{ "time": 0.6 },
+							{ "time": 0.7333, "mode": "loop", "index": 1 },
+							{ "time": 0.8, "mode": "loop", "index": 2, "delay": 0.0333 },
+							{ "time": 0.9667, "index": 7 }
+						]
+					}
+				},
+				"right-wing": {
+					"right-wing": {
+						"sequence": [
+							{ "mode": "loop", "delay": 0.0667 },
+							{ "time": 0.6 },
+							{ "time": 0.7333, "mode": "loop", "index": 1 },
+							{ "time": 0.8, "mode": "loop", "index": 2, "delay": 0.0333 },
+							{ "time": 0.9667, "index": 7 }
+						]
+					}
+				}
+			}
 		}
 	}
 }

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.png


BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon2.png


BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon3.png


+ 108 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon3.png.meta

@@ -0,0 +1,108 @@
+fileFormatVersion: 2
+guid: 9a960996718ee9a4a9872c1a38fc3946
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 11
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 0
+    wrapV: 0
+    wrapW: 0
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 0
+  spriteTessellationDetail: -1
+  textureType: 0
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon4.png


+ 108 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon4.png.meta

@@ -0,0 +1,108 @@
+fileFormatVersion: 2
+guid: 390eb45b86ad95d40855f1cedc5ebe86
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 11
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 0
+    wrapV: 0
+    wrapW: 0
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 0
+  spriteTessellationDetail: -1
+  textureType: 0
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon5.png


+ 108 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon5.png.meta

@@ -0,0 +1,108 @@
+fileFormatVersion: 2
+guid: d3a3452c852fdd84ea122c9533745866
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 11
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 0
+    wrapV: 0
+    wrapW: 0
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 0
+  spriteTessellationDetail: -1
+  textureType: 0
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon6.png


+ 108 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon6.png.meta

@@ -0,0 +1,108 @@
+fileFormatVersion: 2
+guid: a87fe78b999f42f459397732f7c75303
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 11
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 0
+    wrapV: 0
+    wrapW: 0
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 0
+  spriteTessellationDetail: -1
+  textureType: 0
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 1
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 39 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon3.mat

@@ -0,0 +1,39 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: dragon_dragon3
+  m_Shader: {fileID: 4800000, guid: 1e8a610c9e01c3648bac42585e5fc676, type: 3}
+  m_ShaderKeywords: _USE8NEIGHBOURHOOD_ON
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: 9a960996718ee9a4a9872c1a38fc3946, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _Cutoff: 0.1
+    - _OutlineMipLevel: 0
+    - _OutlineReferenceTexWidth: 1024
+    - _OutlineSmoothness: 1
+    - _OutlineWidth: 3
+    - _StencilComp: 8
+    - _StencilRef: 1
+    - _StraightAlphaInput: 0
+    - _ThresholdEnd: 0.25
+    - _Use8Neighbourhood: 1
+    m_Colors:
+    - _OutlineColor: {r: 1, g: 1, b: 0, a: 1}
+  m_BuildTextureStacks: []

+ 8 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon3.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 46ebf60e37c48414f90b2f53f8ce4ea0
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 39 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon4.mat

@@ -0,0 +1,39 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: dragon_dragon4
+  m_Shader: {fileID: 4800000, guid: 1e8a610c9e01c3648bac42585e5fc676, type: 3}
+  m_ShaderKeywords: _USE8NEIGHBOURHOOD_ON
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: 390eb45b86ad95d40855f1cedc5ebe86, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _Cutoff: 0.1
+    - _OutlineMipLevel: 0
+    - _OutlineReferenceTexWidth: 1024
+    - _OutlineSmoothness: 1
+    - _OutlineWidth: 3
+    - _StencilComp: 8
+    - _StencilRef: 1
+    - _StraightAlphaInput: 0
+    - _ThresholdEnd: 0.25
+    - _Use8Neighbourhood: 1
+    m_Colors:
+    - _OutlineColor: {r: 1, g: 1, b: 0, a: 1}
+  m_BuildTextureStacks: []

+ 8 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon4.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1cb51a81cfe737549beec4fdb1f16360
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 39 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon5.mat

@@ -0,0 +1,39 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: dragon_dragon5
+  m_Shader: {fileID: 4800000, guid: 1e8a610c9e01c3648bac42585e5fc676, type: 3}
+  m_ShaderKeywords: _USE8NEIGHBOURHOOD_ON
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: d3a3452c852fdd84ea122c9533745866, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _Cutoff: 0.1
+    - _OutlineMipLevel: 0
+    - _OutlineReferenceTexWidth: 1024
+    - _OutlineSmoothness: 1
+    - _OutlineWidth: 3
+    - _StencilComp: 8
+    - _StencilRef: 1
+    - _StraightAlphaInput: 0
+    - _ThresholdEnd: 0.25
+    - _Use8Neighbourhood: 1
+    m_Colors:
+    - _OutlineColor: {r: 1, g: 1, b: 0, a: 1}
+  m_BuildTextureStacks: []

+ 8 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon5.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: bd1fb273f898c1e4482466fbdfdbd01e
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 39 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon6.mat

@@ -0,0 +1,39 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+  serializedVersion: 6
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_Name: dragon_dragon6
+  m_Shader: {fileID: 4800000, guid: 1e8a610c9e01c3648bac42585e5fc676, type: 3}
+  m_ShaderKeywords: _USE8NEIGHBOURHOOD_ON
+  m_LightmapFlags: 4
+  m_EnableInstancingVariants: 0
+  m_DoubleSidedGI: 0
+  m_CustomRenderQueue: -1
+  stringTagMap: {}
+  disabledShaderPasses: []
+  m_SavedProperties:
+    serializedVersion: 3
+    m_TexEnvs:
+    - _MainTex:
+        m_Texture: {fileID: 2800000, guid: a87fe78b999f42f459397732f7c75303, type: 3}
+        m_Scale: {x: 1, y: 1}
+        m_Offset: {x: 0, y: 0}
+    m_Floats:
+    - _Cutoff: 0.1
+    - _OutlineMipLevel: 0
+    - _OutlineReferenceTexWidth: 1024
+    - _OutlineSmoothness: 1
+    - _OutlineWidth: 3
+    - _StencilComp: 8
+    - _StencilRef: 1
+    - _StraightAlphaInput: 0
+    - _ThresholdEnd: 0.25
+    - _Use8Neighbourhood: 1
+    m_Colors:
+    - _OutlineColor: {r: 1, g: 1, b: 0, a: 1}
+  m_BuildTextureStacks: []

+ 8 - 0
spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon6.mat.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: df19a30178772d14895780e0cbd7c25c
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 2100000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 2 - 2
spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "twyVt4LWmOY",
-	"spine": "4.0.31",
+	"hash": "3Ru4PsHnfWE",
+	"spine": "4.1.04-beta",
 	"x": -434,
 	"y": -133,
 	"width": 868,

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.png


BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.png


+ 2 - 2
spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "t48AsgsO/fQ",
-	"spine": "4.0.31",
+	"hash": "RGdJecpcnMU",
+	"spine": "4.1.04-beta",
 	"x": -79.83,
 	"y": -0.99,
 	"width": 147.64,

+ 2 - 2
spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "mUQaGw4LIww",
-	"spine": "4.0.31",
+	"hash": "Sz0QhWD6Eyg",
+	"spine": "4.1.04-beta",
 	"x": -125,
 	"y": -30,
 	"width": 250,

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.png


+ 304 - 282
spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "PtTAK+zF95I",
-	"spine": "4.0.31",
+	"hash": "5+0u5UUVwqA",
+	"spine": "4.1.04-beta",
 	"x": -134.12,
 	"y": -3.28,
 	"width": 266.94,
@@ -571,7 +571,7 @@
 			"eyes": {
 				"attachment": [
 					{ "time": 0.7, "name": "eyes-closed" },
-					{ "time": 0.8, "name": null }
+					{ "time": 0.8 }
 				]
 			}
 		},
@@ -899,309 +899,331 @@
 				]
 			}
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"right-hand-item": {
-					"dagger": [
-						{
-							"offset": 26,
-							"vertices": [ 2.34755, 0.1447 ],
-							"curve": [ 0.125, 0, 0.375, 1 ]
-						},
-						{
-							"time": 0.5,
-							"offset": 8,
-							"vertices": [ -1.19415, 4.31532, 0.07279, 6.41351, 1.66048, 6.18883, 1.75233, 3.59555 ],
-							"curve": [ 0.625, 0, 0.875, 1 ]
-						},
-						{
-							"time": 1,
-							"offset": 26,
-							"vertices": [ 2.34755, 0.1447 ]
-						}
-					]
+					"dagger": {
+						"deform": [
+							{
+								"offset": 26,
+								"vertices": [ 2.34755, 0.1447 ],
+								"curve": [ 0.125, 0, 0.375, 1 ]
+							},
+							{
+								"time": 0.5,
+								"offset": 8,
+								"vertices": [ -1.19415, 4.31532, 0.07279, 6.41351, 1.66048, 6.18883, 1.75233, 3.59555 ],
+								"curve": [ 0.625, 0, 0.875, 1 ]
+							},
+							{
+								"time": 1,
+								"offset": 26,
+								"vertices": [ 2.34755, 0.1447 ]
+							}
+						]
+					}
 				}
 			},
 			"goblin": {
 				"head": {
-					"head": [
-						{
-							"curve": [ 0.127, 0, 0.15, 1 ]
-						},
-						{
-							"time": 0.2,
-							"vertices": [ -10.97827, -6.68962, -4.68015, -2.46175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08534, 0.08392, -1.08534, 0.08392, -1.08534, 0.08392, 0, 0, -2.22325, 2.66465, -4.83295, 2.70085, -5.70553, -0.51941, -3.15962, -1.61502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.64742, 0.81612, -11.82286, -1.34955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08534, 0.08392 ],
-							"curve": [ 0.242, 0, 0.325, 1 ]
-						},
-						{
-							"time": 0.3667,
-							"vertices": [ 10.69276, 4.05949, 3.66373, 1.85427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.47305, 0.09018, 1.47305, 0.09018, 1.47305, 0.09018, 0, 0, 2.69653, -0.22738, 3.77135, 0.11418, 3.6893, 1.55352, 2.49595, 1.65501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.45881, -3.9113, 9.19594, -1.66854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.47305, 0.09018 ],
-							"curve": [ 0.574, 0, 0.617, 1 ]
-						},
-						{
-							"time": 0.7,
-							"vertices": [ -10.97827, -6.68962, -4.68015, -2.46175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.17551, -0.17183, -1.17551, -0.17183, -1.17551, -0.17183, 0, 0, -2.22325, 2.66465, -4.83295, 2.70085, -5.70553, -0.51941, -3.15962, -1.61502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.64742, 0.81612, -11.82286, -1.34955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.17551, -0.17183 ],
-							"curve": [ 0.742, 0, 0.825, 1 ]
-						},
-						{
-							"time": 0.8667,
-							"vertices": [ 10.69276, 4.05949, 3.66373, 1.85427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.38687, 0.08446, 0.38687, 0.08446, 0.38687, 0.08446, 0, 0, 2.69653, -0.22738, 3.77135, 0.11418, 3.6893, 1.55352, 2.49595, 1.65501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.45881, -3.9113, 9.19594, -1.66854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.38687, 0.08446 ],
-							"curve": [ 0.9, 0, 0.967, 1 ]
-						},
-						{ "time": 1 }
-					]
+					"head": {
+						"deform": [
+							{
+								"curve": [ 0.127, 0, 0.15, 1 ]
+							},
+							{
+								"time": 0.2,
+								"vertices": [ -10.97827, -6.68962, -4.68015, -2.46175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08534, 0.08392, -1.08534, 0.08392, -1.08534, 0.08392, 0, 0, -2.22325, 2.66465, -4.83295, 2.70085, -5.70553, -0.51941, -3.15962, -1.61502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.64742, 0.81612, -11.82286, -1.34955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.08534, 0.08392 ],
+								"curve": [ 0.242, 0, 0.325, 1 ]
+							},
+							{
+								"time": 0.3667,
+								"vertices": [ 10.69276, 4.05949, 3.66373, 1.85427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.47305, 0.09018, 1.47305, 0.09018, 1.47305, 0.09018, 0, 0, 2.69653, -0.22738, 3.77135, 0.11418, 3.6893, 1.55352, 2.49595, 1.65501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.45881, -3.9113, 9.19594, -1.66854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.47305, 0.09018 ],
+								"curve": [ 0.574, 0, 0.617, 1 ]
+							},
+							{
+								"time": 0.7,
+								"vertices": [ -10.97827, -6.68962, -4.68015, -2.46175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.17551, -0.17183, -1.17551, -0.17183, -1.17551, -0.17183, 0, 0, -2.22325, 2.66465, -4.83295, 2.70085, -5.70553, -0.51941, -3.15962, -1.61502, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.64742, 0.81612, -11.82286, -1.34955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.17551, -0.17183 ],
+								"curve": [ 0.742, 0, 0.825, 1 ]
+							},
+							{
+								"time": 0.8667,
+								"vertices": [ 10.69276, 4.05949, 3.66373, 1.85427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.38687, 0.08446, 0.38687, 0.08446, 0.38687, 0.08446, 0, 0, 2.69653, -0.22738, 3.77135, 0.11418, 3.6893, 1.55352, 2.49595, 1.65501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.45881, -3.9113, 9.19594, -1.66854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.38687, 0.08446 ],
+								"curve": [ 0.9, 0, 0.967, 1 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				},
 				"left-foot": {
-					"left-foot": [
-						{
-							"offset": 8,
-							"vertices": [ 3.69298, 2.37573, -7.16969, 18.79733, -12.78162, 14.7778, -12.75776, 6.50514, -3.13476, 1.98906, -0.44402, 0.36629, 0, 0, -3.80085, 2.98474 ]
-						},
-						{ "time": 0.1333 },
-						{
-							"time": 0.2333,
-							"offset": 8,
-							"vertices": [ -3.96073, -2.34594, -5.80446, -12.47629, -2.2313, -12.99038, 2.02942, -9.1036, 0, 0, 0, 0, 0, 0, -1.35254, -5.2883 ]
-						},
-						{
-							"time": 0.3667,
-							"offset": 8,
-							"vertices": [ 0.66505, 0.33548, 0.33902, 2.69014, -0.48171, 2.54524, -1.13593, 1.38562, 0, 0, 0, 0, 0, 0, -0.11908, 0.79273 ]
-						},
-						{ "time": 0.5, "curve": "stepped" },
-						{ "time": 0.6333 },
-						{
-							"time": 0.7333,
-							"offset": 8,
-							"vertices": [ -2.97738, 9.40254, -6.91661, 19.92794, -10.55287, 18.41085, -12.37161, 12.38473, -4.72607, 6.30799, 0, 0, -1.48902, 4.88944, -7.06773, 10.70102 ]
-						},
-						{
-							"time": 0.8333,
-							"offset": 6,
-							"vertices": [ 1.05319, 1.56362, -2.52723, 7.9974, -5.52031, 17.14137, -8.93317, 15.79635, -10.73748, 10.22056, -4.23801, 5.36992, 0, 0, 0, 0, -5.83148, 8.55532 ]
-						},
-						{
-							"time": 1,
-							"offset": 8,
-							"vertices": [ 3.69298, 2.37573, -7.16969, 18.79733, -12.78162, 14.7778, -12.75776, 6.50514, -3.13476, 1.98906, -0.44402, 0.36629, 0, 0, -3.80085, 2.98474 ]
-						}
-					]
+					"left-foot": {
+						"deform": [
+							{
+								"offset": 8,
+								"vertices": [ 3.69298, 2.37573, -7.16969, 18.79733, -12.78162, 14.7778, -12.75776, 6.50514, -3.13476, 1.98906, -0.44402, 0.36629, 0, 0, -3.80085, 2.98474 ]
+							},
+							{ "time": 0.1333 },
+							{
+								"time": 0.2333,
+								"offset": 8,
+								"vertices": [ -3.96073, -2.34594, -5.80446, -12.47629, -2.2313, -12.99038, 2.02942, -9.1036, 0, 0, 0, 0, 0, 0, -1.35254, -5.2883 ]
+							},
+							{
+								"time": 0.3667,
+								"offset": 8,
+								"vertices": [ 0.66505, 0.33548, 0.33902, 2.69014, -0.48171, 2.54524, -1.13593, 1.38562, 0, 0, 0, 0, 0, 0, -0.11908, 0.79273 ]
+							},
+							{ "time": 0.5, "curve": "stepped" },
+							{ "time": 0.6333 },
+							{
+								"time": 0.7333,
+								"offset": 8,
+								"vertices": [ -2.97738, 9.40254, -6.91661, 19.92794, -10.55287, 18.41085, -12.37161, 12.38473, -4.72607, 6.30799, 0, 0, -1.48902, 4.88944, -7.06773, 10.70102 ]
+							},
+							{
+								"time": 0.8333,
+								"offset": 6,
+								"vertices": [ 1.05319, 1.56362, -2.52723, 7.9974, -5.52031, 17.14137, -8.93317, 15.79635, -10.73748, 10.22056, -4.23801, 5.36992, 0, 0, 0, 0, -5.83148, 8.55532 ]
+							},
+							{
+								"time": 1,
+								"offset": 8,
+								"vertices": [ 3.69298, 2.37573, -7.16969, 18.79733, -12.78162, 14.7778, -12.75776, 6.50514, -3.13476, 1.98906, -0.44402, 0.36629, 0, 0, -3.80085, 2.98474 ]
+							}
+						]
+					}
 				},
 				"pelvis": {
-					"pelvis": [
-						{},
-						{
-							"time": 0.1333,
-							"offset": 6,
-							"vertices": [ -0.6899, -4.13284 ]
-						},
-						{
-							"time": 0.3333,
-							"offset": 6,
-							"vertices": [ -1.04945, -3.10477 ]
-						},
-						{
-							"time": 0.7,
-							"offset": 6,
-							"vertices": [ -1.4245, -6.30617 ]
-						},
-						{
-							"time": 0.8667,
-							"offset": 6,
-							"vertices": [ -1.13542, -1.79036 ]
-						},
-						{ "time": 1 }
-					]
+					"pelvis": {
+						"deform": [
+							{},
+							{
+								"time": 0.1333,
+								"offset": 6,
+								"vertices": [ -0.6899, -4.13284 ]
+							},
+							{
+								"time": 0.3333,
+								"offset": 6,
+								"vertices": [ -1.04945, -3.10477 ]
+							},
+							{
+								"time": 0.7,
+								"offset": 6,
+								"vertices": [ -1.4245, -6.30617 ]
+							},
+							{
+								"time": 0.8667,
+								"offset": 6,
+								"vertices": [ -1.13542, -1.79036 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				},
 				"right-foot": {
-					"right-foot": [
-						{},
-						{
-							"time": 0.1333,
-							"offset": 2,
-							"vertices": [ -2.81259, 2.63115, -2.35238, 3.89441, -1.99921, 4.8639, -0.93273, 5.57982, -0.48886, 5.09855, -0.34813, 3.42912, -0.17446, 1.36899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.31305, 1.91372, -1.32986, 3.65703 ]
-						},
-						{
-							"time": 0.2333,
-							"offset": 2,
-							"vertices": [ -6.39088, 6.41246, -7.74575, 8.27192, -7.02471, 11.35894, -4.03471, 13.93454, -2.50399, 12.62963, -1.46125, 7.58915, -0.17446, 1.36899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.84766, 2.61216, -4.53956, 7.92358 ]
-						},
-						{
-							"time": 0.3,
-							"offset": 2,
-							"vertices": [ -8.27185, 6.68822, -9.29764, 10.13797, -8.62231, 14.7134, -4.5863, 18.81939, -2.20304, 17.10709, -0.07795, 9.9046, 2.54452, 1.01642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.94625, 2.38008, -4.59399, 10.01888 ]
-						},
-						{
-							"time": 0.3667,
-							"offset": 2,
-							"vertices": [ -10.47684, 9.44176, -13.36883, 12.40983, -14.32569, 16.94392, -9.24463, 23.55674, -5.51712, 21.51378, -1.19582, 11.53193, 2.54452, 1.01642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.14848, 2.29389, -6.63419, 11.37127 ]
-						},
-						{
-							"time": 0.5,
-							"offset": 2,
-							"vertices": [ -5.42474, 4.36854, -10.59004, 7.04468, -11.64251, 11.55845, -6.19665, 20.12806, -1.45498, 18.05411, 4.8662, 6.41679, 2.81463, 0.27601, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.96412, 4.9483 ]
-						},
-						{ "time": 0.6333 },
-						{
-							"time": 0.7333,
-							"offset": 4,
-							"vertices": [ 1.31462, -6.84099, -0.87905, -12.54479, -5.9851, -14.08368, -7.15892, -11.63194, -5.6792, -4.83545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.06164, -6.93844 ]
-						},
-						{
-							"time": 0.8,
-							"offset": 4,
-							"vertices": [ 0.65731, -3.4205, -0.43953, -6.2724, -2.99255, -7.04184, -3.57946, -5.81597, -2.8396, -2.41772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.79688, -1.28021, 0, 0, 0, 0, -1.03082, -3.46922 ]
-						},
-						{ "time": 0.8667 }
-					]
+					"right-foot": {
+						"deform": [
+							{},
+							{
+								"time": 0.1333,
+								"offset": 2,
+								"vertices": [ -2.81259, 2.63115, -2.35238, 3.89441, -1.99921, 4.8639, -0.93273, 5.57982, -0.48886, 5.09855, -0.34813, 3.42912, -0.17446, 1.36899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.31305, 1.91372, -1.32986, 3.65703 ]
+							},
+							{
+								"time": 0.2333,
+								"offset": 2,
+								"vertices": [ -6.39088, 6.41246, -7.74575, 8.27192, -7.02471, 11.35894, -4.03471, 13.93454, -2.50399, 12.62963, -1.46125, 7.58915, -0.17446, 1.36899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.84766, 2.61216, -4.53956, 7.92358 ]
+							},
+							{
+								"time": 0.3,
+								"offset": 2,
+								"vertices": [ -8.27185, 6.68822, -9.29764, 10.13797, -8.62231, 14.7134, -4.5863, 18.81939, -2.20304, 17.10709, -0.07795, 9.9046, 2.54452, 1.01642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.94625, 2.38008, -4.59399, 10.01888 ]
+							},
+							{
+								"time": 0.3667,
+								"offset": 2,
+								"vertices": [ -10.47684, 9.44176, -13.36883, 12.40983, -14.32569, 16.94392, -9.24463, 23.55674, -5.51712, 21.51378, -1.19582, 11.53193, 2.54452, 1.01642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.14848, 2.29389, -6.63419, 11.37127 ]
+							},
+							{
+								"time": 0.5,
+								"offset": 2,
+								"vertices": [ -5.42474, 4.36854, -10.59004, 7.04468, -11.64251, 11.55845, -6.19665, 20.12806, -1.45498, 18.05411, 4.8662, 6.41679, 2.81463, 0.27601, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.96412, 4.9483 ]
+							},
+							{ "time": 0.6333 },
+							{
+								"time": 0.7333,
+								"offset": 4,
+								"vertices": [ 1.31462, -6.84099, -0.87905, -12.54479, -5.9851, -14.08368, -7.15892, -11.63194, -5.6792, -4.83545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.06164, -6.93844 ]
+							},
+							{
+								"time": 0.8,
+								"offset": 4,
+								"vertices": [ 0.65731, -3.4205, -0.43953, -6.2724, -2.99255, -7.04184, -3.57946, -5.81597, -2.8396, -2.41772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.79688, -1.28021, 0, 0, 0, 0, -1.03082, -3.46922 ]
+							},
+							{ "time": 0.8667 }
+						]
+					}
 				},
 				"right-hand": {
-					"right-hand": [
-						{
-							"offset": 4,
-							"vertices": [ -1.48417, 0.34736, 0, 0, 1.31152, 0.08085, 1.60296, 0.09882, 0.13673, 0.15471, 0, 0, 0, 0, -0.72862, -0.0449 ]
-						},
-						{ "time": 0.5 },
-						{
-							"time": 1,
-							"offset": 4,
-							"vertices": [ -1.48417, 0.34736, 0, 0, 1.31152, 0.08085, 1.60296, 0.09882, 0.13673, 0.15471, 0, 0, 0, 0, -0.72862, -0.0449 ]
-						}
-					]
+					"right-hand": {
+						"deform": [
+							{
+								"offset": 4,
+								"vertices": [ -1.48417, 0.34736, 0, 0, 1.31152, 0.08085, 1.60296, 0.09882, 0.13673, 0.15471, 0, 0, 0, 0, -0.72862, -0.0449 ]
+							},
+							{ "time": 0.5 },
+							{
+								"time": 1,
+								"offset": 4,
+								"vertices": [ -1.48417, 0.34736, 0, 0, 1.31152, 0.08085, 1.60296, 0.09882, 0.13673, 0.15471, 0, 0, 0, 0, -0.72862, -0.0449 ]
+							}
+						]
+					}
 				},
 				"right-lower-leg": {
-					"right-lower-leg": [
-						{},
-						{
-							"time": 0.6,
-							"offset": 6,
-							"vertices": [ 1.80396, -1.56553 ]
-						},
-						{ "time": 1 }
-					]
+					"right-lower-leg": {
+						"deform": [
+							{},
+							{
+								"time": 0.6,
+								"offset": 6,
+								"vertices": [ 1.80396, -1.56553 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				},
 				"right-upper-leg": {
-					"right-upper-leg": [
-						{
-							"vertices": [ -6.03857, -1.46325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.34685, -1.93102, -1.86047, -5.05266, -2.5014, -3.09985 ]
-						},
-						{ "time": 0.3333 },
-						{
-							"time": 0.8667,
-							"offset": 14,
-							"vertices": [ 0.13425, -2.35378, -1.33318, -5.99573, -1.35862, -4.43324 ]
-						},
-						{
-							"time": 1,
-							"vertices": [ -6.03857, -1.46325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.34685, -1.93102, -1.86047, -5.05266, -2.5014, -3.09985 ]
-						}
-					]
+					"right-upper-leg": {
+						"deform": [
+							{
+								"vertices": [ -6.03857, -1.46325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.34685, -1.93102, -1.86047, -5.05266, -2.5014, -3.09985 ]
+							},
+							{ "time": 0.3333 },
+							{
+								"time": 0.8667,
+								"offset": 14,
+								"vertices": [ 0.13425, -2.35378, -1.33318, -5.99573, -1.35862, -4.43324 ]
+							},
+							{
+								"time": 1,
+								"vertices": [ -6.03857, -1.46325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.34685, -1.93102, -1.86047, -5.05266, -2.5014, -3.09985 ]
+							}
+						]
+					}
 				},
 				"torso": {
-					"torso": [
-						{
-							"offset": 2,
-							"vertices": [ 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, -1.24131, 2.62652, -2.47492, 0.71183, -0.26363, -0.5308, 0.24821, 2.86673, 0.24821, 2.86673, 0, 0, 0, 0, 0, 0, 0, 0, 1.34461, 0.25215, 0.24821, 2.86673, 0.82507, 1.61798, 0.24821, 2.86673, 0, 0, -1.86431, -0.4326, 0.24821, 2.86673 ]
-						},
-						{
-							"time": 0.1333,
-							"offset": 2,
-							"vertices": [ 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 1.66908, 3.51187, -0.62355, 2.47979, 1.1045, 3.49684, -1.09009, 6.08429, 0.35589, 4.10914, 0, 0, 0, 0, 0, 0, 0, 0, 3.01291, 0.15693, 0.35589, 4.10914, -1.11398, 3.7954, 0.35589, 4.10914, 0, 0, -2.96167, 0.55563, -2.20741, 4.40587 ]
-						},
-						{
-							"time": 0.3,
-							"offset": 2,
-							"vertices": [ 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 6.32601, 0.19387, 7.84315, 1.94837, 7.08587, 3.64119, 4.52343, 4.46961, 0.2884, 3.32948, 0, 0, 0, 0, 0, 0, 0, 0, 4.36416, -1.83876, 0.2884, 3.32948, 4.2925, 3.60194, 0.2884, 3.32948, 0, 0, 3.72601, -0.19338, 0.2884, 3.32948 ]
-						},
-						{
-							"time": 0.5,
-							"offset": 2,
-							"vertices": [ 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 2.57273, 2.74457, 2.88831, 3.04797, 3.48442, 3.04655, 1.80035, 4.609, 0.3133, 3.61659, 0, 0, 0, 0, 0, 0, 0, 0, 3.53782, -0.82203, 0.3133, 3.61659, 1.80022, 3.63246, 0.3133, 3.61659, 0, 0, 0.62718, 0.33564, -1.22467, 3.79463 ]
-						},
-						{
-							"time": 0.6333,
-							"offset": 2,
-							"vertices": [ 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 1.19401, 3.60798, -0.53546, 3.49565, 1.1926, 4.5127, -1.002, 7.10015, 0.44398, 5.125, 0, 0, 0, 0, 0, 0, 0, 0, 3.101, 1.17278, 0.44398, 5.125, -1.02589, 4.81126, 0.44398, 5.125, 0, 0, -2.87358, 1.57149, -2.11931, 5.42173 ]
-						},
-						{
-							"time": 0.8667,
-							"offset": 2,
-							"vertices": [ 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.92587, 2.24385, 0.68874, 1.29945, 3.55433, 3.00604, 2.71494, 5.89962, 0.30385, 3.50647, 0, 0, 0, 0, 0, 0, 0, 0, 1.96775, 0.40548, 0.30385, 3.50647, 2.6104, 2.3545, 0.30385, 3.50647, 0, 0, 0.22709, -0.12851, -0.62826, 3.61437 ]
-						},
-						{
-							"time": 1,
-							"offset": 2,
-							"vertices": [ 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, -1.1615, 3.54805, -2.39511, 1.63336, -0.18382, 0.39073, 0.32802, 3.78826, 0.32802, 3.78826, 0, 0, 0, 0, 0, 0, 0, 0, 1.42442, 1.17368, 0.32802, 3.78826, 0.90488, 2.53951, 0.32802, 3.78826, 0, 0, -1.7845, 0.48894, 0.32802, 3.78826 ]
-						}
-					]
+					"torso": {
+						"deform": [
+							{
+								"offset": 2,
+								"vertices": [ 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, 0.24821, 2.86673, -1.24131, 2.62652, -2.47492, 0.71183, -0.26363, -0.5308, 0.24821, 2.86673, 0.24821, 2.86673, 0, 0, 0, 0, 0, 0, 0, 0, 1.34461, 0.25215, 0.24821, 2.86673, 0.82507, 1.61798, 0.24821, 2.86673, 0, 0, -1.86431, -0.4326, 0.24821, 2.86673 ]
+							},
+							{
+								"time": 0.1333,
+								"offset": 2,
+								"vertices": [ 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 0.35589, 4.10914, 1.66908, 3.51187, -0.62355, 2.47979, 1.1045, 3.49684, -1.09009, 6.08429, 0.35589, 4.10914, 0, 0, 0, 0, 0, 0, 0, 0, 3.01291, 0.15693, 0.35589, 4.10914, -1.11398, 3.7954, 0.35589, 4.10914, 0, 0, -2.96167, 0.55563, -2.20741, 4.40587 ]
+							},
+							{
+								"time": 0.3,
+								"offset": 2,
+								"vertices": [ 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 0.2884, 3.32948, 6.32601, 0.19387, 7.84315, 1.94837, 7.08587, 3.64119, 4.52343, 4.46961, 0.2884, 3.32948, 0, 0, 0, 0, 0, 0, 0, 0, 4.36416, -1.83876, 0.2884, 3.32948, 4.2925, 3.60194, 0.2884, 3.32948, 0, 0, 3.72601, -0.19338, 0.2884, 3.32948 ]
+							},
+							{
+								"time": 0.5,
+								"offset": 2,
+								"vertices": [ 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 0.3133, 3.61659, 2.57273, 2.74457, 2.88831, 3.04797, 3.48442, 3.04655, 1.80035, 4.609, 0.3133, 3.61659, 0, 0, 0, 0, 0, 0, 0, 0, 3.53782, -0.82203, 0.3133, 3.61659, 1.80022, 3.63246, 0.3133, 3.61659, 0, 0, 0.62718, 0.33564, -1.22467, 3.79463 ]
+							},
+							{
+								"time": 0.6333,
+								"offset": 2,
+								"vertices": [ 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 0.44398, 5.125, 1.19401, 3.60798, -0.53546, 3.49565, 1.1926, 4.5127, -1.002, 7.10015, 0.44398, 5.125, 0, 0, 0, 0, 0, 0, 0, 0, 3.101, 1.17278, 0.44398, 5.125, -1.02589, 4.81126, 0.44398, 5.125, 0, 0, -2.87358, 1.57149, -2.11931, 5.42173 ]
+							},
+							{
+								"time": 0.8667,
+								"offset": 2,
+								"vertices": [ 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.30385, 3.50647, 0.92587, 2.24385, 0.68874, 1.29945, 3.55433, 3.00604, 2.71494, 5.89962, 0.30385, 3.50647, 0, 0, 0, 0, 0, 0, 0, 0, 1.96775, 0.40548, 0.30385, 3.50647, 2.6104, 2.3545, 0.30385, 3.50647, 0, 0, 0.22709, -0.12851, -0.62826, 3.61437 ]
+							},
+							{
+								"time": 1,
+								"offset": 2,
+								"vertices": [ 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, 0.32802, 3.78826, -1.1615, 3.54805, -2.39511, 1.63336, -0.18382, 0.39073, 0.32802, 3.78826, 0.32802, 3.78826, 0, 0, 0, 0, 0, 0, 0, 0, 1.42442, 1.17368, 0.32802, 3.78826, 0.90488, 2.53951, 0.32802, 3.78826, 0, 0, -1.7845, 0.48894, 0.32802, 3.78826 ]
+							}
+						]
+					}
 				},
 				"undie-straps": {
-					"undie-straps": [
-						{
-							"offset": 2,
-							"vertices": [ -1.77697, 0.5476, -0.96145, -1.03793, -0.39148, -0.24072, -1.77697, 0.5476 ]
-						},
-						{
-							"time": 0.1333,
-							"offset": 2,
-							"vertices": [ -2.25684, -1.03177, -1.49719, -4.23862, -0.7447, -2.84907, -1.90072, 0.54478 ]
-						},
-						{
-							"time": 0.3333,
-							"offset": 2,
-							"vertices": [ -2.37974, -0.05432, -0.49433, 0.19437, -0.90861, 1.16519, -1.60956, 2.70799, 0.96186, 0.80615 ]
-						},
-						{
-							"time": 0.7,
-							"offset": 2,
-							"vertices": [ -0.91715, -2.76567, -0.62215, -3.63489, -0.84941, -2.26772, -2.56077, 0.52971 ]
-						},
-						{
-							"time": 0.8667,
-							"offset": 2,
-							"vertices": [ -2.56077, 0.52971, -1.58065, 0.32031, -1.3847, 0.32476, -2.56077, 0.52971 ]
-						},
-						{
-							"time": 1,
-							"offset": 2,
-							"vertices": [ -1.77697, 0.5476, -0.80128, 0.53413, -0.80128, 0.53413, -1.77697, 0.5476 ]
-						}
-					]
+					"undie-straps": {
+						"deform": [
+							{
+								"offset": 2,
+								"vertices": [ -1.77697, 0.5476, -0.96145, -1.03793, -0.39148, -0.24072, -1.77697, 0.5476 ]
+							},
+							{
+								"time": 0.1333,
+								"offset": 2,
+								"vertices": [ -2.25684, -1.03177, -1.49719, -4.23862, -0.7447, -2.84907, -1.90072, 0.54478 ]
+							},
+							{
+								"time": 0.3333,
+								"offset": 2,
+								"vertices": [ -2.37974, -0.05432, -0.49433, 0.19437, -0.90861, 1.16519, -1.60956, 2.70799, 0.96186, 0.80615 ]
+							},
+							{
+								"time": 0.7,
+								"offset": 2,
+								"vertices": [ -0.91715, -2.76567, -0.62215, -3.63489, -0.84941, -2.26772, -2.56077, 0.52971 ]
+							},
+							{
+								"time": 0.8667,
+								"offset": 2,
+								"vertices": [ -2.56077, 0.52971, -1.58065, 0.32031, -1.3847, 0.32476, -2.56077, 0.52971 ]
+							},
+							{
+								"time": 1,
+								"offset": 2,
+								"vertices": [ -1.77697, 0.5476, -0.80128, 0.53413, -0.80128, 0.53413, -1.77697, 0.5476 ]
+							}
+						]
+					}
 				},
 				"undies": {
-					"undies": [
-						{
-							"vertices": [ 0.43099, 0.722, 10.60295, -0.117, 2.29599, 0, 2.29599, 0, 2.29599, 0, 0.58799, 0.244, -2.40018, -0.65335, -2.2782, -0.77534, 2.29599, 0, 0.58799, -0.488, 4.98698, -0.117, 6.50797, -0.23399 ]
-						},
-						{
-							"time": 0.1333,
-							"vertices": [ 0.72659, 0.4332, 7.20417, -0.1638, 1.37759, 0, 1.37759, 0, 1.37759, 0, 1.25279, 0.0464, -0.99862, -2.95085, -1.37543, -3.07404, 1.37759, 0, 0.35279, -0.2928, 2.99219, -0.0702, 3.90478, -0.1404 ]
-						},
-						{
-							"time": 0.3333,
-							"vertices": [ 1.16999, 0, 2.10599, -0.23401, 0, 0, 0, 0, 0, 0, 2.24999, -0.24999, -0.4344, 0.60551, -1.55939, 0.48051 ]
-						},
-						{
-							"time": 0.5333,
-							"vertices": [ 1.16999, 0, -0.234, -0.936, -2.92499, 0.351, 0, 0, 0, 0, 0.5, -0.24999, -0.64079, -2.07915, -0.64079, -2.07915 ]
-						},
-						{
-							"time": 0.7,
-							"vertices": [ 1.86271, -0.11514, 4.66327, -0.091, -1.76428, 0.21171, 0, 0, -0.56833, 0.32833, -1.13833, -1.15111, -2.19996, -3.47068, -1.29719, -3.47068, 0, 0, 0, 0, 1.58785, -0.04643, 2.65942, 0.16715 ]
-						},
-						{
-							"time": 0.8333,
-							"vertices": [ 2.41688, -0.20726, 8.58108, 0.585, -0.83571, 0.10029, 0, 0, -1.02299, 0.59099, -2.449, -1.872, -1.625, 0, 0, 0, 0, 0, 0, 0, 2.85813, -0.08357, 4.78695, 0.30086 ]
-						},
-						{
-							"time": 0.8667,
-							"vertices": [ 2.0197, -0.02141, 8.98546, 0.4446, -0.20937, 0.08023, 0.4592, 0, -0.3592, 0.47279, -1.8416, -1.4488, -0.79153, 1.26421, 0.53286, 1.23981, 0.4592, 0, 0.1176, -0.0976, 3.2839, -0.09025, 5.13116, 0.19389 ]
-						},
-						{
-							"time": 1,
-							"vertices": [ 0.43099, 0.722, 10.60295, -0.117, 2.29599, 0, 2.29599, 0, 2.29599, 0, 0.58799, 0.244, -2.40018, -0.65335, -2.2782, -0.77534, 2.29599, 0, 0.58799, -0.488, 4.98698, -0.117, 6.50797, -0.23399 ]
-						}
-					]
+					"undies": {
+						"deform": [
+							{
+								"vertices": [ 0.43099, 0.722, 10.60295, -0.117, 2.29599, 0, 2.29599, 0, 2.29599, 0, 0.58799, 0.244, -2.40018, -0.65335, -2.2782, -0.77534, 2.29599, 0, 0.58799, -0.488, 4.98698, -0.117, 6.50797, -0.23399 ]
+							},
+							{
+								"time": 0.1333,
+								"vertices": [ 0.72659, 0.4332, 7.20417, -0.1638, 1.37759, 0, 1.37759, 0, 1.37759, 0, 1.25279, 0.0464, -0.99862, -2.95085, -1.37543, -3.07404, 1.37759, 0, 0.35279, -0.2928, 2.99219, -0.0702, 3.90478, -0.1404 ]
+							},
+							{
+								"time": 0.3333,
+								"vertices": [ 1.16999, 0, 2.10599, -0.23401, 0, 0, 0, 0, 0, 0, 2.24999, -0.24999, -0.4344, 0.60551, -1.55939, 0.48051 ]
+							},
+							{
+								"time": 0.5333,
+								"vertices": [ 1.16999, 0, -0.234, -0.936, -2.92499, 0.351, 0, 0, 0, 0, 0.5, -0.24999, -0.64079, -2.07915, -0.64079, -2.07915 ]
+							},
+							{
+								"time": 0.7,
+								"vertices": [ 1.86271, -0.11514, 4.66327, -0.091, -1.76428, 0.21171, 0, 0, -0.56833, 0.32833, -1.13833, -1.15111, -2.19996, -3.47068, -1.29719, -3.47068, 0, 0, 0, 0, 1.58785, -0.04643, 2.65942, 0.16715 ]
+							},
+							{
+								"time": 0.8333,
+								"vertices": [ 2.41688, -0.20726, 8.58108, 0.585, -0.83571, 0.10029, 0, 0, -1.02299, 0.59099, -2.449, -1.872, -1.625, 0, 0, 0, 0, 0, 0, 0, 2.85813, -0.08357, 4.78695, 0.30086 ]
+							},
+							{
+								"time": 0.8667,
+								"vertices": [ 2.0197, -0.02141, 8.98546, 0.4446, -0.20937, 0.08023, 0.4592, 0, -0.3592, 0.47279, -1.8416, -1.4488, -0.79153, 1.26421, 0.53286, 1.23981, 0.4592, 0, 0.1176, -0.0976, 3.2839, -0.09025, 5.13116, 0.19389 ]
+							},
+							{
+								"time": 1,
+								"vertices": [ 0.43099, 0.722, 10.60295, -0.117, 2.29599, 0, 2.29599, 0, 2.29599, 0, 0.58799, 0.244, -2.40018, -0.65335, -2.2782, -0.77534, 2.29599, 0, 0.58799, -0.488, 4.98698, -0.117, 6.50797, -0.23399 ]
+							}
+						]
+					}
 				}
 			}
 		}

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.png


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 548 - 498
spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.json


BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.png


BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.png


+ 2 - 2
spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/raggedy spineboy.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "pCpU7tdx0Yk",
-	"spine": "4.0.31",
+	"hash": "ukmbgK+14T0",
+	"spine": "4.1.04-beta",
 	"x": -78.45,
 	"y": -9.66,
 	"width": 157.48,

+ 43 - 39
spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "1+TtfhbEFt8",
-	"spine": "4.0.31",
+	"hash": "oPVc6FExiik",
+	"spine": "4.1.04-beta",
 	"x": -402.84,
 	"y": -35.99,
 	"width": 611.87,
@@ -1248,7 +1248,7 @@
 			},
 			"gun": {
 				"attachment": [
-					{ "time": 0.1667, "name": null }
+					{ "time": 0.1667 }
 				]
 			}
 		},
@@ -1326,7 +1326,7 @@
 			},
 			"gun": {
 				"attachment": [
-					{ "name": null },
+					{},
 					{ "time": 0.4, "name": "gun_nohand" }
 				]
 			}
@@ -2051,45 +2051,49 @@
 				]
 			}
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"raptor_body": {
-					"raptor_body": [
-						{},
-						{
-							"time": 0.2667,
-							"offset": 452,
-							"vertices": [ 9.66226, 6.07712, -8.39342, 7.73739, -0.31512, 11.41041, 9.05756, 6.94628, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, 0, 0, -1.62274, 0.40576 ]
-						},
-						{ "time": 0.5333 },
-						{
-							"time": 0.8,
-							"offset": 452,
-							"vertices": [ 9.66226, 6.07712, -8.39342, 7.73739, -0.31512, 11.41041, 9.05756, 6.94628, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, 0, 0, -1.62274, 0.40576 ]
-						},
-						{ "time": 1.0667 }
-					]
+					"raptor_body": {
+						"deform": [
+							{},
+							{
+								"time": 0.2667,
+								"offset": 452,
+								"vertices": [ 9.66226, 6.07712, -8.39342, 7.73739, -0.31512, 11.41041, 9.05756, 6.94628, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, 0, 0, -1.62274, 0.40576 ]
+							},
+							{ "time": 0.5333 },
+							{
+								"time": 0.8,
+								"offset": 452,
+								"vertices": [ 9.66226, 6.07712, -8.39342, 7.73739, -0.31512, 11.41041, 9.05756, 6.94628, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, -1.62274, 0.40576, 0, 0, 0, 0, 0, 0, -1.62274, 0.40576, 0, 0, -1.62274, 0.40576 ]
+							},
+							{ "time": 1.0667 }
+						]
+					}
 				},
 				"raptor_front_leg": {
-					"raptor_front_leg": [
-						{ "time": 0.2667 },
-						{
-							"time": 0.5333,
-							"offset": 206,
-							"vertices": [ -1.11804, 10.97701, -10.52314, 3.3174, 10.77458, -2.3777 ]
-						},
-						{
-							"time": 0.6,
-							"offset": 206,
-							"vertices": [ 3.58981, 7.57179, -8.37008, -0.40027, 7.63262, -3.45871 ]
-						},
-						{
-							"time": 0.7333,
-							"offset": 160,
-							"vertices": [ -0.41243, 0.36704, -0.00642, -0.55221, -0.13748, 0.53003, -0.64028, 0.19816, 0, 0, 0, 0, 0, 0, 0, 0, 0.7433, -1.29713, 0.49036, 1.41172, -0.05063, -1.49312, 1.47504, -1.05834, 1.3683, -5.24968, 3.06253, 4.47641, -1.44046, -5.17512, -1.30437, -1.14192, 1.71709, -0.23523, -1.14153, -2.38019, 2.54447, 0.70039, -2.29261, -1.30733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.68984, -0.87758, -1.06615, -0.32834, -1.4312, -0.38682, 1.22995, -0.8266, -1.25796, 0.43206 ]
-						},
-						{ "time": 0.8 }
-					]
+					"raptor_front_leg": {
+						"deform": [
+							{ "time": 0.2667 },
+							{
+								"time": 0.5333,
+								"offset": 206,
+								"vertices": [ -1.11804, 10.97701, -10.52314, 3.3174, 10.77458, -2.3777 ]
+							},
+							{
+								"time": 0.6,
+								"offset": 206,
+								"vertices": [ 3.58981, 7.57179, -8.37008, -0.40027, 7.63262, -3.45871 ]
+							},
+							{
+								"time": 0.7333,
+								"offset": 160,
+								"vertices": [ -0.41243, 0.36704, -0.00642, -0.55221, -0.13748, 0.53003, -0.64028, 0.19816, 0, 0, 0, 0, 0, 0, 0, 0, 0.7433, -1.29713, 0.49036, 1.41172, -0.05063, -1.49312, 1.47504, -1.05834, 1.3683, -5.24968, 3.06253, 4.47641, -1.44046, -5.17512, -1.30437, -1.14192, 1.71709, -0.23523, -1.14153, -2.38019, 2.54447, 0.70039, -2.29261, -1.30733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.68984, -0.87758, -1.06615, -0.32834, -1.4312, -0.38682, 1.22995, -0.8266, -1.25796, 0.43206 ]
+							},
+							{ "time": 0.8 }
+						]
+					}
 				}
 			}
 		},

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.png


+ 252 - 220
spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "dGMI1oAkl8o",
-	"spine": "4.0.31",
+	"hash": "8oWe7nDoZEk",
+	"spine": "4.1.04-beta",
 	"x": -214.04,
 	"y": -80.91,
 	"width": 519.95,
@@ -650,7 +650,7 @@
 			"eyelids closed": {
 				"attachment": [
 					{ "name": "eyelids closed" },
-					{ "time": 0.0667, "name": null }
+					{ "time": 0.0667 }
 				]
 			}
 		},
@@ -2115,255 +2115,287 @@
 				]
 			}
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"armL": {
-					"armL": [
-						{
-							"time": 0.9,
-							"curve": [ 1.029, 0, 1.14, 1 ]
-						},
-						{
-							"time": 1.2667,
-							"offset": 28,
-							"vertices": [ -1.51086, 0.71941, -1.20222, -0.99176, -1.74438, -0.55032, -1.74438, -0.55032, -5.4474, -2.71472, -6.01334, -5.1203, -6.01334, -5.1203, -8.01959, 2.939, -6.01334, -5.1203, -6.01334, -5.1203, -6.01334, -5.1203, -8.01959, 2.939, -6.01334, -5.1203, -3.22636, -2.41086, -3.92453, 0.9055, -2.31032, -2.9559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.92453, 0.9055, -2.31032, -2.9559, -6.81499, -7.15472, 0, 0, 0, 0, 0, 0, -8.9516, 4.12372, -7.38049, -5.44019, -4.89615, -4.35225 ],
-							"curve": [ 1.526, 0, 1.747, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"armL": {
+						"deform": [
+							{
+								"time": 0.9,
+								"curve": [ 1.029, 0, 1.14, 1 ]
+							},
+							{
+								"time": 1.2667,
+								"offset": 28,
+								"vertices": [ -1.51086, 0.71941, -1.20222, -0.99176, -1.74438, -0.55032, -1.74438, -0.55032, -5.4474, -2.71472, -6.01334, -5.1203, -6.01334, -5.1203, -8.01959, 2.939, -6.01334, -5.1203, -6.01334, -5.1203, -6.01334, -5.1203, -8.01959, 2.939, -6.01334, -5.1203, -3.22636, -2.41086, -3.92453, 0.9055, -2.31032, -2.9559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.92453, 0.9055, -2.31032, -2.9559, -6.81499, -7.15472, 0, 0, 0, 0, 0, 0, -8.9516, 4.12372, -7.38049, -5.44019, -4.89615, -4.35225 ],
+								"curve": [ 1.526, 0, 1.747, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"armR": {
-					"armR": [
-						{
-							"curve": [ 0.79, 0, 0.635, 1 ]
-						},
-						{
-							"time": 1,
-							"vertices": [ 3.29417, 7.54852, 7.38307, 4.59549, 3.70951, 3.69086, 3.10799, 4.21008, 2.62421, 2.72685, 2.18121, 3.0929, -2.82712, 1.84239, -3.07339, 1.39288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.41486, -0.02728, 0.41422, 0.03586, 0.41486, -0.02728, 0.41422, 0.03586, 0, 0, 0, 0, -2.70642, -0.02931, -7.84895, 0.7765, -6.89497, 4.14276, -6.60889, 5.26572, -3.56116, 5.85962, -1.18237, 5.82011, 3.62317, 4.25227, 2.84126, 2.91956, 2.36634, 3.31624, -0.12074, 1.8717, -0.40276, 1.8318, 0.84898, 0.3584, 0.78494, 0.48286, 0, 0, 0, 0, -2.5412, 3.44402, -0.37629, 0.85307, 0, 0, 1.2253, -0.49471, 1.28616, -0.30338 ],
-							"curve": [ 1.79, 0, 1.635, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"armR": {
+						"deform": [
+							{
+								"curve": [ 0.79, 0, 0.635, 1 ]
+							},
+							{
+								"time": 1,
+								"vertices": [ 3.29417, 7.54852, 7.38307, 4.59549, 3.70951, 3.69086, 3.10799, 4.21008, 2.62421, 2.72685, 2.18121, 3.0929, -2.82712, 1.84239, -3.07339, 1.39288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.41486, -0.02728, 0.41422, 0.03586, 0.41486, -0.02728, 0.41422, 0.03586, 0, 0, 0, 0, -2.70642, -0.02931, -7.84895, 0.7765, -6.89497, 4.14276, -6.60889, 5.26572, -3.56116, 5.85962, -1.18237, 5.82011, 3.62317, 4.25227, 2.84126, 2.91956, 2.36634, 3.31624, -0.12074, 1.8717, -0.40276, 1.8318, 0.84898, 0.3584, 0.78494, 0.48286, 0, 0, 0, 0, -2.5412, 3.44402, -0.37629, 0.85307, 0, 0, 1.2253, -0.49471, 1.28616, -0.30338 ],
+								"curve": [ 1.79, 0, 1.635, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"bootR": {
-					"bootR": [
-						{
-							"curve": [ 0.294, 0, 0.546, 1 ]
-						},
-						{
-							"time": 0.8333,
-							"offset": 2,
-							"vertices": [ 5.22825, -1.73952, 4.71846, 0.2213, 5.62447, 6.47461, 1.50863, 7.97215, -4.47059, 2.31835, 0, 0, 0, 0, -4.4706, 2.31835, -4.4706, 2.31835, -4.4706, 2.31835, -4.4706, 2.31835 ],
-							"curve": [ 1.245, 0, 1.598, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"bootR": {
+						"deform": [
+							{
+								"curve": [ 0.294, 0, 0.546, 1 ]
+							},
+							{
+								"time": 0.8333,
+								"offset": 2,
+								"vertices": [ 5.22825, -1.73952, 4.71846, 0.2213, 5.62447, 6.47461, 1.50863, 7.97215, -4.47059, 2.31835, 0, 0, 0, 0, -4.4706, 2.31835, -4.4706, 2.31835, -4.4706, 2.31835, -4.4706, 2.31835 ],
+								"curve": [ 1.245, 0, 1.598, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"hairM blob": {
-					"hairM blob": [
-						{
-							"curve": [ 0.542, 0, 0.483, 1 ]
-						},
-						{
-							"time": 1,
-							"vertices": [ -1.08211, 8.65523, -1.11434, 7.5247, -2.24056, 6.26955, -3.82799, 5.99094, -3.91438, 7.22203, -2.67052, 9.0497, -1.38165, 9.20383 ],
-							"curve": [ 1.542, 0, 1.483, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"hairM blob": {
+						"deform": [
+							{
+								"curve": [ 0.542, 0, 0.483, 1 ]
+							},
+							{
+								"time": 1,
+								"vertices": [ -1.08211, 8.65523, -1.11434, 7.5247, -2.24056, 6.26955, -3.82799, 5.99094, -3.91438, 7.22203, -2.67052, 9.0497, -1.38165, 9.20383 ],
+								"curve": [ 1.542, 0, 1.483, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"hairM blobS": {
-					"hairM blobS": [
-						{
-							"curve": [ 0.542, 0, 0.483, 1 ]
-						},
-						{
-							"time": 1,
-							"vertices": [ -5.04186, 4.96768, -4.67044, 7.01031, -4.93049, 10.27776, -5.31269, 10.78222, -5.59053, 8.83483, -5.32308, 5.60685 ],
-							"curve": [ 1.542, 0, 1.483, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"hairM blobS": {
+						"deform": [
+							{
+								"curve": [ 0.542, 0, 0.483, 1 ]
+							},
+							{
+								"time": 1,
+								"vertices": [ -5.04186, 4.96768, -4.67044, 7.01031, -4.93049, 10.27776, -5.31269, 10.78222, -5.59053, 8.83483, -5.32308, 5.60685 ],
+								"curve": [ 1.542, 0, 1.483, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"hairSide": {
-					"hairSide": [
-						{},
-						{
-							"time": 0.6,
-							"vertices": [ -1.60584, 0.69799, -2.39742, 5.14579, 1.78111, 10.4846, -1.31722, -1.77717 ]
-						},
-						{ "time": 1.1 },
-						{
-							"time": 1.6667,
-							"vertices": [ -1.60584, 0.69799, -2.39742, 5.14579, 1.78111, 10.4846, -1.31722, -1.77717 ]
-						},
-						{ "time": 2 }
-					]
+					"hairSide": {
+						"deform": [
+							{},
+							{
+								"time": 0.6,
+								"vertices": [ -1.60584, 0.69799, -2.39742, 5.14579, 1.78111, 10.4846, -1.31722, -1.77717 ]
+							},
+							{ "time": 1.1 },
+							{
+								"time": 1.6667,
+								"vertices": [ -1.60584, 0.69799, -2.39742, 5.14579, 1.78111, 10.4846, -1.31722, -1.77717 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"indexL": {
-					"indexL": [
-						{ "curve": "stepped" },
-						{
-							"time": 0.3333,
-							"curve": [ 0.497, 0, 0.649, 0.49 ]
-						},
-						{
-							"time": 0.8,
-							"vertices": [ 0.3316, -0.01168, 0.33158, -0.01167, 0.33158, -0.01169, 0.32023, -0.02302, -1.0E-5, 1.0E-5, 1.0E-5, 1.0E-5, -4.0E-5, 3.0E-5, 0.32023, -0.02301, 0.33155, -0.01169, 0.3316, -0.01167, 0.3316, -0.01167 ],
-							"curve": [ 0.953, 0.49, 1.105, 1 ]
-						},
-						{
-							"time": 1.2667,
-							"vertices": [ -7.78268, -0.32068, -7.7827, -0.32067, -7.7827, -0.32069, -1.72646, -0.27644, -1.0E-5, 1.0E-5, 1.0E-5, 1.0E-5, -4.0E-5, 3.0E-5, -1.72646, -0.27643, -7.78273, -0.32069, -7.78268, -0.32067, -7.78268, -0.32067 ],
-							"curve": [ 1.526, 0, 1.747, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"indexL": {
+						"deform": [
+							{ "curve": "stepped" },
+							{
+								"time": 0.3333,
+								"curve": [ 0.497, 0, 0.649, 0.49 ]
+							},
+							{
+								"time": 0.8,
+								"vertices": [ 0.3316, -0.01168, 0.33158, -0.01167, 0.33158, -0.01169, 0.32023, -0.02302, -1.0E-5, 1.0E-5, 1.0E-5, 1.0E-5, -4.0E-5, 3.0E-5, 0.32023, -0.02301, 0.33155, -0.01169, 0.3316, -0.01167, 0.3316, -0.01167 ],
+								"curve": [ 0.953, 0.49, 1.105, 1 ]
+							},
+							{
+								"time": 1.2667,
+								"vertices": [ -7.78268, -0.32068, -7.7827, -0.32067, -7.7827, -0.32069, -1.72646, -0.27644, -1.0E-5, 1.0E-5, 1.0E-5, 1.0E-5, -4.0E-5, 3.0E-5, -1.72646, -0.27643, -7.78273, -0.32069, -7.78268, -0.32067, -7.78268, -0.32067 ],
+								"curve": [ 1.526, 0, 1.747, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"indexR": {
-					"indexR": [
-						{
-							"curve": [ 0.353, 0, 0.655, 1 ]
-						},
-						{
-							"time": 1,
-							"vertices": [ -3.70744, 2.07258, -3.56297, 1.70496, -4.31731, -0.57099, -3.25647, -3.29185, -2.18936, -5.81705, 0.70666, -5.57201, 1.93816, -3.54265, 1.80319, 0.17362, 0.49382, -1.71758, 0.49383, -1.71758, 1.0E-5, -1.0E-5, 0, 0, -4.19104, 3.05999, -1.06691, -0.08681 ],
-							"curve": [ 1.353, 0, 1.655, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"indexR": {
+						"deform": [
+							{
+								"curve": [ 0.353, 0, 0.655, 1 ]
+							},
+							{
+								"time": 1,
+								"vertices": [ -3.70744, 2.07258, -3.56297, 1.70496, -4.31731, -0.57099, -3.25647, -3.29185, -2.18936, -5.81705, 0.70666, -5.57201, 1.93816, -3.54265, 1.80319, 0.17362, 0.49382, -1.71758, 0.49383, -1.71758, 1.0E-5, -1.0E-5, 0, 0, -4.19104, 3.05999, -1.06691, -0.08681 ],
+								"curve": [ 1.353, 0, 1.655, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"irisL flatspec": {
-					"irisL flatspec": [
-						{},
-						{
-							"time": 0.5,
-							"vertices": [ 0.61252, -0.47808, -0.34621, -0.26418, -0.95872, 0.2139 ]
-						},
-						{ "time": 1 },
-						{
-							"time": 1.5667,
-							"vertices": [ 0.61252, -0.47808, -0.34621, -0.26418, -1.41387, 0.64572, 1.69759, 0.84319 ]
-						},
-						{ "time": 2 }
-					]
+					"irisL flatspec": {
+						"deform": [
+							{},
+							{
+								"time": 0.5,
+								"vertices": [ 0.61252, -0.47808, -0.34621, -0.26418, -0.95872, 0.2139 ]
+							},
+							{ "time": 1 },
+							{
+								"time": 1.5667,
+								"vertices": [ 0.61252, -0.47808, -0.34621, -0.26418, -1.41387, 0.64572, 1.69759, 0.84319 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"irisL spec": {
-					"irisL spec": [
-						{},
-						{
-							"time": 0.5,
-							"vertices": [ 2.66561, -1.34321, -0.62155, -1.4382, 2.1585, -0.04376, 3.15285, -1.17854 ]
-						},
-						{
-							"time": 1,
-							"vertices": [ 0.98535, -1.29693, -1.2431, -2.87638, -2.16038, -1.52057 ]
-						},
-						{
-							"time": 1.5667,
-							"vertices": [ 2.93274, 1.38345, 1.4911, -0.79594, -0.93617, -0.65891 ]
-						},
-						{ "time": 2 }
-					]
+					"irisL spec": {
+						"deform": [
+							{},
+							{
+								"time": 0.5,
+								"vertices": [ 2.66561, -1.34321, -0.62155, -1.4382, 2.1585, -0.04376, 3.15285, -1.17854 ]
+							},
+							{
+								"time": 1,
+								"vertices": [ 0.98535, -1.29693, -1.2431, -2.87638, -2.16038, -1.52057 ]
+							},
+							{
+								"time": 1.5667,
+								"vertices": [ 2.93274, 1.38345, 1.4911, -0.79594, -0.93617, -0.65891 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"irisR flatspec": {
-					"irisR flatspec": [
-						{},
-						{
-							"time": 0.4667,
-							"offset": 2,
-							"vertices": [ -1.70543, 0.46474, -1.2566, -0.32218, 1.71141, 0.20524 ]
-						},
-						{ "time": 0.9667 },
-						{
-							"time": 1.5667,
-							"vertices": [ 0.42843, -0.47367, -1.277, -0.00896, -1.2566, -0.32218, 1.71141, 0.20524 ]
-						},
-						{ "time": 2 }
-					]
+					"irisR flatspec": {
+						"deform": [
+							{},
+							{
+								"time": 0.4667,
+								"offset": 2,
+								"vertices": [ -1.70543, 0.46474, -1.2566, -0.32218, 1.71141, 0.20524 ]
+							},
+							{ "time": 0.9667 },
+							{
+								"time": 1.5667,
+								"vertices": [ 0.42843, -0.47367, -1.277, -0.00896, -1.2566, -0.32218, 1.71141, 0.20524 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"irisR spec": {
-					"irisR spec": [
-						{},
-						{
-							"time": 0.4,
-							"vertices": [ 1.33019, 0.3099, -0.7722, -1.58121, -0.93541, -2.05612, -0.31694, 1.15223 ]
-						},
-						{
-							"time": 0.9667,
-							"vertices": [ -1.23871, -0.17238, -2.84217, 0.45327, 1.84367, 0.5128, 1.38389, 0.67142 ]
-						},
-						{
-							"time": 1.5,
-							"vertices": [ -0.55319, 2.56626, -1.37525, 0.21934, -0.90461, 0.64045, -1.50449, -0.12951 ]
-						},
-						{ "time": 2 }
-					]
+					"irisR spec": {
+						"deform": [
+							{},
+							{
+								"time": 0.4,
+								"vertices": [ 1.33019, 0.3099, -0.7722, -1.58121, -0.93541, -2.05612, -0.31694, 1.15223 ]
+							},
+							{
+								"time": 0.9667,
+								"vertices": [ -1.23871, -0.17238, -2.84217, 0.45327, 1.84367, 0.5128, 1.38389, 0.67142 ]
+							},
+							{
+								"time": 1.5,
+								"vertices": [ -0.55319, 2.56626, -1.37525, 0.21934, -0.90461, 0.64045, -1.50449, -0.12951 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"middleL": {
-					"middleL": [
-						{
-							"curve": [ 0.379, 0, 0.338, 1 ]
-						},
-						{
-							"time": 0.7,
-							"vertices": [ 1.87502, -1.17947, 2.27197, -0.96694, 2.27365, -1.0802, -0.73205, -0.10651, 0, 0, 0, -1.0E-5, 0, 0, -0.55559, -0.01207, 2.27369, -1.08022, 1.79739, -1.19242, 1.78682, -1.2267 ],
-							"curve": [ 1.061, 0, 1.022, 1 ]
-						},
-						{
-							"time": 1.3667,
-							"vertices": [ -6.16218, -0.21533, -4.73239, 0.55014, -4.72634, 0.14221, -2.6366, -0.38359, 0, 0, 0, -1.0E-5, 0, 0, -2.00113, -0.04347, -4.7263, 0.14219, -6.44176, -0.26199, -6.47987, -0.38544 ],
-							"curve": [ 1.59, 0, 1.782, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"middleL": {
+						"deform": [
+							{
+								"curve": [ 0.379, 0, 0.338, 1 ]
+							},
+							{
+								"time": 0.7,
+								"vertices": [ 1.87502, -1.17947, 2.27197, -0.96694, 2.27365, -1.0802, -0.73205, -0.10651, 0, 0, 0, -1.0E-5, 0, 0, -0.55559, -0.01207, 2.27369, -1.08022, 1.79739, -1.19242, 1.78682, -1.2267 ],
+								"curve": [ 1.061, 0, 1.022, 1 ]
+							},
+							{
+								"time": 1.3667,
+								"vertices": [ -6.16218, -0.21533, -4.73239, 0.55014, -4.72634, 0.14221, -2.6366, -0.38359, 0, 0, 0, -1.0E-5, 0, 0, -2.00113, -0.04347, -4.7263, 0.14219, -6.44176, -0.26199, -6.47987, -0.38544 ],
+								"curve": [ 1.59, 0, 1.782, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"ringL": {
-					"ringL": [
-						{
-							"curve": [ 0.614, 0, 0.547, 1 ]
-						},
-						{
-							"time": 1.1333,
-							"vertices": [ 2.29756, -2.1041, 2.29753, -2.10409, 2.29757, -2.1041, 0, 0, 0, 0, -0.61601, -0.2029 ],
-							"curve": [ 1.35, 0, 1.327, 1 ]
-						},
-						{
-							"time": 1.5333,
-							"vertices": [ -3.41745, -0.94554, -3.41747, -0.94553, -3.41744, -0.94554, 0, 0, 0, 0, -1.24409, -0.40979 ],
-							"curve": [ 1.786, 0, 1.759, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"ringL": {
+						"deform": [
+							{
+								"curve": [ 0.614, 0, 0.547, 1 ]
+							},
+							{
+								"time": 1.1333,
+								"vertices": [ 2.29756, -2.1041, 2.29753, -2.10409, 2.29757, -2.1041, 0, 0, 0, 0, -0.61601, -0.2029 ],
+								"curve": [ 1.35, 0, 1.327, 1 ]
+							},
+							{
+								"time": 1.5333,
+								"vertices": [ -3.41745, -0.94554, -3.41747, -0.94553, -3.41744, -0.94554, 0, 0, 0, 0, -1.24409, -0.40979 ],
+								"curve": [ 1.786, 0, 1.759, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"thumbL": {
-					"thumbL": [
-						{ "curve": "stepped" },
-						{
-							"time": 0.4667,
-							"curve": [ 0.714, 0, 0.925, 1 ]
-						},
-						{
-							"time": 1.1667,
-							"vertices": [ -2.29185, -3.98124, -0.2334, -3.13461, 0.49543, -1.60927, 1.06945, 0.67771, -0.11907, -0.5765, -0.11912, -0.57646, -1.0E-5, 0, -1.0E-5, 2.0E-5, -1.80242, 1.16175, -2.5097, 0.70314, -3.87533, 0.49874, -4.51916, -1.38056, -4.28195, -2.70174, -3.59239, -3.16153, -3.25915, -3.82949, -1.17744, -0.89034, 0.3796, 0.01583 ],
-							"curve": [ 1.461, 0, 1.713, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"thumbL": {
+						"deform": [
+							{ "curve": "stepped" },
+							{
+								"time": 0.4667,
+								"curve": [ 0.714, 0, 0.925, 1 ]
+							},
+							{
+								"time": 1.1667,
+								"vertices": [ -2.29185, -3.98124, -0.2334, -3.13461, 0.49543, -1.60927, 1.06945, 0.67771, -0.11907, -0.5765, -0.11912, -0.57646, -1.0E-5, 0, -1.0E-5, 2.0E-5, -1.80242, 1.16175, -2.5097, 0.70314, -3.87533, 0.49874, -4.51916, -1.38056, -4.28195, -2.70174, -3.59239, -3.16153, -3.25915, -3.82949, -1.17744, -0.89034, 0.3796, 0.01583 ],
+								"curve": [ 1.461, 0, 1.713, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				},
 				"thumbR": {
-					"thumbR": [
-						{
-							"curve": [ 0.353, 0, 0.655, 1 ]
-						},
-						{
-							"time": 1,
-							"offset": 2,
-							"vertices": [ 4.24296, 0.26622, 5.3837, 4.83061, 3.73976, 9.41351, -1.18715, 11.81196, -5.39824, 10.30256, -6.95535, 4.73572, -3.19517, -0.32295, -1.31602, 0.11442, 0, 1.0E-5, 0, -1.0E-5, -1.0E-5, 1.0E-5, -0.93784, 2.97592 ],
-							"curve": [ 1.353, 0, 1.655, 1 ]
-						},
-						{ "time": 2 }
-					]
+					"thumbR": {
+						"deform": [
+							{
+								"curve": [ 0.353, 0, 0.655, 1 ]
+							},
+							{
+								"time": 1,
+								"offset": 2,
+								"vertices": [ 4.24296, 0.26622, 5.3837, 4.83061, 3.73976, 9.41351, -1.18715, 11.81196, -5.39824, 10.30256, -6.95535, 4.73572, -3.19517, -0.32295, -1.31602, 0.11442, 0, 1.0E-5, 0, -1.0E-5, -1.0E-5, 1.0E-5, -0.93784, 2.97592 ],
+								"curve": [ 1.353, 0, 1.655, 1 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				}
 			}
 		}

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.png


+ 140 - 136
spine-unity/Assets/Spine Examples/Spine Skeletons/Stretchyman/stretchyman.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "F+EPhClYhR8",
-	"spine": "4.0.31",
+	"hash": "NNUiOwCxKWo",
+	"spine": "4.1.04-beta",
 	"x": -100.47,
 	"y": -9.21,
 	"width": 260.65,
@@ -1966,144 +1966,148 @@
 				{ "mix": 0 }
 			]
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"back-leg-path": {
-					"back-leg-path": [
-						{
-							"curve": [ 0.158, 0, 0.475, 1 ]
-						},
-						{
-							"time": 0.6333,
-							"offset": 6,
-							"vertices": [ 7.58212, 6.44012, -6.24036, 7.74866, 0, 0, 0, 0, -8.65305, -6.0506, 5.82422, -8.80603 ],
-							"curve": [ 0.771, 0, 1.005, 0.48 ]
-						},
-						{
-							"time": 1.2,
-							"offset": 6,
-							"vertices": [ 1.75757, 1.49285, -1.44654, 1.79617, 0, 0, 0, 0, -2.00581, -1.40255, 1.35008, -2.04128 ],
-							"curve": [ 1.215, 0, 1.225, 0.03 ]
-						},
-						{
-							"time": 1.2333,
-							"offset": 6,
-							"vertices": [ 11.07889, 9.19726, -3.09299, 13.71402, 9.39429, 7.76639, -1.7065, 11.99242, 7.47175, 6.42206, -0.41247, 10.03589 ],
-							"curve": [ 1.246, 0.12, 1.254, 0.27 ]
-						},
-						{
-							"time": 1.2667,
-							"offset": 6,
-							"vertices": [ 10.10474, 8.7463, -2.36874, 12.63447, 8.81438, 7.65029, -1.30674, 11.31577, 7.34177, 6.62058, -0.31555, 9.81713 ],
-							"curve": [ 1.275, 0.62, 1.286, 0.79 ]
-						},
-						{
-							"time": 1.3,
-							"offset": 6,
-							"vertices": [ 3.4599, -0.42859, 1.07778, 1.47922, 2.60141, -1.15778, 1.78435, 0.60187, 1.62166, -1.84286, 2.4438, -0.3952 ],
-							"curve": [ 1.354, 0.76, 1.414, 1 ]
-						},
-						{
-							"time": 1.4333,
-							"offset": 6,
-							"vertices": [ -4.08505, -24.14874, 13.996, -20.09798, -4.08505, -24.14874, 13.996, -20.09798, -4.08505, -24.14874, 13.996, -20.09798 ]
-						},
-						{
-							"time": 1.5,
-							"vertices": [ 4.67719, -35.44354, 0, 0, -11.37146, 49.53738, 17.39343, -2.33365, 4.23248, 5.68374, -9.56653, -24.74756, 11.45203, -23.93552, -27.49841, -64.4725, 35.55432, -56.67893, 34.69244, -51.5341, 0, 0, 13.30164, -100.17206 ]
-						},
-						{
-							"time": 1.5333,
-							"vertices": [ 1.85684, -28.94159, 0, 0, -12.58768, 38.57599, 11.30969, 16.17496, -13.13428, 1.4907, -12.13364, -13.87851, 4.3075, -20.49398, -34.95135, -45.73811, 21.12878, -45.5335, 30.62613, -45.13649, 0, 0, -0.15961, -190.51059 ]
-						},
-						{
-							"time": 1.5667,
-							"vertices": [ -0.9635, -22.43964, 0, 0, -13.80389, 27.61459, 1.79449, 28.22318, -27.06714, -9.07224, -6.2052, -1.21002, 1.34003, -9.39124, -24.41541, -19.97638, 12.56061, -16.52356, 26.55981, -38.73888, 0, 0, -13.62085, -280.84912 ]
-						},
-						{
-							"time": 1.6,
-							"vertices": [ -0.64233, -14.95974, 0, 0, -9.20259, 18.40971, 13.73107, 41.19725, -42.90586, -9.10037, 4.13583, -3.71808, 4.12607, -1.04554, -17.52923, -15.07591, 15.79826, -11.47559, 17.70652, -25.82589, 0, 0, -9.08056, -187.23253 ]
-						},
-						{
-							"time": 1.6333,
-							"vertices": [ -0.32117, -7.47987, 0, 0, -4.60129, 9.20485, 3.14877, 52.3598, -63.25818, -29.05335, -8.042, -8.03761, 2.39843, -12.62472, -33.16191, -11.98693, 14.52224, -26.35249, 8.85326, -12.91294, 0, 0, -4.54028, -93.61627 ]
-						},
-						{ "time": 1.6667 }
-					]
+					"back-leg-path": {
+						"deform": [
+							{
+								"curve": [ 0.158, 0, 0.475, 1 ]
+							},
+							{
+								"time": 0.6333,
+								"offset": 6,
+								"vertices": [ 7.58212, 6.44012, -6.24036, 7.74866, 0, 0, 0, 0, -8.65305, -6.0506, 5.82422, -8.80603 ],
+								"curve": [ 0.771, 0, 1.005, 0.48 ]
+							},
+							{
+								"time": 1.2,
+								"offset": 6,
+								"vertices": [ 1.75757, 1.49285, -1.44654, 1.79617, 0, 0, 0, 0, -2.00581, -1.40255, 1.35008, -2.04128 ],
+								"curve": [ 1.215, 0, 1.225, 0.03 ]
+							},
+							{
+								"time": 1.2333,
+								"offset": 6,
+								"vertices": [ 11.07889, 9.19726, -3.09299, 13.71402, 9.39429, 7.76639, -1.7065, 11.99242, 7.47175, 6.42206, -0.41247, 10.03589 ],
+								"curve": [ 1.246, 0.12, 1.254, 0.27 ]
+							},
+							{
+								"time": 1.2667,
+								"offset": 6,
+								"vertices": [ 10.10474, 8.7463, -2.36874, 12.63447, 8.81438, 7.65029, -1.30674, 11.31577, 7.34177, 6.62058, -0.31555, 9.81713 ],
+								"curve": [ 1.275, 0.62, 1.286, 0.79 ]
+							},
+							{
+								"time": 1.3,
+								"offset": 6,
+								"vertices": [ 3.4599, -0.42859, 1.07778, 1.47922, 2.60141, -1.15778, 1.78435, 0.60187, 1.62166, -1.84286, 2.4438, -0.3952 ],
+								"curve": [ 1.354, 0.76, 1.414, 1 ]
+							},
+							{
+								"time": 1.4333,
+								"offset": 6,
+								"vertices": [ -4.08505, -24.14874, 13.996, -20.09798, -4.08505, -24.14874, 13.996, -20.09798, -4.08505, -24.14874, 13.996, -20.09798 ]
+							},
+							{
+								"time": 1.5,
+								"vertices": [ 4.67719, -35.44354, 0, 0, -11.37146, 49.53738, 17.39343, -2.33365, 4.23248, 5.68374, -9.56653, -24.74756, 11.45203, -23.93552, -27.49841, -64.4725, 35.55432, -56.67893, 34.69244, -51.5341, 0, 0, 13.30164, -100.17206 ]
+							},
+							{
+								"time": 1.5333,
+								"vertices": [ 1.85684, -28.94159, 0, 0, -12.58768, 38.57599, 11.30969, 16.17496, -13.13428, 1.4907, -12.13364, -13.87851, 4.3075, -20.49398, -34.95135, -45.73811, 21.12878, -45.5335, 30.62613, -45.13649, 0, 0, -0.15961, -190.51059 ]
+							},
+							{
+								"time": 1.5667,
+								"vertices": [ -0.9635, -22.43964, 0, 0, -13.80389, 27.61459, 1.79449, 28.22318, -27.06714, -9.07224, -6.2052, -1.21002, 1.34003, -9.39124, -24.41541, -19.97638, 12.56061, -16.52356, 26.55981, -38.73888, 0, 0, -13.62085, -280.84912 ]
+							},
+							{
+								"time": 1.6,
+								"vertices": [ -0.64233, -14.95974, 0, 0, -9.20259, 18.40971, 13.73107, 41.19725, -42.90586, -9.10037, 4.13583, -3.71808, 4.12607, -1.04554, -17.52923, -15.07591, 15.79826, -11.47559, 17.70652, -25.82589, 0, 0, -9.08056, -187.23253 ]
+							},
+							{
+								"time": 1.6333,
+								"vertices": [ -0.32117, -7.47987, 0, 0, -4.60129, 9.20485, 3.14877, 52.3598, -63.25818, -29.05335, -8.042, -8.03761, 2.39843, -12.62472, -33.16191, -11.98693, 14.52224, -26.35249, 8.85326, -12.91294, 0, 0, -4.54028, -93.61627 ]
+							},
+							{ "time": 1.6667 }
+						]
+					}
 				},
 				"front-leg-path": {
-					"front-leg-path": [
-						{
-							"curve": [ 0.075, 0, 0.189, 0.28 ]
-						},
-						{
-							"time": 0.3,
-							"vertices": [ 0.05087, -3.38688, 0, 0, 1.38452, 5.97834, -14.9041, 2.01206, 1.44487, -6.80281, -14.9041, 2.01206, 1.44487, -6.80281, -14.9041, 2.01206, 1.44487, -6.80281 ],
-							"curve": [ 0.323, 0.2, 0.345, 0.35 ]
-						},
-						{
-							"time": 0.3667,
-							"vertices": [ 0.07139, -4.75271, 0, 0, 1.94286, 8.38924, 4.65956, 20.90988, -6.00341, 18.98861, -0.14155, 20.92476, -9.36768, 15.5653, -12.20349, 23.97896, -19.98153, 9.06929 ],
-							"curve": [ 0.39, 0.31, 0.412, 0.53 ]
-						},
-						{
-							"time": 0.4333,
-							"vertices": [ 0.08487, -5.65058, 0, 0, 2.3099, 9.97411, 6.09287, 20.58425, -8.39331, 19.11554, -1.86437, 20.6089, -13.96917, 13.44183, -21.85559, 25.6709, -31.56034, 2.67548 ],
-							"curve": [ 0.438, 0.32, 0.451, 0.54 ]
-						},
-						{
-							"time": 0.4667,
-							"vertices": [ 0.09099, -6.05806, 0, 0, 2.47648, 10.69338, 6.80647, 9.95062, -1.39596, 12.12401, -2.58313, 9.97971, -7.97551, 5.429, -26.17287, 15.95288, -28.7332, -7.27536 ],
-							"curve": [ 0.491, 0.92, 0.521, 0.99 ]
-						},
-						{
-							"time": 0.5333,
-							"vertices": [ 0.0938, -6.24474, 0, 0, 2.55279, 11.0229, 3.37726, -9.77658, 9.35123, -4.41786, -6.66855, -9.74546, 2.31187, -11.58077, -31.90691, -3.35485, -19.89651, -25.173 ],
-							"curve": [ 0.54, 0.52, 0.553, 0.77 ]
-						},
-						{
-							"time": 0.5667,
-							"vertices": [ 0.12554, -7.9214, 0, 0, 0.6047, 13.76218, 28.2061, -4.72442, -24.72498, -10.04851, -1.08998, -15.00371, 3.89968, -14.73675, -45.72995, -9.44002, -7.51602, -33.5578, 22.59846, -13.40422, 0, 0, -21.81488, -287.65363 ],
-							"curve": [ 0.579, 1, 0.592, 1 ]
-						},
-						{
-							"time": 0.6,
-							"vertices": [ 0.12969, -8.14021, 0, 0, 0.35046, 14.11967, 49.51149, 65.25623, -80.01971, 39.68078, -0.36196, -15.68993, 4.10689, -15.14861, -62.03986, -28.71517, 2.78595, -56.47927, 41.45007, -31.91446, 0, 0, -19.75009, -6.99966 ]
-						},
-						{
-							"time": 0.6333,
-							"vertices": [ 0.16366, -9.90768, 0, 0, -1.90419, 16.9905, 99.3634, 33.16509, -81.26534, 35.35141, -0.72391, -31.37989, 8.2138, -30.29725, -84.11658, -22.14578, -6.24997, -61.22949, 46.91129, -33.41971, 0, 0, -31.98465, -262.01813 ]
-						},
-						{
-							"time": 0.6667,
-							"vertices": [ 0.18382, -11.1283, 0, 0, -2.13879, 19.08371, 85.97569, 24.69115, -94.39235, -5.64914, 3.63728, -14.95789, -10.54588, -27.66409, -78.76755, -2.82176, -20.92926, -42.81331, 26.18336, -20.74105, 0, 0, -159.67368, -300.67038 ]
-						},
-						{
-							"time": 0.7,
-							"vertices": [ 0.20398, -12.34892, 0, 0, -2.37338, 21.17692, 70.14705, -52.80042, -51.24022, -73.25025, 20.8386, -23.27967, -12.66359, -23.66, -39.22493, -9.41795, -5.46658, 10.6813, 1.18861, 10.38911, 0, 0, -400.93036, -315.42963 ]
-						},
-						{
-							"time": 0.7333,
-							"vertices": [ 0.13599, -8.23261, 0, 0, -1.58226, 14.11795, 46.76473, -35.2003, -34.16017, -48.83353, 13.89241, -15.51979, -8.4424, -15.77335, -26.14997, -6.27864, -3.64439, 7.12087, 0.8908, 26.32127, 0, 0, -439.48523, -177.52177 ]
-						},
-						{
-							"time": 0.7667,
-							"vertices": [ 0.06799, -4.11631, 0, 0, -0.79113, 7.05898, 23.38236, -17.60015, -17.08008, -24.41677, 6.94621, -7.7599, -4.2212, -7.88667, -13.07498, -3.13932, -1.8222, 3.56044, 6.0198, 23.00182, 0, 0, -365.68442, -226.89883 ]
-						},
-						{ "time": 0.8, "curve": "stepped" },
-						{ "time": 1.1 },
-						{
-							"time": 1.3,
-							"offset": 6,
-							"vertices": [ 22.24737, 20.71245, -17.43828, 31.85296, 22.24737, 20.71245, -17.43828, 31.85296, 22.24737, 20.71245, -17.43828, 31.85296 ]
-						},
-						{
-							"time": 1.4333,
-							"offset": 6,
-							"vertices": [ 50.92273, 30.30164, -15.21045, 57.26978, 50.92273, 30.30164, -15.21045, 57.26978, 50.92273, 30.30164, -15.21045, 57.26978 ]
-						},
-						{ "time": 1.8 }
-					]
+					"front-leg-path": {
+						"deform": [
+							{
+								"curve": [ 0.075, 0, 0.189, 0.28 ]
+							},
+							{
+								"time": 0.3,
+								"vertices": [ 0.05087, -3.38688, 0, 0, 1.38452, 5.97834, -14.9041, 2.01206, 1.44487, -6.80281, -14.9041, 2.01206, 1.44487, -6.80281, -14.9041, 2.01206, 1.44487, -6.80281 ],
+								"curve": [ 0.323, 0.2, 0.345, 0.35 ]
+							},
+							{
+								"time": 0.3667,
+								"vertices": [ 0.07139, -4.75271, 0, 0, 1.94286, 8.38924, 4.65956, 20.90988, -6.00341, 18.98861, -0.14155, 20.92476, -9.36768, 15.5653, -12.20349, 23.97896, -19.98153, 9.06929 ],
+								"curve": [ 0.39, 0.31, 0.412, 0.53 ]
+							},
+							{
+								"time": 0.4333,
+								"vertices": [ 0.08487, -5.65058, 0, 0, 2.3099, 9.97411, 6.09287, 20.58425, -8.39331, 19.11554, -1.86437, 20.6089, -13.96917, 13.44183, -21.85559, 25.6709, -31.56034, 2.67548 ],
+								"curve": [ 0.438, 0.32, 0.451, 0.54 ]
+							},
+							{
+								"time": 0.4667,
+								"vertices": [ 0.09099, -6.05806, 0, 0, 2.47648, 10.69338, 6.80647, 9.95062, -1.39596, 12.12401, -2.58313, 9.97971, -7.97551, 5.429, -26.17287, 15.95288, -28.7332, -7.27536 ],
+								"curve": [ 0.491, 0.92, 0.521, 0.99 ]
+							},
+							{
+								"time": 0.5333,
+								"vertices": [ 0.0938, -6.24474, 0, 0, 2.55279, 11.0229, 3.37726, -9.77658, 9.35123, -4.41786, -6.66855, -9.74546, 2.31187, -11.58077, -31.90691, -3.35485, -19.89651, -25.173 ],
+								"curve": [ 0.54, 0.52, 0.553, 0.77 ]
+							},
+							{
+								"time": 0.5667,
+								"vertices": [ 0.12554, -7.9214, 0, 0, 0.6047, 13.76218, 28.2061, -4.72442, -24.72498, -10.04851, -1.08998, -15.00371, 3.89968, -14.73675, -45.72995, -9.44002, -7.51602, -33.5578, 22.59846, -13.40422, 0, 0, -21.81488, -287.65363 ],
+								"curve": [ 0.579, 1, 0.592, 1 ]
+							},
+							{
+								"time": 0.6,
+								"vertices": [ 0.12969, -8.14021, 0, 0, 0.35046, 14.11967, 49.51149, 65.25623, -80.01971, 39.68078, -0.36196, -15.68993, 4.10689, -15.14861, -62.03986, -28.71517, 2.78595, -56.47927, 41.45007, -31.91446, 0, 0, -19.75009, -6.99966 ]
+							},
+							{
+								"time": 0.6333,
+								"vertices": [ 0.16366, -9.90768, 0, 0, -1.90419, 16.9905, 99.3634, 33.16509, -81.26534, 35.35141, -0.72391, -31.37989, 8.2138, -30.29725, -84.11658, -22.14578, -6.24997, -61.22949, 46.91129, -33.41971, 0, 0, -31.98465, -262.01813 ]
+							},
+							{
+								"time": 0.6667,
+								"vertices": [ 0.18382, -11.1283, 0, 0, -2.13879, 19.08371, 85.97569, 24.69115, -94.39235, -5.64914, 3.63728, -14.95789, -10.54588, -27.66409, -78.76755, -2.82176, -20.92926, -42.81331, 26.18336, -20.74105, 0, 0, -159.67368, -300.67038 ]
+							},
+							{
+								"time": 0.7,
+								"vertices": [ 0.20398, -12.34892, 0, 0, -2.37338, 21.17692, 70.14705, -52.80042, -51.24022, -73.25025, 20.8386, -23.27967, -12.66359, -23.66, -39.22493, -9.41795, -5.46658, 10.6813, 1.18861, 10.38911, 0, 0, -400.93036, -315.42963 ]
+							},
+							{
+								"time": 0.7333,
+								"vertices": [ 0.13599, -8.23261, 0, 0, -1.58226, 14.11795, 46.76473, -35.2003, -34.16017, -48.83353, 13.89241, -15.51979, -8.4424, -15.77335, -26.14997, -6.27864, -3.64439, 7.12087, 0.8908, 26.32127, 0, 0, -439.48523, -177.52177 ]
+							},
+							{
+								"time": 0.7667,
+								"vertices": [ 0.06799, -4.11631, 0, 0, -0.79113, 7.05898, 23.38236, -17.60015, -17.08008, -24.41677, 6.94621, -7.7599, -4.2212, -7.88667, -13.07498, -3.13932, -1.8222, 3.56044, 6.0198, 23.00182, 0, 0, -365.68442, -226.89883 ]
+							},
+							{ "time": 0.8, "curve": "stepped" },
+							{ "time": 1.1 },
+							{
+								"time": 1.3,
+								"offset": 6,
+								"vertices": [ 22.24737, 20.71245, -17.43828, 31.85296, 22.24737, 20.71245, -17.43828, 31.85296, 22.24737, 20.71245, -17.43828, 31.85296 ]
+							},
+							{
+								"time": 1.4333,
+								"offset": 6,
+								"vertices": [ 50.92273, 30.30164, -15.21045, 57.26978, 50.92273, 30.30164, -15.21045, 57.26978, 50.92273, 30.30164, -15.21045, 57.26978 ]
+							},
+							{ "time": 1.8 }
+						]
+					}
 				}
 			}
 		}

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/mix-and-match/mix-and-match-pma.png


+ 20 - 20
spine-unity/Assets/Spine Examples/Spine Skeletons/mix-and-match/mix-and-match-pro.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "bR3EmyUwO+g",
-	"spine": "4.0.31",
+	"hash": "mFaJu+5zxGE",
+	"spine": "4.1.04-beta",
 	"x": -240.58,
 	"y": -3.38,
 	"width": 410.36,
@@ -5263,37 +5263,37 @@
 		"slots": {
 			"eye-back-iris": {
 				"attachment": [
-					{ "time": 0.0333, "name": null },
+					{ "time": 0.0333 },
 					{ "time": 0.0732, "name": "eye-back-iris" }
 				]
 			},
 			"eye-back-pupil": {
 				"attachment": [
-					{ "time": 0.0333, "name": null },
+					{ "time": 0.0333 },
 					{ "time": 0.0732, "name": "eye-back-pupil" }
 				]
 			},
 			"eye-back-white": {
 				"attachment": [
-					{ "time": 0.0333, "name": null },
+					{ "time": 0.0333 },
 					{ "time": 0.0732, "name": "eye-back-white" }
 				]
 			},
 			"eye-front-iris": {
 				"attachment": [
-					{ "time": 0.0333, "name": null },
+					{ "time": 0.0333 },
 					{ "time": 0.0732, "name": "eye-front-iris" }
 				]
 			},
 			"eye-front-pupil": {
 				"attachment": [
-					{ "time": 0.0333, "name": null },
+					{ "time": 0.0333 },
 					{ "time": 0.0732, "name": "eye-front-pupil" }
 				]
 			},
 			"eye-front-white": {
 				"attachment": [
-					{ "time": 0.0333, "name": null },
+					{ "time": 0.0333 },
 					{ "time": 0.0732, "name": "eye-front-white" }
 				]
 			}
@@ -6028,49 +6028,49 @@
 		"slots": {
 			"eye-back-iris": {
 				"attachment": [
-					{ "time": 0.1333, "name": null },
+					{ "time": 0.1333 },
 					{ "time": 0.1732, "name": "eye-back-iris" },
-					{ "time": 2.2667, "name": null },
+					{ "time": 2.2667 },
 					{ "time": 2.3, "name": "eye-back-iris" }
 				]
 			},
 			"eye-back-pupil": {
 				"attachment": [
-					{ "time": 0.1333, "name": null },
+					{ "time": 0.1333 },
 					{ "time": 0.1732, "name": "eye-back-pupil" },
-					{ "time": 2.2667, "name": null },
+					{ "time": 2.2667 },
 					{ "time": 2.3, "name": "eye-back-pupil" }
 				]
 			},
 			"eye-back-white": {
 				"attachment": [
-					{ "time": 0.1333, "name": null },
+					{ "time": 0.1333 },
 					{ "time": 0.1732, "name": "eye-back-white" },
-					{ "time": 2.2667, "name": null },
+					{ "time": 2.2667 },
 					{ "time": 2.3, "name": "eye-back-white" }
 				]
 			},
 			"eye-front-iris": {
 				"attachment": [
-					{ "time": 0.1333, "name": null },
+					{ "time": 0.1333 },
 					{ "time": 0.1732, "name": "eye-front-iris" },
-					{ "time": 2.2667, "name": null },
+					{ "time": 2.2667 },
 					{ "time": 2.3, "name": "eye-front-iris" }
 				]
 			},
 			"eye-front-pupil": {
 				"attachment": [
-					{ "time": 0.1333, "name": null },
+					{ "time": 0.1333 },
 					{ "time": 0.1732, "name": "eye-front-pupil" },
-					{ "time": 2.2667, "name": null },
+					{ "time": 2.2667 },
 					{ "time": 2.3, "name": "eye-front-pupil" }
 				]
 			},
 			"eye-front-white": {
 				"attachment": [
-					{ "time": 0.1333, "name": null },
+					{ "time": 0.1333 },
 					{ "time": 0.1732, "name": "eye-front-white" },
-					{ "time": 2.2667, "name": null },
+					{ "time": 2.2667 },
 					{ "time": 2.3, "name": "eye-front-white" }
 				]
 			}

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/raptor-pro-and-mask/raptor-pma.png


+ 4 - 4
spine-unity/Assets/Spine Examples/Spine Skeletons/raptor-pro-and-mask/raptor-pro.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "c1+xCfJH+TE",
-	"spine": "4.0.31",
+	"hash": "cDRfwRDrCkA",
+	"spine": "4.1.04-beta",
 	"x": -809.16,
 	"y": -73.54,
 	"width": 1287.65,
@@ -879,7 +879,7 @@
 			},
 			"gun": {
 				"attachment": [
-					{ "time": 0.2333, "name": null }
+					{ "time": 0.2333 }
 				]
 			}
 		},
@@ -1006,7 +1006,7 @@
 			},
 			"gun": {
 				"attachment": [
-					{ "name": null },
+					{},
 					{ "time": 0.3, "name": "gun-nohand" }
 				]
 			}

+ 482 - 430
spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "QD71g+lVkOI",
-	"spine": "4.0.31",
+	"hash": "MBDs/ftbFOk",
+	"spine": "4.1.04-beta",
 	"x": -190.61,
 	"y": -7.99,
 	"width": 419.76,
@@ -829,37 +829,45 @@
 				{ "mixRotate": 0.423, "mixX": 0, "mixScaleX": 0, "mixShearY": 0 }
 			]
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"eye": {
-					"eye-indifferent": [
-						{
-							"vertices": [ -0.68777, -17.26618, -0.68778, -17.26618, -0.68777, -17.26618, -0.68781, -17.26618 ]
-						}
-					]
+					"eye-indifferent": {
+						"deform": [
+							{
+								"vertices": [ -0.68777, -17.26618, -0.68778, -17.26618, -0.68777, -17.26618, -0.68781, -17.26618 ]
+							}
+						]
+					}
 				},
 				"goggles": {
-					"goggles": [
-						{
-							"offset": 16,
-							"vertices": [ -0.18341, -4.60426, -0.25211, -6.33094 ]
-						}
-					]
+					"goggles": {
+						"deform": [
+							{
+								"offset": 16,
+								"vertices": [ -0.18341, -4.60426, -0.25211, -6.33094 ]
+							}
+						]
+					}
 				},
 				"head": {
-					"head": [
-						{
-							"offset": 34,
-							"vertices": [ -0.22919, -5.75542, -0.22919, -5.75542, -0.22919, -5.75542 ]
-						}
-					]
+					"head": {
+						"deform": [
+							{
+								"offset": 34,
+								"vertices": [ -0.22919, -5.75542, -0.22919, -5.75542, -0.22919, -5.75542 ]
+							}
+						]
+					}
 				},
 				"mouth": {
-					"mouth-smile": [
-						{
-							"vertices": [ 5.66431, 2.18623, 0.48297, -15.04339, 0.53527, -20.30316, -7.72803, -7.72495 ]
-						}
-					]
+					"mouth-smile": {
+						"deform": [
+							{
+								"vertices": [ 5.66431, 2.18623, 0.48297, -15.04339, 0.53527, -20.30316, -7.72803, -7.72495 ]
+							}
+						]
+					}
 				}
 			}
 		}
@@ -1174,19 +1182,19 @@
 			"side-glow1": {
 				"attachment": [
 					{ "name": "hoverglow-small" },
-					{ "time": 0.9667, "name": null }
+					{ "time": 0.9667 }
 				]
 			},
 			"side-glow2": {
 				"attachment": [
 					{ "time": 0.0667, "name": "hoverglow-small" },
-					{ "time": 1, "name": null }
+					{ "time": 1 }
 				]
 			},
 			"side-glow3": {
 				"attachment": [
 					{ "name": "hoverglow-small" },
-					{ "time": 0.9667, "name": null }
+					{ "time": 0.9667 }
 				]
 			}
 		},
@@ -1669,133 +1677,151 @@
 				{ "mixX": 0, "mixScaleX": 0, "mixShearY": 0 }
 			]
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"eye": {
-					"eye-indifferent": [
-						{
-							"curve": [ 0.067, 0, 0.2, 1 ]
-						},
-						{
-							"time": 0.2667,
-							"vertices": [ 0.22338, -6.575, 0.22338, -6.575, 0.22339, -6.575, 0.22336, -6.575 ],
-							"curve": [ 0.45, 0, 0.817, 1 ]
-						},
-						{ "time": 1 }
-					]
+					"eye-indifferent": {
+						"deform": [
+							{
+								"curve": [ 0.067, 0, 0.2, 1 ]
+							},
+							{
+								"time": 0.2667,
+								"vertices": [ 0.22338, -6.575, 0.22338, -6.575, 0.22339, -6.575, 0.22336, -6.575 ],
+								"curve": [ 0.45, 0, 0.817, 1 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				},
 				"front-foot": {
-					"front-foot": [
-						{
-							"offset": 26,
-							"vertices": [ -0.02832, -5.37024, -0.02832, -5.37024, 3.8188, -3.7757, -0.02832, -5.37024, -3.82159, 3.77847 ]
-						}
-					]
+					"front-foot": {
+						"deform": [
+							{
+								"offset": 26,
+								"vertices": [ -0.02832, -5.37024, -0.02832, -5.37024, 3.8188, -3.7757, -0.02832, -5.37024, -3.82159, 3.77847 ]
+							}
+						]
+					}
 				},
 				"front-shin": {
-					"front-shin": [
-						{
-							"offset": 14,
-							"vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 2.0E-5, 0, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0, 0, 0.54891, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 1.0E-5, 0, 0, 1.0E-5, -1.0E-5, 0, 0, 0, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ]
-						},
-						{
-							"time": 0.3667,
-							"offset": 14,
-							"vertices": [ 0.5298, -1.12677, -11.66571, -9.07211, -25.65866, -17.53735, -25.53217, -16.50978, -11.78232, -11.26097, 0, 0, 0.60489, -1.63589, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0.60486, -1.63589, 0, 0, -2.64523, -7.35739, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0.60488, -1.63589, 0.60487, -1.63588, 0.60487, -1.63589, 0.60487, -1.63589, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -10.06873, -12.0999 ]
-						},
-						{
-							"time": 0.5333,
-							"offset": 14,
-							"vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -7.00775, -8.24771, -6.45482, -6.49312, -6.06447, -6.89757, 0, 0, 2.0E-5, 0, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0, 0, 0.54891, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 1.0E-5, 0, 0, 1.0E-5, -1.0E-5, 0, 0, 0, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ]
-						},
-						{
-							"time": 1,
-							"offset": 14,
-							"vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 2.0E-5, 0, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0, 0, 0.54891, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 1.0E-5, 0, 0, 1.0E-5, -1.0E-5, 0, 0, 0, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ]
-						}
-					]
+					"front-shin": {
+						"deform": [
+							{
+								"offset": 14,
+								"vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 2.0E-5, 0, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0, 0, 0.54891, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 1.0E-5, 0, 0, 1.0E-5, -1.0E-5, 0, 0, 0, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ]
+							},
+							{
+								"time": 0.3667,
+								"offset": 14,
+								"vertices": [ 0.5298, -1.12677, -11.66571, -9.07211, -25.65866, -17.53735, -25.53217, -16.50978, -11.78232, -11.26097, 0, 0, 0.60489, -1.63589, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0.60486, -1.63589, 0, 0, -2.64523, -7.35739, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 0.60488, -1.63589, 0.60487, -1.63588, 0.60487, -1.63589, 0.60487, -1.63589, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.60487, -1.63589, 0, 0, -10.06873, -12.0999 ]
+							},
+							{
+								"time": 0.5333,
+								"offset": 14,
+								"vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -7.00775, -8.24771, -6.45482, -6.49312, -6.06447, -6.89757, 0, 0, 2.0E-5, 0, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0, 0, 0.54891, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 1.0E-5, 0, 0, 1.0E-5, -1.0E-5, 0, 0, 0, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ]
+							},
+							{
+								"time": 1,
+								"offset": 14,
+								"vertices": [ 0.5298, -1.12677, -0.85507, -4.20587, -11.35158, -10.19225, -10.79865, -8.43765, -6.06447, -6.89757, 0, 0, 2.0E-5, 0, 0, 0, 0, 1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 1.0E-5, 0, 0, 0, -2.0E-5, 0, -2.0E-5, 0, -1.0E-5, 0, 0, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, -1.0E-5, 0, 0, 0, 0.54891, -3.06021, 1.48463, -2.29663, 0, 0, 0, 0, 0, 0, 1.0E-5, 0, 0, 1.0E-5, -1.0E-5, 0, 0, 0, 1.0E-5, 0, -1.0E-5, 0, 0, 0, 0, 0, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.80437, -7.01817 ]
+							}
+						]
+					}
 				},
 				"goggles": {
-					"goggles": [
-						{
-							"curve": [ 0.067, 0, 0.2, 1 ]
-						},
-						{
-							"time": 0.2667,
-							"vertices": [ 0.67711, -3.13913, 0.27417, -1.27147, 0.15489, -0.72019, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, 0.42483, -1.97125, 1.55293, -7.20752, 0.18449, -0.85692, 0.62344, -2.89004, 0.80452, -3.72998, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 1.01053, -4.68357, 1.14493, -5.30811, 1.05919, -4.91034, 0.78564, -3.64209, 0.88441, -4.10009, 0.9154, -4.24387, 0.80144, -3.7155, 0.76654, -3.55506, 0.29617, -1.37293, 0.03153, -0.14643, 0.22642, -1.05165, 0.13696, -0.63699, 0.25401, -1.17808, 0.55055, -2.55229, 0.77679, -3.60118, 1.59354, -7.39156, 1.35066, -6.26342, 1.34977, -6.25924, 0.9485, -4.39735, 0.83698, -3.88036, 0.80622, -3.73668, 1.01197, -4.69016, 1.0E-5, 2.0E-5, 0.1845, -0.85692, 0.18449, -0.85691, 0.18452, -0.85692, 0.18451, -0.85691, 0.18453, -0.85692, 0.18451, -0.85691 ],
-							"curve": [ 0.45, 0, 0.817, 1 ]
-						},
-						{ "time": 1 }
-					]
+					"goggles": {
+						"deform": [
+							{
+								"curve": [ 0.067, 0, 0.2, 1 ]
+							},
+							{
+								"time": 0.2667,
+								"vertices": [ 0.67711, -3.13913, 0.27417, -1.27147, 0.15489, -0.72019, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, 0.42483, -1.97125, 1.55293, -7.20752, 0.18449, -0.85692, 0.62344, -2.89004, 0.80452, -3.72998, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 1.01053, -4.68357, 1.14493, -5.30811, 1.05919, -4.91034, 0.78564, -3.64209, 0.88441, -4.10009, 0.9154, -4.24387, 0.80144, -3.7155, 0.76654, -3.55506, 0.29617, -1.37293, 0.03153, -0.14643, 0.22642, -1.05165, 0.13696, -0.63699, 0.25401, -1.17808, 0.55055, -2.55229, 0.77679, -3.60118, 1.59354, -7.39156, 1.35066, -6.26342, 1.34977, -6.25924, 0.9485, -4.39735, 0.83698, -3.88036, 0.80622, -3.73668, 1.01197, -4.69016, 1.0E-5, 2.0E-5, 0.1845, -0.85692, 0.18449, -0.85691, 0.18452, -0.85692, 0.18451, -0.85691, 0.18453, -0.85692, 0.18451, -0.85691 ],
+								"curve": [ 0.45, 0, 0.817, 1 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				},
 				"head": {
-					"head": [
-						{
-							"offset": 60,
-							"vertices": [ 1.93787, 2.56528, 2.77362, 1.62589 ],
-							"curve": [ 0.067, 0, 0.2, 1 ]
-						},
-						{
-							"time": 0.2667,
-							"offset": 34,
-							"vertices": [ 1.96774, -9.13288, 1.96774, -9.13288, 1.96774, -9.13288, 0.52141, -2.41945, 0, 0, 0, 0, 0, 0, 0, 0, -0.28486, 1.32153, -0.28486, 1.32153, 0, 0, 0, 0, 0, 0, 0.7267, 0.96198, 1.04011, 0.60971, 7.3906, -5.46259, 3.91425, 8.31534, 2.51528, -2.75824, 2.21405, 3.0056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.83772, -5.11176, 3.67865, 7.70451, 6.35114, 5.70461, 5.75797, -8.66576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.49945, -3.38693, 0.08572, -3.70304, 0.21432, -9.25756, 0, 0, 0, 0, 0.08572, -3.70304, 0.21432, -9.25756, 0, 0, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0, 0, 0, 0, 0, 0, 0, 0, 0.34761, -1.61296, 0.26072, -1.20974, 0.65176, -3.02431 ],
-							"curve": [ 0.45, 0, 0.817, 1 ]
-						},
-						{
-							"time": 1,
-							"offset": 60,
-							"vertices": [ 1.93787, 2.56528, 2.77362, 1.62589 ]
-						}
-					]
+					"head": {
+						"deform": [
+							{
+								"offset": 60,
+								"vertices": [ 1.93787, 2.56528, 2.77362, 1.62589 ],
+								"curve": [ 0.067, 0, 0.2, 1 ]
+							},
+							{
+								"time": 0.2667,
+								"offset": 34,
+								"vertices": [ 1.96774, -9.13288, 1.96774, -9.13288, 1.96774, -9.13288, 0.52141, -2.41945, 0, 0, 0, 0, 0, 0, 0, 0, -0.28486, 1.32153, -0.28486, 1.32153, 0, 0, 0, 0, 0, 0, 0.7267, 0.96198, 1.04011, 0.60971, 7.3906, -5.46259, 3.91425, 8.31534, 2.51528, -2.75824, 2.21405, 3.0056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.83772, -5.11176, 3.67865, 7.70451, 6.35114, 5.70461, 5.75797, -8.66576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.49945, -3.38693, 0.08572, -3.70304, 0.21432, -9.25756, 0, 0, 0, 0, 0.08572, -3.70304, 0.21432, -9.25756, 0, 0, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0.10735, -0.51047, 0, 0, 0, 0, 0, 0, 0, 0, 0.34761, -1.61296, 0.26072, -1.20974, 0.65176, -3.02431 ],
+								"curve": [ 0.45, 0, 0.817, 1 ]
+							},
+							{
+								"time": 1,
+								"offset": 60,
+								"vertices": [ 1.93787, 2.56528, 2.77362, 1.62589 ]
+							}
+						]
+					}
 				},
 				"hoverboard-board": {
-					"hoverboard-board": [
-						{},
-						{
-							"time": 0.2667,
-							"offset": 1,
-							"vertices": [ 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 3.55673, -3.0E-4, 3.55673, -3.0E-4, 0, 0, 0, 0, 0, 0, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, 0, 0, 0, 0, 0, 0, 0, 0, -4.90558, 0.11214, -9.40706, 6.2E-4, -6.34871, 4.3E-4, -6.34924, -6.57018, -6.34925, -6.57018, -6.34871, 4.3E-4, -2.3308, 1.7E-4, -2.33133, -6.57045, -2.33133, -6.57045, -2.3308, 1.7E-4, 0, 0, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 3.3297, 4.44005, 3.3297, 4.44005, 3.3297, 4.44005, 1.2E-4, 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, 1.2E-4, 2.45856, 1.2E-4, 2.45856, -9.40694, 2.45918, 1.88063, 0.44197, -2.9E-4, -3.54808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.46227, 1.7E-4, 0, 0, 0, 0, 1.2E-4, 2.45856 ]
-						},
-						{ "time": 1 }
-					]
+					"hoverboard-board": {
+						"deform": [
+							{},
+							{
+								"time": 0.2667,
+								"offset": 1,
+								"vertices": [ 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 3.55673, -3.0E-4, 3.55673, -3.0E-4, 0, 0, 0, 0, 0, 0, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, -7.6E-4, -9.84158, 0, 0, 0, 0, 0, 0, 0, 0, -4.90558, 0.11214, -9.40706, 6.2E-4, -6.34871, 4.3E-4, -6.34924, -6.57018, -6.34925, -6.57018, -6.34871, 4.3E-4, -2.3308, 1.7E-4, -2.33133, -6.57045, -2.33133, -6.57045, -2.3308, 1.7E-4, 0, 0, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 1.2E-4, 2.45856, 3.3297, 4.44005, 3.3297, 4.44005, 3.3297, 4.44005, 1.2E-4, 2.45856, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, 1.2E-4, 2.45856, 1.2E-4, 2.45856, -9.40694, 2.45918, 1.88063, 0.44197, -2.9E-4, -3.54808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.52316, 1.1313, -2.52316, 1.1313, -2.52316, 1.1313, -2.46227, 1.7E-4, -2.46227, 1.7E-4, -2.46227, 1.7E-4, 0, 0, 0, 0, 1.2E-4, 2.45856 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				},
 				"mouth": {
-					"mouth-smile": [
-						{
-							"curve": [ 0.067, 0, 0.2, 1 ]
-						},
-						{
-							"time": 0.2667,
-							"vertices": [ 0.15454, -6.69122, 0.15457, -6.6912, 0.15456, -6.6912, 0.15454, -6.69119 ],
-							"curve": [ 0.45, 0, 0.817, 1 ]
-						},
-						{ "time": 1 }
-					]
+					"mouth-smile": {
+						"deform": [
+							{
+								"curve": [ 0.067, 0, 0.2, 1 ]
+							},
+							{
+								"time": 0.2667,
+								"vertices": [ 0.15454, -6.69122, 0.15457, -6.6912, 0.15456, -6.6912, 0.15454, -6.69119 ],
+								"curve": [ 0.45, 0, 0.817, 1 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				},
 				"rear-foot": {
-					"rear-foot": [
-						{
-							"offset": 26,
-							"vertices": [ -0.31417, 2.33363, 3.05122, 0.33946, 2.31472, -2.01678, 2.17583, -2.05795, 1.15429, 0.26328 ]
-						}
-					]
+					"rear-foot": {
+						"deform": [
+							{
+								"offset": 26,
+								"vertices": [ -0.31417, 2.33363, 3.05122, 0.33946, 2.31472, -2.01678, 2.17583, -2.05795, 1.15429, 0.26328 ]
+							}
+						]
+					}
 				},
 				"torso": {
-					"torso": [
-						{},
-						{
-							"time": 0.2667,
-							"offset": 14,
-							"vertices": [ 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 0, 0, -0.59544, -7.5094, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.59544, -7.5094, 3.86935, -7.86369, 3.86934, -7.86369, 3.86935, -7.86369, 3.86934, -7.86369, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, -0.5954, -7.50941, 3.0E-5, -1.0E-5, 0.35962, -1.81179, 0.35948, -1.81172, 0, 0, 0, 0, -0.13678, -6.00883, -0.13666, -6.0088, -0.13699, -6.00874, 2.46274, -6.26834, 2.46227, -6.26817, 2.27148, -5.86322, 2.27164, -5.86306, 2.27113, -5.86305, 0.52808, -3.21825 ]
-						},
-						{ "time": 0.5 },
-						{
-							"time": 0.6333,
-							"offset": 4,
-							"vertices": [ 3.41785, -0.27124, 3.41788, -0.27125, 3.41785, -0.27124, 3.41788, -0.27125, 3.41785, -0.27124, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4682, 5.90338, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.88608, 5.63213, 3.88608, 5.63213, 0.46823, 5.90337, 0.46823, 5.90337, 0.4682, 5.90338, 0, 0, 0, 0, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.46823, 5.90337, 0.46823, 5.90337, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.46823, 5.90337, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, -0.5545, 7.37883, -0.5545, 7.37883, -0.5545, 7.37884, -0.26138, 7.75283, -0.26132, 7.75283, -0.76703, 6.33779, -0.76697, 6.33778, -0.76694, 6.33778 ]
-						},
-						{ "time": 1 }
-					]
+					"torso": {
+						"deform": [
+							{},
+							{
+								"time": 0.2667,
+								"offset": 14,
+								"vertices": [ 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 4.46481, -0.35429, 4.46481, -0.3543, 0, 0, -0.59544, -7.5094, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.59544, -7.5094, 3.86935, -7.86369, 3.86934, -7.86369, 3.86935, -7.86369, 3.86934, -7.86369, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, -0.59544, -7.5094, -0.5954, -7.50941, -0.5954, -7.50941, 3.0E-5, -1.0E-5, 0.35962, -1.81179, 0.35948, -1.81172, 0, 0, 0, 0, -0.13678, -6.00883, -0.13666, -6.0088, -0.13699, -6.00874, 2.46274, -6.26834, 2.46227, -6.26817, 2.27148, -5.86322, 2.27164, -5.86306, 2.27113, -5.86305, 0.52808, -3.21825 ]
+							},
+							{ "time": 0.5 },
+							{
+								"time": 0.6333,
+								"offset": 4,
+								"vertices": [ 3.41785, -0.27124, 3.41788, -0.27125, 3.41785, -0.27124, 3.41788, -0.27125, 3.41785, -0.27124, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4682, 5.90338, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.88608, 5.63213, 3.88608, 5.63213, 0.46823, 5.90337, 0.46823, 5.90337, 0.4682, 5.90338, 0, 0, 0, 0, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.46823, 5.90337, 0.46823, 5.90337, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.4682, 5.90338, 0.46823, 5.90337, 0.46823, 5.90337, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, -0.5545, 7.37883, -0.5545, 7.37883, -0.5545, 7.37884, -0.26138, 7.75283, -0.26132, 7.75283, -0.76703, 6.33779, -0.76697, 6.33778, -0.76694, 6.33778 ]
+							},
+							{ "time": 1 }
+						]
+					}
 				}
 			}
 		}
@@ -2156,21 +2182,23 @@
 				]
 			}
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"torso": {
-					"torso": [
-						{
-							"offset": 4,
-							"vertices": [ 4.71576, 4.44464, 4.71579, 4.44463, 4.7399, 4.67474, 4.73993, 4.67473, 4.73988, 4.67474, 5.0968, 8.08034, 5.0968, 8.08033, 5.0968, 8.08033, 5.11813, 8.28422, 5.1181, 8.28423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 1.21198, -8.88572, 1.21201, -8.88573, 1.2106, -7.18206, 1.21063, -7.18207, 1.21059, -7.18206, 0.98038, -5.14252, 0.98038, -5.14252, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -1.13269, -8.03748, -1.13266, -8.03748, -1.13268, -8.03748, -1.13269, -8.03748, -1.13266, -8.03748, -1.13268, -8.03748, -1.13269, -8.03748, -1.13268, -8.03748, -1.13269, -8.03748, -1.13266, -8.03748, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0.77191, -5.83292, 0.77274, -5.83294, 0.77225, -5.83293, 0, 0, 0, 0, 0.67938, -9.11015, 0.68066, -9.11017, 0.67996, -9.11016 ],
-							"curve": [ 0.067, 0, 0.075, 1 ]
-						},
-						{
-							"time": 0.2667,
-							"offset": 94,
-							"vertices": [ 0.52335, 5.68797, 0.52324, 5.68796, 0.52335, 5.68797, 0.52347, 5.68797, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.49274, 5.35334, 0.49251, 5.35334, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.52335, 5.68797, 0.52324, 5.68796, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 2.59232, 6.1724 ]
-						}
-					]
+					"torso": {
+						"deform": [
+							{
+								"offset": 4,
+								"vertices": [ 4.71576, 4.44464, 4.71579, 4.44463, 4.7399, 4.67474, 4.73993, 4.67473, 4.73988, 4.67474, 5.0968, 8.08034, 5.0968, 8.08033, 5.0968, 8.08033, 5.11813, 8.28422, 5.1181, 8.28423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 1.21198, -8.88572, 1.21201, -8.88573, 1.2106, -7.18206, 1.21063, -7.18207, 1.21059, -7.18206, 0.98038, -5.14252, 0.98038, -5.14252, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -1.13269, -8.03748, -1.13266, -8.03748, -1.13268, -8.03748, -1.13269, -8.03748, -1.13266, -8.03748, -1.13268, -8.03748, -1.13269, -8.03748, -1.13268, -8.03748, -1.13269, -8.03748, -1.13266, -8.03748, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, 0.77191, -5.83292, 0.77274, -5.83294, 0.77225, -5.83293, 0, 0, 0, 0, 0.67938, -9.11015, 0.68066, -9.11017, 0.67996, -9.11016 ],
+								"curve": [ 0.067, 0, 0.075, 1 ]
+							},
+							{
+								"time": 0.2667,
+								"offset": 94,
+								"vertices": [ 0.52335, 5.68797, 0.52324, 5.68796, 0.52335, 5.68797, 0.52347, 5.68797, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.49274, 5.35334, 0.49251, 5.35334, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.52335, 5.68797, 0.52324, 5.68796, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 2.59232, 6.1724 ]
+							}
+						]
+					}
 				}
 			}
 		}
@@ -2573,7 +2601,7 @@
 			"portal-bg": {
 				"attachment": [
 					{ "name": "portal-bg" },
-					{ "time": 3.1, "name": null }
+					{ "time": 3.1 }
 				]
 			},
 			"portal-flare1": {
@@ -2584,7 +2612,7 @@
 					{ "time": 1.2, "name": "portal-flare1" },
 					{ "time": 1.2333, "name": "portal-flare2" },
 					{ "time": 1.2667, "name": "portal-flare1" },
-					{ "time": 1.3333, "name": null }
+					{ "time": 1.3333 }
 				]
 			},
 			"portal-flare2": {
@@ -2594,14 +2622,14 @@
 					{ "time": 1.1667, "name": "portal-flare1" },
 					{ "time": 1.2, "name": "portal-flare2" },
 					{ "time": 1.2333, "name": "portal-flare3" },
-					{ "time": 1.2667, "name": null }
+					{ "time": 1.2667 }
 				]
 			},
 			"portal-flare3": {
 				"attachment": [
 					{ "time": 1.2, "name": "portal-flare3" },
 					{ "time": 1.2333, "name": "portal-flare2" },
-					{ "time": 1.2667, "name": null }
+					{ "time": 1.2667 }
 				]
 			},
 			"portal-flare4": {
@@ -2609,33 +2637,33 @@
 					{ "time": 1.2, "name": "portal-flare2" },
 					{ "time": 1.2333, "name": "portal-flare1" },
 					{ "time": 1.2667, "name": "portal-flare2" },
-					{ "time": 1.3333, "name": null }
+					{ "time": 1.3333 }
 				]
 			},
 			"portal-flare5": {
 				"attachment": [
 					{ "time": 1.2333, "name": "portal-flare3" },
 					{ "time": 1.2667, "name": "portal-flare1" },
-					{ "time": 1.3333, "name": null }
+					{ "time": 1.3333 }
 				]
 			},
 			"portal-flare6": {
 				"attachment": [
 					{ "time": 1.2667, "name": "portal-flare3" },
-					{ "time": 1.3333, "name": null }
+					{ "time": 1.3333 }
 				]
 			},
 			"portal-flare7": {
 				"attachment": [
 					{ "time": 1.1333, "name": "portal-flare2" },
-					{ "time": 1.1667, "name": null }
+					{ "time": 1.1667 }
 				]
 			},
 			"portal-flare8": {
 				"attachment": [
 					{ "time": 1.2, "name": "portal-flare3" },
 					{ "time": 1.2333, "name": "portal-flare2" },
-					{ "time": 1.2667, "name": null }
+					{ "time": 1.2667 }
 				]
 			},
 			"portal-flare9": {
@@ -2643,7 +2671,7 @@
 					{ "time": 1.2, "name": "portal-flare2" },
 					{ "time": 1.2333, "name": "portal-flare3" },
 					{ "time": 1.2667, "name": "portal-flare1" },
-					{ "time": 1.3, "name": null }
+					{ "time": 1.3 }
 				]
 			},
 			"portal-flare10": {
@@ -2651,25 +2679,25 @@
 					{ "time": 1.2, "name": "portal-flare2" },
 					{ "time": 1.2333, "name": "portal-flare1" },
 					{ "time": 1.2667, "name": "portal-flare3" },
-					{ "time": 1.3, "name": null }
+					{ "time": 1.3 }
 				]
 			},
 			"portal-shade": {
 				"attachment": [
 					{ "name": "portal-shade" },
-					{ "time": 3.1, "name": null }
+					{ "time": 3.1 }
 				]
 			},
 			"portal-streaks1": {
 				"attachment": [
 					{ "name": "portal-streaks1" },
-					{ "time": 3.1, "name": null }
+					{ "time": 3.1 }
 				]
 			},
 			"portsl-streaks2": {
 				"attachment": [
 					{ "name": "portsl-streaks2" },
-					{ "time": 3.1, "name": null }
+					{ "time": 3.1 }
 				]
 			}
 		},
@@ -3301,24 +3329,26 @@
 				]
 			}
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"torso": {
-					"torso": [
-						{ "time": 1.3333 },
-						{
-							"time": 1.4667,
-							"offset": 34,
-							"vertices": [ -6.5248, 6.64212, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.65784, 8.28917, 0.65787, 8.28917, 1.41232, 5.06703, 1.41235, 5.067, 1.41232, 5.06705, 0, 0, 0, 0, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, -0.91647, 9.00049, -0.9164, 9.00037, -0.91644, 9.00046, 1.76997, 9.34928, 1.76991, 9.34927, -1.01145, 7.51462, -1.0115, 7.51452, -1.01155, 7.51457 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 1.8333,
-							"offset": 34,
-							"vertices": [ -6.5248, 6.64212, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.65784, 8.28917, 0.65787, 8.28917, 1.41232, 5.06703, 1.41235, 5.067, 1.41232, 5.06705, 0, 0, 0, 0, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, -0.91647, 9.00049, -0.9164, 9.00037, -0.91644, 9.00046, 1.76997, 9.34928, 1.76991, 9.34927, -1.01145, 7.51462, -1.0115, 7.51452, -1.01155, 7.51457 ]
-						},
-						{ "time": 2 }
-					]
+					"torso": {
+						"deform": [
+							{ "time": 1.3333 },
+							{
+								"time": 1.4667,
+								"offset": 34,
+								"vertices": [ -6.5248, 6.64212, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.65784, 8.28917, 0.65787, 8.28917, 1.41232, 5.06703, 1.41235, 5.067, 1.41232, 5.06705, 0, 0, 0, 0, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, -0.91647, 9.00049, -0.9164, 9.00037, -0.91644, 9.00046, 1.76997, 9.34928, 1.76991, 9.34927, -1.01145, 7.51462, -1.0115, 7.51452, -1.01155, 7.51457 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 1.8333,
+								"offset": 34,
+								"vertices": [ -6.5248, 6.64212, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.65784, 8.28917, 0.65787, 8.28917, 1.41232, 5.06703, 1.41235, 5.067, 1.41232, 5.06705, 0, 0, 0, 0, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65784, 8.28917, 0.65787, 8.28917, 3.0E-5, -1.0E-5, 0, 0, 0, 0, 0, 0, 0, 0, -0.91647, 9.00049, -0.9164, 9.00037, -0.91644, 9.00046, 1.76997, 9.34928, 1.76991, 9.34927, -1.01145, 7.51462, -1.0115, 7.51452, -1.01155, 7.51457 ]
+							},
+							{ "time": 2 }
+						]
+					}
 				}
 			}
 		}
@@ -3338,7 +3368,7 @@
 				],
 				"attachment": [
 					{ "name": "dust03" },
-					{ "time": 0.0667, "name": null },
+					{ "time": 0.0667 },
 					{ "time": 0.1333, "name": "dust01" },
 					{ "time": 0.2, "name": "dust02" },
 					{ "time": 0.3, "name": "dust03" },
@@ -3877,96 +3907,106 @@
 				]
 			}
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"eye": {
-					"eye-indifferent": [
-						{
-							"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ],
-							"curve": [ 0.1, 0, 0.3, 1 ]
-						},
-						{
-							"time": 0.4,
-							"vertices": [ 3.92969, -18.23849, 3.92968, -18.23849, 3.92969, -18.23849, 3.92966, -18.23848 ],
-							"curve": [ 0.5, 0, 0.7, 1 ]
-						},
-						{
-							"time": 0.8,
-							"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ]
-						}
-					]
+					"eye-indifferent": {
+						"deform": [
+							{
+								"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ],
+								"curve": [ 0.1, 0, 0.3, 1 ]
+							},
+							{
+								"time": 0.4,
+								"vertices": [ 3.92969, -18.23849, 3.92968, -18.23849, 3.92969, -18.23849, 3.92966, -18.23848 ],
+								"curve": [ 0.5, 0, 0.7, 1 ]
+							},
+							{
+								"time": 0.8,
+								"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ]
+							}
+						]
+					}
 				},
 				"goggles": {
-					"goggles": [
-						{
-							"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, -0.11291, 0.31704, -0.12221, 0.33459, -0.12273, 0.32938, -0.10715, 0.28685, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ],
-							"curve": [ 0.1, 0, 0.3, 1 ]
-						},
-						{
-							"time": 0.4,
-							"vertices": [ 1.7334, -8.03618, 0.70187, -3.25496, 0.39651, -1.84367, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, 1.08755, -5.04639, 3.97546, -18.45124, 0.47231, -2.1937, 1.59597, -7.39851, 2.05962, -9.54876, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 2.5869, -11.98994, 2.93105, -13.58875, 2.7115, -12.57046, 2.01118, -9.32377, 2.26411, -10.49625, 2.34346, -10.8643, 2.0517, -9.51168, 1.9623, -9.10095, 0.7581, -3.51469, 0.08063, -0.37486, 0.57968, -2.69225, 0.35057, -1.63069, 0.65033, -3.01588, 1.40936, -6.53389, 1.98856, -9.21902, 4.07944, -18.92242, 3.45764, -16.03436, 3.45535, -16.02368, 2.42818, -11.25721, 2.14265, -9.93373, 2.06394, -9.5659, 2.59061, -12.00682, 1.0E-5, 2.0E-5, 0.47232, -2.1937, 0.47231, -2.19369, 0.47234, -2.1937, 0.47233, -2.19369, 0.47235, -2.1937, 0.47232, -2.1937 ],
-							"curve": [ 0.5, 0, 0.7, 1 ]
-						},
-						{
-							"time": 0.8,
-							"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, -0.11291, 0.31704, -0.12221, 0.33459, -0.12273, 0.32938, -0.10715, 0.28685, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ]
-						}
-					]
+					"goggles": {
+						"deform": [
+							{
+								"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, -0.11291, 0.31704, -0.12221, 0.33459, -0.12273, 0.32938, -0.10715, 0.28685, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ],
+								"curve": [ 0.1, 0, 0.3, 1 ]
+							},
+							{
+								"time": 0.4,
+								"vertices": [ 1.7334, -8.03618, 0.70187, -3.25496, 0.39651, -1.84367, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, 1.08755, -5.04639, 3.97546, -18.45124, 0.47231, -2.1937, 1.59597, -7.39851, 2.05962, -9.54876, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 2.5869, -11.98994, 2.93105, -13.58875, 2.7115, -12.57046, 2.01118, -9.32377, 2.26411, -10.49625, 2.34346, -10.8643, 2.0517, -9.51168, 1.9623, -9.10095, 0.7581, -3.51469, 0.08063, -0.37486, 0.57968, -2.69225, 0.35057, -1.63069, 0.65033, -3.01588, 1.40936, -6.53389, 1.98856, -9.21902, 4.07944, -18.92242, 3.45764, -16.03436, 3.45535, -16.02368, 2.42818, -11.25721, 2.14265, -9.93373, 2.06394, -9.5659, 2.59061, -12.00682, 1.0E-5, 2.0E-5, 0.47232, -2.1937, 0.47231, -2.19369, 0.47234, -2.1937, 0.47233, -2.19369, 0.47235, -2.1937, 0.47232, -2.1937 ],
+								"curve": [ 0.5, 0, 0.7, 1 ]
+							},
+							{
+								"time": 0.8,
+								"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, -0.11291, 0.31704, -0.12221, 0.33459, -0.12273, 0.32938, -0.10715, 0.28685, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ]
+							}
+						]
+					}
 				},
 				"head": {
-					"head": [
-						{
-							"offset": 32,
-							"vertices": [ 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ],
-							"curve": [ 0.1, 0, 0.3, 1 ]
-						},
-						{
-							"time": 0.4,
-							"offset": 34,
-							"vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0, 0, 0, 0, 0, 0, 0, 0, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ],
-							"curve": [ 0.5, 0, 0.7, 1 ]
-						},
-						{
-							"time": 0.8,
-							"offset": 32,
-							"vertices": [ 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ]
-						}
-					]
+					"head": {
+						"deform": [
+							{
+								"offset": 32,
+								"vertices": [ 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ],
+								"curve": [ 0.1, 0, 0.3, 1 ]
+							},
+							{
+								"time": 0.4,
+								"offset": 34,
+								"vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0.17175, -0.81676, 0, 0, 0, 0, 0, 0, 0, 0, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ],
+								"curve": [ 0.5, 0, 0.7, 1 ]
+							},
+							{
+								"time": 0.8,
+								"offset": 32,
+								"vertices": [ 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ]
+							}
+						]
+					}
 				},
 				"mouth": {
-					"mouth-grind": [
-						{
-							"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ],
-							"curve": [ 0.1, 0, 0.3, 1 ]
-						},
-						{
-							"time": 0.4,
-							"vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ],
-							"curve": [ 0.5, 0, 0.7, 1 ]
-						},
-						{
-							"time": 0.8,
-							"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ]
-						}
-					]
+					"mouth-grind": {
+						"deform": [
+							{
+								"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ],
+								"curve": [ 0.1, 0, 0.3, 1 ]
+							},
+							{
+								"time": 0.4,
+								"vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ],
+								"curve": [ 0.5, 0, 0.7, 1 ]
+							},
+							{
+								"time": 0.8,
+								"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ]
+							}
+						]
+					}
 				},
 				"torso": {
-					"torso": [
-						{
-							"offset": 14,
-							"vertices": [ 6.35962, 1.33517, 6.35968, 1.33517, 6.35965, 1.33517, 6.35962, 1.33517, 6.35965, 1.33517, 0, 0, 0, 0, 0, 0, 0, 0, 0.82059, 5.12242, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12242, 1.43304, 3.92826, 1.43295, 3.92841, 0.82059, 5.12243, 0.82059, 5.12242, 0.82059, 5.12243, 0.82062, 5.12241, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24156, 4.36882, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82062, 5.12241, -0.77551, 4.89193, -0.77553, 4.89196, 0, 0, 0, 0, -0.80437, 5.76189, -0.80463, 5.76189, -0.80443, 5.76191, 0.687, 7.31474, 0.68706, 7.31482, -0.35928, 5.41616, -0.35965, 5.41621, -0.35934, 5.4162 ]
-						},
-						{
-							"time": 0.4,
-							"offset": 4,
-							"vertices": [ 1.46152, 2.96601, 1.46152, 2.966, 0.68634, 3.23446, 0.68634, 3.23445, 0.68634, 3.23445, 2.20618, 0.10388, 2.20624, 0.10387, 2.20619, 0.10388, 0, 0, 0, 0, -0.31027, -2.8986, -0.31029, -2.89859, 0, 0, 0, 0, -0.1851, 0.38208, 0.33795, -3.61552, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.23701, 2.56804, 0.23724, 2.56822, 0.23715, 2.56816, 0.39799, 4.23787, 0.39807, 4.23792, 0.39803, 4.23793, -0.55164, 4.21406, -0.55157, 4.21406, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -0.29404, -8.94628, -0.29398, -8.94629, -0.02417, -9.50224, -0.02417, -9.50224, -0.02417, -9.50224, 0.23019, -9.9391, 0.23018, -9.9391, -4.64133, -8.88915, -4.64136, -8.88914, -2.62137, -9.24012, -2.62134, -9.24013, -1.70071, -5.16261, -1.70071, -5.16262, -1.70074, -5.16261, -1.70071, -5.16261, -1.70071, -5.16262, -1.70074, -5.16261, -1.70071, -5.16261, -1.70074, -5.16261, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -7.37057, -10.47318, 1.06334, -5.92201, 1.06334, -5.92199, 0, 0, 0, 0, -0.49225, -2.67543, -0.49225, -2.67542, -0.49223, -2.6754, 3.36296, -7.48156, 3.36295, -7.48149, -2.08174, -6.76364, -2.08188, -6.76358, -2.08173, -6.76357 ]
-						},
-						{
-							"time": 0.8,
-							"offset": 14,
-							"vertices": [ 6.35962, 1.33517, 6.35968, 1.33517, 6.35965, 1.33517, 6.35962, 1.33517, 6.35965, 1.33517, 0, 0, 0, 0, 0, 0, 0, 0, 0.82059, 5.12242, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12242, 1.43304, 3.92826, 1.43295, 3.92841, 0.82059, 5.12243, 0.82059, 5.12242, 0.82059, 5.12243, 0.82062, 5.12241, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24156, 4.36882, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82062, 5.12241, -0.77551, 4.89193, -0.77553, 4.89196, 0, 0, 0, 0, -0.80437, 5.76189, -0.80463, 5.76189, -0.80443, 5.76191, 0.687, 7.31474, 0.68706, 7.31482, -0.35928, 5.41616, -0.35965, 5.41621, -0.35934, 5.4162 ]
-						}
-					]
+					"torso": {
+						"deform": [
+							{
+								"offset": 14,
+								"vertices": [ 6.35962, 1.33517, 6.35968, 1.33517, 6.35965, 1.33517, 6.35962, 1.33517, 6.35965, 1.33517, 0, 0, 0, 0, 0, 0, 0, 0, 0.82059, 5.12242, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12242, 1.43304, 3.92826, 1.43295, 3.92841, 0.82059, 5.12243, 0.82059, 5.12242, 0.82059, 5.12243, 0.82062, 5.12241, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24156, 4.36882, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82062, 5.12241, -0.77551, 4.89193, -0.77553, 4.89196, 0, 0, 0, 0, -0.80437, 5.76189, -0.80463, 5.76189, -0.80443, 5.76191, 0.687, 7.31474, 0.68706, 7.31482, -0.35928, 5.41616, -0.35965, 5.41621, -0.35934, 5.4162 ]
+							},
+							{
+								"time": 0.4,
+								"offset": 4,
+								"vertices": [ 1.46152, 2.96601, 1.46152, 2.966, 0.68634, 3.23446, 0.68634, 3.23445, 0.68634, 3.23445, 2.20618, 0.10388, 2.20624, 0.10387, 2.20619, 0.10388, 0, 0, 0, 0, -0.31027, -2.8986, -0.31029, -2.89859, 0, 0, 0, 0, -0.1851, 0.38208, 0.33795, -3.61552, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.23701, 2.56804, 0.23724, 2.56822, 0.23715, 2.56816, 0.39799, 4.23787, 0.39807, 4.23792, 0.39803, 4.23793, -0.55164, 4.21406, -0.55157, 4.21406, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -0.29404, -8.94628, -0.29398, -8.94629, -0.02417, -9.50224, -0.02417, -9.50224, -0.02417, -9.50224, 0.23019, -9.9391, 0.23018, -9.9391, -4.64133, -8.88915, -4.64136, -8.88914, -2.62137, -9.24012, -2.62134, -9.24013, -1.70071, -5.16261, -1.70071, -5.16262, -1.70074, -5.16261, -1.70071, -5.16261, -1.70071, -5.16262, -1.70074, -5.16261, -1.70071, -5.16261, -1.70074, -5.16261, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, -7.37057, -10.47318, 1.06334, -5.92201, 1.06334, -5.92199, 0, 0, 0, 0, -0.49225, -2.67543, -0.49225, -2.67542, -0.49223, -2.6754, 3.36296, -7.48156, 3.36295, -7.48149, -2.08174, -6.76364, -2.08188, -6.76358, -2.08173, -6.76357 ]
+							},
+							{
+								"time": 0.8,
+								"offset": 14,
+								"vertices": [ 6.35962, 1.33517, 6.35968, 1.33517, 6.35965, 1.33517, 6.35962, 1.33517, 6.35965, 1.33517, 0, 0, 0, 0, 0, 0, 0, 0, 0.82059, 5.12242, 0, 0, 0, 0, 0, 0, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12243, 0.82062, 5.12241, 0.82059, 5.12242, 1.43304, 3.92826, 1.43295, 3.92841, 0.82059, 5.12243, 0.82059, 5.12242, 0.82059, 5.12243, 0.82062, 5.12241, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24158, 4.36882, 0.24156, 4.36882, 0.24155, 4.36882, 0.24156, 4.36882, 3.0E-5, -1.0E-5, 3.0E-5, -1.0E-5, 0.82062, 5.12241, -0.77551, 4.89193, -0.77553, 4.89196, 0, 0, 0, 0, -0.80437, 5.76189, -0.80463, 5.76189, -0.80443, 5.76191, 0.687, 7.31474, 0.68706, 7.31482, -0.35928, 5.41616, -0.35965, 5.41621, -0.35934, 5.4162 ]
+							}
+						]
+					}
 				}
 			}
 		},
@@ -4116,7 +4156,7 @@
 					{ "time": 0.1, "name": "muzzle03" },
 					{ "time": 0.1333, "name": "muzzle04" },
 					{ "time": 0.1667, "name": "muzzle05" },
-					{ "time": 0.2, "name": null }
+					{ "time": 0.2 }
 				]
 			},
 			"muzzle-glow": {
@@ -4145,7 +4185,7 @@
 				],
 				"attachment": [
 					{ "time": 0.0333, "name": "muzzle-ring" },
-					{ "time": 0.2333, "name": null }
+					{ "time": 0.2333 }
 				]
 			},
 			"muzzle-ring2": {
@@ -4159,7 +4199,7 @@
 				],
 				"attachment": [
 					{ "time": 0.0333, "name": "muzzle-ring" },
-					{ "time": 0.2, "name": null }
+					{ "time": 0.2 }
 				]
 			},
 			"muzzle-ring3": {
@@ -4173,7 +4213,7 @@
 				],
 				"attachment": [
 					{ "time": 0.0333, "name": "muzzle-ring" },
-					{ "time": 0.2, "name": null }
+					{ "time": 0.2 }
 				]
 			},
 			"muzzle-ring4": {
@@ -4187,7 +4227,7 @@
 				],
 				"attachment": [
 					{ "time": 0.0333, "name": "muzzle-ring" },
-					{ "time": 0.2, "name": null }
+					{ "time": 0.2 }
 				]
 			}
 		},
@@ -4708,180 +4748,192 @@
 				]
 			}
 		},
-		"deform": {
+		"attachments": {
 			"default": {
 				"eye": {
-					"eye-indifferent": [
-						{
-							"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.1333,
-							"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ],
-							"curve": [ 0.208, 0, 0.358, 1 ]
-						},
-						{
-							"time": 0.4333,
-							"vertices": [ 3.92969, -18.23849, 3.92968, -18.23849, 3.92969, -18.23849, 3.92966, -18.23848 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.6,
-							"vertices": [ 3.92969, -18.23849, 3.92968, -18.23849, 3.92969, -18.23849, 3.92966, -18.23848 ],
-							"curve": [ 0.667, 0, 0.8, 1 ]
-						},
-						{
-							"time": 0.8667,
-							"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ]
-						}
-					]
+					"eye-indifferent": {
+						"deform": [
+							{
+								"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.1333,
+								"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ],
+								"curve": [ 0.208, 0, 0.358, 1 ]
+							},
+							{
+								"time": 0.4333,
+								"vertices": [ 3.92969, -18.23849, 3.92968, -18.23849, 3.92969, -18.23849, 3.92966, -18.23848 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.6,
+								"vertices": [ 3.92969, -18.23849, 3.92968, -18.23849, 3.92969, -18.23849, 3.92966, -18.23848 ],
+								"curve": [ 0.667, 0, 0.8, 1 ]
+							},
+							{
+								"time": 0.8667,
+								"vertices": [ -0.15329, 0.70867, -0.1533, 0.70867, -0.15329, 0.70867, -0.15332, 0.70868 ]
+							}
+						]
+					}
 				},
 				"goggles": {
-					"goggles": [
-						{
-							"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, 0.7035, 4.33793, 0.69419, 4.35549, 0.69368, 4.35027, 0.70926, 4.30774, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.1333,
-							"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, 0.7035, 4.33793, 0.69419, 4.35549, 0.69368, 4.35027, 0.70926, 4.30774, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ],
-							"curve": [ 0.208, 0, 0.358, 1 ]
-						},
-						{
-							"time": 0.4333,
-							"vertices": [ 0.72116, -13.02244, -0.08078, -15.10207, 0.5881, -9.07231, 0, -1.0E-5, -0.95035, 2.12868, -4.29099, 4.74269, -0.37959, -1.86986, -0.50612, -2.49316, 2.05878, -14.16591, 3.97546, -18.45124, 0.47231, -2.1937, 1.59597, -7.39851, 2.05962, -9.54876, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 2.5869, -11.98994, 2.93105, -13.58875, 2.7115, -12.57046, 1.12065, -13.71135, 1.37358, -14.88383, 1.45292, -15.25188, 1.16116, -13.89926, 0.95006, -14.08721, -0.25414, -8.50095, -0.42554, -2.86805, 0.72943, -6.04102, 2.13203, -10.56477, -0.5799, -18.66593, -1.05817, -18.68786, 1.98856, -9.21902, 2.82358, -21.91229, 3.45764, -16.03436, 3.45535, -16.02368, 2.42818, -11.25721, 2.14265, -9.93373, 2.06394, -9.5659, 2.59061, -12.00682, 1.0E-5, 2.0E-5, 0.47232, -2.1937, 0.47231, -2.19369, 0.47234, -2.1937, 0.47233, -2.19369, 0.47235, -2.1937, -0.53991, -7.17995 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.6,
-							"vertices": [ 0.72116, -13.02244, -0.08078, -15.10207, 0.5881, -9.07231, 0, -1.0E-5, -0.95035, 2.12868, -4.29099, 4.74269, -0.37959, -1.86986, -0.50612, -2.49316, 2.05878, -14.16591, 3.97546, -18.45124, 0.47231, -2.1937, 1.59597, -7.39851, 2.05962, -9.54876, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 2.5869, -11.98994, 2.93105, -13.58875, 2.7115, -12.57046, 1.12065, -13.71135, 1.37358, -14.88383, 1.45292, -15.25188, 1.16116, -13.89926, 0.95006, -14.08721, -0.25414, -8.50095, -0.42554, -2.86805, 0.72943, -6.04102, 2.13203, -10.56477, -0.5799, -18.66593, -1.05817, -18.68786, 1.98856, -9.21902, 2.82358, -21.91229, 3.45764, -16.03436, 3.45535, -16.02368, 2.42818, -11.25721, 2.14265, -9.93373, 2.06394, -9.5659, 2.59061, -12.00682, 1.0E-5, 2.0E-5, 0.47232, -2.1937, 0.47231, -2.19369, 0.47234, -2.1937, 0.47233, -2.19369, 0.47235, -2.1937, -0.53991, -7.17995 ],
-							"curve": [ 0.667, 0, 0.8, 1 ]
-						},
-						{
-							"time": 0.8667,
-							"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, 0.7035, 4.33793, 0.69419, 4.35549, 0.69368, 4.35027, 0.70926, 4.30774, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ]
-						}
-					]
+					"goggles": {
+						"deform": [
+							{
+								"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, 0.7035, 4.33793, 0.69419, 4.35549, 0.69368, 4.35027, 0.70926, 4.30774, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.1333,
+								"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, 0.7035, 4.33793, 0.69419, 4.35549, 0.69368, 4.35027, 0.70926, 4.30774, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ],
+								"curve": [ 0.208, 0, 0.358, 1 ]
+							},
+							{
+								"time": 0.4333,
+								"vertices": [ 0.72116, -13.02244, -0.08078, -15.10207, 0.5881, -9.07231, 0, -1.0E-5, -0.95035, 2.12868, -4.29099, 4.74269, -0.37959, -1.86986, -0.50612, -2.49316, 2.05878, -14.16591, 3.97546, -18.45124, 0.47231, -2.1937, 1.59597, -7.39851, 2.05962, -9.54876, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 2.5869, -11.98994, 2.93105, -13.58875, 2.7115, -12.57046, 1.12065, -13.71135, 1.37358, -14.88383, 1.45292, -15.25188, 1.16116, -13.89926, 0.95006, -14.08721, -0.25414, -8.50095, -0.42554, -2.86805, 0.72943, -6.04102, 2.13203, -10.56477, -0.5799, -18.66593, -1.05817, -18.68786, 1.98856, -9.21902, 2.82358, -21.91229, 3.45764, -16.03436, 3.45535, -16.02368, 2.42818, -11.25721, 2.14265, -9.93373, 2.06394, -9.5659, 2.59061, -12.00682, 1.0E-5, 2.0E-5, 0.47232, -2.1937, 0.47231, -2.19369, 0.47234, -2.1937, 0.47233, -2.19369, 0.47235, -2.1937, -0.53991, -7.17995 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.6,
+								"vertices": [ 0.72116, -13.02244, -0.08078, -15.10207, 0.5881, -9.07231, 0, -1.0E-5, -0.95035, 2.12868, -4.29099, 4.74269, -0.37959, -1.86986, -0.50612, -2.49316, 2.05878, -14.16591, 3.97546, -18.45124, 0.47231, -2.1937, 1.59597, -7.39851, 2.05962, -9.54876, -2.0E-5, 0, 2.0E-5, 0, 1.0E-5, 1.0E-5, 2.0E-5, 2.0E-5, 0, 0, -1.0E-5, 0, 3.0E-5, 2.0E-5, 0, 2.0E-5, 3.0E-5, -2.0E-5, 2.5869, -11.98994, 2.93105, -13.58875, 2.7115, -12.57046, 1.12065, -13.71135, 1.37358, -14.88383, 1.45292, -15.25188, 1.16116, -13.89926, 0.95006, -14.08721, -0.25414, -8.50095, -0.42554, -2.86805, 0.72943, -6.04102, 2.13203, -10.56477, -0.5799, -18.66593, -1.05817, -18.68786, 1.98856, -9.21902, 2.82358, -21.91229, 3.45764, -16.03436, 3.45535, -16.02368, 2.42818, -11.25721, 2.14265, -9.93373, 2.06394, -9.5659, 2.59061, -12.00682, 1.0E-5, 2.0E-5, 0.47232, -2.1937, 0.47231, -2.19369, 0.47234, -2.1937, 0.47233, -2.19369, 0.47235, -2.1937, -0.53991, -7.17995 ],
+								"curve": [ 0.667, 0, 0.8, 1 ]
+							},
+							{
+								"time": 0.8667,
+								"vertices": [ -0.08838, 0.23266, -0.04028, 0.11367, -1.15417, 5.38666, 0, -1.0E-5, 0, -1.0E-5, 1.0E-5, 0, 5.0E-5, -1.0E-5, 4.0E-5, 0, -1.08234, 5.00095, -1.86743, 8.62226, -0.82045, 3.80259, -0.09568, 0.27988, -0.11634, 0.32751, -5.76247, 7.7601, -3.05986, 10.76797, -2.18187, 10.12057, -4.92509, 9.45662, 0, 0, -1.0E-5, 0, 0.65332, -3.03142, 0.55997, -2.59836, -1.40082, 6.49586, -0.16389, 0.42826, -0.14653, 0.37987, -0.13542, 0.35089, 0.7035, 4.33793, 0.69419, 4.35549, 0.69368, 4.35027, 0.70926, 4.30774, -0.90083, 4.0234, -0.04674, 0.13842, -1.07184, 4.9633, -1.06216, 4.94197, -1.04927, 4.90511, -0.04037, 0.1196, -0.0752, 0.20427, -0.10208, 0.26987, -0.12775, 0.33332, -0.13962, 0.36775, -0.14169, 0.3771, -0.13071, 0.35703, -0.1195, 0.33389, -0.14543, 0.39532, -0.16637, 0.43952, -1.40084, 6.49589, -0.82043, 3.80259, -0.82044, 3.8026, -0.8204, 3.80259, -1.82894, 8.48515, -1.82892, 8.48514, -1.82894, 8.48514 ]
+							}
+						]
+					}
 				},
 				"head": {
-					"head": [
-						{
-							"offset": 8,
-							"vertices": [ 8.45337, 4.30371, 2.09991, 9.25076, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.95061, 4.55695, 2.22333, 9.79501, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 3.18365, 15.68383, 0, 0, 0, 0, -3.54895, 9.39622, -6.13202, 7.95453, 1.99811, 9.84312, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.1333,
-							"offset": 8,
-							"vertices": [ 8.45337, 4.30371, 2.09991, 9.25076, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.95061, 4.55695, 2.22333, 9.79501, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 3.18365, 15.68383, 0, 0, 0, 0, -3.54895, 9.39622, -6.13202, 7.95453, 1.99811, 9.84312, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ],
-							"curve": [ 0.208, 0, 0.358, 1 ]
-						},
-						{
-							"time": 0.4333,
-							"offset": 34,
-							"vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -1.59174, -7.84007, -0.89545, -4.41003, -0.89545, -4.41003, -1.59174, -7.84007, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.6,
-							"offset": 34,
-							"vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -1.59174, -7.84007, -0.89545, -4.41003, -0.89545, -4.41003, -1.59174, -7.84007, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ]
-						},
-						{
-							"time": 0.8667,
-							"offset": 8,
-							"vertices": [ 8.45337, 4.30371, 2.09991, 9.25076, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.95061, 4.55695, 2.22333, 9.79501, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 3.18365, 15.68383, 0, 0, 0, 0, -3.54895, 9.39622, -6.13202, 7.95453, 1.99811, 9.84312, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ]
-						}
-					]
+					"head": {
+						"deform": [
+							{
+								"offset": 8,
+								"vertices": [ 8.45337, 4.30371, 2.09991, 9.25076, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.95061, 4.55695, 2.22333, 9.79501, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 3.18365, 15.68383, 0, 0, 0, 0, -3.54895, 9.39622, -6.13202, 7.95453, 1.99811, 9.84312, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.1333,
+								"offset": 8,
+								"vertices": [ 8.45337, 4.30371, 2.09991, 9.25076, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.95061, 4.55695, 2.22333, 9.79501, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 3.18365, 15.68383, 0, 0, 0, 0, -3.54895, 9.39622, -6.13202, 7.95453, 1.99811, 9.84312, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ],
+								"curve": [ 0.208, 0, 0.358, 1 ]
+							},
+							{
+								"time": 0.4333,
+								"offset": 34,
+								"vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -1.59174, -7.84007, -0.89545, -4.41003, -0.89545, -4.41003, -1.59174, -7.84007, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.6,
+								"offset": 34,
+								"vertices": [ 3.14838, -14.61261, 3.14838, -14.61261, 3.14838, -14.61261, 0.83426, -3.87112, 0, 0, 0, 0, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -0.72369, -5.22679, -1.59174, -7.84007, -0.89545, -4.41003, -0.89545, -4.41003, -1.59174, -7.84007, 0.55618, -2.58074, 0.41714, -1.93558, 1.04282, -4.83889 ]
+							},
+							{
+								"time": 0.8667,
+								"offset": 8,
+								"vertices": [ 8.45337, 4.30371, 2.09991, 9.25076, -3.35175, 8.87419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.81555, 0.98518, 1.01535, 8.62647, -2.70273, 4.09556, -4.48743, 7.13697, -4.76981, 3.34322, 0, 0, -2.25769, -4.31037, 0, 0, 0, 0, -0.45578, 2.11445, -0.45578, 2.11445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.95061, 4.55695, 2.22333, 9.79501, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, -6.13202, 7.95453, -3.54895, 9.39622, 8.95061, 4.55695, 0, 0, 14.26176, 7.26074, -5.65479, 14.97183, 3.18365, 15.68383, 3.18365, 15.68383, 0, 0, 0, 0, -3.54895, 9.39622, -6.13202, 7.95453, 1.99811, 9.84312, 0, 0, 0, 0, 2.3309, 11.48366, 0, 0, 0, 0, 0, 0, 2.66449, 13.12421, 0, 0, -3.14777, 14.58548, -2.86661, 13.27987, -2.55057, 11.81706, -2.17331, 10.06675, -1.96667, 9.10786, -2.01523, 9.33308, -2.29977, 10.65304, -2.63971, 12.23277, -3.05856, 14.172, 0, 0, 0, 0, 0, 0, 0, 0, -0.59756, 2.77132, -1.96329, 9.10585, -2.16217, 10.02965 ]
+							}
+						]
+					}
 				},
 				"mouth": {
-					"mouth-grind": [
-						{
-							"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.1333,
-							"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ],
-							"curve": [ 0.208, 0, 0.358, 1 ]
-						},
-						{
-							"time": 0.4333,
-							"vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.6,
-							"vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ],
-							"curve": [ 0.667, 0, 0.8, 1 ]
-						},
-						{
-							"time": 0.8667,
-							"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ]
-						}
-					],
-					"mouth-smile": [
-						{
-							"vertices": [ -6.59216, 5.02814, 5.28668, -1.62104, 2.43059, -7.10703, -6.07846, 8.24726 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.1333,
-							"vertices": [ -6.59216, 5.02814, 5.28668, -1.62104, 2.43059, -7.10703, -6.07846, 8.24726 ],
-							"curve": [ 0.208, 0, 0.358, 1 ]
-						},
-						{
-							"time": 0.4333,
-							"vertices": [ 1.95737, -8.63881, 0.58044, -17.27288, 1.98797, -27.30994, -8.04211, -23.88625 ],
-							"curve": "stepped"
-						},
-						{
-							"time": 0.6,
-							"vertices": [ 1.95737, -8.63881, 0.58044, -17.27288, 1.98797, -27.30994, -8.04211, -23.88625 ],
-							"curve": [ 0.667, 0, 0.8, 1 ]
-						},
-						{
-							"time": 0.8667,
-							"vertices": [ -6.59216, 5.02814, 5.28668, -1.62104, 2.43059, -7.10703, -6.07846, 8.24726 ]
-						}
-					]
+					"mouth-grind": {
+						"deform": [
+							{
+								"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.1333,
+								"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ],
+								"curve": [ 0.208, 0, 0.358, 1 ]
+							},
+							{
+								"time": 0.4333,
+								"vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.6,
+								"vertices": [ -1.87524, -8.97547, 0.00449, -17.7002, 0.00449, -17.7002, -1.87524, -8.97547 ],
+								"curve": [ 0.667, 0, 0.8, 1 ]
+							},
+							{
+								"time": 0.8667,
+								"vertices": [ -10.19202, 11.7786, -1.60019, 14.33763, 0.02328, 8.88684, -8.56857, 6.32779 ]
+							}
+						]
+					},
+					"mouth-smile": {
+						"deform": [
+							{
+								"vertices": [ -6.59216, 5.02814, 5.28668, -1.62104, 2.43059, -7.10703, -6.07846, 8.24726 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.1333,
+								"vertices": [ -6.59216, 5.02814, 5.28668, -1.62104, 2.43059, -7.10703, -6.07846, 8.24726 ],
+								"curve": [ 0.208, 0, 0.358, 1 ]
+							},
+							{
+								"time": 0.4333,
+								"vertices": [ 1.95737, -8.63881, 0.58044, -17.27288, 1.98797, -27.30994, -8.04211, -23.88625 ],
+								"curve": "stepped"
+							},
+							{
+								"time": 0.6,
+								"vertices": [ 1.95737, -8.63881, 0.58044, -17.27288, 1.98797, -27.30994, -8.04211, -23.88625 ],
+								"curve": [ 0.667, 0, 0.8, 1 ]
+							},
+							{
+								"time": 0.8667,
+								"vertices": [ -6.59216, 5.02814, 5.28668, -1.62104, 2.43059, -7.10703, -6.07846, 8.24726 ]
+							}
+						]
+					}
 				},
 				"torso": {
-					"torso": [
-						{
-							"offset": 32,
-							"vertices": [ 0.99754, -8.62222, -4.36671, -11.12821, 3.68875, -3.22399, 3.38991, -3.5328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.00336, 4.8839, -1.39807, 4.78593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.74744, -8.50252, 0.99754, -8.62222, 0, 0, 0, 0, 0, 0, 0.72717, -3.5363, 0.41353, -3.58589, -1.02026, 4.96621, -0.58401, 5.03633, 0, 0, 0, 0, 0, 0, -0.61319, 2.98462, -0.3511, 3.02677, 0.68637, -3.34027, 0.95636, -3.27316, 0.39218, -3.38733, -1.63116, 5.58357 ]
-						},
-						{
-							"time": 0.1,
-							"vertices": [ -2.2937, 0.83079, -1.87766, 0.23508, 10.64218, 3.4945, 8.76065, 8.13096, 7.4079, 0.46964, 6.52606, 4.22304, 6.81654, -2.65173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.46204, -2.67851, 0.25089, -5.88366, -1.00093, -5.80334, 0.15442, -3.62069, 1.01733, -3.47825, -0.61595, -3.57126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.95602, 6.51617, -0.21823, 8.17005, 0.60684, 0.26677, 0.45453, 0.48326, 0.66148, 0.04926, 2.5141, 1.78982, 2.96719, 0.85007, 1.02582, 1.37934, 1.42711, 0.95876, 0.9938, 8.43367, -2.3866, 8.1498, 1.32321, 11.29527, -2.3905, 11.22245, 4.34331, 10.36832, -1.36951, 3.04126, -2.45068, 2.2625, -0.27824, 3.32372, 0.17358, -4.07335, -0.69302, -4.01772, 1.04111, 8.28638, -1.54007, 8.31738, -0.07013, 9.53309, -0.12991, 3.03919, 0.51686, 2.99771, -0.12991, 3.03919, 0.51686, 2.99771, 1.17288, 12.46493, -2.98672, 12.23994, 4.59116, 11.52126, 1.91373, 6.46839, 3.95926, 5.46152, 0.05792, -1.35778, 0.3815, -1.30437, -0.23099, -1.33925, -2.41547, 12.32078 ]
-						},
-						{
-							"time": 0.2,
-							"vertices": [ -1.21463, -3.20385, 0.13651, -3.42358, 14.41745, 0.02832, 13.25629, 5.67007, 12.89688, -0.65636, 12.12503, 4.44476, 11.94255, -4.91476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.237, 0.29979, -0.12337, 0.36149, -1.24411, 3.02848, -0.16426, 3.2699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9.74475, 6.80592, 6.30356, 10.07764, 0.60684, 0.26677, 0.45453, 0.48326, 0.66148, 0.04926, 2.5141, 1.78982, 2.96719, 0.85007, 1.02582, 1.37934, 1.42711, 0.95876, 0.9938, 8.43367, -2.3866, 8.1498, 1.55508, 5.86423, -0.86441, 6.00507, 3.41957, 5.0114, -1.36951, 3.04126, -2.45068, 2.2625, -0.27824, 3.32372, 0, 0, 0, 0, 1.25369, 3.30791, -0.14114, 3.53476, 2.55927, 6.99835, -0.79877, 1.37497, -0.29503, 1.56245, 0, 0, 0, 0, 1.40475, 7.03388, -1.46063, 7.02255, 3.66742, 6.16434, 1.91373, 6.46839, 3.95926, 5.46152, 0, 0, 0, 0, 0, 0, -1.77957, 10.14687 ]
-						},
-						{
-							"time": 0.4333,
-							"offset": 4,
-							"vertices": [ -1.25909, 6.12791, -1.75449, 6.0049, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.74069, -3.60475, 1.03217, -3.53232, 0.74069, -3.60475, 1.03217, -3.53232, 0.42329, -3.65553, 0.74069, -3.60475, 0.42329, -3.65553 ]
-						},
-						{
-							"time": 0.5333,
-							"offset": 4,
-							"vertices": [ -0.19458, 10.61421, -1.69006, 10.61533, -0.19458, 10.61421, -1.69006, 10.61533, 1.1946, 10.40868, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.14001, -9.69365, 2.7449, -9.38902, 1.25098, -11.38506, 3.2207, -11.01592, -0.58665, -11.38687, 0.74069, -3.60475, 0.42329, -3.65553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.237, -4.22984 ]
-						},
-						{
-							"time": 0.6667,
-							"offset": 4,
-							"vertices": [ -1.25909, 6.12791, -1.75449, 6.0049, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.74069, -3.60475, 1.03217, -3.53232, 0.74069, -3.60475, 1.03217, -3.53232, 0.42329, -3.65553, 0.74069, -3.60475, 0.42329, -3.65553 ]
-						},
-						{
-							"time": 0.8667,
-							"offset": 32,
-							"vertices": [ 0.99754, -8.62222, -4.36671, -11.12821, 3.68875, -3.22399, 3.38991, -3.5328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.00336, 4.8839, -1.39807, 4.78593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.74744, -8.50252, 0.99754, -8.62222, 0, 0, 0, 0, 0, 0, 0.72717, -3.5363, 0.41353, -3.58589, -1.02026, 4.96621, -0.58401, 5.03633, 0, 0, 0, 0, 0, 0, -0.61319, 2.98462, -0.3511, 3.02677, 0.68637, -3.34027, 0.95636, -3.27316, 0.39218, -3.38733, -1.63116, 5.58357 ]
-						}
-					]
+					"torso": {
+						"deform": [
+							{
+								"offset": 32,
+								"vertices": [ 0.99754, -8.62222, -4.36671, -11.12821, 3.68875, -3.22399, 3.38991, -3.5328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.00336, 4.8839, -1.39807, 4.78593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.74744, -8.50252, 0.99754, -8.62222, 0, 0, 0, 0, 0, 0, 0.72717, -3.5363, 0.41353, -3.58589, -1.02026, 4.96621, -0.58401, 5.03633, 0, 0, 0, 0, 0, 0, -0.61319, 2.98462, -0.3511, 3.02677, 0.68637, -3.34027, 0.95636, -3.27316, 0.39218, -3.38733, -1.63116, 5.58357 ]
+							},
+							{
+								"time": 0.1,
+								"vertices": [ -2.2937, 0.83079, -1.87766, 0.23508, 10.64218, 3.4945, 8.76065, 8.13096, 7.4079, 0.46964, 6.52606, 4.22304, 6.81654, -2.65173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.46204, -2.67851, 0.25089, -5.88366, -1.00093, -5.80334, 0.15442, -3.62069, 1.01733, -3.47825, -0.61595, -3.57126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.95602, 6.51617, -0.21823, 8.17005, 0.60684, 0.26677, 0.45453, 0.48326, 0.66148, 0.04926, 2.5141, 1.78982, 2.96719, 0.85007, 1.02582, 1.37934, 1.42711, 0.95876, 0.9938, 8.43367, -2.3866, 8.1498, 1.32321, 11.29527, -2.3905, 11.22245, 4.34331, 10.36832, -1.36951, 3.04126, -2.45068, 2.2625, -0.27824, 3.32372, 0.17358, -4.07335, -0.69302, -4.01772, 1.04111, 8.28638, -1.54007, 8.31738, -0.07013, 9.53309, -0.12991, 3.03919, 0.51686, 2.99771, -0.12991, 3.03919, 0.51686, 2.99771, 1.17288, 12.46493, -2.98672, 12.23994, 4.59116, 11.52126, 1.91373, 6.46839, 3.95926, 5.46152, 0.05792, -1.35778, 0.3815, -1.30437, -0.23099, -1.33925, -2.41547, 12.32078 ]
+							},
+							{
+								"time": 0.2,
+								"vertices": [ -1.21463, -3.20385, 0.13651, -3.42358, 14.41745, 0.02832, 13.25629, 5.67007, 12.89688, -0.65636, 12.12503, 4.44476, 11.94255, -4.91476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.237, 0.29979, -0.12337, 0.36149, -1.24411, 3.02848, -0.16426, 3.2699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9.74475, 6.80592, 6.30356, 10.07764, 0.60684, 0.26677, 0.45453, 0.48326, 0.66148, 0.04926, 2.5141, 1.78982, 2.96719, 0.85007, 1.02582, 1.37934, 1.42711, 0.95876, 0.9938, 8.43367, -2.3866, 8.1498, 1.55508, 5.86423, -0.86441, 6.00507, 3.41957, 5.0114, -1.36951, 3.04126, -2.45068, 2.2625, -0.27824, 3.32372, 0, 0, 0, 0, 1.25369, 3.30791, -0.14114, 3.53476, 2.55927, 6.99835, -0.79877, 1.37497, -0.29503, 1.56245, 0, 0, 0, 0, 1.40475, 7.03388, -1.46063, 7.02255, 3.66742, 6.16434, 1.91373, 6.46839, 3.95926, 5.46152, 0, 0, 0, 0, 0, 0, -1.77957, 10.14687 ]
+							},
+							{
+								"time": 0.4333,
+								"offset": 4,
+								"vertices": [ -1.25909, 6.12791, -1.75449, 6.0049, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.74069, -3.60475, 1.03217, -3.53232, 0.74069, -3.60475, 1.03217, -3.53232, 0.42329, -3.65553, 0.74069, -3.60475, 0.42329, -3.65553 ]
+							},
+							{
+								"time": 0.5333,
+								"offset": 4,
+								"vertices": [ -0.19458, 10.61421, -1.69006, 10.61533, -0.19458, 10.61421, -1.69006, 10.61533, 1.1946, 10.40868, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.14001, -9.69365, 2.7449, -9.38902, 1.25098, -11.38506, 3.2207, -11.01592, -0.58665, -11.38687, 0.74069, -3.60475, 0.42329, -3.65553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.237, -4.22984 ]
+							},
+							{
+								"time": 0.6667,
+								"offset": 4,
+								"vertices": [ -1.25909, 6.12791, -1.75449, 6.0049, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -1.75449, 6.0049, -0.72083, 6.21444, -1.25909, 6.12791, -0.72083, 6.21444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.74069, -3.60475, 1.03217, -3.53232, 0.74069, -3.60475, 1.03217, -3.53232, 0.42329, -3.65553, 0.74069, -3.60475, 0.42329, -3.65553 ]
+							},
+							{
+								"time": 0.8667,
+								"offset": 32,
+								"vertices": [ 0.99754, -8.62222, -4.36671, -11.12821, 3.68875, -3.22399, 3.38991, -3.5328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.00336, 4.8839, -1.39807, 4.78593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.74744, -8.50252, 0.99754, -8.62222, 0, 0, 0, 0, 0, 0, 0.72717, -3.5363, 0.41353, -3.58589, -1.02026, 4.96621, -0.58401, 5.03633, 0, 0, 0, 0, 0, 0, -0.61319, 2.98462, -0.3511, 3.02677, 0.68637, -3.34027, 0.95636, -3.27316, 0.39218, -3.38733, -1.63116, 5.58357 ]
+							}
+						]
+					}
 				}
 			}
 		},

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.png


+ 19 - 19
spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "AN/kz0MkBAg",
-	"spine": "4.0.31",
+	"hash": "fJ3tj/bl3Iw",
+	"spine": "4.1.04-beta",
 	"x": -221.22,
 	"y": -8.55,
 	"width": 371.09,
@@ -887,19 +887,19 @@
 			"gun2": {
 				"attachment": [
 					{ "time": 0.6333, "name": "gun" },
-					{ "time": 1.6667, "name": null }
+					{ "time": 1.6667 }
 				]
 			},
 			"gun3": {
 				"attachment": [
 					{ "time": 0.6333, "name": "gun" },
-					{ "time": 1.6667, "name": null }
+					{ "time": 1.6667 }
 				]
 			},
 			"gun4": {
 				"attachment": [
 					{ "time": 0.6333, "name": "gun" },
-					{ "time": 1.6667, "name": null }
+					{ "time": 1.6667 }
 				]
 			},
 			"muzzle": {
@@ -922,39 +922,39 @@
 				],
 				"attachment": [
 					{ "time": 0.7667, "name": "muzzle" },
-					{ "time": 1.3333, "name": null }
+					{ "time": 1.3333 }
 				]
 			},
 			"muzzle2": {
 				"attachment": [
 					{ "time": 0.7667, "name": "muzzle" },
-					{ "time": 0.8333, "name": null },
+					{ "time": 0.8333 },
 					{ "time": 0.8667, "name": "muzzle" },
-					{ "time": 0.9333, "name": null },
+					{ "time": 0.9333 },
 					{ "time": 0.9667, "name": "muzzle" },
-					{ "time": 1.0333, "name": null },
+					{ "time": 1.0333 },
 					{ "time": 1.0667, "name": "muzzle" },
-					{ "time": 1.1333, "name": null },
+					{ "time": 1.1333 },
 					{ "time": 1.1667, "name": "muzzle" },
-					{ "time": 1.2333, "name": null },
+					{ "time": 1.2333 },
 					{ "time": 1.2667, "name": "muzzle" },
-					{ "time": 1.3333, "name": null }
+					{ "time": 1.3333 }
 				]
 			},
 			"muzzle3": {
 				"attachment": [
 					{ "time": 0.8333, "name": "muzzle" },
-					{ "time": 0.9, "name": null },
+					{ "time": 0.9 },
 					{ "time": 0.9333, "name": "muzzle" },
-					{ "time": 1, "name": null },
+					{ "time": 1 },
 					{ "time": 1.0333, "name": "muzzle" },
-					{ "time": 1.1, "name": null },
+					{ "time": 1.1 },
 					{ "time": 1.1333, "name": "muzzle" },
-					{ "time": 1.2, "name": null },
+					{ "time": 1.2 },
 					{ "time": 1.2333, "name": "muzzle" },
-					{ "time": 1.3, "name": null },
+					{ "time": 1.3 },
 					{ "time": 1.3333, "name": "muzzle" },
-					{ "time": 1.4, "name": null }
+					{ "time": 1.4 }
 				]
 			}
 		},
@@ -5232,7 +5232,7 @@
 				],
 				"attachment": [
 					{ "time": 0.0333, "name": "muzzle" },
-					{ "time": 0.1667, "name": null }
+					{ "time": 0.1667 }
 				]
 			},
 			"muzzle2": {

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.png


+ 2 - 2
spine-unity/Assets/Spine Examples/Spine Skeletons/whirlyblendmodes/whirlyblendmodes.json

@@ -1,7 +1,7 @@
 {
 "skeleton": {
-	"hash": "wOLCjLyjs9E",
-	"spine": "4.0.31",
+	"hash": "d53R1Ina68Q",
+	"spine": "4.1.04-beta",
 	"x": -252.71,
 	"y": -232.55,
 	"width": 456.71,

BIN
spine-unity/Assets/Spine Examples/Spine Skeletons/whirlyblendmodes/whirlyblendmodes.png


+ 2 - 2
spine-unity/Assets/Spine Examples/package.json

@@ -2,7 +2,7 @@
   "name": "com.esotericsoftware.spine.spine-unity-examples",
   "displayName": "spine-unity Runtime Examples",
   "description": "This plugin provides example scenes and scripts for the spine-unity runtime.",
-  "version": "4.0.0",
+  "version": "4.1.0",
   "unity": "2018.3",
   "author": {
     "name": "Esoteric Software",
@@ -10,7 +10,7 @@
     "url": "http://esotericsoftware.com/"
   },
   "dependencies": {
-    "com.esotericsoftware.spine.spine-unity": "4.0.0"
+    "com.esotericsoftware.spine.spine-unity": "4.1.0"
   },
   "repository": {
     "type": "git",

+ 38 - 8
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs

@@ -176,6 +176,14 @@ namespace Spine.Unity.Editor {
 							requiredPaths.Add((string)data["path"]);
 						else if (data.ContainsKey("name"))
 							requiredPaths.Add((string)data["name"]);
+						else if (data.ContainsKey("sequence")) {
+							Sequence sequence = SkeletonJson.ReadSequence(data["sequence"]);
+							if (sequence != null)
+								for (int index = 0; index < sequence.Regions.Length; ++index)
+									requiredPaths.Add(sequence.GetPath(attachment.Key, index));
+							else
+								requiredPaths.Add(attachment.Key);
+						}
 						else
 							requiredPaths.Add(attachment.Key);
 					}
@@ -234,14 +242,26 @@ namespace Spine.Unity.Editor {
 				this.requirementList = requirementList;
 			}
 
-			public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
-				requirementList.Add(path);
-				return new RegionAttachment(name);
+			public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
+				var regionAttachment = new RegionAttachment(name);
+				if (sequence != null)
+					LoadSequence(path, sequence);
+				else {
+					requirementList.Add(path);
+					AssignDummyRegion(regionAttachment);
+				}
+				return regionAttachment;
 			}
 
-			public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
-				requirementList.Add(path);
-				return new MeshAttachment(name);
+			public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
+				var meshAttachment = new MeshAttachment(name);
+				if (sequence != null)
+					LoadSequence(path, sequence);
+				else {
+					requirementList.Add(path);
+					AssignDummyRegion(meshAttachment);
+				}
+				return meshAttachment;
 			}
 
 			public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
@@ -259,6 +279,18 @@ namespace Spine.Unity.Editor {
 			public ClippingAttachment NewClippingAttachment (Skin skin, string name) {
 				return new ClippingAttachment(name);
 			}
+
+			private void LoadSequence (string basePath, Sequence sequence) {
+				TextureRegion[] regions = sequence.Regions;
+				for (int i = 0, n = regions.Length; i < n; i++) {
+					string path = sequence.GetPath(basePath, i);
+					requirementList.Add(path);
+				}
+			}
+
+			private static void AssignDummyRegion (IHasTextureRegion attachment) {
+				attachment.Region = new AtlasRegion();
+			}
 		}
 		#endregion
 
@@ -1215,7 +1247,6 @@ namespace Spine.Unity.Editor {
 			}
 
 			newSkeletonAnimation.loop = SpineEditorUtilities.Preferences.defaultInstantiateLoop;
-			newSkeletonAnimation.skeleton.Update(0);
 			newSkeletonAnimation.state.Update(0);
 			newSkeletonAnimation.state.Apply(newSkeletonAnimation.skeleton);
 			newSkeletonAnimation.skeleton.UpdateWorldTransform();
@@ -1301,7 +1332,6 @@ namespace Spine.Unity.Editor {
 				throw e;
 			}
 
-			newSkeletonMecanim.skeleton.Update(0);
 			newSkeletonMecanim.skeleton.UpdateWorldTransform();
 			newSkeletonMecanim.LateUpdate();
 

+ 2 - 2
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/BlendModeMaterialsUtility.cs

@@ -200,9 +200,9 @@ namespace Spine.Unity.Editor {
 					skin.GetAttachments(slotIndex, skinEntries);
 
 				foreach (var entry in skinEntries) {
-					var renderableAttachment = entry.Attachment as IHasRendererObject;
+					var renderableAttachment = entry.Attachment as IHasTextureRegion;
 					if (renderableAttachment != null) {
-						var originalRegion = (AtlasRegion)renderableAttachment.RendererObject;
+						var originalRegion = (AtlasRegion)renderableAttachment.Region;
 						bool replacementExists = replacementMaterials.Exists(
 							replacement => replacement.pageName == originalRegion.page.name);
 						if (!replacementExists) {

+ 3 - 2
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs

@@ -501,7 +501,8 @@ namespace Spine.Unity.Editor {
 		}
 
 		internal static Mesh ExtractRegionAttachment (string name, RegionAttachment attachment, Mesh mesh = null, bool centered = true) {
-			var bone = GetDummyBone();
+			var slot = GetDummySlot();
+			var bone = slot.Bone;
 
 			if (centered) {
 				bone.X = -attachment.X;
@@ -512,7 +513,7 @@ namespace Spine.Unity.Editor {
 
 			Vector2[] uvs = ExtractUV(attachment.UVs);
 			float[] floatVerts = new float[8];
-			attachment.ComputeWorldVertices(bone, floatVerts, 0);
+			attachment.ComputeWorldVertices(slot, floatVerts, 0);
 			Vector3[] verts = ExtractVerts(floatVerts);
 
 			//unrotate verts now that they're centered

+ 5 - 5
spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterials.cs

@@ -70,7 +70,7 @@ namespace Spine.Unity {
 		public bool UpdateBlendmodeMaterialsRequiredState (SkeletonData skeletonData) {
 			requiresBlendModeMaterials = false;
 
-			if (skeletonData == null) throw new ArgumentNullException("skeletonData");
+			if (skeletonData == null) return false;
 
 			var skinEntries = new List<Skin.SkinEntry>();
 			var slotsItems = skeletonData.Slots.Items;
@@ -84,7 +84,7 @@ namespace Spine.Unity {
 					skin.GetAttachments(slotIndex, skinEntries);
 
 				foreach (var entry in skinEntries) {
-					if (entry.Attachment is IHasRendererObject) {
+					if (entry.Attachment is IHasTextureRegion) {
 						requiresBlendModeMaterials = true;
 						return true;
 					}
@@ -125,10 +125,10 @@ namespace Spine.Unity {
 					skin.GetAttachments(slotIndex, skinEntries);
 
 				foreach (var entry in skinEntries) {
-					var renderableAttachment = entry.Attachment as IHasRendererObject;
+					var renderableAttachment = entry.Attachment as IHasTextureRegion;
 					if (renderableAttachment != null) {
-						renderableAttachment.RendererObject = CloneAtlasRegionWithMaterial(
-							(AtlasRegion)renderableAttachment.RendererObject, replacementMaterials);
+						renderableAttachment.Region = CloneAtlasRegionWithMaterial(
+							(AtlasRegion)renderableAttachment.Region, replacementMaterials);
 					}
 				}
 			}

+ 4 - 4
spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/RegionlessAttachmentLoader.cs

@@ -50,16 +50,16 @@ namespace Spine.Unity {
 			}
 		}
 
-		public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
+		public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
 			RegionAttachment attachment = new RegionAttachment(name) {
-				RendererObject = EmptyRegion
+				Region = EmptyRegion
 			};
 			return attachment;
 		}
 
-		public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
+		public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
 			MeshAttachment attachment = new MeshAttachment(name) {
-				RendererObject = EmptyRegion
+				Region = EmptyRegion
 			};
 			return attachment;
 		}

+ 2 - 2
spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/SkeletonDataCompatibility.cs

@@ -41,8 +41,8 @@ namespace Spine.Unity {
 	public static class SkeletonDataCompatibility {
 
 #if UNITY_EDITOR
-		static readonly int[][] compatibleBinaryVersions = { new[] { 4, 0, 0 } };
-		static readonly int[][] compatibleJsonVersions = { new[] { 4, 0, 0 } };
+		static readonly int[][] compatibleBinaryVersions = { new[] { 4, 1, 0 } };
+		static readonly int[][] compatibleJsonVersions = { new[] { 4, 1, 0 } };
 
 		static bool wasVersionDialogShown = false;
 		static readonly Regex jsonVersionRegex = new Regex(@"""spine""\s*:\s*""([^""]+)""", RegexOptions.CultureInvariant);

+ 0 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonAnimation.cs

@@ -215,7 +215,6 @@ namespace Spine.Unity {
 
 		protected void UpdateAnimationStatus (float deltaTime) {
 			deltaTime *= timeScale;
-			skeleton.Update(deltaTime);
 			state.Update(deltaTime);
 		}
 

+ 0 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs

@@ -295,7 +295,6 @@ namespace Spine.Unity {
 
 		protected void UpdateAnimationStatus (float deltaTime) {
 			deltaTime *= timeScale;
-			skeleton.Update(deltaTime);
 			state.Update(deltaTime);
 		}
 

+ 18 - 12
spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs

@@ -191,13 +191,15 @@ namespace Spine.Unity {
 
 				var regionAttachment = attachment as RegionAttachment;
 				if (regionAttachment != null) {
-					rendererObject = regionAttachment.RendererObject;
+					if (regionAttachment.Sequence != null) regionAttachment.Sequence.Apply(slot, regionAttachment);
+					rendererObject = regionAttachment.Region;
 					attachmentVertexCount = 4;
 					attachmentTriangleCount = 6;
 				} else {
 					var meshAttachment = attachment as MeshAttachment;
 					if (meshAttachment != null) {
-						rendererObject = meshAttachment.RendererObject;
+						if (meshAttachment.Sequence != null) meshAttachment.Sequence.Apply(slot, meshAttachment);
+						rendererObject = meshAttachment.Region;
 						attachmentVertexCount = meshAttachment.WorldVerticesLength >> 1;
 						attachmentTriangleCount = meshAttachment.Triangles.Length;
 					} else {
@@ -249,9 +251,10 @@ namespace Spine.Unity {
 				Slot slot = drawOrderItems[i];
 				if (!slot.Bone.Active) continue;
 				Attachment attachment = slot.Attachment;
-				var rendererAttachment = attachment as IHasRendererObject;
+				var rendererAttachment = attachment as IHasTextureRegion;
 				if (rendererAttachment != null) {
-					AtlasRegion atlasRegion = (AtlasRegion)rendererAttachment.RendererObject;
+					if (rendererAttachment.Sequence != null) rendererAttachment.Sequence.Apply(slot, rendererAttachment);
+					AtlasRegion atlasRegion = (AtlasRegion)rendererAttachment.Region;
 					Material material = (Material)atlasRegion.page.rendererObject;
 					if (lastRendererMaterial != material) {
 						if (lastRendererMaterial != null)
@@ -308,12 +311,13 @@ namespace Spine.Unity {
 				int attachmentVertexCount = 0, attachmentTriangleCount = 0;
 #endif
 
-				object rendererObject = null; // An AtlasRegion in plain Spine-Unity. Spine-TK2D hooks into TK2D's system. eventual source of Material object.
+				object region = null;
 				bool noRender = false; // Using this allows empty slots as separators, and keeps separated parts more stable despite slots being reordered
 
 				var regionAttachment = attachment as RegionAttachment;
 				if (regionAttachment != null) {
-					rendererObject = regionAttachment.RendererObject;
+					if (regionAttachment.Sequence != null) regionAttachment.Sequence.Apply(slot, regionAttachment);
+					region = regionAttachment.Region;
 #if SPINE_TRIANGLECHECK
 					attachmentVertexCount = 4;
 					attachmentTriangleCount = 6;
@@ -321,7 +325,8 @@ namespace Spine.Unity {
 				} else {
 					var meshAttachment = attachment as MeshAttachment;
 					if (meshAttachment != null) {
-						rendererObject = meshAttachment.RendererObject;
+						if (meshAttachment.Sequence != null) meshAttachment.Sequence.Apply(slot, meshAttachment);
+						region = meshAttachment.Region;
 #if SPINE_TRIANGLECHECK
 						attachmentVertexCount = meshAttachment.WorldVerticesLength >> 1;
 						attachmentTriangleCount = meshAttachment.Triangles.Length;
@@ -378,12 +383,13 @@ namespace Spine.Unity {
 					Material material;
 					if (isCustomSlotMaterialsPopulated) {
 						if (!customSlotMaterials.TryGetValue(slot, out material))
-							material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
+							material = (Material)((AtlasRegion)region).page.rendererObject;
 					} else {
-						material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
+						material = (Material)((AtlasRegion)region).page.rendererObject;
 					}
 #else
-					Material material = (rendererObject is Material) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
+					// An AtlasRegion in plain spine-unity, spine-TK2D hooks into TK2D's system. eventual source of Material object.
+					Material material = (region is Material) ? (Material)region : (Material)((AtlasRegion)region).page.rendererObject;
 #endif
 
 					if (current.forceSeparate || (current.rawVertexCount > 0 && !System.Object.ReferenceEquals(current.material, material))) { // Material changed. Add the previous submesh.
@@ -531,7 +537,7 @@ namespace Spine.Unity {
 				// Identify and prepare values.
 				var region = attachment as RegionAttachment;
 				if (region != null) {
-					region.ComputeWorldVertices(slot.Bone, workingVerts, 0);
+					region.ComputeWorldVertices(slot, workingVerts, 0);
 					uvs = region.UVs;
 					attachmentTriangleIndices = regionTriangles;
 					c.r = region.R; c.g = region.G; c.b = region.B; c.a = region.A;
@@ -821,7 +827,7 @@ namespace Spine.Unity {
 
 					var regionAttachment = attachment as RegionAttachment;
 					if (regionAttachment != null) {
-						regionAttachment.ComputeWorldVertices(slot.Bone, tempVerts, 0);
+						regionAttachment.ComputeWorldVertices(slot, tempVerts, 0);
 
 						float x1 = tempVerts[RegionAttachment.BLX], y1 = tempVerts[RegionAttachment.BLY];
 						float x2 = tempVerts[RegionAttachment.ULX], y2 = tempVerts[RegionAttachment.ULY];

+ 3 - 2
spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonDataModifierAssets/BlendModeMaterials/BlendModeMaterialsAsset.cs

@@ -77,9 +77,10 @@ namespace Spine.Unity {
 					if (templateMaterial == null) continue;
 
 					foreach (var entry in entryBuffer) {
-						var renderableAttachment = entry.Attachment as IHasRendererObject;
+						var renderableAttachment = entry.Attachment as IHasTextureRegion;
 						if (renderableAttachment != null) {
-							renderableAttachment.RendererObject = materialCache.CloneAtlasRegionWithMaterial((AtlasRegion)renderableAttachment.RendererObject, templateMaterial);
+							renderableAttachment.Region = materialCache.CloneAtlasRegionWithMaterial(
+								(AtlasRegion)renderableAttachment.Region, templateMaterial);
 						}
 					}
 				}

+ 17 - 25
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs

@@ -351,10 +351,10 @@ namespace Spine.Unity.AttachmentTools {
 			for (int attachmentIndex = 0, n = sourceAttachments.Count; attachmentIndex < n; attachmentIndex++) {
 				var originalAttachment = sourceAttachments[attachmentIndex];
 
-				if (originalAttachment is IHasRendererObject) {
+				if (originalAttachment is IHasTextureRegion) {
 					var originalMeshAttachment = originalAttachment as MeshAttachment;
 					Attachment newAttachment = (originalMeshAttachment != null) ? originalMeshAttachment.NewLinkedMesh() : originalAttachment.Copy();
-					var region = ((IHasRendererObject)newAttachment).RendererObject as AtlasRegion;
+					var region = ((IHasTextureRegion)newAttachment).Region as AtlasRegion;
 					int existingIndex;
 					if (existingRegions.TryGetValue(region, out existingIndex)) {
 						regionIndices.Add(existingIndex);
@@ -428,9 +428,12 @@ namespace Spine.Unity.AttachmentTools {
 
 			// Map the cloned attachments to the repacked atlas.
 			for (int i = 0, n = outputAttachments.Count; i < n; i++) {
-				var a = outputAttachments[i];
-				if (a is IHasRendererObject)
-					a.SetRegion(repackedRegions[regionIndices[i]]);
+				Attachment attachment = outputAttachments[i];
+				var iHasRegion = attachment as IHasTextureRegion;
+				if (iHasRegion != null) {
+					iHasRegion.Region = repackedRegions[regionIndices[i]];
+					iHasRegion.UpdateRegion();
+				}
 			}
 
 			// Clean up.
@@ -650,7 +653,7 @@ namespace Spine.Unity.AttachmentTools {
 		}
 
 		static bool IsRenderable (Attachment a) {
-			return a is IHasRendererObject;
+			return a is IHasTextureRegion;
 		}
 
 		/// <summary>
@@ -676,10 +679,7 @@ namespace Spine.Unity.AttachmentTools {
 		/// <summary>
 		/// Returns a Rect of the AtlasRegion according to Spine texture coordinates. (x-right, y-down)</summary>
 		static Rect GetSpineAtlasRect (this AtlasRegion region, bool includeRotate = true) {
-			if (includeRotate && (region.degrees == 90 || region.degrees == 270))
-				return new Rect(region.x, region.y, region.height, region.width);
-			else
-				return new Rect(region.x, region.y, region.width, region.height);
+			return new Rect(region.x, region.y, region.packedWidth, region.packedHeight);
 		}
 
 		/// <summary>
@@ -708,26 +708,18 @@ namespace Spine.Unity.AttachmentTools {
 			var tr = UVRectToTextureRect(uvRect, page.width, page.height);
 			var rr = tr.SpineUnityFlipRect(page.height);
 
-			int x = (int)rr.x, y = (int)rr.y;
-			int w, h;
-			if (referenceRegion.degrees == 90 || referenceRegion.degrees == 270) {
-				w = (int)rr.height;
-				h = (int)rr.width;
-			} else {
-				w = (int)rr.width;
-				h = (int)rr.height;
-			}
-
+			int x = (int)rr.x;
+			int y = (int)rr.y;
+			int w = (int)rr.width;
+			int h = (int)rr.height;
+			// Note: originalW and originalH need to be scaled according to the
+			// repacked width and height, repacking can mess with aspect ratio, etc.
 			int originalW = Mathf.RoundToInt((float)w * ((float)referenceRegion.originalWidth / (float)referenceRegion.width));
 			int originalH = Mathf.RoundToInt((float)h * ((float)referenceRegion.originalHeight / (float)referenceRegion.height));
+
 			int offsetX = Mathf.RoundToInt((float)referenceRegion.offsetX * ((float)w / (float)referenceRegion.width));
 			int offsetY = Mathf.RoundToInt((float)referenceRegion.offsetY * ((float)h / (float)referenceRegion.height));
 
-			if (referenceRegion.degrees == 270) {
-				w = (int)rr.width;
-				h = (int)rr.height;
-			}
-
 			float u = uvRect.xMin;
 			float u2 = uvRect.xMax;
 			float v = uvRect.yMax;

+ 6 - 5
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs

@@ -68,8 +68,8 @@ namespace Spine.Unity.AttachmentTools {
 			float scale = 1f / sprite.pixelsPerUnit;
 			if (useOriginalRegionScale) {
 				var regionAttachment = o as RegionAttachment;
-				if (regionAttachment != null)
-					scale = regionAttachment.Width / regionAttachment.RegionOriginalWidth;
+				if (regionAttachment != null )
+					scale = regionAttachment.Width / regionAttachment.Region.OriginalWidth;
 			}
 			return o.GetRemappedClone(atlasRegion, cloneMeshAsLinked, useOriginalRegionSize, scale);
 		}
@@ -86,18 +86,19 @@ namespace Spine.Unity.AttachmentTools {
 			var regionAttachment = o as RegionAttachment;
 			if (regionAttachment != null) {
 				RegionAttachment newAttachment = (RegionAttachment)regionAttachment.Copy();
-				newAttachment.SetRegion(atlasRegion, false);
+				newAttachment.Region = atlasRegion;
 				if (!useOriginalRegionSize) {
 					newAttachment.Width = atlasRegion.width * scale;
 					newAttachment.Height = atlasRegion.height * scale;
 				}
-				newAttachment.UpdateOffset();
+				newAttachment.UpdateRegion();
 				return newAttachment;
 			} else {
 				var meshAttachment = o as MeshAttachment;
 				if (meshAttachment != null) {
 					MeshAttachment newAttachment = cloneMeshAsLinked ? meshAttachment.NewLinkedMesh() : (MeshAttachment)meshAttachment.Copy();
-					newAttachment.SetRegion(atlasRegion);
+					newAttachment.Region = atlasRegion;
+					newAttachment.UpdateRegion();
 					return newAttachment;
 				}
 			}

+ 8 - 64
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs

@@ -33,58 +33,6 @@ using UnityEngine;
 
 namespace Spine.Unity.AttachmentTools {
 	public static class AttachmentRegionExtensions {
-		#region SetRegion
-		/// <summary>
-		/// Tries to set the region (image) of a renderable attachment. If the attachment is not renderable, nothing is applied.</summary>
-		public static void SetRegion (this Attachment attachment, AtlasRegion region, bool updateOffset = true) {
-			var regionAttachment = attachment as RegionAttachment;
-			if (regionAttachment != null)
-				regionAttachment.SetRegion(region, updateOffset);
-
-			var meshAttachment = attachment as MeshAttachment;
-			if (meshAttachment != null)
-				meshAttachment.SetRegion(region, updateOffset);
-		}
-
-		/// <summary>Sets the region (image) of a RegionAttachment</summary>
-		public static void SetRegion (this RegionAttachment attachment, AtlasRegion region, bool updateOffset = true) {
-			if (region == null) throw new System.ArgumentNullException("region");
-
-			// (AtlasAttachmentLoader.cs)
-			attachment.RendererObject = region;
-			attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.degrees);
-			attachment.RegionOffsetX = region.offsetX;
-			attachment.RegionOffsetY = region.offsetY;
-			attachment.RegionWidth = region.width;
-			attachment.RegionHeight = region.height;
-			attachment.RegionOriginalWidth = region.originalWidth;
-			attachment.RegionOriginalHeight = region.originalHeight;
-
-			if (updateOffset) attachment.UpdateOffset();
-		}
-
-		/// <summary>Sets the region (image) of a MeshAttachment</summary>
-		public static void SetRegion (this MeshAttachment attachment, AtlasRegion region, bool updateUVs = true) {
-			if (region == null) throw new System.ArgumentNullException("region");
-
-			// (AtlasAttachmentLoader.cs)
-			attachment.RendererObject = region;
-			attachment.RegionU = region.u;
-			attachment.RegionV = region.v;
-			attachment.RegionU2 = region.u2;
-			attachment.RegionV2 = region.v2;
-			attachment.RegionDegrees = region.degrees;
-			attachment.RegionOffsetX = region.offsetX;
-			attachment.RegionOffsetY = region.offsetY;
-			attachment.RegionWidth = region.width;
-			attachment.RegionHeight = region.height;
-			attachment.RegionOriginalWidth = region.originalWidth;
-			attachment.RegionOriginalHeight = region.originalHeight;
-
-			if (updateUVs) attachment.UpdateUVs();
-		}
-		#endregion
-
 		#region Runtime RegionAttachments
 		/// <summary>
 		/// Creates a RegionAttachment based on a sprite. This method creates a real, usable AtlasRegion. That AtlasRegion uses a new AtlasPage with the Material provided./// </summary>
@@ -128,15 +76,7 @@ namespace Spine.Unity.AttachmentTools {
 			// (AtlasAttachmentLoader.cs)
 			var attachment = new RegionAttachment(attachmentName);
 
-			attachment.RendererObject = region;
-			attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.degrees);
-			attachment.RegionOffsetX = region.offsetX;
-			attachment.RegionOffsetY = region.offsetY;
-			attachment.RegionWidth = region.width;
-			attachment.RegionHeight = region.height;
-			attachment.RegionOriginalWidth = region.originalWidth;
-			attachment.RegionOriginalHeight = region.originalHeight;
-
+			attachment.Region = region;
 			attachment.Path = region.name;
 			attachment.ScaleX = 1;
 			attachment.ScaleY = 1;
@@ -148,11 +88,15 @@ namespace Spine.Unity.AttachmentTools {
 			attachment.A = 1;
 
 			// pass OriginalWidth and OriginalHeight because UpdateOffset uses it in its calculation.
-			attachment.Width = attachment.RegionOriginalWidth * scale;
-			attachment.Height = attachment.RegionOriginalHeight * scale;
+			var textreRegion = attachment.Region;
+			var atlasRegion = textreRegion as AtlasRegion;
+			float originalWidth = atlasRegion != null ? atlasRegion.originalWidth : textreRegion.width;
+			float originalHeight = atlasRegion != null ? atlasRegion.originalHeight : textreRegion.height;
+			attachment.Width = originalWidth * scale;
+			attachment.Height = originalHeight * scale;
 
 			attachment.SetColor(Color.white);
-			attachment.UpdateOffset();
+			attachment.UpdateRegion();
 			return attachment;
 		}
 

+ 2 - 2
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs

@@ -209,9 +209,9 @@ namespace Spine.Unity {
 		#region Attachments
 		public static Material GetMaterial (this Attachment a) {
 			object rendererObject = null;
-			var renderableAttachment = a as IHasRendererObject;
+			var renderableAttachment = a as IHasTextureRegion;
 			if (renderableAttachment != null)
-				rendererObject = renderableAttachment.RendererObject;
+				rendererObject = renderableAttachment.Region;
 
 			if (rendererObject == null)
 				return null;

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно