From b1f851a2462067da8d1c6db5587cda2fdeb4ad6e Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Mon, 28 Apr 2014 17:52:01 +0200 Subject: [PATCH] Meshes, FFD and skinning for spine-c. Untested since rendering hasn't yet been done for a runtime that extends spine-c. --- spine-c/include/spine/Attachment.h | 2 +- spine-c/include/spine/MeshAttachment.h | 88 +++++++++ spine-c/include/spine/RegionAttachment.h | 1 + spine-c/include/spine/SkinnedMeshAttachment.h | 90 ++++++++++ spine-c/include/spine/Slot.h | 3 + spine-c/include/spine/SlotData.h | 2 +- spine-c/src/spine/AnimationState.c | 5 - spine-c/src/spine/Attachment.c | 2 +- spine-c/src/spine/MeshAttachment.c | 87 +++++++++ spine-c/src/spine/RegionAttachment.c | 2 - spine-c/src/spine/SkeletonJson.c | 167 +++++++++++++++--- spine-c/src/spine/SkinnedMeshAttachment.c | 109 ++++++++++++ spine-c/src/spine/Slot.c | 1 + 13 files changed, 528 insertions(+), 31 deletions(-) create mode 100644 spine-c/include/spine/MeshAttachment.h create mode 100644 spine-c/include/spine/SkinnedMeshAttachment.h create mode 100644 spine-c/src/spine/MeshAttachment.c create mode 100644 spine-c/src/spine/SkinnedMeshAttachment.c diff --git a/spine-c/include/spine/Attachment.h b/spine-c/include/spine/Attachment.h index 8e46224ef..9b516b04f 100644 --- a/spine-c/include/spine/Attachment.h +++ b/spine-c/include/spine/Attachment.h @@ -44,7 +44,7 @@ typedef enum { typedef struct spAttachment spAttachment; struct spAttachment { const char* const name; - spAttachmentType type; + const spAttachmentType type; const void* const vtable; }; diff --git a/spine-c/include/spine/MeshAttachment.h b/spine-c/include/spine/MeshAttachment.h new file mode 100644 index 000000000..ffd21b97e --- /dev/null +++ b/spine-c/include/spine/MeshAttachment.h @@ -0,0 +1,88 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * or (b) remove, delete, alter or obscure any trademarks or any copyright, + * trademark, patent or other intellectual property or proprietary rights + * notices on or in the Software, including any copy thereof. Redistributions + * in binary or source form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_MESHATTACHMENT_H_ +#define SPINE_MESHATTACHMENT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spMeshAttachment spMeshAttachment; +struct spMeshAttachment { + spAttachment super; + const char* path; + + int verticesCount; + float* vertices; + + int uvsCount; + float* regionUVs; + float* uvs; + + int trianglesCount; + int* triangles; + + float r, g, b, a; + + 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/*bool*/regionRotate; + + /* Nonessential. */ + int hullLength; + int edgesCount; + int* edges; + float width, height; +}; + +spMeshAttachment* spMeshAttachment_create (const char* name); +void spMeshAttachment_updateUVs (spMeshAttachment* self); +void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, float x, float y, spSlot* bone, float* worldVertices); + +#ifdef SPINE_SHORT_NAMES +typedef spMeshAttachment MeshAttachment; +#define MeshAttachment_create(...) spMeshAttachment_create(__VA_ARGS__) +#define MeshAttachment_updateUVs(...) spMeshAttachment_updateUVs(__VA_ARGS__) +#define MeshAttachment_computeWorldVertices(...) spMeshAttachment_computeWorldVertices(__VA_ARGS__) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SPINE_MESHATTACHMENT_H_ */ diff --git a/spine-c/include/spine/RegionAttachment.h b/spine-c/include/spine/RegionAttachment.h index 4c41d2fd6..9b91d50e0 100644 --- a/spine-c/include/spine/RegionAttachment.h +++ b/spine-c/include/spine/RegionAttachment.h @@ -46,6 +46,7 @@ typedef enum { typedef struct spRegionAttachment spRegionAttachment; struct spRegionAttachment { spAttachment super; + const char* path; float x, y, scaleX, scaleY, rotation, width, height; float r, g, b, a; diff --git a/spine-c/include/spine/SkinnedMeshAttachment.h b/spine-c/include/spine/SkinnedMeshAttachment.h new file mode 100644 index 000000000..c04c3fbcd --- /dev/null +++ b/spine-c/include/spine/SkinnedMeshAttachment.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * or (b) remove, delete, alter or obscure any trademarks or any copyright, + * trademark, patent or other intellectual property or proprietary rights + * notices on or in the Software, including any copy thereof. Redistributions + * in binary or source form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKINNEDMESHATTACHMENT_H_ +#define SPINE_SKINNEDMESHATTACHMENT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spSkinnedMeshAttachment spSkinnedMeshAttachment; +struct spSkinnedMeshAttachment { + spAttachment super; + const char* path; + + int bonesCount; + int* bones; + + int weightsCount; + float* weights; + + int trianglesCount; + int* triangles; + + int uvsCount; + float* regionUVs; + float* uvs; + + float r, g, b, a; + + 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/*bool*/regionRotate; + + /* Nonessential. */ + int hullLength; + int edgesCount; + int* edges; + float width, height; +}; + +spSkinnedMeshAttachment* spSkinnedMeshAttachment_create (const char* name); +void spSkinnedMeshAttachment_updateUVs (spSkinnedMeshAttachment* self); +void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, float x, float y, spSlot* bone, float* worldVertices); + +#ifdef SPINE_SHORT_NAMES +typedef spSkinnedMeshAttachment SkinnedMeshAttachment; +#define SkinnedMeshAttachment_create(...) spSkinnedMeshAttachment_create(__VA_ARGS__) +#define SkinnedMeshAttachment_updateUVs(...) spSkinnedMeshAttachment_updateUVs(__VA_ARGS__) +#define SkinnedMeshAttachment_computeWorldVertices(...) spSkinnedMeshAttachment_computeWorldVertices(__VA_ARGS__) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SPINE_SKINNEDMESHATTACHMENT_H_ */ diff --git a/spine-c/include/spine/Slot.h b/spine-c/include/spine/Slot.h index 9896e4d6c..3a317a840 100644 --- a/spine-c/include/spine/Slot.h +++ b/spine-c/include/spine/Slot.h @@ -47,6 +47,9 @@ typedef struct spSlot { spBone* const bone; float r, g, b, a; spAttachment* const attachment; + + int attachmentVerticesCount; + float* attachmentVertices; } spSlot; spSlot* spSlot_create (spSlotData* data, struct spSkeleton* skeleton, spBone* bone); diff --git a/spine-c/include/spine/SlotData.h b/spine-c/include/spine/SlotData.h index 728bddb87..f47132638 100644 --- a/spine-c/include/spine/SlotData.h +++ b/spine-c/include/spine/SlotData.h @@ -40,7 +40,7 @@ extern "C" { typedef struct { const char* const name; const spBoneData* const boneData; - const char* const attachmentName; + const char* attachmentName; float r, g, b, a; int/*bool*/additiveBlending; } spSlotData; diff --git a/spine-c/src/spine/AnimationState.c b/spine-c/src/spine/AnimationState.c index 4133a11d5..feb3a08cc 100644 --- a/spine-c/src/spine/AnimationState.c +++ b/spine-c/src/spine/AnimationState.c @@ -28,13 +28,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#include #include -#include -#include #include -#include -#include #include spTrackEntry* _spTrackEntry_create () { diff --git a/spine-c/src/spine/Attachment.c b/spine-c/src/spine/Attachment.c index 25e2e0798..3918837f0 100644 --- a/spine-c/src/spine/Attachment.c +++ b/spine-c/src/spine/Attachment.c @@ -43,7 +43,7 @@ void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType VTABLE(spAttachment, self) ->dispose = dispose; MALLOC_STR(self->name, name); - self->type = type; + CONST_CAST(spAttachmentType, self->type) = type; } void _spAttachment_deinit (spAttachment* self) { diff --git a/spine-c/src/spine/MeshAttachment.c b/spine-c/src/spine/MeshAttachment.c new file mode 100644 index 000000000..5d1c6c954 --- /dev/null +++ b/spine-c/src/spine/MeshAttachment.c @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * or (b) remove, delete, alter or obscure any trademarks or any copyright, + * trademark, patent or other intellectual property or proprietary rights + * notices on or in the Software, including any copy thereof. Redistributions + * in binary or source form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +void _spMeshAttachment_dispose (spAttachment* attachment) { + spMeshAttachment* self = SUB_CAST(spMeshAttachment, attachment); + _spAttachment_deinit(attachment); + FREE(self->path); + FREE(self->vertices); + FREE(self->regionUVs); + FREE(self->uvs); + FREE(self->triangles); + FREE(self->edges); + FREE(self); +} + +spMeshAttachment* spMeshAttachment_create (const char* name) { + spMeshAttachment* self = NEW(spMeshAttachment); + self->r = 1; + self->g = 1; + self->b = 1; + self->a = 1; + _spAttachment_init(SUPER(self), name, SP_ATTACHMENT_MESH, _spMeshAttachment_dispose); + return self; +} + +void spMeshAttachment_updateUVs (spMeshAttachment* self) { + int i; + float width = self->regionU2 - self->regionU, height = self->regionV2 - self->regionV; + FREE(self->uvs); + self->uvs = MALLOC(float, self->uvsCount); + if (self->regionRotate) { + for (i = 0; i < self->uvsCount; i += 2) { + self->uvs[i] = self->regionU + self->regionUVs[i + 1] * width; + self->uvs[i + 1] = self->regionV + height - self->regionUVs[i] * height; + } + } else { + for (i = 0; i < self->uvsCount; i += 2) { + self->uvs[i] = self->regionU + self->regionUVs[i] * width; + self->uvs[i + 1] = self->regionV + self->regionUVs[i + 1] * height; + } + } +} + +void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, float x, float y, spSlot* slot, float* worldVertices) { + int i; + float* vertices = self->vertices; + spBone* bone = slot->bone; + x += bone->worldX; + y += bone->worldY; + if (slot->attachmentVerticesCount == self->verticesCount) vertices = slot->attachmentVertices; + for (i = 0; i < self->verticesCount; i += 2) { + float vx = vertices[i]; + float vy = vertices[i + 1]; + worldVertices[i] = vx * bone->m00 + vy * bone->m01 + x; + worldVertices[i + 1] = vx * bone->m10 + vy * bone->m11 + y; + } +} diff --git a/spine-c/src/spine/RegionAttachment.c b/spine-c/src/spine/RegionAttachment.c index c86caea0c..89aa1618e 100644 --- a/spine-c/src/spine/RegionAttachment.c +++ b/spine-c/src/spine/RegionAttachment.c @@ -33,9 +33,7 @@ void _spRegionAttachment_dispose (spAttachment* attachment) { spRegionAttachment* self = SUB_CAST(spRegionAttachment, attachment); - _spAttachment_deinit(attachment); - FREE(self); } diff --git a/spine-c/src/spine/SkeletonJson.c b/spine-c/src/spine/SkeletonJson.c index f0cafa318..3b9e4e1e4 100644 --- a/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/src/spine/SkeletonJson.c @@ -33,6 +33,8 @@ #include "Json.h" #include #include +#include +#include #include typedef struct { @@ -414,13 +416,19 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha spAttachment* attachment; const char* skinAttachmentName = attachmentMap->name; const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName); - const char* path = Json_getString(attachmentMap, "path", 0); + const char* path = Json_getString(attachmentMap, "path", attachmentName); const char* color; + int i; + Json* entry; const char* typeString = Json_getString(attachmentMap, "type", "region"); spAttachmentType type; if (strcmp(typeString, "region") == 0) type = SP_ATTACHMENT_REGION; + else if (strcmp(typeString, "mesh") == 0) + type = SP_ATTACHMENT_MESH; + else if (strcmp(typeString, "skinnedmesh") == 0) + type = SP_ATTACHMENT_SKINNED_MESH; else if (strcmp(typeString, "boundingbox") == 0) type = SP_ATTACHMENT_BOUNDING_BOX; else { @@ -441,35 +449,152 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha switch (attachment->type) { case SP_ATTACHMENT_REGION: { - spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment; - regionAttachment->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; - regionAttachment->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; - regionAttachment->scaleX = Json_getFloat(attachmentMap, "scaleX", 1); - regionAttachment->scaleY = Json_getFloat(attachmentMap, "scaleY", 1); - regionAttachment->rotation = Json_getFloat(attachmentMap, "rotation", 0); - regionAttachment->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; - regionAttachment->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; + spRegionAttachment* region = (spRegionAttachment*)attachment; + if (path) MALLOC_STR(region->path, path); + region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; + region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; + region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1); + region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1); + region->rotation = Json_getFloat(attachmentMap, "rotation", 0); + region->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; + region->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; color = Json_getString(attachmentMap, "color", 0); if (color) { - regionAttachment->r = toColor(color, 0); - regionAttachment->g = toColor(color, 1); - regionAttachment->b = toColor(color, 2); - regionAttachment->a = toColor(color, 3); + region->r = toColor(color, 0); + region->g = toColor(color, 1); + region->b = toColor(color, 2); + region->a = toColor(color, 3); } - spRegionAttachment_updateOffset(regionAttachment); + spRegionAttachment_updateOffset(region); + break; + } + case SP_ATTACHMENT_MESH: { + spMeshAttachment* mesh = (spMeshAttachment*)attachment; + + MALLOC_STR(mesh->path, path); + + entry = Json_getItem(attachmentMap, "vertices"); + mesh->verticesCount = entry->size; + mesh->vertices = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->vertices[i] = entry->valueFloat * self->scale; + + entry = Json_getItem(attachmentMap, "triangles"); + mesh->trianglesCount = entry->size; + mesh->triangles = MALLOC(int, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->triangles[i] = entry->valueInt; + + entry = Json_getItem(attachmentMap, "uvs"); + mesh->uvsCount = entry->size; + mesh->regionUVs = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->regionUVs[i] = entry->valueFloat; + + spMeshAttachment_updateUVs(mesh); + + color = Json_getString(attachmentMap, "color", 0); + if (color) { + mesh->r = toColor(color, 0); + mesh->g = toColor(color, 1); + mesh->b = toColor(color, 2); + mesh->a = toColor(color, 3); + } + + mesh->hullLength = Json_getFloat(attachmentMap, "hull", 0); + + entry = Json_getItem(attachmentMap, "edges"); + if (entry) { + mesh->edgesCount = entry->size; + mesh->edges = MALLOC(int, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->edges[i] = entry->valueInt; + } + + mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; + mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; + break; + } + case SP_ATTACHMENT_SKINNED_MESH: { + spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)attachment; + int verticesCount, b, w, nn; + float* vertices; + + MALLOC_STR(mesh->path, path); + + entry = Json_getItem(attachmentMap, "uvs"); + mesh->uvsCount = entry->size; + mesh->regionUVs = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->regionUVs[i] = entry->valueFloat; + + entry = Json_getItem(attachmentMap, "vertices"); + verticesCount = entry->size; + vertices = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + vertices[i] = entry->valueFloat; + + for (i = 0; i < verticesCount;) { + int boneCount = (int)vertices[i++]; + mesh->bonesCount += boneCount + 1; + mesh->weightsCount += boneCount * 3; + } + mesh->bones = MALLOC(int, mesh->bonesCount); + mesh->weights = MALLOC(float, mesh->weightsCount); + + for (i = 0, b = 0, w = 0; i < verticesCount;) { + int boneCount = (int)vertices[i++]; + mesh->bones[b++] = boneCount; + for (nn = i + boneCount * 4; i < nn;) { + mesh->bones[b++] = (int)vertices[i]; + mesh->weights[w++] = vertices[i + 1] * self->scale; + mesh->weights[w++] = vertices[i + 2] * self->scale; + mesh->weights[w++] = vertices[i + 3]; + i += 4; + } + } + + FREE(vertices); + + entry = Json_getItem(attachmentMap, "triangles"); + mesh->trianglesCount = entry->size; + mesh->triangles = MALLOC(int, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->triangles[i] = entry->valueInt; + + spSkinnedMeshAttachment_updateUVs(mesh); + + color = Json_getString(attachmentMap, "color", 0); + if (color) { + mesh->r = toColor(color, 0); + mesh->g = toColor(color, 1); + mesh->b = toColor(color, 2); + mesh->a = toColor(color, 3); + } + + mesh->hullLength = Json_getFloat(attachmentMap, "hull", 0); + + entry = Json_getItem(attachmentMap, "edges"); + if (entry) { + mesh->edgesCount = entry->size; + mesh->edges = MALLOC(int, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->edges[i] = entry->valueInt; + } + + mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; + mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; break; } case SP_ATTACHMENT_BOUNDING_BOX: { spBoundingBoxAttachment* box = (spBoundingBoxAttachment*)attachment; - Json* verticesArray = Json_getItem(attachmentMap, "vertices"); - Json* vertex; - int i; - box->verticesCount = verticesArray->size; - box->vertices = MALLOC(float, verticesArray->size); - for (vertex = verticesArray->child, i = 0; vertex; vertex = vertex->next, ++i) - box->vertices[i] = vertex->valueFloat * self->scale; + entry = Json_getItem(attachmentMap, "vertices"); + box->verticesCount = entry->size; + box->vertices = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + box->vertices[i] = entry->valueFloat * self->scale; break; } } diff --git a/spine-c/src/spine/SkinnedMeshAttachment.c b/spine-c/src/spine/SkinnedMeshAttachment.c new file mode 100644 index 000000000..f7a9c3040 --- /dev/null +++ b/spine-c/src/spine/SkinnedMeshAttachment.c @@ -0,0 +1,109 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * or (b) remove, delete, alter or obscure any trademarks or any copyright, + * trademark, patent or other intellectual property or proprietary rights + * notices on or in the Software, including any copy thereof. Redistributions + * in binary or source form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +void _spSkinnedMeshAttachment_dispose (spAttachment* attachment) { + spSkinnedMeshAttachment* self = SUB_CAST(spSkinnedMeshAttachment, attachment); + _spAttachment_deinit(attachment); + FREE(self->path); + FREE(self->bones); + FREE(self->weights); + FREE(self->regionUVs); + FREE(self->uvs); + FREE(self->triangles); + FREE(self->edges); + FREE(self); +} + +spSkinnedMeshAttachment* spSkinnedMeshAttachment_create (const char* name) { + spSkinnedMeshAttachment* self = NEW(spSkinnedMeshAttachment); + self->r = 1; + self->g = 1; + self->b = 1; + self->a = 1; + _spAttachment_init(SUPER(self), name, SP_ATTACHMENT_SKINNED_MESH, _spSkinnedMeshAttachment_dispose); + return self; +} + +void spSkinnedMeshAttachment_updateUVs (spSkinnedMeshAttachment* self) { + int i; + float width = self->regionU2 - self->regionU, height = self->regionV2 - self->regionV; + FREE(self->uvs); + self->uvs = MALLOC(float, self->uvsCount); + if (self->regionRotate) { + for (i = 0; i < self->uvsCount; i += 2) { + self->uvs[i] = self->regionU + self->regionUVs[i + 1] * width; + self->uvs[i + 1] = self->regionV + height - self->regionUVs[i] * height; + } + } else { + for (i = 0; i < self->uvsCount; i += 2) { + self->uvs[i] = self->regionU + self->regionUVs[i] * width; + self->uvs[i + 1] = self->regionV + self->regionUVs[i + 1] * height; + } + } +} + +void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, float x, float y, spSlot* slot, + float* worldVertices) { + int w = 0, v = 0, b = 0, f = 0; + spBone** skeletonBones = slot->skeleton->bones; + if (slot->attachmentVerticesCount == 0) { + for (; v < self->bonesCount; w += 2) { + float wx = 0, wy = 0; + int nn = self->bones[v] + v; + v++; + for (; v <= nn; v++, b += 3) { + spBone* bone = skeletonBones[self->bones[v]]; + float vx = self->weights[b], vy = self->weights[b + 1], weight = self->weights[b + 2]; + wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight; + wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight; + } + worldVertices[w] = wx + x; + worldVertices[w + 1] = wy + y; + } + } else { + float* ffd = slot->attachmentVertices; + for (; v < self->bonesCount; w += 2) { + float wx = 0, wy = 0; + int nn = self->bones[v] + v; + v++; + for (; v <= nn; v++, b += 3, f += 2) { + spBone* bone = skeletonBones[self->bones[v]]; + float vx = self->weights[b] + ffd[f], vy = self->weights[b + 1] + ffd[f + 1], weight = self->weights[b + 2]; + wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight; + wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight; + } + worldVertices[w] = wx + x; + worldVertices[w + 1] = wy + y; + } + } +} diff --git a/spine-c/src/spine/Slot.c b/spine-c/src/spine/Slot.c index ce6bf9105..32c0dd530 100644 --- a/spine-c/src/spine/Slot.c +++ b/spine-c/src/spine/Slot.c @@ -47,6 +47,7 @@ spSlot* spSlot_create (spSlotData* data, spSkeleton* skeleton, spBone* bone) { } void spSlot_dispose (spSlot* self) { + FREE(self->attachmentVertices); FREE(self); }