Added IK, refactoring.

Skeleton moved from Slot to Bone.
Attachments no longer take x,y to compute vertices.
Bezier curves are calculated up front.
This commit is contained in:
NathanSweet 2014-08-31 15:24:27 +02:00
parent 2d5b2cdb87
commit 593956b51d
32 changed files with 1297 additions and 363 deletions

View File

@ -45,25 +45,25 @@ typedef struct {
const char* const name;
float duration;
int timelineCount;
int timelinesCount;
spTimeline** timelines;
} spAnimation;
spAnimation* spAnimation_create (const char* name, int timelineCount);
spAnimation* spAnimation_create (const char* name, int timelinesCount);
void spAnimation_dispose (spAnimation* self);
/** Poses the skeleton at the specified time for this animation.
* @param lastTime The last time the animation was applied.
* @param events Any triggered events are added. */
void spAnimation_apply (const spAnimation* self, struct spSkeleton* skeleton, float lastTime, float time, int loop,
spEvent** events, int* eventCount);
spEvent** events, int* eventsCount);
/** Poses the skeleton at the specified time for this animation mixed with the current pose.
* @param lastTime The last time the animation was applied.
* @param events Any triggered events are added.
* @param alpha The amount of this animation that affects the current pose. */
void spAnimation_mix (const spAnimation* self, struct spSkeleton* skeleton, float lastTime, float time, int loop,
spEvent** events, int* eventCount, float alpha);
spEvent** events, int* eventsCount, float alpha);
#ifdef SPINE_SHORT_NAMES
typedef spAnimation Animation;
@ -83,7 +83,8 @@ typedef enum {
SP_TIMELINE_ATTACHMENT,
SP_TIMELINE_EVENT,
SP_TIMELINE_DRAWORDER,
SP_TIMELINE_FFD
SP_TIMELINE_FFD,
SP_TIMELINE_IKCONSTRAINT
} spTimelineType;
struct spTimeline {
@ -94,7 +95,7 @@ struct spTimeline {
void spTimeline_dispose (spTimeline* self);
void spTimeline_apply (const spTimeline* self, struct spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha);
int* eventsCount, float alpha);
#ifdef SPINE_SHORT_NAMES
typedef spTimeline Timeline;
@ -113,7 +114,7 @@ typedef spTimeline Timeline;
typedef struct {
spTimeline super;
float* curves; /* dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... */
float* curves; /* type, x, y, ... */
} spCurveTimeline;
void spCurveTimeline_setLinear (spCurveTimeline* self, int frameIndex);
@ -142,7 +143,7 @@ typedef struct spBaseTimeline {
int boneIndex;
} spRotateTimeline;
spRotateTimeline* spRotateTimeline_create (int frameCount);
spRotateTimeline* spRotateTimeline_create (int framesCount);
void spRotateTimeline_setFrame (spRotateTimeline* self, int frameIndex, float time, float angle);
@ -156,7 +157,7 @@ typedef spRotateTimeline RotateTimeline;
typedef struct spBaseTimeline spTranslateTimeline;
spTranslateTimeline* spTranslateTimeline_create (int frameCount);
spTranslateTimeline* spTranslateTimeline_create (int framesCount);
void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, float time, float x, float y);
@ -170,7 +171,7 @@ typedef spTranslateTimeline TranslateTimeline;
typedef struct spBaseTimeline spScaleTimeline;
spScaleTimeline* spScaleTimeline_create (int frameCount);
spScaleTimeline* spScaleTimeline_create (int framesCount);
void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time, float x, float y);
@ -189,7 +190,7 @@ typedef struct {
int slotIndex;
} spColorTimeline;
spColorTimeline* spColorTimeline_create (int frameCount);
spColorTimeline* spColorTimeline_create (int framesCount);
void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a);
@ -209,7 +210,7 @@ typedef struct {
const char** const attachmentNames;
} spAttachmentTimeline;
spAttachmentTimeline* spAttachmentTimeline_create (int frameCount);
spAttachmentTimeline* spAttachmentTimeline_create (int framesCount);
/* @param attachmentName May be 0. */
void spAttachmentTimeline_setFrame (spAttachmentTimeline* self, int frameIndex, float time, const char* attachmentName);
@ -229,7 +230,7 @@ typedef struct {
spEvent** const events;
} spEventTimeline;
spEventTimeline* spEventTimeline_create (int frameCount);
spEventTimeline* spEventTimeline_create (int framesCount);
void spEventTimeline_setFrame (spEventTimeline* self, int frameIndex, float time, spEvent* event);
@ -246,10 +247,10 @@ typedef struct {
int const framesCount;
float* const frames; /* time, ... */
const int** const drawOrders;
int const slotCount;
int const slotsCount;
} spDrawOrderTimeline;
spDrawOrderTimeline* spDrawOrderTimeline_create (int frameCount, int slotCount);
spDrawOrderTimeline* spDrawOrderTimeline_create (int framesCount, int slotsCount);
void spDrawOrderTimeline_setFrame (spDrawOrderTimeline* self, int frameIndex, float time, const int* drawOrder);
@ -271,7 +272,7 @@ typedef struct {
spAttachment* attachment;
} spFFDTimeline;
spFFDTimeline* spFFDTimeline_create (int frameCount, int frameVerticesCount);
spFFDTimeline* spFFDTimeline_create (int framesCount, int frameVerticesCount);
void spFFDTimeline_setFrame (spFFDTimeline* self, int frameIndex, float time, float* vertices);
@ -281,6 +282,28 @@ typedef spFFDTimeline FFDTimeline;
#define FFDTimeline_setFrame(...) spFFDTimeline_setFrame(__VA_ARGS__)
#endif
/**/
typedef struct {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, mix, bendDirection, ... */
int ikConstraintIndex;
} spIkConstraintTimeline;
spIkConstraintTimeline* spIkConstraintTimeline_create (int framesCount);
/* @param attachmentName May be 0. */
void spIkConstraintTimeline_setFrame (spIkConstraintTimeline* self, int frameIndex, float time, float mix, int bendDirection);
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraintTimeline IkConstraintTimeline;
#define IkConstraintTimeline_create(...) spIkConstraintTimeline_create(__VA_ARGS__)
#define IkConstraintTimeline_setFrame(...) spIkConstraintTimeline_setFrame(__VA_ARGS__)
#endif
/**/
#ifdef __cplusplus
}
#endif

View File

@ -67,7 +67,7 @@ struct spAnimationState {
float timeScale;
spAnimationStateListener listener;
int trackCount;
int tracksCount;
spTrackEntry** tracks;
void* rendererObject;

View File

@ -37,13 +37,17 @@
extern "C" {
#endif
struct spSkeleton;
typedef struct spBone spBone;
struct spBone {
spBoneData* const data;
struct spSkeleton* const skeleton;
spBone* const parent;
float x, y;
float rotation;
float rotation, rotationIK;
float scaleX, scaleY;
int/*bool*/flipX, flipY;
float const m00, m01, worldX; /* a b x */
float const m10, m11, worldY; /* c d y */
@ -54,12 +58,15 @@ struct spBone {
void spBone_setYDown (int/*bool*/yDown);
/* @param parent May be 0. */
spBone* spBone_create (spBoneData* data, spBone* parent);
spBone* spBone_create (spBoneData* data, struct spSkeleton* skeleton, spBone* parent);
void spBone_dispose (spBone* self);
void spBone_setToSetupPose (spBone* self);
void spBone_updateWorldTransform (spBone* self, int/*bool*/flipX, int/*bool*/flipY);
void spBone_updateWorldTransform (spBone* self);
void spBone_worldToLocal (spBone* self, float worldX, float worldY, float* localX, float* localY);
void spBone_localToWorld (spBone* self, float localX, float localY, float* worldX, float* worldY);
#ifdef SPINE_SHORT_NAMES
typedef spBone Bone;
@ -68,6 +75,8 @@ typedef spBone Bone;
#define Bone_dispose(...) spBone_dispose(__VA_ARGS__)
#define Bone_setToSetupPose(...) spBone_setToSetupPose(__VA_ARGS__)
#define Bone_updateWorldTransform(...) spBone_updateWorldTransform(__VA_ARGS__)
#define Bone_worldToLocal(...) spBone_worldToLocal(__VA_ARGS__)
#define Bone_localToWorld(...) spBone_localToWorld(__VA_ARGS__)
#endif
#ifdef __cplusplus

View File

@ -47,7 +47,7 @@ struct spBoundingBoxAttachment {
};
spBoundingBoxAttachment* spBoundingBoxAttachment_create (const char* name);
void spBoundingBoxAttachment_computeWorldVertices (spBoundingBoxAttachment* self, float x, float y, spBone* bone, float* vertices);
void spBoundingBoxAttachment_computeWorldVertices (spBoundingBoxAttachment* self, spBone* bone, float* vertices);
#ifdef SPINE_SHORT_NAMES
typedef spBoundingBoxAttachment BoundingBoxAttachment;

View File

@ -0,0 +1,73 @@
/******************************************************************************
* 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_IKCONSTRAINT_H_
#define SPINE_IKCONSTRAINT_H_
#include <spine/IkConstraintData.h>
#include <spine/Bone.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spSkeleton;
typedef struct spIkConstraint spIkConstraint;
struct spIkConstraint {
spIkConstraintData* const data;
int bonesCount;
spBone** bones;
spBone* target;
int bendDirection;
float mix;
};
spIkConstraint* spIkConstraint_create (spIkConstraintData* data, const struct spSkeleton* skeleton);
void spIkConstraint_dispose (spIkConstraint* self);
void spIkConstraint_apply (spIkConstraint* self);
void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha);
void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, float alpha);
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraint IkConstraint;
#define IkConstraint_create(...) spIkConstraint_create(__VA_ARGS__)
#define IkConstraint_dispose(...) spIkConstraint_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_IKCONSTRAINT_H_ */

View File

@ -0,0 +1,65 @@
/******************************************************************************
* 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_IKCONSTRAINTDATA_H_
#define SPINE_IKCONSTRAINTDATA_H_
#include <spine/BoneData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spIkConstraintData spIkConstraintData;
struct spIkConstraintData {
const char* const name;
int bonesCount;
spBoneData** bones;
spBoneData* target;
int bendDirection;
float mix;
};
spIkConstraintData* spIkConstraintData_create (const char* name);
void spIkConstraintData_dispose (spIkConstraintData* self);
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraintData IkConstraintData;
#define IkConstraintData_create(...) spIkConstraintData_create(__VA_ARGS__)
#define IkConstraintData_dispose(...) spIkConstraintData_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_IKCONSTRAINTDATA_H_ */

View File

@ -71,7 +71,7 @@ struct spMeshAttachment {
spMeshAttachment* spMeshAttachment_create (const char* name);
void spMeshAttachment_updateUVs (spMeshAttachment* self);
void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, float x, float y, spSlot* slot, float* worldVertices);
void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, spSlot* slot, float* worldVertices);
#ifdef SPINE_SHORT_NAMES
typedef spMeshAttachment MeshAttachment;

View File

@ -62,7 +62,7 @@ struct spRegionAttachment {
spRegionAttachment* spRegionAttachment_create (const char* name);
void spRegionAttachment_setUVs (spRegionAttachment* self, float u, float v, float u2, float v2, int/*bool*/rotate);
void spRegionAttachment_updateOffset (spRegionAttachment* self);
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, float x, float y, spBone* bone, float* vertices);
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, spBone* bone, float* vertices);
#ifdef SPINE_SHORT_NAMES
typedef spVertexIndex VertexIndex;

View File

@ -34,6 +34,7 @@
#include <spine/SkeletonData.h>
#include <spine/Slot.h>
#include <spine/Skin.h>
#include <spine/IkConstraint.h>
#ifdef __cplusplus
extern "C" {
@ -43,14 +44,17 @@ typedef struct spSkeleton spSkeleton;
struct spSkeleton {
spSkeletonData* const data;
int boneCount;
int bonesCount;
spBone** bones;
spBone* const root;
int slotCount;
int slotsCount;
spSlot** slots;
spSlot** drawOrder;
int ikConstraintsCount;
spIkConstraint** ikConstraints;
spSkin* const skin;
float r, g, b, a;
float time;
@ -61,6 +65,8 @@ struct spSkeleton {
spSkeleton* spSkeleton_create (spSkeletonData* data);
void spSkeleton_dispose (spSkeleton* self);
/* Caches information about bones and IK constraints. Must be called if bones or IK constraints are added or removed. */
void spSkeleton_updateCache (const spSkeleton* self);
void spSkeleton_updateWorldTransform (const spSkeleton* self);
void spSkeleton_setToSetupPose (const spSkeleton* self);
@ -92,6 +98,9 @@ spAttachment* spSkeleton_getAttachmentForSlotIndex (const spSkeleton* self, int
/* Returns 0 if the slot or attachment was not found. */
int spSkeleton_setAttachment (spSkeleton* self, const char* slotName, const char* attachmentName);
/* Returns 0 if the IK constraint was not found. */
spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* ikConstraintName);
void spSkeleton_update (spSkeleton* self, float deltaTime);
#ifdef SPINE_SHORT_NAMES

View File

@ -36,27 +36,35 @@
#include <spine/Skin.h>
#include <spine/EventData.h>
#include <spine/Animation.h>
#include <spine/IkConstraintData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int boneCount;
const char* version;
const char* hash;
float width, height;
int bonesCount;
spBoneData** bones;
int slotCount;
int slotsCount;
spSlotData** slots;
int skinCount;
int skinsCount;
spSkin** skins;
spSkin* defaultSkin;
int eventCount;
int eventsCount;
spEventData** events;
int animationCount;
int animationsCount;
spAnimation** animations;
int ikConstraintsCount;
spIkConstraintData** ikConstraints;
} spSkeletonData;
spSkeletonData* spSkeletonData_create ();
@ -74,6 +82,8 @@ spEventData* spSkeletonData_findEvent (const spSkeletonData* self, const char* e
spAnimation* spSkeletonData_findAnimation (const spSkeletonData* self, const char* animationName);
spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* ikConstraintName);
#ifdef SPINE_SHORT_NAMES
typedef spSkeletonData SkeletonData;
#define SkeletonData_create(...) spSkeletonData_create(__VA_ARGS__)

View File

@ -74,7 +74,7 @@ struct spSkinnedMeshAttachment {
spSkinnedMeshAttachment* spSkinnedMeshAttachment_create (const char* name);
void spSkinnedMeshAttachment_updateUVs (spSkinnedMeshAttachment* self);
void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, float x, float y, spSlot* bone, float* worldVertices);
void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, spSlot* slot, float* worldVertices);
#ifdef SPINE_SHORT_NAMES
typedef spSkinnedMeshAttachment SkinnedMeshAttachment;

View File

@ -39,11 +39,8 @@
extern "C" {
#endif
struct spSkeleton;
typedef struct spSlot {
spSlotData* const data;
struct spSkeleton* const skeleton;
spBone* const bone;
float r, g, b, a;
spAttachment* const attachment;
@ -53,7 +50,7 @@ typedef struct spSlot {
float* attachmentVertices;
} spSlot;
spSlot* spSlot_create (spSlotData* data, struct spSkeleton* skeleton, spBone* bone);
spSlot* spSlot_create (spSlotData* data, spBone* bone);
void spSlot_dispose (spSlot* self);
/* @param attachment May be 0 to clear the attachment for the slot. */

View File

@ -57,10 +57,24 @@
/* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const types. */
#define MALLOC_STR(TO,FROM) strcpy(CONST_CAST(char*, TO) = (char*)MALLOC(char, strlen(FROM) + 1), FROM)
#define PI 3.1415926535897932385f
#define DEG_RAD (PI / 180)
#define RAD_DEG (180 / PI)
#ifdef __STDC_VERSION__
#define FMOD(A,B) fmodf(A, B)
#define ATAN2(A,B) atan2f(A, B)
#define SIN(A) sinf(A)
#define COS(A) cosf(A)
#define SQRT(A) sqrtf(A)
#define ACOS(A) acosf(A)
#else
#define FMOD(A,B) (float)fmod(A, B)
#define ATAN2(A,B) (float)atan2(A, B)
#define COS(A) (float)cos(A)
#define SIN(A) (float)sin(A)
#define SQRT(A) (float)sqrt(A)
#define ACOS(A) (float)acos(A)
#endif
#include <stdlib.h>
@ -154,7 +168,7 @@ void _spAttachment_deinit (spAttachment* self);
void _spTimeline_init (spTimeline* self, spTimelineType type, /**/
void (*dispose) (spTimeline* self), /**/
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha));
int* eventsCount, float alpha));
void _spTimeline_deinit (spTimeline* self);
#ifdef SPINE_SHORT_NAMES
@ -164,10 +178,10 @@ void _spTimeline_deinit (spTimeline* self);
/**/
void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int frameCount, /**/
void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount, /**/
void (*dispose) (spTimeline* self), /**/
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha));
int* eventsCount, float alpha));
void _spCurveTimeline_deinit (spCurveTimeline* self);
#ifdef SPINE_SHORT_NAMES

View File

@ -29,20 +29,21 @@
*****************************************************************************/
#include <spine/Animation.h>
#include <spine/IkConstraint.h>
#include <limits.h>
#include <spine/extension.h>
spAnimation* spAnimation_create (const char* name, int timelineCount) {
spAnimation* spAnimation_create (const char* name, int timelinesCount) {
spAnimation* self = NEW(spAnimation);
MALLOC_STR(self->name, name);
self->timelineCount = timelineCount;
self->timelines = MALLOC(spTimeline*, timelineCount);
self->timelinesCount = timelinesCount;
self->timelines = MALLOC(spTimeline*, timelinesCount);
return self;
}
void spAnimation_dispose (spAnimation* self) {
int i;
for (i = 0; i < self->timelineCount; ++i)
for (i = 0; i < self->timelinesCount; ++i)
spTimeline_dispose(self->timelines[i]);
FREE(self->timelines);
FREE(self->name);
@ -50,8 +51,8 @@ void spAnimation_dispose (spAnimation* self) {
}
void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events,
int* eventCount) {
int i, n = self->timelineCount;
int* eventsCount) {
int i, n = self->timelinesCount;
if (loop && self->duration) {
time = FMOD(time, self->duration);
@ -59,12 +60,12 @@ void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float las
}
for (i = 0; i < n; ++i)
spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventCount, 1);
spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, 1);
}
void spAnimation_mix (const spAnimation* self, spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events,
int* eventCount, float alpha) {
int i, n = self->timelineCount;
int* eventsCount, float alpha) {
int i, n = self->timelinesCount;
if (loop && self->duration) {
time = FMOD(time, self->duration);
@ -72,21 +73,21 @@ void spAnimation_mix (const spAnimation* self, spSkeleton* skeleton, float lastT
}
for (i = 0; i < n; ++i)
spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventCount, alpha);
spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha);
}
/**/
typedef struct _spTimelineVtable {
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha);
int* eventsCount, float alpha);
void (*dispose) (spTimeline* self);
} _spTimelineVtable;
void _spTimeline_init (spTimeline* self, spTimelineType type, /**/
void (*dispose) (spTimeline* self), /**/
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha)) {
int* eventsCount, float alpha)) {
CONST_CAST(spTimelineType, self->type) = type;
CONST_CAST(_spTimelineVtable*, self->vtable) = NEW(_spTimelineVtable);
VTABLE(spTimeline, self)->dispose = dispose;
@ -102,22 +103,21 @@ void spTimeline_dispose (spTimeline* self) {
}
void spTimeline_apply (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha) {
VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventCount, alpha);
int* eventsCount, float alpha) {
VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventsCount, alpha);
}
/**/
static const float CURVE_LINEAR = 0;
static const float CURVE_STEPPED = -1;
static const int CURVE_SEGMENTS = 10;
static const float CURVE_LINEAR = 0, CURVE_STEPPED = 1, CURVE_BEZIER = 2;
static const int BEZIER_SEGMENTS = 10, BEZIER_SIZE = 10 * 2 - 1;
void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int frameCount, /**/
void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount, /**/
void (*dispose) (spTimeline* self), /**/
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha)) {
int* eventsCount, float alpha)) {
_spTimeline_init(SUPER(self), type, dispose, apply);
self->curves = CALLOC(float, (frameCount - 1) * 6);
self->curves = CALLOC(float, (framesCount - 1) * BEZIER_SIZE);
}
void _spCurveTimeline_deinit (spCurveTimeline* self) {
@ -126,61 +126,28 @@ void _spCurveTimeline_deinit (spCurveTimeline* self) {
}
void spCurveTimeline_setLinear (spCurveTimeline* self, int frameIndex) {
self->curves[frameIndex * 6] = CURVE_LINEAR;
self->curves[frameIndex * BEZIER_SIZE] = CURVE_LINEAR;
}
void spCurveTimeline_setStepped (spCurveTimeline* self, int frameIndex) {
self->curves[frameIndex * 6] = CURVE_STEPPED;
self->curves[frameIndex * BEZIER_SIZE] = CURVE_STEPPED;
}
void spCurveTimeline_setCurve (spCurveTimeline* self, int frameIndex, float cx1, float cy1, float cx2, float cy2) {
float subdiv_step = 1.0f / CURVE_SEGMENTS;
float subdiv_step2 = subdiv_step * subdiv_step;
float subdiv_step3 = subdiv_step2 * subdiv_step;
float pre1 = 3 * subdiv_step;
float pre2 = 3 * subdiv_step2;
float pre4 = 6 * subdiv_step2;
float pre5 = 6 * subdiv_step3;
float tmp1x = -cx1 * 2 + cx2;
float tmp1y = -cy1 * 2 + cy2;
float tmp2x = (cx1 - cx2) * 3 + 1;
float tmp2y = (cy1 - cy2) * 3 + 1;
int i = frameIndex * 6;
self->curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3;
self->curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3;
self->curves[i + 2] = tmp1x * pre4 + tmp2x * pre5;
self->curves[i + 3] = tmp1y * pre4 + tmp2y * pre5;
self->curves[i + 4] = tmp2x * pre5;
self->curves[i + 5] = tmp2y * pre5;
}
float subdiv1 = 1.0f / BEZIER_SEGMENTS, subdiv2 = subdiv1 * subdiv1, subdiv3 = subdiv2 * subdiv1;
float pre1 = 3 * subdiv1, pre2 = 3 * subdiv2, pre4 = 6 * subdiv2, pre5 = 6 * subdiv3;
float tmp1x = -cx1 * 2 + cx2, tmp1y = -cy1 * 2 + cy2, tmp2x = (cx1 - cx2) * 3 + 1, tmp2y = (cy1 - cy2) * 3 + 1;
float dfx = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv3, dfy = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv3;
float ddfx = tmp1x * pre4 + tmp2x * pre5, ddfy = tmp1y * pre4 + tmp2y * pre5;
float dddfx = tmp2x * pre5, dddfy = tmp2y * pre5;
float x = dfx, y = dfy;
float spCurveTimeline_getCurvePercent (const spCurveTimeline* self, int frameIndex, float percent) {
float dfy;
float ddfx;
float ddfy;
float dddfx;
float dddfy;
float x, y;
int i;
int curveIndex = frameIndex * 6;
float dfx = self->curves[curveIndex];
if (dfx == CURVE_LINEAR) return percent;
if (dfx == CURVE_STEPPED) return 0;
dfy = self->curves[curveIndex + 1];
ddfx = self->curves[curveIndex + 2];
ddfy = self->curves[curveIndex + 3];
dddfx = self->curves[curveIndex + 4];
dddfy = self->curves[curveIndex + 5];
x = dfx, y = dfy;
i = CURVE_SEGMENTS - 2;
while (1) {
if (x >= percent) {
float lastX = x - dfx;
float lastY = y - dfy;
return lastY + (y - lastY) * (percent - lastX) / (x - lastX);
}
if (i == 0) break;
i--;
int i = frameIndex * BEZIER_SIZE, n = i + BEZIER_SIZE - 1;
self->curves[i++] = CURVE_BEZIER;
for (; i < n; i += 2) {
self->curves[i] = x;
self->curves[i + 1] = y;
dfx += ddfx;
dfy += ddfy;
ddfx += dddfx;
@ -188,6 +155,31 @@ float spCurveTimeline_getCurvePercent (const spCurveTimeline* self, int frameInd
x += dfx;
y += dfy;
}
}
float spCurveTimeline_getCurvePercent (const spCurveTimeline* self, int frameIndex, float percent) {
float x, y;
int i = frameIndex * BEZIER_SIZE, start, n;
float type = self->curves[i];
if (type == CURVE_LINEAR) return percent;
if (type == CURVE_STEPPED) return 0;
i++;
x = 0;
for (start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) {
x = self->curves[i];
if (x >= percent) {
float prevX, prevY;
if (i == start) {
prevX = 0;
prevY = 0;
} else {
prevX = self->curves[i - 2];
prevY = self->curves[i - 1];
}
return prevY + (self->curves[i + 1] - prevY) * (percent - prevX) / (x - prevX);
}
}
y = self->curves[i - 1];
return y + (1 - y) * (percent - x) / (1 - x); /* Last point is 1,1. */
}
@ -208,6 +200,23 @@ static int binarySearch (float *values, int valuesLength, float target, int step
return 0;
}
/* @param target After the first and before the last entry. */
static int binarySearch1 (float *values, int valuesLength, float target) {
int low = 0, current;
int high = valuesLength - 2;
if (high == 0) return 1;
current = high >> 1;
while (1) {
if (values[(current + 1)] <= target)
low = current + 1;
else
high = current;
if (low == high) return low + 1;
current = (low + high) >> 1;
}
return 0;
}
/*static int linearSearch (float *values, int valuesLength, float target, int step) {
int i, last = valuesLength - step;
for (i = 0; i <= last; i += step) {
@ -227,13 +236,13 @@ void _spBaseTimeline_dispose (spTimeline* timeline) {
}
/* Many timelines have structure identical to struct spBaseTimeline and extend spCurveTimeline. **/
struct spBaseTimeline* _spBaseTimeline_create (int frameCount, spTimelineType type, int frameSize, /**/
struct spBaseTimeline* _spBaseTimeline_create (int framesCount, spTimelineType type, int frameSize, /**/
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha)) {
int* eventsCount, float alpha)) {
struct spBaseTimeline* self = NEW(struct spBaseTimeline);
_spCurveTimeline_init(SUPER(self), type, frameCount, _spBaseTimeline_dispose, apply);
_spCurveTimeline_init(SUPER(self), type, framesCount, _spBaseTimeline_dispose, apply);
CONST_CAST(int, self->framesCount) = frameCount * frameSize;
CONST_CAST(int, self->framesCount) = framesCount * frameSize;
CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount);
return self;
@ -241,14 +250,14 @@ struct spBaseTimeline* _spBaseTimeline_create (int frameCount, spTimelineType ty
/**/
static const int ROTATE_LAST_FRAME_TIME = -2;
static const int ROTATE_PREV_FRAME_TIME = -2;
static const int ROTATE_FRAME_VALUE = 1;
void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha) {
int* eventsCount, float alpha) {
spBone *bone;
int frameIndex;
float lastFrameValue, frameTime, percent, amount;
float prevFrameValue, frameTime, percent, amount;
spRotateTimeline* self = SUB_CAST(spRotateTimeline, timeline);
@ -268,17 +277,17 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
/* Interpolate between the previous frame and the current frame. */
frameIndex = binarySearch(self->frames, self->framesCount, time, 2);
lastFrameValue = self->frames[frameIndex - 1];
prevFrameValue = self->frames[frameIndex - 1];
frameTime = self->frames[frameIndex];
percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
percent = spCurveTimeline_getCurvePercent(SUPER(self), frameIndex / 2 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_PREV_FRAME_TIME] - frameTime);
percent = spCurveTimeline_getCurvePercent(SUPER(self), (frameIndex >> 1) - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
amount = self->frames[frameIndex + ROTATE_FRAME_VALUE] - lastFrameValue;
amount = self->frames[frameIndex + ROTATE_FRAME_VALUE] - prevFrameValue;
while (amount > 180)
amount -= 360;
while (amount < -180)
amount += 360;
amount = bone->data->rotation + (lastFrameValue + amount * percent) - bone->rotation;
amount = bone->data->rotation + (prevFrameValue + amount * percent) - bone->rotation;
while (amount > 180)
amount -= 360;
while (amount < -180)
@ -286,8 +295,8 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
bone->rotation += amount * alpha;
}
spRotateTimeline* spRotateTimeline_create (int frameCount) {
return _spBaseTimeline_create(frameCount, SP_TIMELINE_ROTATE, 2, _spRotateTimeline_apply);
spRotateTimeline* spRotateTimeline_create (int framesCount) {
return _spBaseTimeline_create(framesCount, SP_TIMELINE_ROTATE, 2, _spRotateTimeline_apply);
}
void spRotateTimeline_setFrame (spRotateTimeline* self, int frameIndex, float time, float angle) {
@ -298,15 +307,15 @@ void spRotateTimeline_setFrame (spRotateTimeline* self, int frameIndex, float ti
/**/
static const int TRANSLATE_LAST_FRAME_TIME = -3;
static const int TRANSLATE_PREV_FRAME_TIME = -3;
static const int TRANSLATE_FRAME_X = 1;
static const int TRANSLATE_FRAME_Y = 2;
void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
spEvent** firedEvents, int* eventCount, float alpha) {
spEvent** firedEvents, int* eventsCount, float alpha) {
spBone *bone;
int frameIndex;
float lastFrameX, lastFrameY, frameTime, percent;
float prevFrameX, prevFrameY, frameTime, percent;
spTranslateTimeline* self = SUB_CAST(spTranslateTimeline, timeline);
@ -322,20 +331,20 @@ void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto
/* Interpolate between the previous frame and the current frame. */
frameIndex = binarySearch(self->frames, self->framesCount, time, 3);
lastFrameX = self->frames[frameIndex - 2];
lastFrameY = self->frames[frameIndex - 1];
prevFrameX = self->frames[frameIndex - 2];
prevFrameY = self->frames[frameIndex - 1];
frameTime = self->frames[frameIndex];
percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime);
percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_PREV_FRAME_TIME] - frameTime);
percent = spCurveTimeline_getCurvePercent(SUPER(self), frameIndex / 3 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
bone->x += (bone->data->x + lastFrameX + (self->frames[frameIndex + TRANSLATE_FRAME_X] - lastFrameX) * percent - bone->x)
bone->x += (bone->data->x + prevFrameX + (self->frames[frameIndex + TRANSLATE_FRAME_X] - prevFrameX) * percent - bone->x)
* alpha;
bone->y += (bone->data->y + lastFrameY + (self->frames[frameIndex + TRANSLATE_FRAME_Y] - lastFrameY) * percent - bone->y)
bone->y += (bone->data->y + prevFrameY + (self->frames[frameIndex + TRANSLATE_FRAME_Y] - prevFrameY) * percent - bone->y)
* alpha;
}
spTranslateTimeline* spTranslateTimeline_create (int frameCount) {
return _spBaseTimeline_create(frameCount, SP_TIMELINE_TRANSLATE, 3, _spTranslateTimeline_apply);
spTranslateTimeline* spTranslateTimeline_create (int framesCount) {
return _spBaseTimeline_create(framesCount, SP_TIMELINE_TRANSLATE, 3, _spTranslateTimeline_apply);
}
void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, float time, float x, float y) {
@ -348,10 +357,10 @@ void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, fl
/**/
void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha) {
int* eventsCount, float alpha) {
spBone *bone;
int frameIndex;
float lastFrameX, lastFrameY, frameTime, percent;
float prevFrameX, prevFrameY, frameTime, percent;
spScaleTimeline* self = SUB_CAST(spScaleTimeline, timeline);
@ -366,20 +375,20 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
/* Interpolate between the previous frame and the current frame. */
frameIndex = binarySearch(self->frames, self->framesCount, time, 3);
lastFrameX = self->frames[frameIndex - 2];
lastFrameY = self->frames[frameIndex - 1];
prevFrameX = self->frames[frameIndex - 2];
prevFrameY = self->frames[frameIndex - 1];
frameTime = self->frames[frameIndex];
percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime);
percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_PREV_FRAME_TIME] - frameTime);
percent = spCurveTimeline_getCurvePercent(SUPER(self), frameIndex / 3 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
bone->scaleX += (bone->data->scaleX - 1 + lastFrameX + (self->frames[frameIndex + TRANSLATE_FRAME_X] - lastFrameX) * percent
bone->scaleX += (bone->data->scaleX - 1 + prevFrameX + (self->frames[frameIndex + TRANSLATE_FRAME_X] - prevFrameX) * percent
- bone->scaleX) * alpha;
bone->scaleY += (bone->data->scaleY - 1 + lastFrameY + (self->frames[frameIndex + TRANSLATE_FRAME_Y] - lastFrameY) * percent
bone->scaleY += (bone->data->scaleY - 1 + prevFrameY + (self->frames[frameIndex + TRANSLATE_FRAME_Y] - prevFrameY) * percent
- bone->scaleY) * alpha;
}
spScaleTimeline* spScaleTimeline_create (int frameCount) {
return _spBaseTimeline_create(frameCount, SP_TIMELINE_SCALE, 3, _spScaleTimeline_apply);
spScaleTimeline* spScaleTimeline_create (int framesCount) {
return _spBaseTimeline_create(framesCount, SP_TIMELINE_SCALE, 3, _spScaleTimeline_apply);
}
void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time, float x, float y) {
@ -388,17 +397,17 @@ void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time
/**/
static const int COLOR_LAST_FRAME_TIME = -5;
static const int COLOR_PREV_FRAME_TIME = -5;
static const int COLOR_FRAME_R = 1;
static const int COLOR_FRAME_G = 2;
static const int COLOR_FRAME_B = 3;
static const int COLOR_FRAME_A = 4;
void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha) {
int* eventsCount, float alpha) {
spSlot *slot;
int frameIndex;
float lastFrameR, lastFrameG, lastFrameB, lastFrameA, percent, frameTime;
float prevFrameR, prevFrameG, prevFrameB, prevFrameA, percent, frameTime;
float r, g, b, a;
spColorTimeline* self = (spColorTimeline*)timeline;
@ -414,18 +423,18 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
} else {
/* Interpolate between the previous frame and the current frame. */
frameIndex = binarySearch(self->frames, self->framesCount, time, 5);
lastFrameR = self->frames[frameIndex - 4];
lastFrameG = self->frames[frameIndex - 3];
lastFrameB = self->frames[frameIndex - 2];
lastFrameA = self->frames[frameIndex - 1];
prevFrameR = self->frames[frameIndex - 4];
prevFrameG = self->frames[frameIndex - 3];
prevFrameB = self->frames[frameIndex - 2];
prevFrameA = self->frames[frameIndex - 1];
frameTime = self->frames[frameIndex];
percent = 1 - (time - frameTime) / (self->frames[frameIndex + COLOR_LAST_FRAME_TIME] - frameTime);
percent = 1 - (time - frameTime) / (self->frames[frameIndex + COLOR_PREV_FRAME_TIME] - frameTime);
percent = spCurveTimeline_getCurvePercent(SUPER(self), frameIndex / 5 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
r = lastFrameR + (self->frames[frameIndex + COLOR_FRAME_R] - lastFrameR) * percent;
g = lastFrameG + (self->frames[frameIndex + COLOR_FRAME_G] - lastFrameG) * percent;
b = lastFrameB + (self->frames[frameIndex + COLOR_FRAME_B] - lastFrameB) * percent;
a = lastFrameA + (self->frames[frameIndex + COLOR_FRAME_A] - lastFrameA) * percent;
r = prevFrameR + (self->frames[frameIndex + COLOR_FRAME_R] - prevFrameR) * percent;
g = prevFrameG + (self->frames[frameIndex + COLOR_FRAME_G] - prevFrameG) * percent;
b = prevFrameB + (self->frames[frameIndex + COLOR_FRAME_B] - prevFrameB) * percent;
a = prevFrameA + (self->frames[frameIndex + COLOR_FRAME_A] - prevFrameA) * percent;
}
slot = skeleton->slots[self->slotIndex];
if (alpha < 1) {
@ -441,8 +450,8 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
}
}
spColorTimeline* spColorTimeline_create (int frameCount) {
return (spColorTimeline*)_spBaseTimeline_create(frameCount, SP_TIMELINE_COLOR, 5, _spColorTimeline_apply);
spColorTimeline* spColorTimeline_create (int framesCount) {
return (spColorTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_COLOR, 5, _spColorTimeline_apply);
}
void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a) {
@ -457,17 +466,20 @@ void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time
/**/
void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
spEvent** firedEvents, int* eventCount, float alpha) {
spEvent** firedEvents, int* eventsCount, float alpha) {
int frameIndex;
const char* attachmentName;
spAttachmentTimeline* self = (spAttachmentTimeline*)timeline;
if (time < self->frames[0]) return; /* Time is before first frame. */
if (time < self->frames[0]) {
if (lastTime > time) _spAttachmentTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, 0, 0, 0);
return;
} else if (lastTime > time) /**/
lastTime = -1;
if (time >= self->frames[self->framesCount - 1]) /* Time is after last frame. */
frameIndex = self->framesCount - 1;
else
frameIndex = binarySearch(self->frames, self->framesCount, time, 1) - 1;
frameIndex = time >= self->frames[self->framesCount - 1] ?
self->framesCount - 1 : binarySearch1(self->frames, self->framesCount, time) - 1;
if (self->frames[frameIndex] <= lastTime) return;
attachmentName = self->attachmentNames[frameIndex];
spSlot_setAttachment(skeleton->slots[self->slotIndex],
@ -487,13 +499,13 @@ void _spAttachmentTimeline_dispose (spTimeline* timeline) {
FREE(self);
}
spAttachmentTimeline* spAttachmentTimeline_create (int frameCount) {
spAttachmentTimeline* spAttachmentTimeline_create (int framesCount) {
spAttachmentTimeline* self = NEW(spAttachmentTimeline);
_spTimeline_init(SUPER(self), SP_TIMELINE_ATTACHMENT, _spAttachmentTimeline_dispose, _spAttachmentTimeline_apply);
CONST_CAST(int, self->framesCount) = frameCount;
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, frameCount);
CONST_CAST(int, self->framesCount) = framesCount;
CONST_CAST(float*, self->frames) = CALLOC(float, framesCount);
CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, framesCount);
return self;
}
@ -512,13 +524,13 @@ void spAttachmentTimeline_setFrame (spAttachmentTimeline* self, int frameIndex,
/** Fires events for frames > lastTime and <= time. */
void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha) {
int* eventsCount, float alpha) {
spEventTimeline* self = (spEventTimeline*)timeline;
int frameIndex;
if (!firedEvents) return;
if (lastTime > time) { /* Fire events after last time for looped animations. */
_spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventCount, alpha);
_spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventsCount, alpha);
lastTime = -1;
} else if (lastTime >= self->frames[self->framesCount - 1]) /* Last time is after last frame. */
return;
@ -528,7 +540,7 @@ void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
frameIndex = 0;
else {
float frame;
frameIndex = binarySearch(self->frames, self->framesCount, lastTime, 1);
frameIndex = binarySearch1(self->frames, self->framesCount, lastTime);
frame = self->frames[frameIndex];
while (frameIndex > 0) { /* Fire multiple events with the same frame. */
if (self->frames[frameIndex - 1] != frame) break;
@ -536,8 +548,8 @@ void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
}
}
for (; frameIndex < self->framesCount && time >= self->frames[frameIndex]; ++frameIndex) {
firedEvents[*eventCount] = self->events[frameIndex];
(*eventCount)++;
firedEvents[*eventsCount] = self->events[frameIndex];
(*eventsCount)++;
}
}
@ -554,13 +566,13 @@ void _spEventTimeline_dispose (spTimeline* timeline) {
FREE(self);
}
spEventTimeline* spEventTimeline_create (int frameCount) {
spEventTimeline* spEventTimeline_create (int framesCount) {
spEventTimeline* self = NEW(spEventTimeline);
_spTimeline_init(SUPER(self), SP_TIMELINE_EVENT, _spEventTimeline_dispose, _spEventTimeline_apply);
CONST_CAST(int, self->framesCount) = frameCount;
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
CONST_CAST(spEvent**, self->events) = CALLOC(spEvent*, frameCount);
CONST_CAST(int, self->framesCount) = framesCount;
CONST_CAST(float*, self->frames) = CALLOC(float, framesCount);
CONST_CAST(spEvent**, self->events) = CALLOC(spEvent*, framesCount);
return self;
}
@ -575,7 +587,7 @@ void spEventTimeline_setFrame (spEventTimeline* self, int frameIndex, float time
/**/
void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
spEvent** firedEvents, int* eventCount, float alpha) {
spEvent** firedEvents, int* eventsCount, float alpha) {
int i;
int frameIndex;
const int* drawOrderToSetupIndex;
@ -586,13 +598,13 @@ void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto
if (time >= self->frames[self->framesCount - 1]) /* Time is after last frame. */
frameIndex = self->framesCount - 1;
else
frameIndex = binarySearch(self->frames, self->framesCount, time, 1) - 1;
frameIndex = binarySearch1(self->frames, self->framesCount, time) - 1;
drawOrderToSetupIndex = self->drawOrders[frameIndex];
if (!drawOrderToSetupIndex)
memcpy(skeleton->drawOrder, skeleton->slots, self->slotCount * sizeof(int));
memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(int));
else {
for (i = 0; i < self->slotCount; ++i)
for (i = 0; i < self->slotsCount; ++i)
skeleton->drawOrder[i] = skeleton->slots[drawOrderToSetupIndex[i]];
}
}
@ -610,14 +622,14 @@ void _spDrawOrderTimeline_dispose (spTimeline* timeline) {
FREE(self);
}
spDrawOrderTimeline* spDrawOrderTimeline_create (int frameCount, int slotCount) {
spDrawOrderTimeline* spDrawOrderTimeline_create (int framesCount, int slotsCount) {
spDrawOrderTimeline* self = NEW(spDrawOrderTimeline);
_spTimeline_init(SUPER(self), SP_TIMELINE_DRAWORDER, _spDrawOrderTimeline_dispose, _spDrawOrderTimeline_apply);
CONST_CAST(int, self->framesCount) = frameCount;
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
CONST_CAST(int**, self->drawOrders) = CALLOC(int*, frameCount);
CONST_CAST(int, self->slotCount) = slotCount;
CONST_CAST(int, self->framesCount) = framesCount;
CONST_CAST(float*, self->frames) = CALLOC(float, framesCount);
CONST_CAST(int**, self->drawOrders) = CALLOC(int*, framesCount);
CONST_CAST(int, self->slotsCount) = slotsCount;
return self;
}
@ -629,15 +641,15 @@ void spDrawOrderTimeline_setFrame (spDrawOrderTimeline* self, int frameIndex, fl
if (!drawOrder)
self->drawOrders[frameIndex] = 0;
else {
self->drawOrders[frameIndex] = MALLOC(int, self->slotCount);
memcpy(CONST_CAST(int*, self->drawOrders[frameIndex]), drawOrder, self->slotCount * sizeof(int));
self->drawOrders[frameIndex] = MALLOC(int, self->slotsCount);
memcpy(CONST_CAST(int*, self->drawOrders[frameIndex]), drawOrder, self->slotsCount * sizeof(int));
}
}
/**/
void _spFFDTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventCount, float alpha) {
int* eventsCount, float alpha) {
int frameIndex, i;
float percent, frameTime;
const float* prevVertices;
@ -674,7 +686,7 @@ void _spFFDTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, flo
}
/* Interpolate between the previous frame and the current frame. */
frameIndex = binarySearch(self->frames, self->framesCount, time, 1);
frameIndex = binarySearch1(self->frames, self->framesCount, time);
frameTime = self->frames[frameIndex];
percent = 1 - (time - frameTime) / (self->frames[frameIndex - 1] - frameTime);
percent = spCurveTimeline_getCurvePercent(SUPER(self), frameIndex - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
@ -708,12 +720,12 @@ void _spFFDTimeline_dispose (spTimeline* timeline) {
FREE(self);
}
spFFDTimeline* spFFDTimeline_create (int frameCount, int frameVerticesCount) {
spFFDTimeline* spFFDTimeline_create (int framesCount, int frameVerticesCount) {
spFFDTimeline* self = NEW(spFFDTimeline);
_spCurveTimeline_init(SUPER(self), SP_TIMELINE_FFD, frameCount, _spFFDTimeline_dispose, _spFFDTimeline_apply);
CONST_CAST(int, self->framesCount) = frameCount;
_spCurveTimeline_init(SUPER(self), SP_TIMELINE_FFD, framesCount, _spFFDTimeline_dispose, _spFFDTimeline_apply);
CONST_CAST(int, self->framesCount) = framesCount;
CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount);
CONST_CAST(float**, self->frameVertices) = CALLOC(float*, frameCount);
CONST_CAST(float**, self->frameVertices) = CALLOC(float*, framesCount);
CONST_CAST(int, self->frameVerticesCount) = frameVerticesCount;
return self;
}
@ -729,3 +741,49 @@ void spFFDTimeline_setFrame (spFFDTimeline* self, int frameIndex, float time, fl
memcpy(CONST_CAST(float*, self->frameVertices[frameIndex]), vertices, self->frameVerticesCount * sizeof(float));
}
}
/**/
static const int IKCONSTRAINT_PREV_FRAME_TIME = -3;
static const int IKCONSTRAINT_FRAME_MIX = 1;
static const int IKCONSTRAINT_FRAME_BEND_DIRECTION = 2;
void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
spEvent** firedEvents, int* eventsCount, float alpha) {
int frameIndex;
spIkConstraint* ikConstraint;
spIkConstraintTimeline* self = (spIkConstraintTimeline*)timeline;
if (time < self->frames[0]) return; /* Time is before first frame. */
ikConstraint = skeleton->ikConstraints[self->ikConstraintIndex];
if (time >= self->frames[self->framesCount - 3]) { /* Time is after last frame. */
ikConstraint->mix += (self->frames[self->framesCount - 2] - ikConstraint->mix) * alpha;
ikConstraint->bendDirection = (int)self->frames[self->framesCount - 1];
return;
}
/* Interpolate between the previous frame and the current frame. */
frameIndex = binarySearch(self->frames, self->framesCount, time, 3);
float prevFrameMix = self->frames[frameIndex - 2];
float frameTime = self->frames[frameIndex];
float percent = 1 - (time - frameTime) / (self->frames[frameIndex + IKCONSTRAINT_PREV_FRAME_TIME] - frameTime);
percent = spCurveTimeline_getCurvePercent(SUPER(self), frameIndex / 3 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
float mix = prevFrameMix + (self->frames[frameIndex + IKCONSTRAINT_FRAME_MIX] - prevFrameMix) * percent;
ikConstraint->mix += (mix - ikConstraint->mix) * alpha;
ikConstraint->bendDirection = (int)self->frames[frameIndex + IKCONSTRAINT_FRAME_BEND_DIRECTION];
}
spIkConstraintTimeline* spIkConstraintTimeline_create (int framesCount) {
return (spIkConstraintTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_IKCONSTRAINT, 3, _spIkConstraintTimeline_apply);
}
void spIkConstraintTimeline_setFrame (spIkConstraintTimeline* self, int frameIndex, float time, float mix, int bendDirection) {
frameIndex *= 3;
self->frames[frameIndex] = time;
self->frames[frameIndex + 1] = mix;
self->frames[frameIndex + 2] = bendDirection;
}

View File

@ -80,7 +80,7 @@ void spAnimationState_dispose (spAnimationState* self) {
int i;
_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
FREE(internal->events);
for (i = 0; i < self->trackCount; ++i)
for (i = 0; i < self->tracksCount; ++i)
_spAnimationState_disposeAllEntries(self, self->tracks[i]);
FREE(self->tracks);
FREE(self);
@ -92,7 +92,7 @@ void spAnimationState_update (spAnimationState* self, float delta) {
int i;
float previousDelta;
delta *= self->timeScale;
for (i = 0; i < self->trackCount; ++i) {
for (i = 0; i < self->tracksCount; ++i) {
spTrackEntry* current = self->tracks[i];
if (!current) continue;
@ -117,15 +117,15 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
int i, ii;
int eventCount;
int eventsCount;
int entryChanged;
float time;
spTrackEntry* previous;
for (i = 0; i < self->trackCount; ++i) {
for (i = 0; i < self->tracksCount; ++i) {
spTrackEntry* current = self->tracks[i];
if (!current) continue;
eventCount = 0;
eventsCount = 0;
time = current->time;
if (!current->loop && time > current->endTime) time = current->endTime;
@ -134,10 +134,10 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
if (!previous) {
if (current->mix == 1) {
spAnimation_apply(current->animation, skeleton, current->lastTime, time,
current->loop, internal->events, &eventCount);
current->loop, internal->events, &eventsCount);
} else {
spAnimation_mix(current->animation, skeleton, current->lastTime, time,
current->loop, internal->events, &eventCount, current->mix);
current->loop, internal->events, &eventsCount, current->mix);
}
} else {
float alpha = current->mixTime / current->mixDuration * current->mix;
@ -152,11 +152,11 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
current->previous = 0;
}
spAnimation_mix(current->animation, skeleton, current->lastTime, time,
current->loop, internal->events, &eventCount, alpha);
current->loop, internal->events, &eventsCount, alpha);
}
entryChanged = 0;
for (ii = 0; ii < eventCount; ++ii) {
for (ii = 0; ii < eventsCount; ++ii) {
spEvent* event = internal->events[ii];
if (current->listener) {
current->listener(self, i, SP_ANIMATION_EVENT, event, 0);
@ -195,14 +195,14 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
void spAnimationState_clearTracks (spAnimationState* self) {
int i;
for (i = 0; i < self->trackCount; ++i)
for (i = 0; i < self->tracksCount; ++i)
spAnimationState_clearTrack(self, i);
self->trackCount = 0;
self->tracksCount = 0;
}
void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) {
spTrackEntry* current;
if (trackIndex >= self->trackCount) return;
if (trackIndex >= self->tracksCount) return;
current = self->tracks[trackIndex];
if (!current) return;
@ -216,12 +216,12 @@ void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) {
spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index) {
spTrackEntry** newTracks;
if (index < self->trackCount) return self->tracks[index];
if (index < self->tracksCount) return self->tracks[index];
newTracks = CALLOC(spTrackEntry*, index + 1);
memcpy(newTracks, self->tracks, self->trackCount * sizeof(spTrackEntry*));
memcpy(newTracks, self->tracks, self->tracksCount * sizeof(spTrackEntry*));
FREE(self->tracks);
self->tracks = newTracks;
self->trackCount = index + 1;
self->tracksCount = index + 1;
return 0;
}
@ -317,6 +317,6 @@ spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIn
}
spTrackEntry* spAnimationState_getCurrent (spAnimationState* self, int trackIndex) {
if (trackIndex >= self->trackCount) return 0;
if (trackIndex >= self->tracksCount) return 0;
return self->tracks[trackIndex];
}

View File

@ -37,9 +37,10 @@ void spBone_setYDown (int value) {
yDown = value;
}
spBone* spBone_create (spBoneData* data, spBone* parent) {
spBone* spBone_create (spBoneData* data, spSkeleton* skeleton, spBone* parent) {
spBone* self = NEW(spBone);
CONST_CAST(spBoneData*, self->data) = data;
CONST_CAST(spSkeleton*, self->skeleton) = skeleton;
CONST_CAST(spBone*, self->parent) = parent;
spBone_setToSetupPose(self);
return self;
@ -49,15 +50,7 @@ void spBone_dispose (spBone* self) {
FREE(self);
}
void spBone_setToSetupPose (spBone* self) {
self->x = self->data->x;
self->y = self->data->y;
self->rotation = self->data->rotation;
self->scaleX = self->data->scaleX;
self->scaleY = self->data->scaleY;
}
void spBone_updateWorldTransform (spBone* self, int flipX, int flipY) {
void spBone_updateWorldTransform (spBone* self) {
float radians, cosine, sine;
if (self->parent) {
CONST_CAST(float, self->worldX) = self->x * self->parent->m00 + self->y * self->parent->m01 + self->parent->worldX;
@ -70,32 +63,55 @@ void spBone_updateWorldTransform (spBone* self, int flipX, int flipY) {
CONST_CAST(float, self->worldScaleY) = self->scaleY;
}
CONST_CAST(float, self->worldRotation) =
self->data->inheritRotation ? self->parent->worldRotation + self->rotation : self->rotation;
self->data->inheritRotation ? self->parent->worldRotation + self->rotationIK : self->rotationIK;
} else {
CONST_CAST(float, self->worldX) = flipX ? -self->x : self->x;
CONST_CAST(float, self->worldY) = flipY != yDown ? -self->y : self->y;
CONST_CAST(float, self->worldX) = self->flipX ? -self->x : self->x;
CONST_CAST(float, self->worldY) = self->flipY != yDown ? -self->y : self->y;
CONST_CAST(float, self->worldScaleX) = self->scaleX;
CONST_CAST(float, self->worldScaleY) = self->scaleY;
CONST_CAST(float, self->worldRotation) = self->rotation;
CONST_CAST(float, self->worldRotation) = self->rotationIK;
}
radians = (float)(self->worldRotation * 3.1415926535897932385 / 180);
#ifdef __STDC_VERSION__
cosine = cosf(radians);
sine = sinf(radians);
#else
cosine = (float)cos(radians);
sine = (float)sin(radians);
#endif
CONST_CAST(float, self->m00) = cosine * self->worldScaleX;
CONST_CAST(float, self->m10) = sine * self->worldScaleX;
CONST_CAST(float, self->m01) = -sine * self->worldScaleY;
CONST_CAST(float, self->m11) = cosine * self->worldScaleY;
if (flipX) {
CONST_CAST(float, self->m00) = -self->m00;
CONST_CAST(float, self->m01) = -self->m01;
radians = self->worldRotation * DEG_RAD;
cosine = COS(radians);
sine = SIN(radians);
if (self->flipX) {
CONST_CAST(float, self->m00) = -cosine * self->worldScaleX;
CONST_CAST(float, self->m01) = sine * self->worldScaleY;
} else {
CONST_CAST(float, self->m00) = cosine * self->worldScaleX;
CONST_CAST(float, self->m01) = -sine * self->worldScaleY;
}
if (flipY != yDown) {
CONST_CAST(float, self->m10) = -self->m10;
CONST_CAST(float, self->m11) = -self->m11;
if (self->flipY != yDown) {
CONST_CAST(float, self->m10) = -sine * self->worldScaleX;
CONST_CAST(float, self->m11) = -cosine * self->worldScaleY;
} else {
CONST_CAST(float, self->m10) = sine * self->worldScaleX;
CONST_CAST(float, self->m11) = cosine * self->worldScaleY;
}
}
void spBone_setToSetupPose (spBone* self) {
self->x = self->data->x;
self->y = self->data->y;
self->rotation = self->data->rotation;
self->rotationIK = self->rotation;
self->scaleX = self->data->scaleX;
self->scaleY = self->data->scaleY;
}
void spBone_worldToLocal (spBone* self, float worldX, float worldY, float* localX, float* localY) {
float dx = worldX - self->worldX, dy = worldY - self->worldY;
float m00 = self->m00, m11 = self->m11;
if (self->flipX != (self->flipY != yDown)) {
m00 *= -1;
m11 *= -1;
}
float invDet = 1 / (m00 * m11 - self->m01 * self->m10);
*localX = (dx * m00 * invDet - dy * self->m01 * invDet);
*localY = (dy * m11 * invDet - dx * self->m10 * invDet);
}
void spBone_localToWorld (spBone* self, float localX, float localY, float* worldX, float* worldY) {
*worldX = localX * self->m00 + localY * self->m01 + self->worldX;
*worldY = localX * self->m10 + localY * self->m11 + self->worldY;
}

View File

@ -46,13 +46,11 @@ spBoundingBoxAttachment* spBoundingBoxAttachment_create (const char* name) {
return self;
}
void spBoundingBoxAttachment_computeWorldVertices (spBoundingBoxAttachment* self, float x, float y, spBone* bone, float* worldVertices) {
void spBoundingBoxAttachment_computeWorldVertices (spBoundingBoxAttachment* self, spBone* bone, float* worldVertices) {
int i;
float px, py;
float* vertices = self->vertices;
x += bone->worldX;
y += bone->worldY;
float x = bone->skeleton->x + bone->worldX, y = bone->skeleton->y + bone->worldY;
for (i = 0; i < self->verticesCount; i += 2) {
px = vertices[i];
py = vertices[i + 1];

View File

@ -0,0 +1,129 @@
/******************************************************************************
* 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 <spine/IkConstraint.h>
#include <spine/Skeleton.h>
#include <spine/extension.h>
spIkConstraint* spIkConstraint_create (spIkConstraintData* data, const spSkeleton* skeleton) {
int i;
spIkConstraint* self = NEW(spIkConstraint);
CONST_CAST(spIkConstraintData*, self->data) = data;
self->bendDirection = data->bendDirection;
self->mix = data->mix;
self->bonesCount = self->data->bonesCount;
self->bones = MALLOC(spBone*, self->bonesCount);
for (i = 0; i < self->bonesCount; ++i)
self->bones[i] = spSkeleton_findBone(skeleton, self->data->bones[i]->name);
self->target = spSkeleton_findBone(skeleton, self->data->target->name);
return self;
}
void spIkConstraint_dispose (spIkConstraint* self) {
FREE(self->bones);
FREE(self);
}
void spIkConstraint_apply (spIkConstraint* self) {
switch (self->bonesCount) {
case 1:
spIkConstraint_apply1(self->bones[0], self->target->worldX, self->target->worldY, self->mix);
break;
case 2:
spIkConstraint_apply2(self->bones[0], self->bones[1], self->target->worldX, self->target->worldY, self->bendDirection,
self->mix);
break;
}
}
void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha) {
float parentRotation = (!bone->data->inheritRotation || !bone->parent) ? 0 : bone->parent->worldRotation;
float rotation = bone->rotation;
float rotationIK = ATAN2(targetY - bone->worldY, targetX - bone->worldX) * RAD_DEG - parentRotation;
bone->rotationIK = rotation + (rotationIK - rotation) * alpha;
}
void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, float alpha) {
float childRotation = child->rotation, parentRotation = parent->rotation;
if (alpha == 0) {
child->rotationIK = childRotation;
parent->rotationIK = parentRotation;
return;
}
float positionX, positionY;
spBone* parentParent = parent->parent;
if (parentParent) {
spBone_worldToLocal(parentParent, targetX, targetY, &positionX, &positionY);
targetX = (positionX - parent->x) * parentParent->worldScaleX;
targetY = (positionY - parent->y) * parentParent->worldScaleY;
} else {
targetX -= parent->x;
targetY -= parent->y;
}
if (child->parent == parent) {
positionX = child->x;
positionY = child->y;
} else {
spBone_localToWorld(child->parent, child->x, child->y, &positionX, &positionY);
spBone_worldToLocal(parent, positionX, positionY, &positionX, &positionY);
}
float childX = positionX * parent->worldScaleX, childY = positionY * parent->worldScaleY;
float offset = ATAN2(childY, childX);
float len1 = SQRT(childX * childX + childY * childY);
float len2 = child->data->length * child->worldScaleX;
/* Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/ */
float cosDenom = 2 * len1 * len2;
if (cosDenom < 0.0001f) {
child->rotationIK = childRotation + (ATAN2(targetY, targetX) * RAD_DEG - parentRotation - childRotation) * alpha;
return;
}
float cos = (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom;
if (cos < -1)
cos = -1;
else if (cos > 1) cos = 1;
float childAngle = ACOS(cos) * bendDirection;
float adjacent = len1 + len2 * cos, opposite = len2 * SIN(childAngle);
float parentAngle = ATAN2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
float rotation = (parentAngle - offset) * RAD_DEG - parentRotation;
if (rotation > 180)
rotation -= 360;
else if (rotation < -180) /**/
rotation += 360;
parent->rotationIK = parentRotation + rotation * alpha;
rotation = (childAngle + offset) * RAD_DEG - childRotation;
if (rotation > 180)
rotation -= 360;
else if (rotation < -180) /**/
rotation += 360;
child->rotationIK = childRotation + (rotation + parent->worldRotation - child->parent->worldRotation) * alpha;
}

View File

@ -0,0 +1,46 @@
/******************************************************************************
* 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 <spine/IkConstraintData.h>
#include <spine/extension.h>
spIkConstraintData* spIkConstraintData_create (const char* name) {
spIkConstraintData* self = NEW(spIkConstraintData);
MALLOC_STR(self->name, name);
self->bendDirection = 1;
self->mix = 1;
return self;
}
void spIkConstraintData_dispose (spIkConstraintData* self) {
FREE(self->name);
FREE(self->bones);
FREE(self);
}

View File

@ -71,12 +71,11 @@ void spMeshAttachment_updateUVs (spMeshAttachment* self) {
}
}
void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, float x, float y, spSlot* slot, float* worldVertices) {
void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, spSlot* slot, float* worldVertices) {
int i;
float* vertices = self->vertices;
const spBone* bone = slot->bone;
x += bone->worldX;
y += bone->worldY;
float x = bone->skeleton->x + bone->worldX, y = bone->skeleton->y + bone->worldY;
if (slot->attachmentVerticesCount == self->verticesCount) vertices = slot->attachmentVertices;
for (i = 0; i < self->verticesCount; i += 2) {
const float vx = vertices[i], vy = vertices[i + 1];

View File

@ -79,14 +79,8 @@ void spRegionAttachment_updateOffset (spRegionAttachment* self) {
float localY = -self->height / 2 * self->scaleY + self->regionOffsetY * regionScaleY;
float localX2 = localX + self->regionWidth * regionScaleX;
float localY2 = localY + self->regionHeight * regionScaleY;
float radians = (float)(self->rotation * 3.1415926535897932385 / 180);
#ifdef __STDC_VERSION__
float cosine = cosf(radians);
float sine = sinf(radians);
#else
float cosine = (float)cos(radians);
float sine = (float)sin(radians);
#endif
float radians = self->rotation * DEG_RAD;
float cosine = COS(radians), sine = SIN(radians);
float localXCos = localX * cosine + self->x;
float localXSin = localX * sine;
float localYCos = localY * cosine + self->y;
@ -105,10 +99,9 @@ void spRegionAttachment_updateOffset (spRegionAttachment* self) {
self->offset[SP_VERTEX_Y4] = localYCos + localX2Sin;
}
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, float x, float y, spBone* bone, float* vertices) {
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, spBone* bone, float* vertices) {
const float* offset = self->offset;
x += bone->worldX;
y += bone->worldY;
float x = bone->skeleton->x + bone->worldX, y = bone->skeleton->y + bone->worldY;
vertices[SP_VERTEX_X1] = offset[SP_VERTEX_X1] * bone->m00 + offset[SP_VERTEX_Y1] * bone->m01 + x;
vertices[SP_VERTEX_Y1] = offset[SP_VERTEX_X1] * bone->m10 + offset[SP_VERTEX_Y1] * bone->m11 + y;
vertices[SP_VERTEX_X2] = offset[SP_VERTEX_X2] * bone->m00 + offset[SP_VERTEX_Y2] * bone->m01 + x;

View File

@ -32,65 +32,88 @@
#include <string.h>
#include <spine/extension.h>
typedef struct {
spSkeleton super;
int boneCacheCount;
int* boneCacheCounts;
spBone*** boneCache;
} _spSkeleton;
spSkeleton* spSkeleton_create (spSkeletonData* data) {
int i, ii;
spSkeleton* self = NEW(spSkeleton);
_spSkeleton* internal = NEW(_spSkeleton);
spSkeleton* self = SUPER(internal);
CONST_CAST(spSkeletonData*, self->data) = data;
self->boneCount = self->data->boneCount;
self->bones = MALLOC(spBone*, self->boneCount);
self->bonesCount = self->data->bonesCount;
self->bones = MALLOC(spBone*, self->bonesCount);
for (i = 0; i < self->boneCount; ++i) {
for (i = 0; i < self->bonesCount; ++i) {
spBoneData* boneData = self->data->bones[i];
spBone* parent = 0;
if (boneData->parent) {
/* Find parent bone. */
for (ii = 0; ii < self->boneCount; ++ii) {
for (ii = 0; ii < self->bonesCount; ++ii) {
if (data->bones[ii] == boneData->parent) {
parent = self->bones[ii];
break;
}
}
}
self->bones[i] = spBone_create(boneData, parent);
self->bones[i] = spBone_create(boneData, self, parent);
}
CONST_CAST(spBone*, self->root) = self->bones[0];
self->slotCount = data->slotCount;
self->slots = MALLOC(spSlot*, self->slotCount);
for (i = 0; i < self->slotCount; ++i) {
self->slotsCount = data->slotsCount;
self->slots = MALLOC(spSlot*, self->slotsCount);
for (i = 0; i < self->slotsCount; ++i) {
spSlotData *slotData = data->slots[i];
/* Find bone for the slotData's boneData. */
spBone* bone = 0;
for (ii = 0; ii < self->boneCount; ++ii) {
for (ii = 0; ii < self->bonesCount; ++ii) {
if (data->bones[ii] == slotData->boneData) {
bone = self->bones[ii];
break;
}
}
self->slots[i] = spSlot_create(slotData, self, bone);
self->slots[i] = spSlot_create(slotData, bone);
}
self->drawOrder = MALLOC(spSlot*, self->slotCount);
memcpy(self->drawOrder, self->slots, sizeof(spSlot*) * self->slotCount);
self->drawOrder = MALLOC(spSlot*, self->slotsCount);
memcpy(self->drawOrder, self->slots, sizeof(spSlot*) * self->slotsCount);
self->r = 1;
self->g = 1;
self->b = 1;
self->a = 1;
self->ikConstraintsCount = data->ikConstraintsCount;
self->ikConstraints = MALLOC(spIkConstraint*, self->ikConstraintsCount);
for (i = 0; i < self->data->ikConstraintsCount; ++i)
self->ikConstraints[i] = spIkConstraint_create(self->data->ikConstraints[i], self);
spSkeleton_updateCache(self);
return self;
}
void spSkeleton_dispose (spSkeleton* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
for (i = 0; i < internal->boneCacheCount; ++i)
FREE(internal->boneCache[i]);
FREE(internal->boneCache);
FREE(internal->boneCacheCounts);
for (i = 0; i < self->bonesCount; ++i)
spBone_dispose(self->bones[i]);
FREE(self->bones);
for (i = 0; i < self->slotCount; ++i)
for (i = 0; i < self->slotsCount; ++i)
spSlot_dispose(self->slots[i]);
FREE(self->slots);
@ -98,10 +121,89 @@ void spSkeleton_dispose (spSkeleton* self) {
FREE(self);
}
void spSkeleton_updateCache (const spSkeleton* self) {
int i, ii;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
for (i = 0; i < internal->boneCacheCount; ++i)
FREE(internal->boneCache[i]);
FREE(internal->boneCache);
FREE(internal->boneCacheCounts);
internal->boneCacheCount = self->ikConstraintsCount + 1;
internal->boneCache = MALLOC(spBone**, internal->boneCacheCount);
internal->boneCacheCounts = CALLOC(int, internal->boneCacheCount);
/* Compute array sizes. */
for (i = 0; i < self->bonesCount; ++i) {
spBone* current = self->bones[i];
do {
for (ii = 0; ii < self->ikConstraintsCount; ++ii) {
spIkConstraint* ikConstraint = self->ikConstraints[ii];
spBone* parent = ikConstraint->bones[0];
spBone* child = ikConstraint->bones[ikConstraint->bonesCount - 1];
while (1) {
if (current == child) {
internal->boneCacheCounts[ii]++;
internal->boneCacheCounts[ii + 1]++;
goto outer1;
}
if (child == parent) break;
child = child->parent;
}
}
current = current->parent;
} while (current);
internal->boneCacheCounts[0]++;
outer1: {}
}
for (i = 0; i < internal->boneCacheCount; ++i)
internal->boneCache[i] = MALLOC(spBone*, internal->boneCacheCounts[i]);
memset(internal->boneCacheCounts, 0, internal->boneCacheCount * sizeof(int));
/* Populate arrays. */
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
spBone* current = bone;
do {
for (ii = 0; ii < self->ikConstraintsCount; ++ii) {
spIkConstraint* ikConstraint = self->ikConstraints[ii];
spBone* parent = ikConstraint->bones[0];
spBone* child = ikConstraint->bones[ikConstraint->bonesCount - 1];
while (1) {
if (current == child) {
internal->boneCache[ii][internal->boneCacheCounts[ii]++] = bone;
internal->boneCache[ii + 1][internal->boneCacheCounts[ii + 1]++] = bone;
goto outer2;
}
if (child == parent) break;
child = child->parent;
}
}
current = current->parent;
} while (current);
internal->boneCache[0][internal->boneCacheCounts[0]++] = bone;
outer2: {}
}
}
void spSkeleton_updateWorldTransform (const spSkeleton* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
spBone_updateWorldTransform(self->bones[i], self->flipX, self->flipY);
int i, ii, nn, last;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
for (i = 0; i < self->bonesCount; ++i)
self->bones[i]->rotationIK = self->bones[i]->rotation;
i = 0;
last = internal->boneCacheCount - 1;
while (1) {
for (ii = 0, nn = internal->boneCacheCounts[i]; ii < nn; ++ii)
spBone_updateWorldTransform(internal->boneCache[i][ii]);
if (i == last) break;
spIkConstraint_apply(self->ikConstraints[i]);
i++;
}
}
void spSkeleton_setToSetupPose (const spSkeleton* self) {
@ -111,41 +213,47 @@ void spSkeleton_setToSetupPose (const spSkeleton* self) {
void spSkeleton_setBonesToSetupPose (const spSkeleton* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
for (i = 0; i < self->bonesCount; ++i)
spBone_setToSetupPose(self->bones[i]);
for (i = 0; i < self->ikConstraintsCount; ++i) {
spIkConstraint* ikConstraint = self->ikConstraints[i];
ikConstraint->bendDirection = ikConstraint->data->bendDirection;
ikConstraint->mix = ikConstraint->data->mix;
}
}
void spSkeleton_setSlotsToSetupPose (const spSkeleton* self) {
int i;
memcpy(self->drawOrder, self->slots, self->slotCount * sizeof(spSlot*));
for (i = 0; i < self->slotCount; ++i)
memcpy(self->drawOrder, self->slots, self->slotsCount * sizeof(spSlot*));
for (i = 0; i < self->slotsCount; ++i)
spSlot_setToSetupPose(self->slots[i]);
}
spBone* spSkeleton_findBone (const spSkeleton* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->data->bones[i]->name, boneName) == 0) return self->bones[i];
return 0;
}
int spSkeleton_findBoneIndex (const spSkeleton* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->data->bones[i]->name, boneName) == 0) return i;
return -1;
}
spSlot* spSkeleton_findSlot (const spSkeleton* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->data->slots[i]->name, slotName) == 0) return self->slots[i];
return 0;
}
int spSkeleton_findSlotIndex (const spSkeleton* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->data->slots[i]->name, slotName) == 0) return i;
return -1;
}
@ -169,7 +277,7 @@ void spSkeleton_setSkin (spSkeleton* self, spSkin* newSkin) {
else {
/* No previous skin, attach setup pose attachments. */
int i;
for (i = 0; i < self->slotCount; ++i) {
for (i = 0; i < self->slotsCount; ++i) {
spSlot* slot = self->slots[i];
if (slot->data->attachmentName) {
spAttachment* attachment = spSkin_getAttachment(newSkin, i, slot->data->attachmentName);
@ -201,7 +309,7 @@ spAttachment* spSkeleton_getAttachmentForSlotIndex (const spSkeleton* self, int
int spSkeleton_setAttachment (spSkeleton* self, const char* slotName, const char* attachmentName) {
int i;
for (i = 0; i < self->slotCount; ++i) {
for (i = 0; i < self->slotsCount; ++i) {
spSlot *slot = self->slots[i];
if (strcmp(slot->data->name, slotName) == 0) {
if (!attachmentName)
@ -217,6 +325,13 @@ int spSkeleton_setAttachment (spSkeleton* self, const char* slotName, const char
return 0;
}
spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* ikConstraintName) {
int i;
for (i = 0; i < self->ikConstraintsCount; ++i)
if (strcmp(self->ikConstraints[i]->data->name, ikConstraintName) == 0) return self->ikConstraints[i];
return 0;
}
void spSkeleton_update (spSkeleton* self, float deltaTime) {
self->time += deltaTime;
}

View File

@ -105,18 +105,18 @@ void spSkeletonBounds_update (spSkeletonBounds* self, spSkeleton* skeleton, int/
int i;
_spSkeletonBounds* internal = SUB_CAST(_spSkeletonBounds, self);
if (internal->capacity < skeleton->slotCount) {
if (internal->capacity < skeleton->slotsCount) {
spPolygon** newPolygons;
FREE(self->boundingBoxes);
self->boundingBoxes = MALLOC(spBoundingBoxAttachment*, skeleton->slotCount);
self->boundingBoxes = MALLOC(spBoundingBoxAttachment*, skeleton->slotsCount);
newPolygons = CALLOC(spPolygon*, skeleton->slotCount);
newPolygons = CALLOC(spPolygon*, skeleton->slotsCount);
memcpy(newPolygons, self->polygons, internal->capacity);
FREE(self->polygons);
self->polygons = newPolygons;
internal->capacity = skeleton->slotCount;
internal->capacity = skeleton->slotsCount;
}
self->minX = (float)INT_MAX;
@ -125,7 +125,7 @@ void spSkeletonBounds_update (spSkeletonBounds* self, spSkeleton* skeleton, int/
self->maxY = (float)INT_MIN;
self->count = 0;
for (i = 0; i < skeleton->slotCount; ++i) {
for (i = 0; i < skeleton->slotsCount; ++i) {
spPolygon* polygon;
spBoundingBoxAttachment* boundingBox;
@ -141,7 +141,7 @@ void spSkeletonBounds_update (spSkeletonBounds* self, spSkeleton* skeleton, int/
self->polygons[self->count] = polygon = spPolygon_create(boundingBox->verticesCount);
}
polygon->count = boundingBox->verticesCount;
spBoundingBoxAttachment_computeWorldVertices(boundingBox, skeleton->x, skeleton->y, slot->bone, polygon->vertices);
spBoundingBoxAttachment_computeWorldVertices(boundingBox, slot->bone, polygon->vertices);
if (updateAabb) {
int ii = 0;
@ -155,7 +155,7 @@ void spSkeletonBounds_update (spSkeletonBounds* self, spSkeleton* skeleton, int/
}
}
++self->count;
self->count++;
}
}

View File

@ -38,74 +38,85 @@ spSkeletonData* spSkeletonData_create () {
void spSkeletonData_dispose (spSkeletonData* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
for (i = 0; i < self->bonesCount; ++i)
spBoneData_dispose(self->bones[i]);
FREE(self->bones);
for (i = 0; i < self->slotCount; ++i)
for (i = 0; i < self->slotsCount; ++i)
spSlotData_dispose(self->slots[i]);
FREE(self->slots);
for (i = 0; i < self->skinCount; ++i)
for (i = 0; i < self->skinsCount; ++i)
spSkin_dispose(self->skins[i]);
FREE(self->skins);
for (i = 0; i < self->animationCount; ++i)
for (i = 0; i < self->eventsCount; ++i)
spEventData_dispose(self->events[i]);
FREE(self->events);
for (i = 0; i < self->animationsCount; ++i)
spAnimation_dispose(self->animations[i]);
FREE(self->animations);
for (i = 0; i < self->eventCount; ++i)
spEventData_dispose(self->events[i]);
FREE(self->events);
for (i = 0; i < self->ikConstraintsCount; ++i)
spIkConstraintData_dispose(self->ikConstraints[i]);
FREE(self->ikConstraints);
FREE(self);
}
spBoneData* spSkeletonData_findBone (const spSkeletonData* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->bones[i]->name, boneName) == 0) return self->bones[i];
return 0;
}
int spSkeletonData_findBoneIndex (const spSkeletonData* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->bones[i]->name, boneName) == 0) return i;
return -1;
}
spSlotData* spSkeletonData_findSlot (const spSkeletonData* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->slots[i]->name, slotName) == 0) return self->slots[i];
return 0;
}
int spSkeletonData_findSlotIndex (const spSkeletonData* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->slots[i]->name, slotName) == 0) return i;
return -1;
}
spSkin* spSkeletonData_findSkin (const spSkeletonData* self, const char* skinName) {
int i;
for (i = 0; i < self->skinCount; ++i)
for (i = 0; i < self->skinsCount; ++i)
if (strcmp(self->skins[i]->name, skinName) == 0) return self->skins[i];
return 0;
}
spEventData* spSkeletonData_findEvent (const spSkeletonData* self, const char* eventName) {
int i;
for (i = 0; i < self->eventCount; ++i)
for (i = 0; i < self->eventsCount; ++i)
if (strcmp(self->events[i]->name, eventName) == 0) return self->events[i];
return 0;
}
spAnimation* spSkeletonData_findAnimation (const spSkeletonData* self, const char* animationName) {
int i;
for (i = 0; i < self->animationCount; ++i)
for (i = 0; i < self->animationsCount; ++i)
if (strcmp(self->animations[i]->name, animationName) == 0) return self->animations[i];
return 0;
}
spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* ikConstraintName) {
int i;
for (i = 0; i < self->ikConstraintsCount; ++i)
if (strcmp(self->ikConstraints[i]->name, ikConstraintName) == 0) return self->ikConstraints[i];
return 0;
}

View File

@ -109,27 +109,29 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
Json* bones = Json_getItem(root, "bones");
Json* slots = Json_getItem(root, "slots");
Json* ik = Json_getItem(root, "ik");
Json* ffd = Json_getItem(root, "ffd");
Json* drawOrder = Json_getItem(root, "draworder");
Json* events = Json_getItem(root, "events");
Json *boneMap, *slotMap, *ffdMap;
Json *boneMap, *slotMap, *ikMap, *ffdMap;
int timelineCount = 0;
int timelinesCount = 0;
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next)
timelineCount += boneMap->size;
timelinesCount += boneMap->size;
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next)
timelineCount += slotMap->size;
timelinesCount += slotMap->size;
timelinesCount += ik ? ik->size : 0;
for (ffdMap = ffd ? ffd->child : 0; ffdMap; ffdMap = ffdMap->next)
for (slotMap = ffdMap->child; slotMap; slotMap = slotMap->next)
timelineCount += slotMap->size;
if (events) ++timelineCount;
if (drawOrder) ++timelineCount;
timelinesCount += slotMap->size;
if (events) ++timelinesCount;
if (drawOrder) ++timelinesCount;
animation = spAnimation_create(root->name, timelineCount);
animation->timelineCount = 0;
skeletonData->animations[skeletonData->animationCount] = animation;
++skeletonData->animationCount;
animation = spAnimation_create(root->name, timelinesCount);
animation->timelinesCount = 0;
skeletonData->animations[skeletonData->animationsCount++] = animation;
/* Slot timelines. */
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) {
Json *timelineArray;
@ -150,7 +152,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
toColor(s, 3));
readCurve(SUPER(timeline), i, frame);
}
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[timelineArray->size * 5 - 5];
if (duration > animation->duration) animation->duration = duration;
@ -162,7 +164,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
spAttachmentTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0),
name->type == Json_NULL ? 0 : name->valueString);
}
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[timelineArray->size - 1];
if (duration > animation->duration) animation->duration = duration;
@ -174,13 +176,14 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
}
}
/* Bone timelines. */
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) {
Json *timelineArray;
int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name);
if (boneIndex == -1) {
spAnimation_dispose(animation);
_spSkeletonJson_setError(self, root, "spBone not found: ", boneMap->name);
_spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name);
return 0;
}
@ -192,7 +195,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
spRotateTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "angle", 0));
readCurve(SUPER(timeline), i, frame);
}
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[timelineArray->size * 2 - 2];
if (duration > animation->duration) animation->duration = duration;
@ -208,7 +211,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
Json_getFloat(frame, "y", 0) * scale);
readCurve(SUPER(timeline), i, frame);
}
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[timelineArray->size * 3 - 3];
if (duration > animation->duration) animation->duration = duration;
} else {
@ -220,6 +223,27 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
}
}
/* IK timelines. */
for (ikMap = ik ? ik->child : 0; ikMap; ikMap = ikMap->next) {
spIkConstraintData* ikConstraint = spSkeletonData_findIkConstraint(skeletonData, ikMap->name);
spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(ikMap->size);
for (i = 0; i < skeletonData->ikConstraintsCount; ++i) {
if (ikConstraint == skeletonData->ikConstraints[i]) {
timeline->ikConstraintIndex = i;
break;
}
}
for (frame = events->child, i = 0; frame; frame = frame->next, ++i) {
spIkConstraintTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "mix", 0),
Json_getFloat(frame, "bendPositive", 1) ? 1 : -1);
readCurve(SUPER(timeline), i, frame);
}
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[ikMap->size * 3 - 3];
if (duration > animation->duration) animation->duration = duration;
}
/* FFD timelines. */
for (ffdMap = ffd ? ffd->child : 0; ffdMap; ffdMap = ffdMap->next) {
spSkin* skin = spSkeletonData_findSkin(skeletonData, ffdMap->name);
for (slotMap = ffdMap->child; slotMap; slotMap = slotMap->next) {
@ -281,26 +305,27 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
}
FREE(tempVertices);
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[timelineArray->size - 1];
if (duration > animation->duration) animation->duration = duration;
}
}
}
/* Draw order timeline. */
if (drawOrder) {
spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotCount);
spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotsCount);
for (frame = drawOrder->child, i = 0; frame; frame = frame->next, ++i) {
int ii;
int* drawOrder = 0;
Json* offsets = Json_getItem(frame, "offsets");
if (offsets) {
Json* offsetMap;
int* unchanged = MALLOC(int, skeletonData->slotCount - offsets->size);
int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->size);
int originalIndex = 0, unchangedIndex = 0;
drawOrder = MALLOC(int, skeletonData->slotCount);
for (ii = skeletonData->slotCount - 1; ii >= 0; --ii)
drawOrder = MALLOC(int, skeletonData->slotsCount);
for (ii = skeletonData->slotsCount - 1; ii >= 0; --ii)
drawOrder[ii] = -1;
for (offsetMap = offsets->child; offsetMap; offsetMap = offsetMap->next) {
@ -315,24 +340,25 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
unchanged[unchangedIndex++] = originalIndex++;
/* Set changed items. */
drawOrder[originalIndex + Json_getInt(offsetMap, "offset", 0)] = originalIndex;
++originalIndex;
originalIndex++;
}
/* Collect remaining unchanged items. */
while (originalIndex < skeletonData->slotCount)
while (originalIndex < skeletonData->slotsCount)
unchanged[unchangedIndex++] = originalIndex++;
/* Fill in unchanged items. */
for (ii = skeletonData->slotCount - 1; ii >= 0; ii--)
for (ii = skeletonData->slotsCount - 1; ii >= 0; ii--)
if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];
FREE(unchanged);
}
spDrawOrderTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), drawOrder);
FREE(drawOrder);
}
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[drawOrder->size - 1];
if (duration > animation->duration) animation->duration = duration;
}
/* Event timeline. */
if (events) {
Json* frame;
@ -353,7 +379,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
if (stringValue) MALLOC_STR(event->stringValue, stringValue);
spEventTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), event);
}
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[events->size - 1];
if (duration > animation->duration) animation->duration = duration;
}
@ -375,9 +401,9 @@ spSkeletonData* spSkeletonJson_readSkeletonDataFile (spSkeletonJson* self, const
}
spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const char* json) {
int i;
int i, ii;
spSkeletonData* skeletonData;
Json *root, *bones, *boneMap, *slots, *skins, *animations, *events;
Json *root, *skeleton, *bones, *boneMap, *ik, *slots, *skins, *animations, *events;
FREE(self->error);
CONST_CAST(char*, self->error) = 0;
@ -390,6 +416,15 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
skeletonData = spSkeletonData_create();
skeleton = Json_getItem(root, "skeleton");
if (skeleton) {
skeletonData->hash = Json_getString(skeleton, "hash", 0);
skeletonData->version = Json_getString(skeleton, "spine", 0);
skeletonData->width = Json_getFloat(skeleton, "width", 0);
skeletonData->height = Json_getFloat(skeleton, "height", 0);
}
/* Bones. */
bones = Json_getItem(root, "bones");
skeletonData->bones = MALLOC(spBoneData*, bones->size);
for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) {
@ -417,12 +452,49 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
boneData->inheritRotation = Json_getInt(boneMap, "inheritRotation", 1);
skeletonData->bones[i] = boneData;
++skeletonData->boneCount;
skeletonData->bonesCount++;
}
/* IK constraints. */
ik = Json_getItem(root, "ik");
if (ik) {
Json *ikMap;
skeletonData->ikConstraintsCount = ik->size;
skeletonData->ikConstraints = MALLOC(spIkConstraintData*, ik->size);
for (ikMap = ik->child, i = 0; ikMap; ikMap = ikMap->next, ++i) {
spIkConstraintData* ikConstraintData = spIkConstraintData_create(Json_getString(ikMap, "name", 0));
boneMap = Json_getItem(ikMap, "bones");
ikConstraintData->bonesCount = boneMap->size;
ikConstraintData->bones = MALLOC(spBoneData*, boneMap->size);
for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) {
ikConstraintData->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString);
if (!ikConstraintData->bones[ii]) {
spSkeletonData_dispose(skeletonData);
_spSkeletonJson_setError(self, root, "IK bone not found: ", boneMap->valueString);
return 0;
}
}
const char* targetName = Json_getString(ikMap, "target", 0);
ikConstraintData->target = spSkeletonData_findBone(skeletonData, targetName);
if (!ikConstraintData->target) {
spSkeletonData_dispose(skeletonData);
_spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name);
return 0;
}
ikConstraintData->bendDirection = Json_getInt(ikMap, "bendPositive", 1) ? 1 : -1;
ikConstraintData->mix = Json_getFloat(ikMap, "mix", 1);
skeletonData->ikConstraints[i] = ikConstraintData;
}
}
/* Slots. */
slots = Json_getItem(root, "slots");
if (slots) {
Json *slotMap;
skeletonData->slotsCount = slots->size;
skeletonData->slots = MALLOC(spSlotData*, slots->size);
for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) {
spSlotData* slotData;
@ -433,7 +505,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
spBoneData* boneData = spSkeletonData_findBone(skeletonData, boneName);
if (!boneData) {
spSkeletonData_dispose(skeletonData);
_spSkeletonJson_setError(self, root, "spSlot bone not found: ", boneName);
_spSkeletonJson_setError(self, root, "Slot bone not found: ", boneName);
return 0;
}
@ -453,20 +525,20 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
slotData->additiveBlending = Json_getInt(slotMap, "additive", 0);
skeletonData->slots[i] = slotData;
++skeletonData->slotCount;
}
}
/* Skins. */
skins = Json_getItem(root, "skins");
if (skins) {
Json *slotMap;
skeletonData->skinsCount = skins->size;
skeletonData->skins = MALLOC(spSkin*, skins->size);
for (slotMap = skins->child, i = 0; slotMap; slotMap = slotMap->next, ++i) {
Json *attachmentsMap;
spSkin *skin = spSkin_create(slotMap->name);
skeletonData->skins[i] = skin;
++skeletonData->skinCount;
if (strcmp(slotMap->name, "default") == 0) skeletonData->defaultSkin = skin;
for (attachmentsMap = slotMap->child; attachmentsMap; attachmentsMap = attachmentsMap->next) {
@ -597,18 +669,18 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
vertices[i] = entry->valueFloat;
for (i = 0; i < verticesCount;) {
int boneCount = (int)vertices[i];
mesh->bonesCount += boneCount + 1;
mesh->weightsCount += boneCount * 3;
i += 1 + boneCount * 4;
int bonesCount = (int)vertices[i];
mesh->bonesCount += bonesCount + 1;
mesh->weightsCount += bonesCount * 3;
i += 1 + bonesCount * 4;
}
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; i += 4, ++b, w += 3) {
int bonesCount = (int)vertices[i++];
mesh->bones[b++] = bonesCount;
for (nn = i + bonesCount * 4; i < nn; i += 4, ++b, w += 3) {
mesh->bones[b] = (int)vertices[i];
mesh->weights[w] = vertices[i + 1] * self->scale;
mesh->weights[w + 1] = vertices[i + 2] * self->scale;
@ -670,14 +742,15 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
if (events) {
Json *eventMap;
const char* stringValue;
skeletonData->eventsCount = events->size;
skeletonData->events = MALLOC(spEventData*, events->size);
for (eventMap = events->child; eventMap; eventMap = eventMap->next) {
for (eventMap = events->child, i = 0; eventMap; eventMap = eventMap->next, ++i) {
spEventData* eventData = spEventData_create(eventMap->name);
eventData->intValue = Json_getInt(eventMap, "int", 0);
eventData->floatValue = Json_getFloat(eventMap, "float", 0);
stringValue = Json_getString(eventMap, "string", 0);
if (stringValue) MALLOC_STR(eventData->stringValue, stringValue);
skeletonData->events[skeletonData->eventCount++] = eventData;
skeletonData->events[i] = eventData;
}
}

View File

@ -72,10 +72,10 @@ void spSkinnedMeshAttachment_updateUVs (spSkinnedMeshAttachment* self) {
}
}
void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, float x, float y, spSlot* slot,
float* worldVertices) {
void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, spSlot* slot, float* worldVertices) {
int w = 0, v = 0, b = 0, f = 0;
spBone** skeletonBones = slot->skeleton->bones;
float x = slot->bone->skeleton->x, y = slot->bone->skeleton->y;
spBone** skeletonBones = slot->bone->skeleton->bones;
if (slot->attachmentVerticesCount == 0) {
for (; v < self->bonesCount; w += 2) {
float wx = 0, wy = 0;

View File

@ -30,17 +30,15 @@
#include <spine/Slot.h>
#include <spine/extension.h>
#include <spine/Skeleton.h>
typedef struct {
spSlot super;
float attachmentTime;
} _spSlot;
spSlot* spSlot_create (spSlotData* data, spSkeleton* skeleton, spBone* bone) {
spSlot* spSlot_create (spSlotData* data, spBone* bone) {
spSlot* self = SUPER(NEW(_spSlot));
CONST_CAST(spSlotData*, self->data) = data;
CONST_CAST(spSkeleton*, self->skeleton) = skeleton;
CONST_CAST(spBone*, self->bone) = bone;
spSlot_setToSetupPose(self);
return self;
@ -53,15 +51,15 @@ void spSlot_dispose (spSlot* self) {
void spSlot_setAttachment (spSlot* self, spAttachment* attachment) {
CONST_CAST(spAttachment*, self->attachment) = attachment;
SUB_CAST(_spSlot, self) ->attachmentTime = self->skeleton->time;
SUB_CAST(_spSlot, self) ->attachmentTime = self->bone->skeleton->time;
}
void spSlot_setAttachmentTime (spSlot* self, float time) {
SUB_CAST(_spSlot, self) ->attachmentTime = self->skeleton->time - time;
SUB_CAST(_spSlot, self) ->attachmentTime = self->bone->skeleton->time - time;
}
float spSlot_getAttachmentTime (const spSlot* self) {
return self->skeleton->time - SUB_CAST(_spSlot, self) ->attachmentTime;
return self->bone->skeleton->time - SUB_CAST(_spSlot, self) ->attachmentTime;
}
void spSlot_setToSetupPose (spSlot* self) {
@ -74,9 +72,9 @@ void spSlot_setToSetupPose (spSlot* self) {
if (self->data->attachmentName) {
/* Find slot index. */
int i;
for (i = 0; i < self->skeleton->data->slotCount; ++i) {
if (self->data == self->skeleton->data->slots[i]) {
attachment = spSkeleton_getAttachmentForSlotIndex(self->skeleton, i, self->data->attachmentName);
for (i = 0; i < self->bone->skeleton->data->slotsCount; ++i) {
if (self->data == self->bone->skeleton->data->slots[i]) {
attachment = spSkeleton_getAttachmentForSlotIndex(self->bone->skeleton, i, self->data->attachmentName);
break;
}
}

View File

@ -0,0 +1,251 @@
raptor.png
size: 1022,1022
format: RGBA8888
filter: Linear,Linear
repeat: none
images/back_arm
rotate: false
xy: 410, 545
size: 46, 29
orig: 46, 29
offset: 0, 0
index: -1
images/back_bracer
rotate: false
xy: 540, 548
size: 39, 28
orig: 39, 28
offset: 0, 0
index: -1
images/back_hand
rotate: true
xy: 504, 538
size: 36, 34
orig: 36, 34
offset: 0, 0
index: -1
images/back_knee
rotate: false
xy: 299, 478
size: 49, 67
orig: 49, 67
offset: 0, 0
index: -1
images/back_thigh
rotate: true
xy: 140, 247
size: 39, 24
orig: 39, 24
offset: 0, 0
index: -1
images/eyes_open
rotate: true
xy: 2, 2
size: 47, 45
orig: 47, 45
offset: 0, 0
index: -1
images/front_arm
rotate: false
xy: 360, 544
size: 48, 30
orig: 48, 30
offset: 0, 0
index: -1
images/front_bracer
rotate: false
xy: 538, 578
size: 41, 29
orig: 41, 29
offset: 0, 0
index: -1
images/front_hand
rotate: false
xy: 538, 609
size: 41, 38
orig: 41, 38
offset: 0, 0
index: -1
images/front_open_hand
rotate: false
xy: 894, 782
size: 43, 44
orig: 43, 44
offset: 0, 0
index: -1
images/front_thigh
rotate: false
xy: 942, 849
size: 57, 29
orig: 57, 29
offset: 0, 0
index: -1
images/gun
rotate: false
xy: 785, 774
size: 107, 103
orig: 107, 103
offset: 0, 0
index: -1
images/gun_nohand
rotate: false
xy: 614, 703
size: 105, 102
orig: 105, 102
offset: 0, 0
index: -1
images/head
rotate: false
xy: 2, 137
size: 136, 149
orig: 136, 149
offset: 0, 0
index: -1
images/lower_leg
rotate: true
xy: 780, 699
size: 73, 98
orig: 73, 98
offset: 0, 0
index: -1
images/mouth_smile
rotate: true
xy: 49, 2
size: 47, 30
orig: 47, 30
offset: 0, 0
index: -1
images/neck
rotate: true
xy: 1001, 860
size: 18, 21
orig: 18, 21
offset: 0, 0
index: -1
images/raptor_arm_back
rotate: false
xy: 940, 936
size: 82, 86
orig: 82, 86
offset: 0, 0
index: -1
images/raptor_body
rotate: false
xy: 2, 737
size: 610, 285
orig: 610, 285
offset: 0, 0
index: -1
images/raptor_front_arm
rotate: true
xy: 195, 464
size: 81, 102
orig: 81, 102
offset: 0, 0
index: -1
images/raptor_front_leg
rotate: false
xy: 2, 478
size: 191, 257
orig: 191, 257
offset: 0, 0
index: -1
images/raptor_hindleg_back
rotate: false
xy: 614, 807
size: 169, 215
orig: 169, 215
offset: 0, 0
index: -1
images/raptor_horn
rotate: false
xy: 360, 655
size: 182, 80
orig: 182, 80
offset: 0, 0
index: -1
images/raptor_horn_back
rotate: false
xy: 360, 576
size: 176, 77
orig: 176, 77
offset: 0, 0
index: -1
images/raptor_jaw
rotate: false
xy: 785, 879
size: 153, 143
orig: 153, 143
offset: 0, 0
index: -1
images/raptor_saddle_noshadow
rotate: false
xy: 2, 288
size: 163, 188
orig: 163, 188
offset: 0, 0
index: -1
images/raptor_saddle_strap_front
rotate: false
xy: 721, 710
size: 57, 95
orig: 57, 95
offset: 0, 0
index: -1
images/raptor_saddle_strap_rear
rotate: true
xy: 940, 880
size: 54, 74
orig: 54, 74
offset: 0, 0
index: -1
images/raptor_saddle_w_shadow
rotate: false
xy: 195, 547
size: 163, 188
orig: 163, 188
offset: 0, 0
index: -1
images/raptor_tongue
rotate: true
xy: 544, 649
size: 86, 64
orig: 86, 64
offset: 0, 0
index: -1
images/stirrup_back
rotate: false
xy: 458, 539
size: 44, 35
orig: 44, 35
offset: 0, 0
index: -1
images/stirrup_front
rotate: true
xy: 81, 4
size: 45, 50
orig: 45, 50
offset: 0, 0
index: -1
images/stirrup_strap
rotate: true
xy: 894, 828
size: 49, 46
orig: 49, 46
offset: 0, 0
index: -1
images/torso
rotate: true
xy: 610, 647
size: 54, 91
orig: 54, 91
offset: 0, 0
index: -1
images/visor
rotate: false
xy: 2, 51
size: 131, 84
orig: 131, 84
offset: 0, 0
index: -1

File diff suppressed because one or more lines are too long

BIN
spine-sfml/data/raptor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

View File

@ -101,7 +101,7 @@ void spineboy () {
AnimationState_addAnimationByName(drawable->state, 0, "run", true, 0);
}
sf::RenderWindow window(sf::VideoMode(640, 480), "Spine SFML");
sf::RenderWindow window(sf::VideoMode(640, 480), "Spine SFML - spineboy");
window.setFramerateLimit(60);
sf::Event event;
sf::Clock deltaClock;
@ -163,7 +163,52 @@ void goblins () {
AnimationState_setAnimation(drawable->state, 0, walkAnimation, true);
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML");
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - goblins");
window.setFramerateLimit(60);
sf::Event event;
sf::Clock deltaClock;
while (window.isOpen()) {
while (window.pollEvent(event))
if (event.type == sf::Event::Closed) window.close();
float delta = deltaClock.getElapsedTime().asSeconds();
deltaClock.restart();
drawable->update(delta);
window.clear();
window.draw(*drawable);
window.display();
}
SkeletonData_dispose(skeletonData);
Atlas_dispose(atlas);
}
void raptor () {
// Load atlas, skeleton, and animations.
Atlas* atlas = Atlas_createFromFile("data/raptor.atlas", 0);
SkeletonJson* json = SkeletonJson_create(atlas);
json->scale = 0.5f;
SkeletonData *skeletonData = SkeletonJson_readSkeletonDataFile(json, "data/raptor.json");
if (!skeletonData) {
printf("Error: %s\n", json->error);
exit(0);
}
Animation* walkAnimation = SkeletonData_findAnimation(skeletonData, "walk");
SkeletonJson_dispose(json);
SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData);
drawable->timeScale = 1;
Skeleton* skeleton = drawable->skeleton;
skeleton->x = 320;
skeleton->y = 590;
Skeleton_updateWorldTransform(skeleton);
AnimationState_setAnimation(drawable->state, 0, walkAnimation, true);
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - raptor");
window.setFramerateLimit(60);
sf::Event event;
sf::Clock deltaClock;
@ -186,6 +231,7 @@ void goblins () {
}
int main () {
raptor();
spineboy();
goblins();
}

View File

@ -66,7 +66,7 @@ namespace spine {
SkeletonDrawable::SkeletonDrawable (SkeletonData* skeletonData, AnimationStateData* stateData) :
timeScale(1),
vertexArray(new VertexArray(Triangles, skeletonData->boneCount * 4)),
vertexArray(new VertexArray(Triangles, skeletonData->bonesCount * 4)),
worldVertices(0) {
Bone_setYDown(true);
worldVertices = MALLOC(float, SPINE_MESH_VERTEX_COUNT_MAX);
@ -94,7 +94,7 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
sf::Vertex vertices[4];
sf::Vertex vertex;
for (int i = 0; i < skeleton->slotCount; ++i) {
for (int i = 0; i < skeleton->slotsCount; ++i) {
Slot* slot = skeleton->drawOrder[i];
Attachment* attachment = slot->attachment;
if (!attachment) continue;
@ -102,7 +102,7 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
if (attachment->type == ATTACHMENT_REGION) {
RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
texture = (Texture*)((AtlasRegion*)regionAttachment->rendererObject)->page->rendererObject;
RegionAttachment_computeWorldVertices(regionAttachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
RegionAttachment_computeWorldVertices(regionAttachment, slot->bone, worldVertices);
Uint8 r = static_cast<Uint8>(skeleton->r * slot->r * 255);
Uint8 g = static_cast<Uint8>(skeleton->g * slot->g * 255);
@ -157,7 +157,7 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
MeshAttachment* mesh = (MeshAttachment*)attachment;
if (mesh->verticesCount > SPINE_MESH_VERTEX_COUNT_MAX) continue;
texture = (Texture*)((AtlasRegion*)mesh->rendererObject)->page->rendererObject;
MeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
MeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
Uint8 r = static_cast<Uint8>(skeleton->r * slot->r * 255);
Uint8 g = static_cast<Uint8>(skeleton->g * slot->g * 255);
@ -182,7 +182,7 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
SkinnedMeshAttachment* mesh = (SkinnedMeshAttachment*)attachment;
if (mesh->uvsCount > SPINE_MESH_VERTEX_COUNT_MAX) continue;
texture = (Texture*)((AtlasRegion*)mesh->rendererObject)->page->rendererObject;
SkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
SkinnedMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
Uint8 r = static_cast<Uint8>(skeleton->r * slot->r * 255);
Uint8 g = static_cast<Uint8>(skeleton->g * slot->g * 255);