Browse Source

[c] Initial port of Sequence timelines

Everything is broken, WIP to transfer to other machine.
Mario Zechner 3 years ago
parent
commit
83c0b0c559

+ 3 - 4
spine-c/spine-c/include/spine/Atlas.h

@@ -32,6 +32,7 @@
 
 #include <spine/dll.h>
 #include <spine/Array.h>
+#include "TextureRegion.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -96,11 +97,9 @@ _SP_ARRAY_DECLARE_TYPE(spKeyValueArray, spKeyValue)
 /**/
 typedef struct spAtlasRegion spAtlasRegion;
 struct spAtlasRegion {
+	spTextureRegion super;
 	const char *name;
-	int x, y, width, height;
-	float u, v, u2, v2;
-	int offsetX, offsetY;
-	int originalWidth, originalHeight;
+	int x, y;
 	int index;
 	int degrees;
 	int *splits;

+ 5 - 6
spine-c/spine-c/include/spine/MeshAttachment.h

@@ -35,6 +35,7 @@
 #include <spine/VertexAttachment.h>
 #include <spine/Atlas.h>
 #include <spine/Slot.h>
+#include <spine/Sequence.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -45,11 +46,7 @@ struct spMeshAttachment {
 	spVertexAttachment super;
 
 	void *rendererObject;
-	int regionOffsetX, regionOffsetY; /* Pixels stripped from the bottom left, unrotated. */
-	int regionWidth, regionHeight; /* Unrotated, stripped pixel size. */
-	int regionOriginalWidth, regionOriginalHeight; /* Unrotated, unstripped pixel size. */
-	float regionU, regionV, regionU2, regionV2;
-	int regionDegrees;
+	spTextureRegion *region;
 
 	const char *path;
 
@@ -65,6 +62,8 @@ struct spMeshAttachment {
 
 	spMeshAttachment *const parentMesh;
 
+	spSequence *sequence;
+
 	/* Nonessential. */
 	int edgesCount;
 	int *edges;
@@ -73,7 +72,7 @@ struct spMeshAttachment {
 
 SP_API spMeshAttachment *spMeshAttachment_create(const char *name);
 
-SP_API void spMeshAttachment_updateUVs(spMeshAttachment *self);
+SP_API void spMeshAttachment_updateRegion(spMeshAttachment *self);
 
 SP_API void spMeshAttachment_setParentMesh(spMeshAttachment *self, spMeshAttachment *parentMesh);
 

+ 6 - 5
spine-c/spine-c/include/spine/RegionAttachment.h

@@ -34,6 +34,7 @@
 #include <spine/Attachment.h>
 #include <spine/Atlas.h>
 #include <spine/Slot.h>
+#include <spine/Sequence.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -46,21 +47,21 @@ typedef struct spRegionAttachment {
 	spColor color;
 
 	void *rendererObject;
-	int regionOffsetX, regionOffsetY; /* Pixels stripped from the bottom left, unrotated. */
-	int regionWidth, regionHeight; /* Unrotated, stripped pixel size. */
-	int regionOriginalWidth, regionOriginalHeight; /* Unrotated, unstripped pixel size. */
+	spTextureRegion *region;
 
 	float offset[8];
 	float uvs[8];
+
+	spSequence *sequence;
 } spRegionAttachment;
 
 SP_API spRegionAttachment *spRegionAttachment_create(const char *name);
 
 SP_API void spRegionAttachment_setUVs(spRegionAttachment *self, float u, float v, float u2, float v2, float degrees);
 
-SP_API void spRegionAttachment_updateOffset(spRegionAttachment *self);
+SP_API void spRegionAttachment_updateRegion(spRegionAttachment *self);
 
-SP_API void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spBone *bone, float *vertices, int offset,
+SP_API void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spSlot *slot, float *vertices, int offset,
 													int stride);
 
 #ifdef __cplusplus

+ 67 - 0
spine-c/spine-c/include/spine/Sequence.h

@@ -0,0 +1,67 @@
+/******************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#ifndef SPINE_SEQUENCE_H
+#define SPINE_SEQUENCE_H
+
+#include <spine/dll.h>
+#include <spine/TextureRegion.h>
+#include <spine/Atlas.h>
+#include "Attachment.h"
+#include "Slot.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_SP_ARRAY_DECLARE_TYPE(spTextureRegionArray, spTextureRegion*)
+
+typedef struct spSequence {
+	int id;
+	int start;
+	int digits;
+	int setupIndex;
+	spTextureRegionArray *regions;
+} spSequence;
+
+SP_API spSequence *spSequence_create(int start, int digits, int setupIndex, int numRegions);
+
+SP_API void spSequence_dispose(spSequence *self);
+
+SP_API spSequence *spSequence_copy(spSequence *self);
+
+SP_API void spSequence_apply(spSequence *self, spSlot *slot, spAttachment *attachment);
+
+SP_API char *spSequence_getPath(const char* basePath, int index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 2 - 4
spine-c/spine-c/include/spine/Slot.h

@@ -50,6 +50,8 @@ typedef struct spSlot {
 	int deformCapacity;
 	int deformCount;
 	float *deform;
+
+	int sequenceIndex;
 } spSlot;
 
 SP_API spSlot *spSlot_create(spSlotData *data, spBone *bone);
@@ -59,10 +61,6 @@ SP_API void spSlot_dispose(spSlot *self);
 /* @param attachment May be 0 to clear the attachment for the slot. */
 SP_API void spSlot_setAttachment(spSlot *self, spAttachment *attachment);
 
-SP_API void spSlot_setAttachmentTime(spSlot *self, float time);
-
-SP_API float spSlot_getAttachmentTime(const spSlot *self);
-
 SP_API void spSlot_setToSetupPose(spSlot *self);
 
 #ifdef __cplusplus

+ 50 - 0
spine-c/spine-c/include/spine/TextureRegion.h

@@ -0,0 +1,50 @@
+/******************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#ifndef SPINE_TEXTURE_REGION_H
+#define SPINE_TEXTURE_REGION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct spTextureRegion {
+	void *rendererObject;
+	float u, v, u2, v2;
+	int degrees;
+	float offsetX, offsetY;
+	int width, height;
+	int originalWidth, originalHeight;
+} spTextureRegion;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 1 - 1
spine-c/spine-c/include/spine/VertexAttachment.h

@@ -50,7 +50,7 @@ struct spVertexAttachment {
 
 	int worldVerticesLength;
 
-	spVertexAttachment *deformAttachment;
+	spVertexAttachment *timelineAttachment;
 
 	int id;
 };

+ 1 - 1
spine-c/spine-c/src/spine/Animation.c

@@ -1775,7 +1775,7 @@ void _spDeformTimeline_apply(
 		case SP_ATTACHMENT_MESH:
 		case SP_ATTACHMENT_PATH: {
 			spVertexAttachment *vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment);
-			if (vertexAttachment->deformAttachment != SUB_CAST(spVertexAttachment, self->attachment)) return;
+			if (vertexAttachment->timelineAttachment != SUB_CAST(spVertexAttachment, self->attachment)) return;
 			break;
 		}
 		default:

+ 21 - 21
spine-c/spine-c/src/spine/Atlas.c

@@ -356,24 +356,24 @@ spAtlas *spAtlas_create(const char *begin, int length, const char *dir, void *re
 					region->x = ss_toInt(&entry[1]);
 					region->y = ss_toInt(&entry[2]);
 				} else if (ss_equals(&entry[0], "size")) {
-					region->width = ss_toInt(&entry[1]);
-					region->height = ss_toInt(&entry[2]);
+					region->super.width = ss_toInt(&entry[1]);
+					region->super.height = ss_toInt(&entry[2]);
 				} else if (ss_equals(&entry[0], "bounds")) {
 					region->x = ss_toInt(&entry[1]);
 					region->y = ss_toInt(&entry[2]);
-					region->width = ss_toInt(&entry[3]);
-					region->height = ss_toInt(&entry[4]);
+					region->super.width = ss_toInt(&entry[3]);
+					region->super.height = ss_toInt(&entry[4]);
 				} else if (ss_equals(&entry[0], "offset")) {
-					region->offsetX = ss_toInt(&entry[1]);
-					region->offsetY = ss_toInt(&entry[2]);
+					region->super.offsetX = ss_toInt(&entry[1]);
+					region->super.offsetY = ss_toInt(&entry[2]);
 				} else if (ss_equals(&entry[0], "orig")) {
-					region->originalWidth = ss_toInt(&entry[1]);
-					region->originalHeight = ss_toInt(&entry[2]);
+					region->super.originalWidth = ss_toInt(&entry[1]);
+					region->super.originalHeight = ss_toInt(&entry[2]);
 				} else if (ss_equals(&entry[0], "offsets")) {
-					region->offsetX = ss_toInt(&entry[1]);
-					region->offsetY = ss_toInt(&entry[2]);
-					region->originalWidth = ss_toInt(&entry[3]);
-					region->originalHeight = ss_toInt(&entry[4]);
+					region->super.offsetX = ss_toInt(&entry[1]);
+					region->super.offsetY = ss_toInt(&entry[2]);
+					region->super.originalWidth = ss_toInt(&entry[3]);
+					region->super.originalHeight = ss_toInt(&entry[4]);
 				} else if (ss_equals(&entry[0], "rotate")) {
 					if (ss_equals(&entry[1], "true")) {
 						region->degrees = 90;
@@ -392,19 +392,19 @@ spAtlas *spAtlas_create(const char *begin, int length, const char *dir, void *re
 					spKeyValueArray_add(region->keyValues, keyValue);
 				}
 			}
-			if (region->originalWidth == 0 && region->originalHeight == 0) {
-				region->originalWidth = region->width;
-				region->originalHeight = region->height;
+			if (region->super.originalWidth == 0 && region->super.originalHeight == 0) {
+				region->super.originalWidth = region->super.width;
+				region->super.originalHeight = region->super.height;
 			}
 
-			region->u = (float) region->x / page->width;
-			region->v = (float) region->y / page->height;
+			region->super.u = (float) region->x / page->width;
+			region->super.v = (float) region->y / page->height;
 			if (region->degrees == 90) {
-				region->u2 = (float) (region->x + region->height) / page->width;
-				region->v2 = (float) (region->y + region->width) / page->height;
+				region->super.u2 = (float) (region->x + region->super.height) / page->width;
+				region->super.v2 = (float) (region->y + region->super.width) / page->height;
 			} else {
-				region->u2 = (float) (region->x + region->width) / page->width;
-				region->v2 = (float) (region->y + region->height) / page->height;
+				region->super.u2 = (float) (region->x + region->super.width) / page->width;
+				region->super.v2 = (float) (region->y + region->super.height) / page->height;
 			}
 		}
 	}

+ 3 - 18
spine-c/spine-c/src/spine/AtlasAttachmentLoader.c

@@ -43,13 +43,8 @@ spAttachment *_spAtlasAttachmentLoader_createAttachment(spAttachmentLoader *load
 			}
 			attachment = spRegionAttachment_create(name);
 			attachment->rendererObject = region;
-			spRegionAttachment_setUVs(attachment, 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;
+			spRegionAttachment_setUVs(attachment, region->super.u, region->super.v, region->super.u2, region->super.v2, region->degrees);
+			attachment->region = SUPER(region);
 			return SUPER(attachment);
 		}
 		case SP_ATTACHMENT_MESH:
@@ -62,17 +57,7 @@ spAttachment *_spAtlasAttachmentLoader_createAttachment(spAttachmentLoader *load
 			}
 			attachment = spMeshAttachment_create(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;
+			attachment->region = SUPER(region);
 			return SUPER(SUPER(attachment));
 		}
 		case SP_ATTACHMENT_BOUNDING_BOX:

+ 34 - 52
spine-c/spine-c/src/spine/MeshAttachment.c

@@ -42,6 +42,7 @@ void _spMeshAttachment_dispose(spAttachment *attachment) {
 		FREE(self->edges);
 	} else
 		_spAttachment_deinit(attachment);
+	if (self->sequence) FREE(self->sequence);
 	FREE(self);
 }
 
@@ -52,17 +53,8 @@ spAttachment *_spMeshAttachment_copy(spAttachment *attachment) {
 		return SUPER(SUPER(spMeshAttachment_newLinkedMesh(self)));
 	copy = spMeshAttachment_create(attachment->name);
 	copy->rendererObject = self->rendererObject;
-	copy->regionU = self->regionU;
-	copy->regionV = self->regionV;
-	copy->regionU2 = self->regionU2;
-	copy->regionV2 = self->regionV2;
-	copy->regionDegrees = self->regionDegrees;
-	copy->regionOffsetX = self->regionOffsetX;
-	copy->regionOffsetY = self->regionOffsetY;
-	copy->regionWidth = self->regionWidth;
-	copy->regionHeight = self->regionHeight;
-	copy->regionOriginalWidth = self->regionOriginalWidth;
-	copy->regionOriginalHeight = self->regionOriginalHeight;
+	copy->region = self->region;
+	copy->sequence = self->sequence != NULL ? spSequence_copy(self->sequence) : NULL;
 	MALLOC_STR(copy->path, self->path);
 	spColor_setFromColor(&copy->color, &self->color);
 
@@ -90,22 +82,12 @@ spMeshAttachment *spMeshAttachment_newLinkedMesh(spMeshAttachment *self) {
 	spMeshAttachment *copy = spMeshAttachment_create(self->super.super.name);
 
 	copy->rendererObject = self->rendererObject;
-	copy->regionU = self->regionU;
-	copy->regionV = self->regionV;
-	copy->regionU2 = self->regionU2;
-	copy->regionV2 = self->regionV2;
-	copy->regionDegrees = self->regionDegrees;
-	copy->regionOffsetX = self->regionOffsetX;
-	copy->regionOffsetY = self->regionOffsetY;
-	copy->regionWidth = self->regionWidth;
-	copy->regionHeight = self->regionHeight;
-	copy->regionOriginalWidth = self->regionOriginalWidth;
-	copy->regionOriginalHeight = self->regionOriginalHeight;
+	copy->region = self->region;
 	MALLOC_STR(copy->path, self->path);
 	spColor_setFromColor(&copy->color, &self->color);
-	copy->super.deformAttachment = self->super.deformAttachment;
+	copy->super.timelineAttachment = self->super.timelineAttachment;
 	spMeshAttachment_setParentMesh(copy, self->parentMesh ? self->parentMesh : self);
-	spMeshAttachment_updateUVs(copy);
+	spMeshAttachment_updateRegion(copy);
 	return copy;
 }
 
@@ -117,7 +99,7 @@ spMeshAttachment *spMeshAttachment_create(const char *name) {
 	return self;
 }
 
-void spMeshAttachment_updateUVs(spMeshAttachment *self) {
+void spMeshAttachment_updateRegion(spMeshAttachment *self) {
 	int i, n;
 	float *uvs;
 	float u, v, width, height;
@@ -125,17 +107,17 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
 	FREE(self->uvs);
 	uvs = self->uvs = MALLOC(float, verticesLength);
 	n = verticesLength;
-	u = self->regionU;
-	v = self->regionV;
+	u = self->region->u;
+	v = self->region->v;
 
-	switch (self->regionDegrees) {
+	switch (self->region->degrees) {
 		case 90: {
-			float textureWidth = self->regionHeight / (self->regionU2 - self->regionU);
-			float textureHeight = self->regionWidth / (self->regionV2 - self->regionV);
-			u -= (self->regionOriginalHeight - self->regionOffsetY - self->regionHeight) / textureWidth;
-			v -= (self->regionOriginalWidth - self->regionOffsetX - self->regionWidth) / textureHeight;
-			width = self->regionOriginalHeight / textureWidth;
-			height = self->regionOriginalWidth / textureHeight;
+			float textureWidth = self->region->height / (self->region->u2 - self->region->u);
+			float textureHeight = self->region->width / (self->region->v2 - self->region->v);
+			u -= (self->region->originalHeight - self->region->offsetY - self->region->height) / textureWidth;
+			v -= (self->region->originalWidth - self->region->offsetX - self->region->width) / textureHeight;
+			width = self->region->originalHeight / textureWidth;
+			height = self->region->originalWidth / textureHeight;
 			for (i = 0; i < n; i += 2) {
 				uvs[i] = u + self->regionUVs[i + 1] * width;
 				uvs[i + 1] = v + (1 - self->regionUVs[i]) * height;
@@ -143,12 +125,12 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
 			return;
 		}
 		case 180: {
-			float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
-			float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
-			u -= (self->regionOriginalWidth - self->regionOffsetX - self->regionWidth) / textureWidth;
-			v -= self->regionOffsetY / textureHeight;
-			width = self->regionOriginalWidth / textureWidth;
-			height = self->regionOriginalHeight / textureHeight;
+			float textureWidth = self->region->width / (self->region->u2 - self->region->u);
+			float textureHeight = self->region->height / (self->region->v2 - self->region->v);
+			u -= (self->region->originalWidth - self->region->offsetX - self->region->width) / textureWidth;
+			v -= self->region->offsetY / textureHeight;
+			width = self->region->originalWidth / textureWidth;
+			height = self->region->originalHeight / textureHeight;
 			for (i = 0; i < n; i += 2) {
 				uvs[i] = u + (1 - self->regionUVs[i]) * width;
 				uvs[i + 1] = v + (1 - self->regionUVs[i + 1]) * height;
@@ -156,12 +138,12 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
 			return;
 		}
 		case 270: {
-			float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
-			float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
-			u -= self->regionOffsetY / textureWidth;
-			v -= self->regionOffsetX / textureHeight;
-			width = self->regionOriginalHeight / textureWidth;
-			height = self->regionOriginalWidth / textureHeight;
+			float textureHeight = self->region->height / (self->region->v2 - self->region->v);
+			float textureWidth = self->region->width / (self->region->u2 - self->region->u);
+			u -= self->region->offsetY / textureWidth;
+			v -= self->region->offsetX / textureHeight;
+			width = self->region->originalHeight / textureWidth;
+			height = self->region->originalWidth / textureHeight;
 			for (i = 0; i < n; i += 2) {
 				uvs[i] = u + (1 - self->regionUVs[i + 1]) * width;
 				uvs[i + 1] = v + self->regionUVs[i] * height;
@@ -169,12 +151,12 @@ void spMeshAttachment_updateUVs(spMeshAttachment *self) {
 			return;
 		}
 		default: {
-			float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
-			float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
-			u -= self->regionOffsetX / textureWidth;
-			v -= (self->regionOriginalHeight - self->regionOffsetY - self->regionHeight) / textureHeight;
-			width = self->regionOriginalWidth / textureWidth;
-			height = self->regionOriginalHeight / textureHeight;
+			float textureWidth = self->region->width / (self->region->u2 - self->region->u);
+			float textureHeight = self->region->height / (self->region->v2 - self->region->v);
+			u -= self->region->offsetX / textureWidth;
+			v -= (self->region->originalHeight - self->region->offsetY - self->region->height) / textureHeight;
+			width = self->region->originalWidth / textureWidth;
+			height = self->region->originalHeight / textureHeight;
 			for (i = 0; i < n; i += 2) {
 				uvs[i] = u + self->regionUVs[i] * width;
 				uvs[i + 1] = v + self->regionUVs[i + 1] * height;

+ 15 - 14
spine-c/spine-c/src/spine/RegionAttachment.c

@@ -51,12 +51,12 @@ void _spRegionAttachment_dispose(spAttachment *attachment) {
 spAttachment *_spRegionAttachment_copy(spAttachment *attachment) {
 	spRegionAttachment *self = SUB_CAST(spRegionAttachment, attachment);
 	spRegionAttachment *copy = spRegionAttachment_create(attachment->name);
-	copy->regionWidth = self->regionWidth;
-	copy->regionHeight = self->regionHeight;
-	copy->regionOffsetX = self->regionOffsetX;
-	copy->regionOffsetY = self->regionOffsetY;
-	copy->regionOriginalWidth = self->regionOriginalWidth;
-	copy->regionOriginalHeight = self->regionOriginalHeight;
+	copy->region->width = self->region->width;
+	copy->region->height = self->region->height;
+	copy->region->offsetX = self->region->offsetX;
+	copy->region->offsetY = self->region->offsetY;
+	copy->region->originalWidth = self->region->originalWidth;
+	copy->region->originalHeight = self->region->originalHeight;
 	copy->rendererObject = self->rendererObject;
 	MALLOC_STR(copy->path, self->path);
 	copy->x = self->x;
@@ -103,13 +103,13 @@ void spRegionAttachment_setUVs(spRegionAttachment *self, float u, float v, float
 	}
 }
 
-void spRegionAttachment_updateOffset(spRegionAttachment *self) {
-	float regionScaleX = self->width / self->regionOriginalWidth * self->scaleX;
-	float regionScaleY = self->height / self->regionOriginalHeight * self->scaleY;
-	float localX = -self->width / 2 * self->scaleX + self->regionOffsetX * regionScaleX;
-	float localY = -self->height / 2 * self->scaleY + self->regionOffsetY * regionScaleY;
-	float localX2 = localX + self->regionWidth * regionScaleX;
-	float localY2 = localY + self->regionHeight * regionScaleY;
+void spRegionAttachment_updateRegion(spRegionAttachment *self) {
+	float regionScaleX = self->width / self->region->originalWidth * self->scaleX;
+	float regionScaleY = self->height / self->region->originalHeight * self->scaleY;
+	float localX = -self->width / 2 * self->scaleX + self->region->offsetX * regionScaleX;
+	float localY = -self->height / 2 * self->scaleY + self->region->offsetY * regionScaleY;
+	float localX2 = localX + self->region->width * regionScaleX;
+	float localY2 = localY + self->region->height * regionScaleY;
 	float radians = self->rotation * DEG_RAD;
 	float cosine = COS(radians), sine = SIN(radians);
 	float localXCos = localX * cosine + self->x;
@@ -130,9 +130,10 @@ void spRegionAttachment_updateOffset(spRegionAttachment *self) {
 	self->offset[BRY] = localYCos + localX2Sin;
 }
 
-void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spBone *bone, float *vertices, int offset,
+void spRegionAttachment_computeWorldVertices(spRegionAttachment *self, spSlot *slot, float *vertices, int offset,
 											 int stride) {
 	const float *offsets = self->offset;
+	spBone *bone = slot->bone;
 	float x = bone->worldX, y = bone->worldY;
 	float offsetX, offsetY;
 

+ 92 - 0
spine-c/spine-c/src/spine/Sequence.c

@@ -0,0 +1,92 @@
+/******************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#include <spine/Sequence.h>
+#include <spine/extension.h>
+
+_SP_ARRAY_IMPLEMENT_TYPE(spTextureRegionArray, spTextureRegion*)
+
+static int nextSequenceId = 0;
+
+spSequence *spSequence_create(int start, int digits, int setupIndex, int numRegions) {
+	spSequence *self = NEW(spSequence);
+	self->id = nextSequenceId++;
+	self->start = start;
+	self->digits = digits;
+	self->setupIndex = setupIndex;
+	self->regions = spTextureRegionArray_create(numRegions);
+	spTextureRegionArray_setSize(self->regions, numRegions);
+	return self;
+}
+
+void spSequence_dispose(spSequence *self) {
+	FREE(self->regions);
+	FREE(self);
+}
+
+spSequence *spSequence_copy(spSequence *self) {
+	int i = 0;
+	spSequence *copy = spSequence_create(self->start, self->digits, self->setupIndex, self->regions->size);
+	for (; i < self->regions->size; i++)
+		copy->regions->items[i] = self->regions->items[i];
+	copy->start = self->start;
+	copy->digits = self->digits;
+	copy->setupIndex = self->setupIndex;
+	return copy;
+}
+
+void spSequence_apply(spSequence *self, spSlot *slot, spAttachment *attachment) {
+	int index = slot->sequenceIndex;
+	spTextureRegion *region = NULL;
+	if (index == -1) index = self->setupIndex;
+	if (index >= (int) self->regions->size) index = self->regions->size - 1;
+	region = self->regions->items[index];
+
+	if (attachment->type == SP_ATTACHMENT_REGION) {
+		spRegionAttachment *regionAttachment = (spRegionAttachment*)attachment;
+		if (regionAttachment->region != region) {
+			regionAttachment->rendererObject = region;
+			regionAttachment->region = region;
+			spRegionAttachment_updateRegion(regionAttachment);
+		}
+	}
+
+	if (attachment->type == SP_ATTACHMENT_MESH) {
+		spMeshAttachment *meshAttachment = (spMeshAttachment*)attachment;
+		if (meshAttachment->region != region) {
+			meshAttachment->rendererObject = region;
+			meshAttachment->region = region;
+			spMeshAttachment_updateRegion(meshAttachment);
+		}
+	}
+}
+
+char *spSequence_getPath(const char* basePath, int index) {
+	fix me
+}

+ 2 - 2
spine-c/spine-c/src/spine/SkeletonBinary.c

@@ -1418,8 +1418,8 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
 			_spSkeletonBinary_setError(self, "Parent mesh not found: ", linkedMesh->parent);
 			return NULL;
 		}
-		linkedMesh->mesh->super.deformAttachment = linkedMesh->inheritDeform ? SUB_CAST(spVertexAttachment, parent)
-																			 : SUB_CAST(spVertexAttachment,
+		linkedMesh->mesh->super.timelineAttachment = linkedMesh->inheritDeform ? SUB_CAST(spVertexAttachment, parent)
+																			   : SUB_CAST(spVertexAttachment,
 																						linkedMesh->mesh);
 		spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent));
 		spMeshAttachment_updateUVs(linkedMesh->mesh);

+ 2 - 2
spine-c/spine-c/src/spine/SkeletonJson.c

@@ -1514,8 +1514,8 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			_spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent);
 			return NULL;
 		}
-		linkedMesh->mesh->super.deformAttachment = linkedMesh->inheritDeform ? SUB_CAST(spVertexAttachment, parent)
-																			 : SUB_CAST(spVertexAttachment,
+		linkedMesh->mesh->super.timelineAttachment = linkedMesh->inheritDeform ? SUB_CAST(spVertexAttachment, parent)
+																			   : SUB_CAST(spVertexAttachment,
 																						linkedMesh->mesh);
 		spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent));
 		spMeshAttachment_updateUVs(linkedMesh->mesh);

+ 2 - 16
spine-c/spine-c/src/spine/Slot.c

@@ -30,13 +30,8 @@
 #include <spine/Slot.h>
 #include <spine/extension.h>
 
-typedef struct {
-	spSlot super;
-	float attachmentTime;
-} _spSlot;
-
 spSlot *spSlot_create(spSlotData *data, spBone *bone) {
-	spSlot *self = SUPER(NEW(_spSlot));
+	spSlot *self = NEW(spSlot);
 	CONST_CAST(spSlotData *, self->data) = data;
 	CONST_CAST(spBone *, self->bone) = bone;
 	spColor_setFromFloats(&self->color, 1, 1, 1, 1);
@@ -68,20 +63,11 @@ void spSlot_setAttachment(spSlot *self, spAttachment *attachment) {
 	if (attachment == self->attachment) return;
 
 	if (!isVertexAttachment(attachment) ||
-		!isVertexAttachment(self->attachment) || (SUB_CAST(spVertexAttachment, attachment)->deformAttachment != SUB_CAST(spVertexAttachment, self->attachment)->deformAttachment)) {
+		!isVertexAttachment(self->attachment) || (SUB_CAST(spVertexAttachment, attachment)->timelineAttachment != SUB_CAST(spVertexAttachment, self->attachment)->timelineAttachment)) {
 		self->deformCount = 0;
 	}
 
 	CONST_CAST(spAttachment *, self->attachment) = attachment;
-	SUB_CAST(_spSlot, self)->attachmentTime = self->bone->skeleton->time;
-}
-
-void spSlot_setAttachmentTime(spSlot *self, float time) {
-	SUB_CAST(_spSlot, self)->attachmentTime = self->bone->skeleton->time - time;
-}
-
-float spSlot_getAttachmentTime(const spSlot *self) {
-	return self->bone->skeleton->time - SUB_CAST(_spSlot, self)->attachmentTime;
 }
 
 void spSlot_setToSetupPose(spSlot *self) {

+ 1 - 1
spine-c/spine-c/src/spine/VertexAttachment.c

@@ -35,7 +35,7 @@ static int nextID = 0;
 
 void _spVertexAttachment_init(spVertexAttachment *attachment) {
 	attachment->id = nextID++;
-	attachment->deformAttachment = attachment;
+	attachment->timelineAttachment = attachment;
 }
 
 void _spVertexAttachment_deinit(spVertexAttachment *attachment) {