issue #2075: Adding spine editor support. Adding a new test 'SpineTest' in TestCpp, adding the parse code in "extensions/spine". It works only on iOS now.

This commit is contained in:
James Chen 2013-04-24 13:57:34 +08:00
parent dc0e89e839
commit 2d1172814d
46 changed files with 4647 additions and 3 deletions

View File

@ -51,7 +51,26 @@ GUI/CCEditBox/CCEditBoxImplAndroid.cpp \
network/HttpClient.cpp \
physics_nodes/CCPhysicsDebugNode.cpp \
physics_nodes/CCPhysicsSprite.cpp \
LocalStorage/LocalStorageAndroid.cpp
LocalStorage/LocalStorageAndroid.cpp \
spine/Animation.cpp \
spine/AnimationState.cpp \
spine/AnimationStateData.cpp \
spine/Atlas.cpp \
spine/AtlasAttachmentLoader.cpp \
spine/Attachment.cpp \
spine/AttachmentLoader.cpp \
spine/Bone.cpp \
spine/BoneData.cpp \
spine/Json.cpp \
spine/RegionAttachment.cpp \
spine/Skeleton.cpp \
spine/SkeletonData.cpp \
spine/SkeletonJson.cpp \
spine/Skin.cpp \
spine/Slot.cpp \
spine/SlotData.cpp \
spine/extension.cpp \
spine/spine-cocos2dx.cpp
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static

View File

@ -0,0 +1,462 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/Animation.h>
#include <math.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
Animation* Animation_create (const char* name, int timelineCount) {
Animation* self = NEW(Animation);
MALLOC_STR(self->name, name);
self->timelineCount = timelineCount;
self->timelines = MALLOC(Timeline*, timelineCount);
return self;
}
void Animation_dispose (Animation* self) {
int i;
for (i = 0; i < self->timelineCount; ++i)
Timeline_dispose(self->timelines[i]);
FREE(self->timelines);
FREE(self);
}
void Animation_apply (const Animation* self, Skeleton* skeleton, float time, int/*bool*/loop) {
if (loop && self->duration) time = fmodf(time, self->duration);
int i, n = self->timelineCount;
for (i = 0; i < n; ++i)
Timeline_apply(self->timelines[i], skeleton, time, 1);
}
void Animation_mix (const Animation* self, Skeleton* skeleton, float time, int/*bool*/loop, float alpha) {
if (loop && self->duration) time = fmodf(time, self->duration);
int i, n = self->timelineCount;
for (i = 0; i < n; ++i)
Timeline_apply(self->timelines[i], skeleton, time, alpha);
}
/**/
typedef struct _TimelineVtable {
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha);
void (*dispose) (Timeline* self);
} _TimelineVtable;
void _Timeline_init (Timeline* self, //
void (*dispose) (Timeline* self), //
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) {
CONST_CAST(_TimelineVtable*, self->vtable) = NEW(_TimelineVtable);
VTABLE(Timeline, self) ->dispose = dispose;
VTABLE(Timeline, self) ->apply = apply;
}
void _Timeline_deinit (Timeline* self) {
FREE(self->vtable);
}
void Timeline_dispose (Timeline* self) {
VTABLE(Timeline, self) ->dispose(self);
}
void Timeline_apply (const Timeline* self, Skeleton* skeleton, float time, float alpha) {
VTABLE(Timeline, self) ->apply(self, skeleton, time, alpha);
}
/**/
static const float CURVE_LINEAR = 0;
static const float CURVE_STEPPED = -1;
static const int CURVE_SEGMENTS = 10;
void _CurveTimeline_init (CurveTimeline* self, int frameCount, //
void (*dispose) (Timeline* self), //
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) {
_Timeline_init(SUPER(self), dispose, apply);
self->curves = CALLOC(float, (frameCount - 1) * 6);
}
void _CurveTimeline_deinit (CurveTimeline* self) {
_Timeline_deinit(SUPER(self));
FREE(self->curves);
}
void CurveTimeline_setLinear (CurveTimeline* self, int frameIndex) {
self->curves[frameIndex * 6] = CURVE_LINEAR;
}
void CurveTimeline_setStepped (CurveTimeline* self, int frameIndex) {
self->curves[frameIndex * 6] = CURVE_STEPPED;
}
void CurveTimeline_setCurve (CurveTimeline* 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 CurveTimeline_getCurvePercent (const CurveTimeline* self, int frameIndex, float percent) {
int curveIndex = frameIndex * 6;
float dfx = self->curves[curveIndex];
if (dfx == CURVE_LINEAR) return percent;
if (dfx == CURVE_STEPPED) return 0;
float dfy = self->curves[curveIndex + 1];
float ddfx = self->curves[curveIndex + 2];
float ddfy = self->curves[curveIndex + 3];
float dddfx = self->curves[curveIndex + 4];
float dddfy = self->curves[curveIndex + 5];
float x = dfx, y = dfy;
int 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--;
dfx += ddfx;
dfy += ddfy;
ddfx += dddfx;
ddfy += dddfy;
x += dfx;
y += dfy;
}
return y + (1 - y) * (percent - x) / (1 - x); /* Last point is 1,1. */
}
/* @param target After the first and before the last entry. */
static int binarySearch (float *values, int valuesLength, float target, int step) {
int low = 0;
int high = valuesLength / step - 2;
if (high == 0) return step;
int current = high >> 1;
while (1) {
if (values[(current + 1) * step] <= target)
low = current + 1;
else
high = current;
if (low == high) return (low + 1) * step;
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) {
if (values[i] <= target) continue;
return i;
}
return -1;
}*/
/**/
void _BaseTimeline_dispose (Timeline* timeline) {
struct BaseTimeline* self = SUB_CAST(struct BaseTimeline, timeline);
_CurveTimeline_deinit(SUPER(self));
FREE(self->frames);
FREE(self);
}
/* Many timelines have structure identical to struct BaseTimeline and extend CurveTimeline. **/
struct BaseTimeline* _BaseTimeline_create (int frameCount, int frameSize, //
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) {
struct BaseTimeline* self = NEW(struct BaseTimeline);
_CurveTimeline_init(SUPER(self), frameCount, _BaseTimeline_dispose, apply);
CONST_CAST(int, self->framesLength) = frameCount * frameSize;
CONST_CAST(float*, self->frames) = CALLOC(float, self->framesLength);
return self;
}
/**/
static const int ROTATE_LAST_FRAME_TIME = -2;
static const int ROTATE_FRAME_VALUE = 1;
void _RotateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) {
RotateTimeline* self = SUB_CAST(RotateTimeline, timeline);
if (time < self->frames[0]) return; /* Time is before first frame. */
Bone *bone = skeleton->bones[self->boneIndex];
if (time >= self->frames[self->framesLength - 2]) { /* Time is after last frame. */
float amount = bone->data->rotation + self->frames[self->framesLength - 1] - bone->rotation;
while (amount > 180)
amount -= 360;
while (amount < -180)
amount += 360;
bone->rotation += amount * alpha;
return;
}
/* Interpolate between the last frame and the current frame. */
int frameIndex = binarySearch(self->frames, self->framesLength, time, 2);
float lastFrameValue = self->frames[frameIndex - 1];
float frameTime = self->frames[frameIndex];
float percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
percent = CurveTimeline_getCurvePercent(SUPER(self), frameIndex / 2 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
float amount = self->frames[frameIndex + ROTATE_FRAME_VALUE] - lastFrameValue;
while (amount > 180)
amount -= 360;
while (amount < -180)
amount += 360;
amount = bone->data->rotation + (lastFrameValue + amount * percent) - bone->rotation;
while (amount > 180)
amount -= 360;
while (amount < -180)
amount += 360;
bone->rotation += amount * alpha;
}
RotateTimeline* RotateTimeline_create (int frameCount) {
return _BaseTimeline_create(frameCount, 2, _RotateTimeline_apply);
}
void RotateTimeline_setFrame (RotateTimeline* self, int frameIndex, float time, float angle) {
frameIndex *= 2;
self->frames[frameIndex] = time;
self->frames[frameIndex + 1] = angle;
}
/**/
static const int TRANSLATE_LAST_FRAME_TIME = -3;
static const int TRANSLATE_FRAME_X = 1;
static const int TRANSLATE_FRAME_Y = 2;
void _TranslateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) {
TranslateTimeline* self = SUB_CAST(TranslateTimeline, timeline);
if (time < self->frames[0]) return; /* Time is before first frame. */
Bone *bone = skeleton->bones[self->boneIndex];
if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */
bone->x += (bone->data->x + self->frames[self->framesLength - 2] - bone->x) * alpha;
bone->y += (bone->data->y + self->frames[self->framesLength - 1] - bone->y) * alpha;
return;
}
/* Interpolate between the last frame and the current frame. */
int frameIndex = binarySearch(self->frames, self->framesLength, time, 3);
float lastFrameX = self->frames[frameIndex - 2];
float lastFrameY = self->frames[frameIndex - 1];
float frameTime = self->frames[frameIndex];
float percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime);
percent = CurveTimeline_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)
* alpha;
bone->y += (bone->data->y + lastFrameY + (self->frames[frameIndex + TRANSLATE_FRAME_Y] - lastFrameY) * percent - bone->y)
* alpha;
}
TranslateTimeline* TranslateTimeline_create (int frameCount) {
return _BaseTimeline_create(frameCount, 3, _TranslateTimeline_apply);
}
void TranslateTimeline_setFrame (TranslateTimeline* self, int frameIndex, float time, float x, float y) {
frameIndex *= 3;
self->frames[frameIndex] = time;
self->frames[frameIndex + 1] = x;
self->frames[frameIndex + 2] = y;
}
/**/
void _ScaleTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) {
ScaleTimeline* self = SUB_CAST(ScaleTimeline, timeline);
if (time < self->frames[0]) return; /* Time is before first frame. */
Bone *bone = skeleton->bones[self->boneIndex];
if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */
bone->scaleX += (bone->data->scaleX - 1 + self->frames[self->framesLength - 2] - bone->scaleX) * alpha;
bone->scaleY += (bone->data->scaleY - 1 + self->frames[self->framesLength - 1] - bone->scaleY) * alpha;
return;
}
/* Interpolate between the last frame and the current frame. */
int frameIndex = binarySearch(self->frames, self->framesLength, time, 3);
float lastFrameX = self->frames[frameIndex - 2];
float lastFrameY = self->frames[frameIndex - 1];
float frameTime = self->frames[frameIndex];
float percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime);
percent = CurveTimeline_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) * alpha;
bone->scaleY += (bone->data->scaleY - 1 + lastFrameY + (self->frames[frameIndex + TRANSLATE_FRAME_Y] - lastFrameY) * percent
- bone->scaleY) * alpha;
}
ScaleTimeline* ScaleTimeline_create (int frameCount) {
return _BaseTimeline_create(frameCount, 3, _ScaleTimeline_apply);
}
void ScaleTimeline_setFrame (ScaleTimeline* self, int frameIndex, float time, float x, float y) {
TranslateTimeline_setFrame(self, frameIndex, time, x, y);
}
/**/
static const int COLOR_LAST_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 _ColorTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) {
ColorTimeline* self = (ColorTimeline*)timeline;
if (time < self->frames[0]) return; /* Time is before first frame. */
Slot *slot = skeleton->slots[self->slotIndex];
if (time >= self->frames[self->framesLength - 5]) { /* Time is after last frame. */
int i = self->framesLength - 1;
slot->r = self->frames[i - 3];
slot->g = self->frames[i - 2];
slot->b = self->frames[i - 1];
slot->a = self->frames[i];
return;
}
/* Interpolate between the last frame and the current frame. */
int frameIndex = binarySearch(self->frames, self->framesLength, time, 5);
float lastFrameR = self->frames[frameIndex - 4];
float lastFrameG = self->frames[frameIndex - 3];
float lastFrameB = self->frames[frameIndex - 2];
float lastFrameA = self->frames[frameIndex - 1];
float frameTime = self->frames[frameIndex];
float percent = 1 - (time - frameTime) / (self->frames[frameIndex + COLOR_LAST_FRAME_TIME] - frameTime);
percent = CurveTimeline_getCurvePercent(SUPER(self), frameIndex / 5 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
float r = lastFrameR + (self->frames[frameIndex + COLOR_FRAME_R] - lastFrameR) * percent;
float g = lastFrameG + (self->frames[frameIndex + COLOR_FRAME_G] - lastFrameG) * percent;
float b = lastFrameB + (self->frames[frameIndex + COLOR_FRAME_B] - lastFrameB) * percent;
float a = lastFrameA + (self->frames[frameIndex + COLOR_FRAME_A] - lastFrameA) * percent;
if (alpha < 1) {
slot->r += (r - slot->r) * alpha;
slot->g += (g - slot->g) * alpha;
slot->b += (b - slot->b) * alpha;
slot->a += (a - slot->a) * alpha;
} else {
slot->r = r;
slot->g = g;
slot->b = b;
slot->a = a;
}
}
ColorTimeline* ColorTimeline_create (int frameCount) {
return (ColorTimeline*)_BaseTimeline_create(frameCount, 5, _ColorTimeline_apply);
}
void ColorTimeline_setFrame (ColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a) {
frameIndex *= 5;
self->frames[frameIndex] = time;
self->frames[frameIndex + 1] = r;
self->frames[frameIndex + 2] = g;
self->frames[frameIndex + 3] = b;
self->frames[frameIndex + 4] = a;
}
/**/
void _AttachmentTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) {
AttachmentTimeline* self = (AttachmentTimeline*)timeline;
if (time < self->frames[0]) return; /* Time is before first frame. */
int frameIndex;
if (time >= self->frames[self->framesLength - 1]) /* Time is after last frame. */
frameIndex = self->framesLength - 1;
else
frameIndex = binarySearch(self->frames, self->framesLength, time, 1) - 1;
const char* attachmentName = self->attachmentNames[frameIndex];
Slot_setAttachment(skeleton->slots[self->slotIndex],
attachmentName ? Skeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0);
}
void _AttachmentTimeline_dispose (Timeline* timeline) {
_Timeline_deinit(timeline);
AttachmentTimeline* self = (AttachmentTimeline*)timeline;
int i;
for (i = 0; i < self->framesLength; ++i)
FREE(self->attachmentNames[i]);
FREE(self->attachmentNames);
FREE(self);
}
AttachmentTimeline* AttachmentTimeline_create (int frameCount) {
AttachmentTimeline* self = NEW(AttachmentTimeline);
_Timeline_init(SUPER(self), _AttachmentTimeline_dispose, _AttachmentTimeline_apply);
CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, frameCount);
CONST_CAST(int, self->framesLength) = frameCount;
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
return self;
}
void AttachmentTimeline_setFrame (AttachmentTimeline* self, int frameIndex, float time, const char* attachmentName) {
self->frames[frameIndex] = time;
FREE(self->attachmentNames[frameIndex]);
if (attachmentName)
MALLOC_STR(self->attachmentNames[frameIndex], attachmentName);
else
self->attachmentNames[frameIndex] = 0;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,132 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_ANIMATION_H_
#define SPINE_ANIMATION_H_
namespace cocos2d { namespace extension {
typedef struct Timeline Timeline;
struct Skeleton;
typedef struct {
const char* const name;
float duration;
int timelineCount;
Timeline** timelines;
} Animation;
Animation* Animation_create (const char* name, int timelineCount);
void Animation_dispose (Animation* self);
void Animation_apply (const Animation* self, struct Skeleton* skeleton, float time, int/*bool*/loop);
void Animation_mix (const Animation* self, struct Skeleton* skeleton, float time, int/*bool*/loop, float alpha);
/**/
struct Timeline {
const void* const vtable;
};
void Timeline_dispose (Timeline* self);
void Timeline_apply (const Timeline* self, struct Skeleton* skeleton, float time, float alpha);
/**/
typedef struct {
Timeline super;
float* curves; /* dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... */
} CurveTimeline;
void CurveTimeline_setLinear (CurveTimeline* self, int frameIndex);
void CurveTimeline_setStepped (CurveTimeline* self, int frameIndex);
/* Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
* cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
* the difference between the keyframe's values. */
void CurveTimeline_setCurve (CurveTimeline* self, int frameIndex, float cx1, float cy1, float cx2, float cy2);
float CurveTimeline_getCurvePercent (const CurveTimeline* self, int frameIndex, float percent);
/**/
typedef struct BaseTimeline {
CurveTimeline super;
int const framesLength;
float* const frames; /* time, angle, ... for rotate. time, x, y, ... for translate and scale. */
int boneIndex;
} RotateTimeline;
RotateTimeline* RotateTimeline_create (int frameCount);
void RotateTimeline_setFrame (RotateTimeline* self, int frameIndex, float time, float angle);
/**/
typedef struct BaseTimeline TranslateTimeline;
TranslateTimeline* TranslateTimeline_create (int frameCount);
void TranslateTimeline_setFrame (TranslateTimeline* self, int frameIndex, float time, float x, float y);
/**/
typedef struct BaseTimeline ScaleTimeline;
ScaleTimeline* ScaleTimeline_create (int frameCount);
void ScaleTimeline_setFrame (ScaleTimeline* self, int frameIndex, float time, float x, float y);
/**/
typedef struct {
CurveTimeline super;
int const framesLength;
float* const frames; /* time, r, g, b, a, ... */
int slotIndex;
} ColorTimeline;
ColorTimeline* ColorTimeline_create (int frameCount);
void ColorTimeline_setFrame (ColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a);
/**/
typedef struct {
Timeline super;
int const framesLength;
float* const frames; /* time, ... */
int slotIndex;
const char** const attachmentNames;
} AttachmentTimeline;
AttachmentTimeline* AttachmentTimeline_create (int frameCount);
/* @param attachmentName May be 0. */
void AttachmentTimeline_setFrame (AttachmentTimeline* self, int frameIndex, float time, const char* attachmentName);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_ANIMATION_H_ */

View File

@ -0,0 +1,102 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/AnimationState.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
typedef struct {
AnimationState super;
Animation *previous;
float previousTime;
int/*bool*/previousLoop;
float mixTime;
float mixDuration;
} _Internal;
AnimationState* AnimationState_create (AnimationStateData* data) {
AnimationState* self = SUPER(NEW(_Internal));
CONST_CAST(AnimationStateData*, self->data) = data;
return self;
}
void AnimationState_dispose (AnimationState* self) {
FREE(self);
}
void AnimationState_update (AnimationState* self, float delta) {
self->time += delta;
SUB_CAST(_Internal, self) ->previousTime += delta;
SUB_CAST(_Internal, self) ->mixTime += delta;
}
void AnimationState_apply (AnimationState* self, Skeleton* skeleton) {
if (!self->animation) return;
_Internal* internal = SUB_CAST(_Internal, self);
if (internal->previous) {
Animation_apply(internal->previous, skeleton, internal->previousTime, internal->previousLoop);
float alpha = internal->mixTime / internal->mixDuration;
if (alpha >= 1) {
alpha = 1;
internal->previous = 0;
}
Animation_mix(self->animation, skeleton, self->time, self->loop, alpha);
} else
Animation_apply(self->animation, skeleton, self->time, self->loop);
}
void AnimationState_setAnimationByName (AnimationState* self, const char* animationName, int/**/loop) {
Animation* animation = SkeletonData_findAnimation(self->data->skeletonData, animationName);
AnimationState_setAnimation(self, animation, loop);
}
void AnimationState_setAnimation (AnimationState* self, Animation* newAnimation, int/**/loop) {
_Internal* internal = SUB_CAST(_Internal, self);
internal->previous = 0;
if (newAnimation && self->animation && self->data) {
internal->mixDuration = AnimationStateData_getMix(self->data, self->animation, newAnimation);
if (internal->mixDuration > 0) {
internal->mixTime = 0;
internal->previous = self->animation;
internal->previousTime = self->time;
internal->previousLoop = self->loop;
}
}
CONST_CAST(Animation*, self->animation) = newAnimation;
self->loop = loop;
self->time = 0;
}
void AnimationState_clearAnimation (AnimationState* self) {
SUB_CAST(_Internal, self) ->previous = 0;
CONST_CAST(Animation*, self->animation) = 0;
}
int/*bool*/AnimationState_isComplete (AnimationState* self) {
return !self->animation || self->time >= self->animation->duration;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_ANIMATIONSTATE_H_
#define SPINE_ANIMATIONSTATE_H_
#include <spine/AnimationStateData.h>
namespace cocos2d { namespace extension {
typedef struct {
AnimationStateData* const data;
Animation* const animation;
float time;
int/*bool*/loop;
} AnimationState;
/* @param data May be 0 for no mixing. */
AnimationState* AnimationState_create (AnimationStateData* data);
void AnimationState_dispose (AnimationState* self);
void AnimationState_update (AnimationState* self, float delta);
void AnimationState_apply (AnimationState* self, struct Skeleton* skeleton);
/* @param animationName May be 0. */
void AnimationState_setAnimationByName (AnimationState* self, const char* animationName, int/**/loop);
/* @param animation May be 0. */
void AnimationState_setAnimation (AnimationState* self, Animation* animation, int/**/loop);
void AnimationState_clearAnimation (AnimationState* self);
int/*bool*/AnimationState_isComplete (AnimationState* self);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_ANIMATIONSTATE_H_ */

View File

@ -0,0 +1,144 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/AnimationStateData.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
typedef struct _ToEntry _ToEntry;
struct _ToEntry {
Animation* animation;
float duration;
_ToEntry* next;
};
_ToEntry* _ToEntry_create (Animation* to, float duration) {
_ToEntry* self = NEW(_ToEntry);
self->animation = to;
self->duration = duration;
return self;
}
void _ToEntry_dispose (_ToEntry* self) {
FREE(self);
}
/**/
typedef struct _FromEntry _FromEntry;
struct _FromEntry {
Animation* animation;
_ToEntry* toEntries;
_FromEntry* next;
};
_FromEntry* _FromEntry_create (Animation* from) {
_FromEntry* self = NEW(_FromEntry);
self->animation = from;
return self;
}
void _FromEntry_dispose (_FromEntry* self) {
FREE(self);
}
/**/
AnimationStateData* AnimationStateData_create (SkeletonData* skeletonData) {
AnimationStateData* self = NEW(AnimationStateData);
CONST_CAST(SkeletonData*, self->skeletonData) = skeletonData;
return self;
}
void AnimationStateData_dispose (AnimationStateData* self) {
_FromEntry* fromEntry = (_FromEntry*)self->entries;
while (fromEntry) {
_ToEntry* toEntry = fromEntry->toEntries;
while (toEntry) {
_ToEntry* next = toEntry->next;
_ToEntry_dispose(toEntry);
toEntry = next;
}
_FromEntry* next = fromEntry->next;
_FromEntry_dispose(fromEntry);
fromEntry = next;
}
FREE(self);
}
void AnimationStateData_setMixByName (AnimationStateData* self, const char* fromName, const char* toName, float duration) {
Animation* from = SkeletonData_findAnimation(self->skeletonData, fromName);
if (!from) return;
Animation* to = SkeletonData_findAnimation(self->skeletonData, toName);
if (!to) return;
AnimationStateData_setMix(self, from, to, duration);
}
void AnimationStateData_setMix (AnimationStateData* self, Animation* from, Animation* to, float duration) {
/* Find existing FromEntry. */
_FromEntry* fromEntry = (_FromEntry*)self->entries;
while (fromEntry) {
if (fromEntry->animation == from) {
/* Find existing ToEntry. */
_ToEntry* toEntry = fromEntry->toEntries;
while (toEntry) {
if (toEntry->animation == to) {
toEntry->duration = duration;
return;
}
toEntry = toEntry->next;
}
break; /* Add new ToEntry to the existing FromEntry. */
}
fromEntry = fromEntry->next;
}
if (!fromEntry) {
fromEntry = _FromEntry_create(from);
fromEntry->next = (_FromEntry*)self->entries;
CONST_CAST(_FromEntry*, self->entries) = fromEntry;
}
_ToEntry* toEntry = _ToEntry_create(to, duration);
toEntry->next = fromEntry->toEntries;
fromEntry->toEntries = toEntry;
}
float AnimationStateData_getMix (AnimationStateData* self, Animation* from, Animation* to) {
_FromEntry* fromEntry = (_FromEntry*)self->entries;
while (fromEntry) {
if (fromEntry->animation == from) {
_ToEntry* toEntry = fromEntry->toEntries;
while (toEntry) {
if (toEntry->animation == to) return toEntry->duration;
toEntry = toEntry->next;
}
}
fromEntry = fromEntry->next;
}
return 0;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_ANIMATIONSTATEDATA_H_
#define SPINE_ANIMATIONSTATEDATA_H_
#include <spine/Animation.h>
#include <spine/SkeletonData.h>
namespace cocos2d { namespace extension {
typedef struct {
SkeletonData* const skeletonData;
const void* const entries;
} AnimationStateData;
AnimationStateData* AnimationStateData_create (SkeletonData* skeletonData);
void AnimationStateData_dispose (AnimationStateData* self);
void AnimationStateData_setMixByName (AnimationStateData* self, const char* fromName, const char* toName, float duration);
void AnimationStateData_setMix (AnimationStateData* self, Animation* from, Animation* to, float duration);
/* Returns 0 if there is no mixing between the animations. */
float AnimationStateData_getMix (AnimationStateData* self, Animation* from, Animation* to);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_ANIMATIONSTATEDATA_H_ */

327
extensions/spine/Atlas.cpp Normal file
View File

@ -0,0 +1,327 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/Atlas.h>
#include <ctype.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
AtlasPage* AtlasPage_create (const char* name) {
AtlasPage* self = NEW(AtlasPage);
MALLOC_STR(self->name, name);
return self;
}
void AtlasPage_dispose (AtlasPage* self) {
FREE(self->name);
_AtlasPage_disposeTexture(self);
}
/**/
AtlasRegion* AtlasRegion_create () {
return NEW(AtlasRegion) ;
}
void AtlasRegion_dispose (AtlasRegion* self) {
FREE(self->name);
FREE(self->splits);
FREE(self->pads);
FREE(self);
}
/**/
typedef struct {
const char* begin;
const char* end;
} Str;
static void trim (Str* str) {
while (isspace(*str->begin) && str->begin < str->end)
(str->begin)++;
if (str->begin == str->end) return;
str->end--;
while (isspace(*str->end) && str->end >= str->begin)
str->end--;
str->end++;
}
/* Tokenize string without modification. Returns 0 on failure. */
static int readLine (const char* begin, const char* end, Str* str) {
static const char* nextStart;
if (begin) {
nextStart = begin;
return 1;
}
if (nextStart == end) return 0;
str->begin = nextStart;
/* Find next delimiter. */
while (nextStart != end && *nextStart != '\n')
nextStart++;
str->end = nextStart;
trim(str);
if (nextStart != end) nextStart++;
return 1;
}
/* Moves str->begin past the first occurence of c. Returns 0 on failure. */
static int beginPast (Str* str, char c) {
const char* begin = str->begin;
while (1) {
char lastSkippedChar = *begin;
if (begin == str->end) return 0;
begin++;
if (lastSkippedChar == c) break;
}
str->begin = begin;
return 1;
}
/* Returns 0 on failure. */
static int readValue (const char* end, Str* str) {
readLine(0, end, str);
if (!beginPast(str, ':')) return 0;
trim(str);
return 1;
}
/* Returns the number of tuple values read (2, 4, or 0 for failure). */
static int readTuple (const char* end, Str tuple[]) {
Str str;
readLine(0, end, &str);
if (!beginPast(&str, ':')) return 0;
int i = 0;
for (i = 0; i < 3; ++i) {
tuple[i].begin = str.begin;
if (!beginPast(&str, ',')) {
if (i == 0) return 0;
break;
}
tuple[i].end = str.begin - 2;
trim(&tuple[i]);
}
tuple[i].begin = str.begin;
tuple[i].end = str.end;
trim(&tuple[i]);
return i + 1;
}
static char* mallocString (Str* str) {
int length = str->end - str->begin;
char* string = MALLOC(char, length + 1);
memcpy(string, str->begin, length);
string[length] = '\0';
return string;
}
static int indexOf (const char** array, int count, Str* str) {
int length = str->end - str->begin;
int i;
for (i = count - 1; i >= 0; i--)
if (strncmp(array[i], str->begin, length) == 0) return i;
return -1;
}
static int equals (Str* str, const char* other) {
return strncmp(other, str->begin, str->end - str->begin) == 0;
}
static int toInt (Str* str) {
return strtol(str->begin, (char**)&str->end, 10);
}
static Atlas* abortAtlas (Atlas* self) {
Atlas_dispose(self);
return 0;
}
static const char* formatNames[] = {"Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888"};
static const char* textureFilterNames[] = {"Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest",
"MipMapNearestLinear", "MipMapLinearLinear"};
Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) {
const char* end = begin + length;
int dirLength = strlen(dir);
int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\';
Atlas* self = NEW(Atlas);
AtlasPage *page = 0;
AtlasPage *lastPage = 0;
AtlasRegion *lastRegion = 0;
Str str;
Str tuple[4];
readLine(begin, 0, 0);
while (readLine(0, end, &str)) {
if (str.end - str.begin == 0) {
page = 0;
} else if (!page) {
char* name = mallocString(&str);
char* path = MALLOC(char, dirLength + needsSlash + strlen(name) + 1);
memcpy(path, dir, dirLength);
if (needsSlash) path[dirLength] = '/';
strcpy(path + dirLength + needsSlash, name);
page = AtlasPage_create(name);
FREE(name);
if (lastPage)
lastPage->next = page;
else
self->pages = page;
lastPage = page;
if (!readValue(end, &str)) return abortAtlas(self);
page->format = (AtlasFormat)indexOf(formatNames, 7, &str);
if (!readTuple(end, tuple)) return abortAtlas(self);
page->minFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple);
page->magFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple + 1);
if (!readValue(end, &str)) return abortAtlas(self);
if (!equals(&str, "none")) {
page->uWrap = *str.begin == 'x' ? ATLAS_REPEAT : (*str.begin == 'y' ? ATLAS_CLAMPTOEDGE : ATLAS_REPEAT);
page->vWrap = *str.begin == 'x' ? ATLAS_CLAMPTOEDGE : (*str.begin == 'y' ? ATLAS_REPEAT : ATLAS_REPEAT);
}
_AtlasPage_createTexture(page, path);
FREE(path);
} else {
AtlasRegion *region = AtlasRegion_create();
if (lastRegion)
lastRegion->next = region;
else
self->regions = region;
lastRegion = region;
region->page = page;
region->name = mallocString(&str);
if (!readValue(end, &str)) return abortAtlas(self);
region->rotate = equals(&str, "true");
if (readTuple(end, tuple) != 2) return abortAtlas(self);
region->x = toInt(tuple);
region->y = toInt(tuple + 1);
if (readTuple(end, tuple) != 2) return abortAtlas(self);
region->width = toInt(tuple);
region->height = toInt(tuple + 1);
region->u = region->x / (float)page->width;
region->v = region->y / (float)page->height;
region->u2 = (region->x + region->width) / (float)page->width;
region->v2 = (region->y + region->height) / (float)page->height;
int count;
if (!(count = readTuple(end, tuple))) return abortAtlas(self);
if (count == 4) { /* split is optional */
region->splits = MALLOC(int, 4);
region->splits[0] = toInt(tuple);
region->splits[1] = toInt(tuple + 1);
region->splits[2] = toInt(tuple + 2);
region->splits[3] = toInt(tuple + 3);
if (!(count = readTuple(end, tuple))) return abortAtlas(self);
if (count == 4) { /* pad is optional, but only present with splits */
region->pads = MALLOC(int, 4);
region->pads[0] = toInt(tuple);
region->pads[1] = toInt(tuple + 1);
region->pads[2] = toInt(tuple + 2);
region->pads[3] = toInt(tuple + 3);
if (!readTuple(end, tuple)) return abortAtlas(self);
}
}
region->originalWidth = toInt(tuple);
region->originalHeight = toInt(tuple + 1);
readTuple(end, tuple);
region->offsetX = (float)toInt(tuple);
region->offsetY = (float)toInt(tuple + 1);
if (!readValue(end, &str)) return abortAtlas(self);
region->index = toInt(&str);
}
}
return self;
}
Atlas* Atlas_readAtlasFile (const char* path) {
Atlas* atlas = 0;
/* Get directory from atlas path. */
const char* lastForwardSlash = strrchr(path, '/');
const char* lastBackwardSlash = strrchr(path, '\\');
const char* lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash;
if (lastSlash == path) lastSlash++; /* Never drop starting slash. */
int dirLength = lastSlash ? lastSlash - path : 0;
char* dir = MALLOC(char, dirLength + 1);
memcpy(dir, path, dirLength);
dir[dirLength] = '\0';
int length;
const char* data = _Util_readFile(path, &length);
if (data) atlas = Atlas_readAtlas(data, length, dir);
FREE(data);
FREE(dir);
return atlas;
}
void Atlas_dispose (Atlas* self) {
AtlasPage* page = self->pages;
while (page) {
AtlasPage* nextPage = page->next;
AtlasPage_dispose(page);
page = nextPage;
}
AtlasRegion* region = self->regions;
while (region) {
AtlasRegion* nextRegion = region->next;
AtlasRegion_dispose(region);
region = nextRegion;
}
FREE(self);
}
AtlasRegion* Atlas_findRegion (const Atlas* self, const char* name) {
AtlasRegion* region = self->regions;
while (region) {
if (strcmp(region->name, name) == 0) return region;
region = region->next;
}
return 0;
}
}} // namespace cocos2d { namespace extension {

106
extensions/spine/Atlas.h Normal file
View File

@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_ATLAS_H_
#define SPINE_ATLAS_H_
namespace cocos2d { namespace extension {
typedef enum {
ATLAS_ALPHA, ATLAS_INTENSITY, ATLAS_LUMINANCE_ALPHA, ATLAS_RGB565, ATLAS_RGBA4444, ATLAS_RGB888, ATLAS_RGBA8888
} AtlasFormat;
typedef enum {
ATLAS_NEAREST,
ATLAS_LINEAR,
ATLAS_MIPMAP,
ATLAS_MIPMAP_NEAREST_NEAREST,
ATLAS_MIPMAP_LINEAR_NEAREST,
ATLAS_MIPMAP_NEAREST_LINEAR,
ATLAS_MIPMAP_LINEAR_LINEAR
} AtlasFilter;
typedef enum {
ATLAS_MIRROREDREPEAT, ATLAS_CLAMPTOEDGE, ATLAS_REPEAT
} AtlasWrap;
typedef struct AtlasPage AtlasPage;
struct AtlasPage {
const char* name;
AtlasFormat format;
AtlasFilter minFilter, magFilter;
AtlasWrap uWrap, vWrap;
void* texture;
int width, height;
AtlasPage* next;
};
AtlasPage* AtlasPage_create (const char* name);
void AtlasPage_dispose (AtlasPage* self);
/**/
typedef struct AtlasRegion AtlasRegion;
struct AtlasRegion {
const char* name;
int x, y, width, height;
float u, v, u2, v2;
float offsetX, offsetY;
int originalWidth, originalHeight;
int index;
int/*bool*/rotate;
int/*bool*/flip;
int* splits;
int* pads;
AtlasPage* page;
AtlasRegion* next;
};
AtlasRegion* AtlasRegion_create ();
void AtlasRegion_dispose (AtlasRegion* self);
/**/
typedef struct {
AtlasPage* pages;
AtlasRegion* regions;
} Atlas;
/* Image files referenced in the atlas file will be prefixed with dir. */
Atlas* Atlas_readAtlas (const char* data, int length, const char* dir);
/* Image files referenced in the atlas file will be prefixed with the directory containing the atlas file. */
Atlas* Atlas_readAtlasFile (const char* path);
void Atlas_dispose (Atlas* atlas);
/* Returns 0 if the region was not found. */
AtlasRegion* Atlas_findRegion (const Atlas* self, const char* name);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_ATLAS_H_ */

View File

@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/AtlasAttachmentLoader.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
Attachment* _AtlasAttachmentLoader_newAttachment (AttachmentLoader* loader, Skin* skin, AttachmentType type, const char* name) {
AtlasAttachmentLoader* self = SUB_CAST(AtlasAttachmentLoader, loader);
switch (type) {
case ATTACHMENT_REGION: {
AtlasRegion* region = Atlas_findRegion(self->atlas, name);
if (!region) {
_AttachmentLoader_setError(loader, "Region not found: ", name);
return 0;
}
RegionAttachment* attachment = RegionAttachment_create(name);
attachment->region = region;
return SUPER(attachment);
}
default:
_AttachmentLoader_setUnknownTypeError(loader, type);
return 0;
}
}
AtlasAttachmentLoader* AtlasAttachmentLoader_create (Atlas* atlas) {
AtlasAttachmentLoader* self = NEW(AtlasAttachmentLoader);
_AttachmentLoader_init(SUPER(self), _AttachmentLoader_deinit, _AtlasAttachmentLoader_newAttachment);
self->atlas = atlas;
return self;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_ATLASATTACHMENTLOADER_H_
#define SPINE_ATLASATTACHMENTLOADER_H_
#include <spine/AttachmentLoader.h>
#include <spine/Atlas.h>
namespace cocos2d { namespace extension {
typedef struct {
AttachmentLoader super;
Atlas* atlas;
} AtlasAttachmentLoader;
AtlasAttachmentLoader* AtlasAttachmentLoader_create (Atlas* atlas);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_ATLASATTACHMENTLOADER_H_ */

View File

@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/Attachment.h>
#include <spine/extension.h>
#include <spine/Slot.h>
namespace cocos2d { namespace extension {
typedef struct _AttachmentVtable {
void (*dispose) (Attachment* self);
} _AttachmentVtable;
void _Attachment_init (Attachment* self, const char* name, AttachmentType type, //
void (*dispose) (Attachment* self)) {
CONST_CAST(_AttachmentVtable*, self->vtable) = NEW(_AttachmentVtable);
VTABLE(Attachment, self) ->dispose = dispose;
MALLOC_STR(self->name, name);
self->type = type;
}
void _Attachment_deinit (Attachment* self) {
FREE(self->vtable);
FREE(self->name);
}
void Attachment_dispose (Attachment* self) {
VTABLE(Attachment, self) ->dispose(self);
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_ATTACHMENT_H_
#define SPINE_ATTACHMENT_H_
namespace cocos2d { namespace extension {
struct Slot;
typedef enum {
ATTACHMENT_REGION, ATTACHMENT_REGION_SEQUENCE
} AttachmentType;
typedef struct Attachment Attachment;
struct Attachment {
const char* const name;
AttachmentType type;
const void* const vtable;
};
void Attachment_dispose (Attachment* self);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_ATTACHMENT_H_ */

View File

@ -0,0 +1,76 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/AttachmentLoader.h>
#include <stdio.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
typedef struct _AttachmentLoaderVtable {
Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name);
void (*dispose) (AttachmentLoader* self);
} _AttachmentLoaderVtable;
void _AttachmentLoader_init (AttachmentLoader* self, //
void (*dispose) (AttachmentLoader* self), //
Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name)) {
CONST_CAST(_AttachmentLoaderVtable*, self->vtable) = NEW(_AttachmentLoaderVtable);
VTABLE(AttachmentLoader, self) ->dispose = dispose;
VTABLE(AttachmentLoader, self) ->newAttachment = newAttachment;
}
void _AttachmentLoader_deinit (AttachmentLoader* self) {
FREE(self->vtable);
FREE(self->error1);
FREE(self->error2);
}
void AttachmentLoader_dispose (AttachmentLoader* self) {
VTABLE(AttachmentLoader, self) ->dispose(self);
}
Attachment* AttachmentLoader_newAttachment (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name) {
FREE(self->error1);
FREE(self->error2);
self->error1 = 0;
self->error2 = 0;
return VTABLE(AttachmentLoader, self) ->newAttachment(self, skin, type, name);
}
void _AttachmentLoader_setError (AttachmentLoader* self, const char* error1, const char* error2) {
FREE(self->error1);
FREE(self->error2);
MALLOC_STR(self->error1, error1);
MALLOC_STR(self->error2, error2);
}
void _AttachmentLoader_setUnknownTypeError (AttachmentLoader* self, AttachmentType type) {
char buffer[16];
sprintf(buffer, "%d", type);
_AttachmentLoader_setError(self, "Unknown attachment type: ", buffer);
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_ATTACHMENTLOADER_H_
#define SPINE_ATTACHMENTLOADER_H_
#include <spine/Attachment.h>
#include <spine/Skin.h>
namespace cocos2d { namespace extension {
typedef struct AttachmentLoader AttachmentLoader;
struct AttachmentLoader {
const char* error1;
const char* error2;
const void* const vtable;
};
void AttachmentLoader_dispose (AttachmentLoader* self);
/* Returns 0 to not load an attachment. If 0 is returned and AttachmentLoader.error1 is set, an error occurred. */
Attachment* AttachmentLoader_newAttachment (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_ATTACHMENTLOADER_H_ */

93
extensions/spine/Bone.cpp Normal file
View File

@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/Bone.h>
#include <math.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
static int yDown;
void Bone_setYDown (int value) {
yDown = value;
}
Bone* Bone_create (BoneData* data, Bone* parent) {
Bone* self = NEW(Bone);
CONST_CAST(BoneData*, self->data) = data;
CONST_CAST(Bone*, self->parent) = parent;
Bone_setToBindPose(self);
return self;
}
void Bone_dispose (Bone* self) {
FREE(self);
}
void Bone_setToBindPose (Bone* 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 Bone_updateWorldTransform (Bone* self, int flipX, int flipY) {
if (self->parent) {
CONST_CAST(float, self->worldX) = self->x * self->parent->m00 + self->y * self->parent->m01 + self->parent->worldX;
CONST_CAST(float, self->worldY) = self->x * self->parent->m10 + self->y * self->parent->m11 + self->parent->worldY;
CONST_CAST(float, self->worldScaleX) = self->parent->worldScaleX * self->scaleX;
CONST_CAST(float, self->worldScaleY) = self->parent->worldScaleY * self->scaleY;
CONST_CAST(float, self->worldRotation) = self->parent->worldRotation + self->rotation;
} else {
CONST_CAST(float, self->worldX) = self->x;
CONST_CAST(float, self->worldY) = self->y;
CONST_CAST(float, self->worldScaleX) = self->scaleX;
CONST_CAST(float, self->worldScaleY) = self->scaleY;
CONST_CAST(float, self->worldRotation) = self->rotation;
}
float radians = (float)(self->worldRotation * 3.1415926535897932385 / 180);
float cosine = cosf(radians);
float sine = sinf(radians);
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;
}
if (flipY) {
CONST_CAST(float, self->m10) = -self->m10;
CONST_CAST(float, self->m11) = -self->m11;
}
if (yDown) {
CONST_CAST(float, self->m10) = -self->m10;
CONST_CAST(float, self->m11) = -self->m11;
}
}
}} // namespace cocos2d { namespace extension {

59
extensions/spine/Bone.h Normal file
View File

@ -0,0 +1,59 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_BONE_H_
#define SPINE_BONE_H_
#include <spine/BoneData.h>
namespace cocos2d { namespace extension {
typedef struct Bone Bone;
struct Bone {
BoneData* const data;
Bone* const parent;
float x, y;
float rotation;
float scaleX, scaleY;
float const m00, m01, worldX; /* a b x */
float const m10, m11, worldY; /* c d y */
float const worldRotation;
float const worldScaleX, worldScaleY;
};
void Bone_setYDown (int/*bool*/yDown);
/* @param parent May be 0. */
Bone* Bone_create (BoneData* data, Bone* parent);
void Bone_dispose (Bone* self);
void Bone_setToBindPose (Bone* self);
void Bone_updateWorldTransform (Bone* self, int/*bool*/flipX, int/*bool*/flipY);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_BONE_H_ */

View File

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/BoneData.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
BoneData* BoneData_create (const char* name, BoneData* parent) {
BoneData* self = NEW(BoneData);
MALLOC_STR(self->name, name);
CONST_CAST(BoneData*, self->parent) = parent;
self->scaleX = 1;
self->scaleY = 1;
return self;
}
void BoneData_dispose (BoneData* self) {
FREE(self->name);
FREE(self);
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_BONEDATA_H_
#define SPINE_BONEDATA_H_
namespace cocos2d { namespace extension {
typedef struct BoneData BoneData;
struct BoneData {
const char* const name;
BoneData* const parent;
float length;
float x, y;
float rotation;
float scaleX, scaleY;
};
BoneData* BoneData_create (const char* name, BoneData* parent);
void BoneData_dispose (BoneData* self);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_BONEDATA_H_ */

375
extensions/spine/Json.cpp Normal file
View File

@ -0,0 +1,375 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, dispose of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* Json */
/* JSON parser in C. */
#include "Json.h"
#include <math.h>
#include <stdio.h>
#include <ctype.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
static const char* ep;
const char* Json_getError (void) {
return ep;
}
static int Json_strcasecmp (const char* s1, const char* s2) {
if (!s1) return (s1 == s2) ? 0 : 1;
if (!s2) return 1;
for (; tolower(*s1) == tolower(*s2); ++s1, ++s2)
if (*s1 == 0) return 0;
return tolower(*(const unsigned char*)s1) - tolower(*(const unsigned char*)s2);
}
/* Internal constructor. */
static Json *Json_new (void) {
return (Json*)CALLOC(Json, 1);
}
/* Delete a Json structure. */
void Json_dispose (Json *c) {
Json *next;
while (c) {
next = c->next;
if (c->child) Json_dispose(c->child);
if (c->valuestring) FREE(c->valuestring);
if (c->name) FREE(c->name);
FREE(c);
c = next;
}
}
/* Parse the input text to generate a number, and populate the result into item. */
static const char* parse_number (Json *item, const char* num) {
float n = 0, sign = 1, scale = 0;
int subscale = 0, signsubscale = 1;
/* Could use sscanf for this? */
if (*num == '-') sign = -1, num++; /* Has sign? */
if (*num == '0') num++; /* is zero */
if (*num >= '1' && *num <= '9') do
n = (n * 10.0f) + (*num++ - '0');
while (*num >= '0' && *num <= '9'); /* Number? */
if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
num++;
do
n = (n * 10.0f) + (*num++ - '0'), scale--;
while (*num >= '0' && *num <= '9');
} /* Fractional part? */
if (*num == 'e' || *num == 'E') /* Exponent? */
{
num++;
if (*num == '+')
num++;
else if (*num == '-') signsubscale = -1, num++; /* With sign? */
while (*num >= '0' && *num <= '9')
subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
}
n = sign * n * pow(10.0f, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuefloat = n;
item->valueint = (int)n;
item->type = Json_Number;
return num;
}
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
static const char* parse_string (Json *item, const char* str) {
const char* ptr = str + 1;
char* ptr2;
char* out;
int len = 0;
unsigned uc, uc2;
if (*str != '\"') {
ep = str;
return 0;
} /* not a string! */
while (*ptr != '\"' && *ptr && ++len)
if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out = (char*)malloc(len + 1); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr = str + 1;
ptr2 = out;
while (*ptr != '\"' && *ptr) {
if (*ptr != '\\')
*ptr2++ = *ptr++;
else {
ptr++;
switch (*ptr) {
case 'b':
*ptr2++ = '\b';
break;
case 'f':
*ptr2++ = '\f';
break;
case 'n':
*ptr2++ = '\n';
break;
case 'r':
*ptr2++ = '\r';
break;
case 't':
*ptr2++ = '\t';
break;
case 'u': /* transcode utf16 to utf8. */
sscanf(ptr + 1, "%4x", &uc);
ptr += 4; /* get the unicode char. */
if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) break; /* check for invalid. */
if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */
{
if (ptr[1] != '\\' || ptr[2] != 'u') break; /* missing second-half of surrogate. */
sscanf(ptr + 3, "%4x", &uc2);
ptr += 6;
if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate. */
uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
}
len = 4;
if (uc < 0x80)
len = 1;
else if (uc < 0x800)
len = 2;
else if (uc < 0x10000) len = 3;
ptr2 += len;
switch (len) {
case 4:
*--ptr2 = ((uc | 0x80) & 0xBF);
uc >>= 6;
case 3:
*--ptr2 = ((uc | 0x80) & 0xBF);
uc >>= 6;
case 2:
*--ptr2 = ((uc | 0x80) & 0xBF);
uc >>= 6;
case 1:
*--ptr2 = (uc | firstByteMark[len]);
}
ptr2 += len;
break;
default:
*ptr2++ = *ptr;
break;
}
ptr++;
}
}
*ptr2 = 0;
if (*ptr == '\"') ptr++;
item->valuestring = out;
item->type = Json_String;
return ptr;
}
/* Predeclare these prototypes. */
static const char* parse_value (Json *item, const char* value);
static const char* parse_array (Json *item, const char* value);
static const char* parse_object (Json *item, const char* value);
/* Utility to jump whitespace and cr/lf */
static const char* skip (const char* in) {
while (in && *in && (unsigned char)*in <= 32)
in++;
return in;
}
/* Parse an object - create a new root, and populate. */
Json *Json_create (const char* value) {
const char* end = 0;
Json *c = Json_new();
ep = 0;
if (!c) return 0; /* memory fail */
end = parse_value(c, skip(value));
if (!end) {
Json_dispose(c);
return 0;
} /* parse failure. ep is set. */
return c;
}
/* Parser core - when encountering text, process appropriately. */
static const char* parse_value (Json *item, const char* value) {
if (!value) return 0; /* Fail on null. */
if (!strncmp(value, "null", 4)) {
item->type = Json_NULL;
return value + 4;
}
if (!strncmp(value, "false", 5)) {
item->type = Json_False;
return value + 5;
}
if (!strncmp(value, "true", 4)) {
item->type = Json_True;
item->valueint = 1;
return value + 4;
}
if (*value == '\"') {
return parse_string(item, value);
}
if (*value == '-' || (*value >= '0' && *value <= '9')) {
return parse_number(item, value);
}
if (*value == '[') {
return parse_array(item, value);
}
if (*value == '{') {
return parse_object(item, value);
}
ep = value;
return 0; /* failure. */
}
/* Build an array from input text. */
static const char* parse_array (Json *item, const char* value) {
Json *child;
if (*value != '[') {
ep = value;
return 0;
} /* not an array! */
item->type = Json_Array;
value = skip(value + 1);
if (*value == ']') return value + 1; /* empty array. */
item->child = child = Json_new();
if (!item->child) return 0; /* memory fail */
value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value == ',') {
Json *new_item;
if (!(new_item = Json_new())) return 0; /* memory fail */
child->next = new_item;
new_item->prev = child;
child = new_item;
value = skip(parse_value(child, skip(value + 1)));
if (!value) return 0; /* memory fail */
}
if (*value == ']') return value + 1; /* end of array */
ep = value;
return 0; /* malformed. */
}
/* Build an object from the text. */
static const char* parse_object (Json *item, const char* value) {
Json *child;
if (*value != '{') {
ep = value;
return 0;
} /* not an object! */
item->type = Json_Object;
value = skip(value + 1);
if (*value == '}') return value + 1; /* empty array. */
item->child = child = Json_new();
if (!item->child) return 0;
value = skip(parse_string(child, skip(value)));
if (!value) return 0;
child->name = child->valuestring;
child->valuestring = 0;
if (*value != ':') {
ep = value;
return 0;
} /* fail! */
value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value == ',') {
Json *new_item;
if (!(new_item = Json_new())) return 0; /* memory fail */
child->next = new_item;
new_item->prev = child;
child = new_item;
value = skip(parse_string(child, skip(value + 1)));
if (!value) return 0;
child->name = child->valuestring;
child->valuestring = 0;
if (*value != ':') {
ep = value;
return 0;
} /* fail! */
value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
if (!value) return 0;
}
if (*value == '}') return value + 1; /* end of array */
ep = value;
return 0; /* malformed. */
}
/* Get Array size/item / object item. */
int Json_getSize (Json *array) {
Json *c = array->child;
int i = 0;
while (c)
i++, c = c->next;
return i;
}
Json *Json_getItemAt (Json *array, int item) {
Json *c = array->child;
while (c && item > 0)
item--, c = c->next;
return c;
}
Json *Json_getItem (Json *object, const char* string) {
Json *c = object->child;
while (c && Json_strcasecmp(c->name, string))
c = c->next;
return c;
}
const char* Json_getString (Json* object, const char* name, const char* defaultValue) {
object = Json_getItem(object, name);
if (object) return object->valuestring;
return defaultValue;
}
float Json_getFloat (Json* value, const char* name, float defaultValue) {
value = Json_getItem(value, name);
return value ? value->valuefloat : defaultValue;
}
int Json_getInt (Json* value, const char* name, int defaultValue) {
value = Json_getItem(value, name);
return value ? (int)value->valuefloat : defaultValue;
}
}} // namespace cocos2d { namespace extension {

77
extensions/spine/Json.h Normal file
View File

@ -0,0 +1,77 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, dispose of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* Esoteric Software: Removed everything except parsing, shorter method names, more get methods, double to float, formatted. */
#ifndef SPINE_JSON_H_
#define SPINE_JSON_H_
namespace cocos2d { namespace extension {
/* Json Types: */
#define Json_False 0
#define Json_True 1
#define Json_NULL 2
#define Json_Number 3
#define Json_String 4
#define Json_Array 5
#define Json_Object 6
/* The Json structure: */
typedef struct Json {
struct Json* next;
struct Json* prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItemAt/getItem */
struct Json* child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
const char* valuestring; /* The item's string, if type==Json_String */
int valueint; /* The item's number, if type==Json_Number */
float valuefloat; /* The item's number, if type==Json_Number */
const char* name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} Json;
/* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */
Json* Json_create (const char* value);
/* Delete a Json entity and all subentities. */
void Json_dispose (Json* json);
/* Returns the number of items in an array (or object). */
int Json_getSize (Json* json);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
Json* Json_getItemAt (Json* json, int item);
/* Get item "string" from object. Case insensitive. */
Json* Json_getItem (Json* json, const char* string);
const char* Json_getString (Json* json, const char* name, const char* defaultValue);
float Json_getFloat (Json* json, const char* name, float defaultValue);
int Json_getInt (Json* json, const char* name, int defaultValue);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */
const char* Json_getError (void);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_JSON_H_ */

View File

@ -0,0 +1,94 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/RegionAttachment.h>
#include <math.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
RegionAttachment* RegionAttachment_create (const char* name) {
RegionAttachment* self = NEW(RegionAttachment);
self->scaleX = 1;
self->scaleY = 1;
_Attachment_init(SUPER(self), name, ATTACHMENT_REGION, _Attachment_deinit);
return self;
}
void RegionAttachment_updateOffset (RegionAttachment* self) {
float localX2 = self->width / 2;
float localY2 = self->height / 2;
float localX = -localX2;
float localY = -localY2;
if (self->region->rotate) {
localX += self->region->offsetX / self->region->originalWidth * self->height;
localY += self->region->offsetY / self->region->originalHeight * self->width;
localX2 -= (self->region->originalWidth - self->region->offsetX - self->region->height) / self->region->originalWidth * self->width;
localY2 -= (self->region->originalHeight - self->region->offsetY - self->region->width) / self->region->originalHeight * self->height;
} else {
localX += self->region->offsetX / self->region->originalWidth * self->width;
localY += self->region->offsetY / self->region->originalHeight * self->height;
localX2 -= (self->region->originalWidth - self->region->offsetX - self->region->width) / self->region->originalWidth * self->width;
localY2 -= (self->region->originalHeight - self->region->offsetY - self->region->height) / self->region->originalHeight * self->height;
}
localX *= self->scaleX;
localY *= self->scaleY;
localX2 *= self->scaleX;
localY2 *= self->scaleY;
float radians = (float)(self->rotation * 3.1415926535897932385 / 180);
float cosine = cosf(radians);
float sine = sinf(radians);
float localXCos = localX * cosine + self->x;
float localXSin = localX * sine;
float localYCos = localY * cosine + self->y;
float localYSin = localY * sine;
float localX2Cos = localX2 * cosine + self->x;
float localX2Sin = localX2 * sine;
float localY2Cos = localY2 * cosine + self->y;
float localY2Sin = localY2 * sine;
self->offset[VERTEX_X1] = localXCos - localYSin;
self->offset[VERTEX_Y1] = localYCos + localXSin;
self->offset[VERTEX_X2] = localXCos - localY2Sin;
self->offset[VERTEX_Y2] = localY2Cos + localXSin;
self->offset[VERTEX_X3] = localX2Cos - localY2Sin;
self->offset[VERTEX_Y3] = localY2Cos + localX2Sin;
self->offset[VERTEX_X4] = localX2Cos - localYSin;
self->offset[VERTEX_Y4] = localYCos + localX2Sin;
}
void RegionAttachment_updateVertices (RegionAttachment* self, Slot* slot) {
float* offset = self->offset;
Bone* bone = slot->bone;
self->vertices[VERTEX_X1] = offset[VERTEX_X1] * bone->m00 + offset[VERTEX_Y1] * bone->m01 + bone->worldX;
self->vertices[VERTEX_Y1] = offset[VERTEX_X1] * bone->m10 + offset[VERTEX_Y1] * bone->m11 + bone->worldY;
self->vertices[VERTEX_X2] = offset[VERTEX_X2] * bone->m00 + offset[VERTEX_Y2] * bone->m01 + bone->worldX;
self->vertices[VERTEX_Y2] = offset[VERTEX_X2] * bone->m10 + offset[VERTEX_Y2] * bone->m11 + bone->worldY;
self->vertices[VERTEX_X3] = offset[VERTEX_X3] * bone->m00 + offset[VERTEX_Y3] * bone->m01 + bone->worldX;
self->vertices[VERTEX_Y3] = offset[VERTEX_X3] * bone->m10 + offset[VERTEX_Y3] * bone->m11 + bone->worldY;
self->vertices[VERTEX_X4] = offset[VERTEX_X4] * bone->m00 + offset[VERTEX_Y4] * bone->m01 + bone->worldX;
self->vertices[VERTEX_Y4] = offset[VERTEX_X4] * bone->m10 + offset[VERTEX_Y4] * bone->m11 + bone->worldY;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_REGIONATTACHMENT_H_
#define SPINE_REGIONATTACHMENT_H_
#include <spine/Attachment.h>
#include <spine/Atlas.h>
#include <spine/Slot.h>
namespace cocos2d { namespace extension {
typedef enum {
VERTEX_X1 = 0, VERTEX_Y1, VERTEX_X2, VERTEX_Y2, VERTEX_X3, VERTEX_Y3, VERTEX_X4, VERTEX_Y4
} VertexIndex;
typedef struct RegionAttachment RegionAttachment;
struct RegionAttachment {
Attachment super;
float x, y, scaleX, scaleY, rotation, width, height;
AtlasRegion* region;
float offset[8];
float vertices[8];
float uvs[8];
};
RegionAttachment* RegionAttachment_create (const char* name);
void RegionAttachment_updateOffset (RegionAttachment* self);
void RegionAttachment_updateVertices (RegionAttachment* self, Slot* slot);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_REGIONATTACHMENT_H_ */

View File

@ -0,0 +1,199 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/Skeleton.h>
#include <string.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
Skeleton* Skeleton_create (SkeletonData* data) {
Skeleton* self = NEW(Skeleton);
CONST_CAST(SkeletonData*, self->data) = data;
self->boneCount = self->data->boneCount;
self->bones = MALLOC(Bone*, self->boneCount);
int i, ii;
for (i = 0; i < self->boneCount; ++i) {
BoneData* boneData = self->data->bones[i];
Bone* parent = 0;
if (boneData->parent) {
/* Find parent bone. */
for (ii = 0; ii < self->boneCount; ++ii) {
if (data->bones[ii] == boneData->parent) {
parent = self->bones[ii];
break;
}
}
}
self->bones[i] = Bone_create(boneData, parent);
}
CONST_CAST(Bone*, self->root) = self->bones[0];
self->slotCount = data->slotCount;
self->slots = MALLOC(Slot*, self->slotCount);
for (i = 0; i < self->slotCount; ++i) {
SlotData *slotData = data->slots[i];
/* Find bone for the slotData's boneData. */
Bone *bone;
for (ii = 0; ii < self->boneCount; ++ii) {
if (data->bones[ii] == slotData->boneData) {
bone = self->bones[ii];
break;
}
}
self->slots[i] = Slot_create(slotData, self, bone);
}
self->drawOrder = MALLOC(Slot*, self->slotCount);
memcpy(self->drawOrder, self->slots, sizeof(Slot*) * self->slotCount);
self->r = 1;
self->g = 1;
self->b = 1;
self->a = 1;
return self;
}
void Skeleton_dispose (Skeleton* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
Bone_dispose(self->bones[i]);
FREE(self->bones);
for (i = 0; i < self->slotCount; ++i)
Slot_dispose(self->slots[i]);
FREE(self->slots);
FREE(self->drawOrder);
}
void Skeleton_updateWorldTransform (const Skeleton* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
Bone_updateWorldTransform(self->bones[i], self->flipX, self->flipY);
}
void Skeleton_setToBindPose (const Skeleton* self) {
Skeleton_setBonesToBindPose(self);
Skeleton_setSlotsToBindPose(self);
}
void Skeleton_setBonesToBindPose (const Skeleton* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
Bone_setToBindPose(self->bones[i]);
}
void Skeleton_setSlotsToBindPose (const Skeleton* self) {
int i;
for (i = 0; i < self->slotCount; ++i)
Slot_setToBindPose(self->slots[i]);
}
Bone* Skeleton_findBone (const Skeleton* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
if (strcmp(self->data->bones[i]->name, boneName) == 0) return self->bones[i];
return 0;
}
int Skeleton_findBoneIndex (const Skeleton* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
if (strcmp(self->data->bones[i]->name, boneName) == 0) return i;
return -1;
}
Slot* Skeleton_findSlot (const Skeleton* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
if (strcmp(self->data->slots[i]->name, slotName) == 0) return self->slots[i];
return 0;
}
int Skeleton_findSlotIndex (const Skeleton* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
if (strcmp(self->data->slots[i]->name, slotName) == 0) return i;
return -1;
}
int Skeleton_setSkinByName (Skeleton* self, const char* skinName) {
if (!skinName) {
Skeleton_setSkin(self, 0);
return 1;
}
Skin *skin = SkeletonData_findSkin(self->data, skinName);
if (!skin) return 0;
Skeleton_setSkin(self, skin);
return 1;
}
void Skeleton_setSkin (Skeleton* self, Skin* newSkin) {
if (self->skin && newSkin) Skin_attachAll(newSkin, self, self->skin);
CONST_CAST(Skin*, self->skin) = newSkin;
}
Attachment* Skeleton_getAttachmentForSlotName (const Skeleton* self, const char* slotName, const char* attachmentName) {
int slotIndex = SkeletonData_findSlotIndex(self->data, slotName);
return Skeleton_getAttachmentForSlotIndex(self, slotIndex, attachmentName);
}
Attachment* Skeleton_getAttachmentForSlotIndex (const Skeleton* self, int slotIndex, const char* attachmentName) {
if (slotIndex == -1) return 0;
if (self->skin) {
Attachment *attachment = Skin_getAttachment(self->skin, slotIndex, attachmentName);
if (attachment) return attachment;
}
if (self->data->defaultSkin) {
Attachment *attachment = Skin_getAttachment(self->data->defaultSkin, slotIndex, attachmentName);
if (attachment) return attachment;
}
return 0;
}
int Skeleton_setAttachment (Skeleton* self, const char* slotName, const char* attachmentName) {
int i;
for (i = 0; i < self->slotCount; ++i) {
Slot *slot = self->slots[i];
if (strcmp(slot->data->name, slotName) == 0) {
Attachment* attachment = Skeleton_getAttachmentForSlotIndex(self, i, attachmentName);
if (!attachment) return 0;
Slot_setAttachment(slot, attachment);
return 1;
}
}
return 0;
}
void Skeleton_update (Skeleton* self, float deltaTime) {
self->time += deltaTime;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,91 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_SKELETON_H_
#define SPINE_SKELETON_H_
#include <spine/SkeletonData.h>
#include <spine/Slot.h>
#include <spine/Skin.h>
namespace cocos2d { namespace extension {
typedef struct Skeleton Skeleton;
struct Skeleton {
SkeletonData* const data;
int boneCount;
Bone** bones;
Bone* const root;
int slotCount;
Slot** slots;
Slot** drawOrder;
Skin* const skin;
float r, g, b, a;
float time;
int/*bool*/flipX, flipY;
};
Skeleton* Skeleton_create (SkeletonData* data);
void Skeleton_dispose (Skeleton* self);
void Skeleton_updateWorldTransform (const Skeleton* self);
void Skeleton_setToBindPose (const Skeleton* self);
void Skeleton_setBonesToBindPose (const Skeleton* self);
void Skeleton_setSlotsToBindPose (const Skeleton* self);
/* Returns 0 if the bone was not found. */
Bone* Skeleton_findBone (const Skeleton* self, const char* boneName);
/* Returns -1 if the bone was not found. */
int Skeleton_findBoneIndex (const Skeleton* self, const char* boneName);
/* Returns 0 if the slot was not found. */
Slot* Skeleton_findSlot (const Skeleton* self, const char* slotName);
/* Returns -1 if the slot was not found. */
int Skeleton_findSlotIndex (const Skeleton* self, const char* slotName);
/* Sets the skin used to look up attachments not found in the SkeletonData defaultSkin. Attachments from the new skin are
* attached if the corresponding attachment from the old skin was attached.
* @param skin May be 0.*/
void Skeleton_setSkin (Skeleton* self, Skin* skin);
/* Returns 0 if the skin was not found. See Skeleton_setSkin.
* @param skinName May be 0. */
int Skeleton_setSkinByName (Skeleton* self, const char* skinName);
/* Returns 0 if the slot or attachment was not found. */
Attachment* Skeleton_getAttachmentForSlotName (const Skeleton* self, const char* slotName, const char* attachmentName);
/* Returns 0 if the slot or attachment was not found. */
Attachment* Skeleton_getAttachmentForSlotIndex (const Skeleton* self, int slotIndex, const char* attachmentName);
/* Returns 0 if the slot or attachment was not found. */
int Skeleton_setAttachment (Skeleton* self, const char* slotName, const char* attachmentName);
void Skeleton_update (Skeleton* self, float deltaTime);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_SKELETON_H_*/

View File

@ -0,0 +1,99 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/SkeletonData.h>
#include <string.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
SkeletonData* SkeletonData_create () {
return NEW(SkeletonData);
}
void SkeletonData_dispose (SkeletonData* self) {
int i;
for (i = 0; i < self->boneCount; ++i)
BoneData_dispose(self->bones[i]);
FREE(self->bones);
for (i = 0; i < self->slotCount; ++i)
SlotData_dispose(self->slots[i]);
FREE(self->slots);
for (i = 0; i < self->skinCount; ++i)
Skin_dispose(self->skins[i]);
FREE(self->skins);
for (i = 0; i < self->animationCount; ++i)
Animation_dispose(self->animations[i]);
FREE(self->animations);
FREE(self);
}
BoneData* SkeletonData_findBone (const SkeletonData* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
if (strcmp(self->bones[i]->name, boneName) == 0) return self->bones[i];
return 0;
}
int SkeletonData_findBoneIndex (const SkeletonData* self, const char* boneName) {
int i;
for (i = 0; i < self->boneCount; ++i)
if (strcmp(self->bones[i]->name, boneName) == 0) return i;
return 0;
}
SlotData* SkeletonData_findSlot (const SkeletonData* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
if (strcmp(self->slots[i]->name, slotName) == 0) return self->slots[i];
return 0;
}
int SkeletonData_findSlotIndex (const SkeletonData* self, const char* slotName) {
int i;
for (i = 0; i < self->slotCount; ++i)
if (strcmp(self->slots[i]->name, slotName) == 0) return i;
return 0;
}
Skin* SkeletonData_findSkin (const SkeletonData* self, const char* skinName) {
int i;
for (i = 0; i < self->skinCount; ++i)
if (strcmp(self->skins[i]->name, skinName) == 0) return self->skins[i];
return 0;
}
Animation* SkeletonData_findAnimation (const SkeletonData* self, const char* animationName) {
int i;
for (i = 0; i < self->animationCount; ++i)
if (strcmp(self->animations[i]->name, animationName) == 0) return self->animations[i];
return 0;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_SKELETONDATA_H_
#define SPINE_SKELETONDATA_H_
#include <spine/BoneData.h>
#include <spine/SlotData.h>
#include <spine/Skin.h>
#include <spine/Animation.h>
namespace cocos2d { namespace extension {
typedef struct {
int boneCount;
BoneData** bones;
int slotCount;
SlotData** slots;
int skinCount;
Skin** skins;
Skin* defaultSkin;
int animationCount;
Animation** animations;
} SkeletonData;
SkeletonData* SkeletonData_create ();
void SkeletonData_dispose (SkeletonData* self);
BoneData* SkeletonData_findBone (const SkeletonData* self, const char* boneName);
int SkeletonData_findBoneIndex (const SkeletonData* self, const char* boneName);
SlotData* SkeletonData_findSlot (const SkeletonData* self, const char* slotName);
int SkeletonData_findSlotIndex (const SkeletonData* self, const char* slotName);
Skin* SkeletonData_findSkin (const SkeletonData* self, const char* skinName);
Animation* SkeletonData_findAnimation (const SkeletonData* self, const char* animationName);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_SKELETONDATA_H_ */

View File

@ -0,0 +1,392 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/SkeletonJson.h>
#include <math.h>
#include <stdio.h>
#include <math.h>
#include "Json.h"
#include <spine/extension.h>
#include <spine/RegionAttachment.h>
#include <spine/AtlasAttachmentLoader.h>
namespace cocos2d { namespace extension {
typedef struct {
SkeletonJson super;
int ownsLoader;
} _Internal;
SkeletonJson* SkeletonJson_createWithLoader (AttachmentLoader* attachmentLoader) {
SkeletonJson* self = SUPER(NEW(_Internal));
self->scale = 1;
self->attachmentLoader = attachmentLoader;
return self;
}
SkeletonJson* SkeletonJson_create (Atlas* atlas) {
AtlasAttachmentLoader* attachmentLoader = AtlasAttachmentLoader_create(atlas);
SkeletonJson* self = SkeletonJson_createWithLoader(SUPER(attachmentLoader));
SUB_CAST(_Internal, self) ->ownsLoader = 1;
return self;
}
void SkeletonJson_dispose (SkeletonJson* self) {
if (SUB_CAST(_Internal, self) ->ownsLoader) AttachmentLoader_dispose(self->attachmentLoader);
FREE(self->error);
FREE(self);
}
void _SkeletonJson_setError (SkeletonJson* self, Json* root, const char* value1, const char* value2) {
FREE(self->error);
char message[256];
strcpy(message, value1);
int length = strlen(value1);
if (value2) strncat(message + length, value2, 256 - length);
MALLOC_STR(self->error, message);
if (root) Json_dispose(root);
}
static float toColor (const char* value, int index) {
if (strlen(value) != 8) return -1;
value += index * 2;
char digits[3];
digits[0] = *value;
digits[1] = *(value + 1);
digits[2] = '\0';
char* error;
int color = strtoul(digits, &error, 16);
if (*error != 0) return -1;
return color / (float)255;
}
static void readCurve (CurveTimeline* timeline, int frameIndex, Json* frame) {
Json* curve = Json_getItem(frame, "curve");
if (!curve) return;
if (curve->type == Json_String && strcmp(curve->valuestring, "stepped") == 0)
CurveTimeline_setStepped(timeline, frameIndex);
else if (curve->type == Json_Array) {
CurveTimeline_setCurve(timeline, frameIndex, Json_getItemAt(curve, 0)->valuefloat, Json_getItemAt(curve, 1)->valuefloat,
Json_getItemAt(curve, 2)->valuefloat, Json_getItemAt(curve, 3)->valuefloat);
}
}
static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, SkeletonData *skeletonData) {
Json* bones = Json_getItem(root, "bones");
int boneCount = bones ? Json_getSize(bones) : 0;
Json* slots = Json_getItem(root, "slots");
int slotCount = slots ? Json_getSize(slots) : 0;
int timelineCount = 0;
int i, ii, iii;
for (i = 0; i < boneCount; ++i)
timelineCount += Json_getSize(Json_getItemAt(bones, i));
for (i = 0; i < slotCount; ++i)
timelineCount += Json_getSize(Json_getItemAt(slots, i));
Animation* animation = Animation_create(root->name, timelineCount);
animation->timelineCount = 0;
skeletonData->animations[skeletonData->animationCount] = animation;
skeletonData->animationCount++;
for (i = 0; i < boneCount; ++i) {
Json* boneMap = Json_getItemAt(bones, i);
const char* boneName = boneMap->name;
int boneIndex = SkeletonData_findBoneIndex(skeletonData, boneName);
if (boneIndex == -1) {
Animation_dispose(animation);
_SkeletonJson_setError(self, root, "Bone not found: ", boneName);
return 0;
}
int timelineCount = Json_getSize(boneMap);
for (ii = 0; ii < timelineCount; ++ii) {
Json* timelineArray = Json_getItemAt(boneMap, ii);
int frameCount = Json_getSize(timelineArray);
const char* timelineType = timelineArray->name;
if (strcmp(timelineType, "rotate") == 0) {
RotateTimeline *timeline = RotateTimeline_create(frameCount);
timeline->boneIndex = boneIndex;
for (iii = 0; iii < frameCount; ++iii) {
Json* frame = Json_getItemAt(timelineArray, iii);
RotateTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "angle", 0));
readCurve(SUPER(timeline), iii, frame);
}
animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
float duration = timeline->frames[frameCount * 2 - 2];
if (duration > animation->duration) animation->duration = duration;
} else {
int isScale = strcmp(timelineType, "scale") == 0;
if (isScale || strcmp(timelineType, "translate") == 0) {
TranslateTimeline *timeline = isScale ? ScaleTimeline_create(frameCount) : TranslateTimeline_create(frameCount);
float scale = isScale ? 1 : self->scale;
timeline->boneIndex = boneIndex;
for (iii = 0; iii < frameCount; ++iii) {
Json* frame = Json_getItemAt(timelineArray, iii);
TranslateTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "x", 0) * scale,
Json_getFloat(frame, "y", 0) * scale);
readCurve(SUPER(timeline), iii, frame);
}
animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
float duration = timeline->frames[frameCount * 3 - 3];
if (duration > animation->duration) animation->duration = duration;
} else {
Animation_dispose(animation);
_SkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineType);
return 0;
}
}
}
}
for (i = 0; i < slotCount; ++i) {
Json* slotMap = Json_getItemAt(slots, i);
const char* slotName = slotMap->name;
int slotIndex = SkeletonData_findSlotIndex(skeletonData, slotName);
if (slotIndex == -1) {
Animation_dispose(animation);
_SkeletonJson_setError(self, root, "Slot not found: ", slotName);
return 0;
}
int timelineCount = Json_getSize(slotMap);
for (ii = 0; ii < timelineCount; ++ii) {
Json* timelineArray = Json_getItemAt(slotMap, ii);
int frameCount = Json_getSize(timelineArray);
const char* timelineType = timelineArray->name;
if (strcmp(timelineType, "color") == 0) {
ColorTimeline *timeline = ColorTimeline_create(frameCount);
timeline->slotIndex = slotIndex;
for (iii = 0; iii < frameCount; ++iii) {
Json* frame = Json_getItemAt(timelineArray, iii);
const char* s = Json_getString(frame, "color", 0);
ColorTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2),
toColor(s, 3));
readCurve(SUPER(timeline), iii, frame);
}
animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
float duration = timeline->frames[frameCount * 5 - 5];
if (duration > animation->duration) animation->duration = duration;
} else if (strcmp(timelineType, "attachment") == 0) {
AttachmentTimeline *timeline = AttachmentTimeline_create(frameCount);
timeline->slotIndex = slotIndex;
for (iii = 0; iii < frameCount; ++iii) {
Json* frame = Json_getItemAt(timelineArray, iii);
Json* name = Json_getItem(frame, "name");
AttachmentTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0),
name->type == Json_NULL ? 0 : name->valuestring);
}
animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
float duration = timeline->frames[frameCount - 1];
if (duration > animation->duration) animation->duration = duration;
} else {
Animation_dispose(animation);
_SkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineType);
return 0;
}
}
}
return animation;
}
SkeletonData* SkeletonJson_readSkeletonDataFile (SkeletonJson* self, const char* path) {
int length;
const char* json = _Util_readFile(path, &length);
if (!json) {
_SkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path);
return 0;
}
SkeletonData* skeletonData = SkeletonJson_readSkeletonData(self, json);
FREE(json);
return skeletonData;
}
SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* json) {
FREE(self->error);
CONST_CAST(char*, self->error) = 0;
Json* root = Json_create(json);
if (!root) {
_SkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError());
return 0;
}
SkeletonData* skeletonData = SkeletonData_create();
int i, ii, iii;
Json* bones = Json_getItem(root, "bones");
int boneCount = Json_getSize(bones);
skeletonData->bones = MALLOC(BoneData*, boneCount);
for (i = 0; i < boneCount; ++i) {
Json* boneMap = Json_getItemAt(bones, i);
const char* boneName = Json_getString(boneMap, "name", 0);
BoneData* parent = 0;
const char* parentName = Json_getString(boneMap, "parent", 0);
if (parentName) {
parent = SkeletonData_findBone(skeletonData, parentName);
if (!parent) {
SkeletonData_dispose(skeletonData);
_SkeletonJson_setError(self, root, "Parent bone not found: ", parentName);
return 0;
}
}
BoneData* boneData = BoneData_create(boneName, parent);
boneData->length = Json_getFloat(boneMap, "length", 0) * self->scale;
boneData->x = Json_getFloat(boneMap, "x", 0) * self->scale;
boneData->y = Json_getFloat(boneMap, "y", 0) * self->scale;
boneData->rotation = Json_getFloat(boneMap, "rotation", 0);
boneData->scaleX = Json_getFloat(boneMap, "scaleX", 1);
boneData->scaleY = Json_getFloat(boneMap, "scaleY", 1);
skeletonData->bones[i] = boneData;
skeletonData->boneCount++;
}
Json* slots = Json_getItem(root, "slots");
if (slots) {
int slotCount = Json_getSize(slots);
skeletonData->slots = MALLOC(SlotData*, slotCount);
for (i = 0; i < slotCount; ++i) {
Json* slotMap = Json_getItemAt(slots, i);
const char* slotName = Json_getString(slotMap, "name", 0);
const char* boneName = Json_getString(slotMap, "bone", 0);
BoneData* boneData = SkeletonData_findBone(skeletonData, boneName);
if (!boneData) {
SkeletonData_dispose(skeletonData);
_SkeletonJson_setError(self, root, "Slot bone not found: ", boneName);
return 0;
}
SlotData* slotData = SlotData_create(slotName, boneData);
const char* color = Json_getString(slotMap, "color", 0);
if (color) {
slotData->r = toColor(color, 0);
slotData->g = toColor(color, 1);
slotData->b = toColor(color, 2);
slotData->a = toColor(color, 3);
}
Json *attachmentItem = Json_getItem(slotMap, "attachment");
if (attachmentItem) SlotData_setAttachmentName(slotData, attachmentItem->valuestring);
skeletonData->slots[i] = slotData;
skeletonData->slotCount++;
}
}
Json* skinsMap = Json_getItem(root, "skins");
if (skinsMap) {
int skinCount = Json_getSize(skinsMap);
skeletonData->skins = MALLOC(Skin*, skinCount);
for (i = 0; i < skinCount; ++i) {
Json* slotMap = Json_getItemAt(skinsMap, i);
const char* skinName = slotMap->name;
Skin *skin = Skin_create(skinName);
skeletonData->skins[i] = skin;
skeletonData->skinCount++;
if (strcmp(skinName, "default") == 0) skeletonData->defaultSkin = skin;
int slotNameCount = Json_getSize(slotMap);
for (ii = 0; ii < slotNameCount; ++ii) {
Json* attachmentsMap = Json_getItemAt(slotMap, ii);
const char* slotName = attachmentsMap->name;
int slotIndex = SkeletonData_findSlotIndex(skeletonData, slotName);
int attachmentCount = Json_getSize(attachmentsMap);
for (iii = 0; iii < attachmentCount; ++iii) {
Json* attachmentMap = Json_getItemAt(attachmentsMap, iii);
const char* skinAttachmentName = attachmentMap->name;
const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName);
const char* typeString = Json_getString(attachmentMap, "type", "region");
AttachmentType type;
if (strcmp(typeString, "region") == 0)
type = ATTACHMENT_REGION;
else if (strcmp(typeString, "regionSequence") == 0)
type = ATTACHMENT_REGION_SEQUENCE;
else {
SkeletonData_dispose(skeletonData);
_SkeletonJson_setError(self, root, "Unknown attachment type: ", typeString);
return 0;
}
Attachment* attachment = AttachmentLoader_newAttachment(self->attachmentLoader, skin, type, attachmentName);
if (!attachment) {
if (self->attachmentLoader->error1) {
SkeletonData_dispose(skeletonData);
_SkeletonJson_setError(self, root, self->attachmentLoader->error1, self->attachmentLoader->error2);
return 0;
}
continue;
}
if (attachment->type == ATTACHMENT_REGION || attachment->type == ATTACHMENT_REGION_SEQUENCE) {
RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
regionAttachment->x = Json_getFloat(attachmentMap, "x", 0) * self->scale;
regionAttachment->y = Json_getFloat(attachmentMap, "y", 0) * self->scale;
regionAttachment->scaleX = Json_getFloat(attachmentMap, "scaleX", 1);
regionAttachment->scaleY = Json_getFloat(attachmentMap, "scaleY", 1);
regionAttachment->rotation = Json_getFloat(attachmentMap, "rotation", 0);
regionAttachment->width = Json_getFloat(attachmentMap, "width", 32) * self->scale;
regionAttachment->height = Json_getFloat(attachmentMap, "height", 32) * self->scale;
RegionAttachment_updateOffset(regionAttachment);
}
Skin_addAttachment(skin, slotIndex, skinAttachmentName, attachment);
}
}
}
}
Json* animations = Json_getItem(root, "animations");
if (animations) {
int animationCount = Json_getSize(animations);
skeletonData->animations = MALLOC(Animation*, animationCount);
for (i = 0; i < animationCount; ++i) {
Json* animationMap = Json_getItemAt(animations, i);
_SkeletonJson_readAnimation(self, animationMap, skeletonData);
}
}
Json_dispose(root);
return skeletonData;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_SKELETONJSON_H_
#define SPINE_SKELETONJSON_H_
#include <spine/Attachment.h>
#include <spine/AttachmentLoader.h>
#include <spine/SkeletonData.h>
#include <spine/Atlas.h>
#include <spine/Animation.h>
namespace cocos2d { namespace extension {
typedef struct {
float scale;
AttachmentLoader* attachmentLoader;
const char* const error;
} SkeletonJson;
SkeletonJson* SkeletonJson_createWithLoader (AttachmentLoader* attachmentLoader);
SkeletonJson* SkeletonJson_create (Atlas* atlas);
void SkeletonJson_dispose (SkeletonJson* self);
SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* json);
SkeletonData* SkeletonJson_readSkeletonDataFile (SkeletonJson* self, const char* path);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_SKELETONJSON_H_ */

105
extensions/spine/Skin.cpp Normal file
View File

@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/Skin.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
typedef struct _Entry _Entry;
struct _Entry {
int slotIndex;
const char* name;
Attachment* attachment;
_Entry* next;
};
_Entry* _Entry_create (int slotIndex, const char* name, Attachment* attachment) {
_Entry* self = NEW(_Entry);
self->slotIndex = slotIndex;
MALLOC_STR(self->name, name);
self->attachment = attachment;
return self;
}
void _Entry_dispose (_Entry* self) {
Attachment_dispose(self->attachment);
FREE(self->name);
FREE(self);
}
/**/
typedef struct {
Skin super;
_Entry* entries;
} _Internal;
Skin* Skin_create (const char* name) {
Skin* self = SUPER(NEW(_Internal));
MALLOC_STR(self->name, name);
return self;
}
void Skin_dispose (Skin* self) {
_Entry* entry = SUB_CAST(_Internal, self)->entries;
while (entry) {
_Entry* nextEtry = entry->next;
_Entry_dispose(entry);
entry = nextEtry;
}
FREE(self->name);
FREE(self);
}
#include <stdio.h>
void Skin_addAttachment (Skin* self, int slotIndex, const char* name, Attachment* attachment) {
_Entry* newEntry = _Entry_create(slotIndex, name, attachment);
newEntry->next = SUB_CAST(_Internal, self)->entries;
SUB_CAST(_Internal, self)->entries = newEntry;
}
Attachment* Skin_getAttachment (const Skin* self, int slotIndex, const char* name) {
const _Entry* entry = SUB_CAST(_Internal, self) ->entries;
while (entry) {
if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0) return entry->attachment;
entry = entry->next;
}
return 0;
}
void Skin_attachAll (const Skin* self, Skeleton* skeleton, const Skin* oldSkin) {
const _Entry *entry = SUB_CAST(_Internal, oldSkin) ->entries;
while (entry) {
Slot *slot = skeleton->slots[entry->slotIndex];
if (slot->attachment == entry->attachment) {
Attachment *attachment = Skin_getAttachment(self, entry->slotIndex, entry->name);
if (attachment) Slot_setAttachment(slot, attachment);
}
entry = entry->next;
}
}
}} // namespace cocos2d { namespace extension {

52
extensions/spine/Skin.h Normal file
View File

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_SKIN_H_
#define SPINE_SKIN_H_
#include <spine/Attachment.h>
namespace cocos2d { namespace extension {
struct Skeleton;
typedef struct {
const char* const name;
} Skin;
Skin* Skin_create (const char* name);
void Skin_dispose (Skin* self);
/* The Skin owns the attachment. */
void Skin_addAttachment (Skin* self, int slotIndex, const char* name, Attachment* attachment);
/* Returns 0 if the attachment was not found. */
Attachment* Skin_getAttachment (const Skin* self, int slotIndex, const char* name);
/** Attach each attachment in this skin if the corresponding attachment in oldSkin is currently attached. */
void Skin_attachAll (const Skin* self, struct Skeleton* skeleton, const Skin* oldSkin);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_SKIN_H_ */

83
extensions/spine/Slot.cpp Normal file
View File

@ -0,0 +1,83 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/Slot.h>
#include <spine/extension.h>
#include <spine/Skeleton.h>
namespace cocos2d { namespace extension {
typedef struct {
Slot super;
float attachmentTime;
} _Internal;
Slot* Slot_create (SlotData* data, Skeleton* skeleton, Bone* bone) {
Slot* self = SUPER(NEW(_Internal));
CONST_CAST(SlotData*, self->data) = data;
CONST_CAST(Skeleton*, self->skeleton) = skeleton;
CONST_CAST(Bone*, self->bone) = bone;
Slot_setToBindPose(self);
return self;
}
void Slot_dispose (Slot* self) {
FREE(self);
}
void Slot_setAttachment (Slot* self, Attachment* attachment) {
CONST_CAST(Attachment*, self->attachment) = attachment;
SUB_CAST(_Internal, self) ->attachmentTime = self->skeleton->time;
}
void Slot_setAttachmentTime (Slot* self, float time) {
SUB_CAST(_Internal, self) ->attachmentTime = self->skeleton->time - time;
}
float Slot_getAttachmentTime (const Slot* self) {
return self->skeleton->time - SUB_CAST(_Internal, self) ->attachmentTime;
}
void Slot_setToBindPose (Slot* self) {
self->r = self->data->r;
self->g = self->data->g;
self->b = self->data->b;
self->a = self->data->a;
Attachment* attachment = 0;
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 = Skeleton_getAttachmentForSlotIndex(self->skeleton, i, self->data->attachmentName);
break;
}
}
}
Slot_setAttachment(self, attachment);
}
}} // namespace cocos2d { namespace extension {

58
extensions/spine/Slot.h Normal file
View File

@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_SLOT_H_
#define SPINE_SLOT_H_
#include <spine/Bone.h>
#include <spine/Attachment.h>
#include <spine/SlotData.h>
namespace cocos2d { namespace extension {
struct Skeleton;
typedef struct Slot {
SlotData* const data;
struct Skeleton* const skeleton;
Bone* const bone;
float r, g, b, a;
Attachment* const attachment;
} Slot;
Slot* Slot_create (SlotData* data, struct Skeleton* skeleton, Bone* bone);
void Slot_dispose (Slot* self);
/* @param attachment May be 0 to clear the attachment for the slot. */
void Slot_setAttachment (Slot* self, Attachment* attachment);
void Slot_setAttachmentTime (Slot* self, float time);
float Slot_getAttachmentTime (const Slot* self);
void Slot_setToBindPose (Slot* self);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_SLOT_H_ */

View File

@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/SlotData.h>
#include <spine/extension.h>
namespace cocos2d { namespace extension {
SlotData* SlotData_create (const char* name, BoneData* boneData) {
SlotData* self = NEW(SlotData);
MALLOC_STR(self->name, name);
CONST_CAST(BoneData*, self->boneData) = boneData;
self->r = 1;
self->g = 1;
self->b = 1;
self->a = 1;
return self;
}
void SlotData_dispose (SlotData* self) {
FREE(self->name);
FREE(self->attachmentName);
FREE(self);
}
void SlotData_setAttachmentName (SlotData* self, const char* attachmentName) {
FREE(self->attachmentName);
if (attachmentName)
MALLOC_STR(self->attachmentName, attachmentName);
else
CONST_CAST(char*, self->attachmentName) = 0;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_SLOTDATA_H_
#define SPINE_SLOTDATA_H_
#include <spine/BoneData.h>
namespace cocos2d { namespace extension {
typedef struct {
const char* const name;
const BoneData* const boneData;
const char* const attachmentName;
float r, g, b, a;
} SlotData;
SlotData* SlotData_create (const char* name, BoneData* boneData);
void SlotData_dispose (SlotData* self);
/* @param attachmentName May be 0 for no bind pose attachment. */
void SlotData_setAttachmentName (SlotData* self, const char* attachmentName);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_SLOTDATA_H_ */

View File

@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/extension.h>
#include <stdio.h>
namespace cocos2d { namespace extension {
static void* (*mallocFunc) (size_t size) = malloc;
static void (*freeFunc) (void* ptr) = free;
void* _malloc (size_t size) {
return mallocFunc(size);
}
void* _calloc (size_t num, size_t size) {
void* ptr = mallocFunc(size);
if (ptr) memset(ptr, 0, size);
return ptr;
}
void _free (void* ptr) {
freeFunc(ptr);
}
void _setMalloc (void* (*malloc) (size_t size)) {
mallocFunc = malloc;
}
void _setFree (void (*free) (void* ptr)) {
freeFunc = free;
}
char* _readFile (const char* path, int* length) {
FILE *file = fopen(path, "rb");
if (!file) return 0;
fseek(file, 0, SEEK_END);
*length = ftell(file);
fseek(file, 0, SEEK_SET);
char* data = MALLOC(char, *length);
fread(data, 1, *length, file);
fclose(file);
return data;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,145 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
******************************************************************************/
/*
Implementation notes:
- An OOP style is used where each "class" is made up of a struct and a number of functions prefixed with the struct name.
- struct fields that are const are readonly. Either they are set in a create function and can never be changed, or they can only
be changed by calling a function.
- Inheritance is done using a struct field named "super" as the first field, allowing the struct to be cast to its "super class".
This works because a pointer to a struct is guaranteed to be a pointer to the first struct field.
- Classes intended for inheritance provide init/deinit functions which subclasses must call in their create/dispose functions.
- Polymorphism is done by a base class providing function pointers in its init function. The public API delegates to this
function.
- Subclasses do not provide a dispose function, instead the base class' dispose function should be used, which will delegate to
a dispose function.
- Classes not designed for inheritance cannot be extended. They may use an internal subclass to hide private data and don't
expose function pointers.
- The public API hides implementation details such init/deinit functions. An internal API is exposed in extension.h to allow
classes to be extended. Internal functions begin with underscore (_).
- OOP in C tends to lose type safety. Macros are provided in extension.h to give context for why a cast is being done.
*/
#ifndef SPINE_EXTENSION_H_
#define SPINE_EXTENSION_H_
/* All allocation uses these. */
#define MALLOC(TYPE,COUNT) ((TYPE*)_malloc(sizeof(TYPE) * COUNT))
#define CALLOC(TYPE,COUNT) ((TYPE*)_calloc(1, sizeof(TYPE) * COUNT))
#define NEW(TYPE) CALLOC(TYPE,1)
/* Gets the direct super class. Type safe. */
#define SUPER(VALUE) (&VALUE->super)
/* Cast to a super class. Not type safe, use with care. Prefer SUPER() where possible. */
#define SUPER_CAST(TYPE,VALUE) ((TYPE*)VALUE)
/* Cast to a sub class. Not type safe, use with care. */
#define SUB_CAST(TYPE,VALUE) ((TYPE*)VALUE)
/* Casts away const. Can be used as an lvalue. Not type safe, use with care. */
#define CONST_CAST(TYPE,VALUE) (*(TYPE*)&VALUE)
/* Gets the vtable for the specified type. Not type safe, use with care. */
#define VTABLE(TYPE,VALUE) ((_##TYPE##Vtable*)((TYPE*)VALUE)->vtable)
/* Frees memory. Can be used on const types. */
#define FREE(VALUE) _free((void*)VALUE)
/* 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(strlen(FROM) + 1), FROM)
#include <stdlib.h>
#include <string.h>
#include <spine/Skeleton.h>
#include <spine/RegionAttachment.h>
#include <spine/Animation.h>
#include <spine/Atlas.h>
#include <spine/AttachmentLoader.h>
namespace cocos2d { namespace extension {
/*
* Functions that must be implemented:
*/
void _AtlasPage_createTexture (AtlasPage* self, const char* path);
void _AtlasPage_disposeTexture (AtlasPage* self);
char* _Util_readFile (const char* path, int* length);
/*
* Internal API available for extension:
*/
void* _malloc (size_t size);
void* _calloc (size_t num, size_t size);
void _free (void* ptr);
void _setMalloc (void* (*_malloc) (size_t size));
void _setFree (void (*_free) (void* ptr));
char* _readFile (const char* path, int* length);
/**/
void _AttachmentLoader_init (AttachmentLoader* self, //
void (*dispose) (AttachmentLoader* self), //
Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name));
void _AttachmentLoader_deinit (AttachmentLoader* self);
void _AttachmentLoader_setError (AttachmentLoader* self, const char* error1, const char* error2);
void _AttachmentLoader_setUnknownTypeError (AttachmentLoader* self, AttachmentType type);
/**/
void _Attachment_init (Attachment* self, const char* name, AttachmentType type, //
void (*dispose) (Attachment* self));
void _Attachment_deinit (Attachment* self);
/**/
void _Timeline_init (Timeline* self, //
void (*dispose) (Timeline* self), //
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha));
void _Timeline_deinit (Timeline* self);
/**/
void _CurveTimeline_init (CurveTimeline* self, int frameCount, //
void (*dispose) (Timeline* self), //
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha));
void _CurveTimeline_deinit (CurveTimeline* self);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_EXTENSION_H_ */

View File

@ -0,0 +1,307 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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/spine-cocos2dx.h>
#include <spine/extension.h>
USING_NS_CC;
using std::min;
using std::max;
namespace cocos2d { namespace extension {
void _AtlasPage_createTexture (AtlasPage* self, const char* path) {
CCTexture2D* texture = CCTextureCache::sharedTextureCache()->addImage(path);
CCTextureAtlas* textureAtlas = CCTextureAtlas::createWithTexture(texture, 4);
textureAtlas->retain();
self->texture = textureAtlas;
// Using getContentSize to make it supports the strategy of loading resources in cocos2d-x.
// self->width = texture->getPixelsWide();
// self->height = texture->getPixelsHigh();
self->width = texture->getContentSize().width;
self->height = texture->getContentSize().height;
}
void _AtlasPage_disposeTexture (AtlasPage* self) {
((CCTextureAtlas*)self->texture)->release();
}
char* _Util_readFile (const char* path, int* length) {
unsigned long size;
char* data = reinterpret_cast<char*>(CCFileUtils::sharedFileUtils()->getFileData(path, "r", &size));
*length = size;
return data;
}
/**/
void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_T2F_Quad* quad) {
RegionAttachment_updateVertices(self, slot);
GLubyte r = slot->skeleton->r * slot->r * 255;
GLubyte g = slot->skeleton->g * slot->g * 255;
GLubyte b = slot->skeleton->b * slot->b * 255;
GLubyte a = slot->skeleton->a * slot->a * 255;
quad->bl.colors.r = r;
quad->bl.colors.g = g;
quad->bl.colors.b = b;
quad->bl.colors.a = a;
quad->tl.colors.r = r;
quad->tl.colors.g = g;
quad->tl.colors.b = b;
quad->tl.colors.a = a;
quad->tr.colors.r = r;
quad->tr.colors.g = g;
quad->tr.colors.b = b;
quad->tr.colors.a = a;
quad->br.colors.r = r;
quad->br.colors.g = g;
quad->br.colors.b = b;
quad->br.colors.a = a;
quad->bl.vertices.x = self->vertices[VERTEX_X1];
quad->bl.vertices.y = self->vertices[VERTEX_Y1];
quad->tl.vertices.x = self->vertices[VERTEX_X2];
quad->tl.vertices.y = self->vertices[VERTEX_Y2];
quad->tr.vertices.x = self->vertices[VERTEX_X3];
quad->tr.vertices.y = self->vertices[VERTEX_Y3];
quad->br.vertices.x = self->vertices[VERTEX_X4];
quad->br.vertices.y = self->vertices[VERTEX_Y4];
if (self->region->rotate) {
quad->tl.texCoords.u = self->region->u;
quad->tl.texCoords.v = self->region->v2;
quad->tr.texCoords.u = self->region->u;
quad->tr.texCoords.v = self->region->v;
quad->br.texCoords.u = self->region->u2;
quad->br.texCoords.v = self->region->v;
quad->bl.texCoords.u = self->region->u2;
quad->bl.texCoords.v = self->region->v2;
} else {
quad->bl.texCoords.u = self->region->u;
quad->bl.texCoords.v = self->region->v2;
quad->tl.texCoords.u = self->region->u;
quad->tl.texCoords.v = self->region->v;
quad->tr.texCoords.u = self->region->u2;
quad->tr.texCoords.v = self->region->v;
quad->br.texCoords.u = self->region->u2;
quad->br.texCoords.v = self->region->v2;
}
}
/**/
CCSkeleton* CCSkeleton::createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale) {
SkeletonJson* json = SkeletonJson_create(atlas);
json->scale = scale;
SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
SkeletonJson_dispose(json);
CCSkeleton* node = skeletonData ? createWithData(skeletonData) : 0;
node->ownsSkeleton = true;
return node;
}
CCSkeleton* CCSkeleton::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) {
Atlas* atlas = Atlas_readAtlasFile(atlasFile);
if (!atlas) return 0;
SkeletonJson* json = SkeletonJson_create(atlas);
json->scale = scale;
SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
SkeletonJson_dispose(json);
if (!skeletonData) {
Atlas_dispose(atlas);
return 0;
}
CCSkeleton* node = createWithData(skeletonData);
node->ownsSkeleton = true;
node->atlas = atlas;
return node;
}
CCSkeleton* CCSkeleton::createWithData (SkeletonData* skeletonData, AnimationStateData* stateData) {
CCSkeleton* node = new CCSkeleton(skeletonData, stateData);
node->autorelease();
return node;
}
CCSkeleton::CCSkeleton (SkeletonData *skeletonData, AnimationStateData *stateData) :
ownsSkeleton(false), ownsStateData(false), atlas(0),
skeleton(0), state(0), debugSlots(false), debugBones(false) {
CONST_CAST(Skeleton*, skeleton) = Skeleton_create(skeletonData);
if (!stateData) {
stateData = AnimationStateData_create(skeletonData);
ownsStateData = true;
}
CONST_CAST(AnimationState*, state) = AnimationState_create(stateData);
blendFunc.src = GL_ONE;
blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
timeScale = 1;
setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor));
scheduleUpdate();
}
CCSkeleton::~CCSkeleton () {
if (ownsSkeleton) Skeleton_dispose(skeleton);
if (ownsStateData) AnimationStateData_dispose(state->data);
if (atlas) Atlas_dispose(atlas);
AnimationState_dispose(state);
}
void CCSkeleton::update (float deltaTime) {
Skeleton_update(skeleton, deltaTime);
AnimationState_update(state, deltaTime * timeScale);
AnimationState_apply(state, skeleton);
Skeleton_updateWorldTransform(skeleton);
}
void CCSkeleton::draw () {
CC_NODE_DRAW_SETUP();
ccGLBlendFunc(blendFunc.src, blendFunc.dst);
ccColor3B color = getColor();
skeleton->r = color.r / (float)255;
skeleton->g = color.g / (float)255;
skeleton->b = color.b / (float)255;
skeleton->a = getOpacity() / (float)255;
CCTextureAtlas* textureAtlas = 0;
ccV3F_C4B_T2F_Quad quad;
quad.tl.vertices.z = 0;
quad.tr.vertices.z = 0;
quad.bl.vertices.z = 0;
quad.br.vertices.z = 0;
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
Slot* slot = skeleton->slots[i];
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
CCTextureAtlas* regionTextureAtlas = (CCTextureAtlas*)attachment->region->page->texture;
if (regionTextureAtlas != textureAtlas) {
if (textureAtlas) {
textureAtlas->drawQuads();
textureAtlas->removeAllQuads();
}
}
textureAtlas = regionTextureAtlas;
if (textureAtlas->getCapacity() == textureAtlas->getTotalQuads() &&
!textureAtlas->resizeCapacity(textureAtlas->getCapacity() * 2)) return;
RegionAttachment_updateQuad(attachment, slot, &quad);
textureAtlas->updateQuad(&quad, textureAtlas->getTotalQuads());
}
if (textureAtlas) {
textureAtlas->drawQuads();
textureAtlas->removeAllQuads();
}
if (debugSlots) {
// Slots.
ccDrawColor4B(0, 0, 255, 255);
glLineWidth(1);
CCPoint points[4];
ccV3F_C4B_T2F_Quad quad;
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
Slot* slot = skeleton->slots[i];
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
RegionAttachment_updateQuad(attachment, slot, &quad);
points[0] = ccp(quad.bl.vertices.x, quad.bl.vertices.y);
points[1] = ccp(quad.br.vertices.x, quad.br.vertices.y);
points[2] = ccp(quad.tr.vertices.x, quad.tr.vertices.y);
points[3] = ccp(quad.tl.vertices.x, quad.tl.vertices.y);
ccDrawPoly(points, 4, true);
}
}
if (debugBones) {
// Bone lengths.
glLineWidth(2);
ccDrawColor4B(255, 0, 0, 255);
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
Bone *bone = skeleton->bones[i];
float x = bone->data->length * bone->m00 + bone->worldX;
float y = bone->data->length * bone->m10 + bone->worldY;
ccDrawLine(ccp(bone->worldX, bone->worldY), ccp(x, y));
}
// Bone origins.
ccPointSize(4);
ccDrawColor4B(0, 0, 255, 255); // Root bone is blue.
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
Bone *bone = skeleton->bones[i];
ccDrawPoint(ccp(bone->worldX, bone->worldY));
if (i == 0) ccDrawColor4B(0, 255, 0, 255);
}
}
}
CCRect CCSkeleton::boundingBox () {
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
float scaleX = getScaleX();
float scaleY = getScaleY();
ccV3F_C4B_T2F_Quad quad;
for (int i = 0; i < skeleton->slotCount; ++i) {
Slot* slot = skeleton->slots[i];
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
RegionAttachment_updateQuad(attachment, slot, &quad);
minX = min(minX, quad.bl.vertices.x * scaleX);
minY = min(minY, quad.bl.vertices.y * scaleY);
maxX = max(maxX, quad.bl.vertices.x * scaleX);
maxY = max(maxY, quad.bl.vertices.y * scaleY);
minX = min(minX, quad.br.vertices.x * scaleX);
minY = min(minY, quad.br.vertices.y * scaleY);
maxX = max(maxX, quad.br.vertices.x * scaleX);
maxY = max(maxY, quad.br.vertices.y * scaleY);
minX = min(minX, quad.tl.vertices.x * scaleX);
minY = min(minY, quad.tl.vertices.y * scaleY);
maxX = max(maxX, quad.tl.vertices.x * scaleX);
maxY = max(maxY, quad.tl.vertices.y * scaleY);
minX = min(minX, quad.tr.vertices.x * scaleX);
minY = min(minY, quad.tr.vertices.y * scaleY);
maxX = max(maxX, quad.tr.vertices.x * scaleX);
maxY = max(maxY, quad.tr.vertices.y * scaleY);
}
CCPoint position = getPosition();
minX = position.x + minX;
minY = position.y + minY;
maxX = position.x + maxX;
maxY = position.y + maxY;
return CCRectMake(minX, minY, maxX - minX, maxY - minY);
}
// CCBlendProtocol
ccBlendFunc CCSkeleton::getBlendFunc () {
return blendFunc;
}
void CCSkeleton::setBlendFunc (ccBlendFunc blendFunc) {
this->blendFunc = blendFunc;
}
}} // namespace cocos2d { namespace extension {

View File

@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_COCOS2DX_H_
#define SPINE_COCOS2DX_H_
#include <spine/spine.h>
#include "cocos2d.h"
namespace cocos2d { namespace extension {
class CCSkeleton: public cocos2d::CCNodeRGBA, public cocos2d::CCBlendProtocol {
private:
bool ownsSkeleton;
bool ownsStateData;
Atlas* atlas;
public:
Skeleton* const skeleton;
AnimationState* const state;
float timeScale;
bool debugSlots;
bool debugBones;
static CCSkeleton* createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale = 1);
static CCSkeleton* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 1);
static CCSkeleton* createWithData (SkeletonData* skeletonData, AnimationStateData* stateData = 0);
CCSkeleton (SkeletonData* skeletonData, AnimationStateData* stateData = 0);
virtual ~CCSkeleton ();
virtual void update (float deltaTime);
virtual void draw ();
virtual cocos2d::CCRect boundingBox ();
// CCBlendProtocol
CC_PROPERTY(cocos2d::ccBlendFunc, blendFunc, BlendFunc);
};
/**/
void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, cocos2d::ccV3F_C4B_T2F_Quad* quad);
}} // namespace cocos2d { namespace extension {
#endif /* SPINE_COCOS2DX_H_ */

46
extensions/spine/spine.h Normal file
View File

@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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_SPINE_H_
#define SPINE_SPINE_H_
#include <spine/Animation.h>
#include <spine/AnimationState.h>
#include <spine/AnimationStateData.h>
#include <spine/Atlas.h>
#include <spine/AtlasAttachmentLoader.h>
#include <spine/Attachment.h>
#include <spine/AttachmentLoader.h>
#include <spine/Bone.h>
#include <spine/BoneData.h>
#include <spine/RegionAttachment.h>
#include <spine/Skeleton.h>
#include <spine/SkeletonData.h>
#include <spine/SkeletonJson.h>
#include <spine/Skin.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#endif /* SPINE_SPINE_H_ */

View File

@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 "SpineTest.h"
#include <iostream>
#include <fstream>
#include <string.h>
using namespace cocos2d;
using namespace cocos2d::extension;
using namespace std;
//------------------------------------------------------------------
//
// SpineTestScene
//
//------------------------------------------------------------------
void SpineTestScene::runThisTest()
{
CCLayer* pLayer = SpineTestLayer::create();
addChild(pLayer);
CCDirector::sharedDirector()->replaceScene(this);
}
bool SpineTestLayer::init () {
if (!CCLayer::init()) return false;
skeletonNode = CCSkeleton::createWithFile("spine/spineboy.json", "spine/spineboy.atlas");
AnimationStateData_setMixByName(skeletonNode->state->data, "walk", "jump", 0.4f);
AnimationStateData_setMixByName(skeletonNode->state->data, "jump", "walk", 0.4f);
AnimationState_setAnimationByName(skeletonNode->state, "walk", true);
skeletonNode->timeScale = 0.3f;
skeletonNode->debugBones = true;
skeletonNode->runAction(CCRepeatForever::create(CCSequence::create(CCFadeOut::create(1),
CCFadeIn::create(1),
CCDelayTime::create(5),
NULL)));
CCSize windowSize = CCDirector::sharedDirector()->getWinSize();
skeletonNode->setPosition(ccp(windowSize.width / 2, 20));
addChild(skeletonNode);
scheduleUpdate();
return true;
}
void SpineTestLayer::update (float deltaTime) {
if (skeletonNode->state->loop) {
if (skeletonNode->state->time > 2) AnimationState_setAnimationByName(skeletonNode->state, "jump", false);
} else {
if (skeletonNode->state->time > 1) AnimationState_setAnimationByName(skeletonNode->state, "walk", true);
}
}

View File

@ -0,0 +1,51 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 _SPINETEST_H_
#define _SPINETEST_H_
#include "cocos2d.h"
#include "../testBasic.h"
#include <spine/spine-cocos2dx.h>
class SpineTestScene : public TestScene
{
public:
virtual void runThisTest();
};
class SpineTestLayer: public cocos2d::CCLayer {
private:
cocos2d::extension::CCSkeleton* skeletonNode;
public:
virtual bool init ();
virtual void update (float deltaTime);
CREATE_FUNC (SpineTestLayer);
};
#endif // _EXAMPLELAYER_H_

View File

@ -119,6 +119,9 @@ static TestScene* CreateTestScene(int nIdx)
case TEST_FILEUTILS:
pScene = new FileUtilsTestScene();
break;
case TEST_SPINE:
pScene = new SpineTestScene();
break;
default:
break;
}

View File

@ -53,6 +53,7 @@
#include "ChipmunkTest/ChipmunkTest.h"
#endif
#include "FileUtilsTest/FileUtilsTest.h"
#include "SpineTest/SpineTest.h"
enum
{
@ -109,6 +110,7 @@ enum
TEST_CLIPPINGNODE,
#endif
TEST_FILEUTILS,
TEST_SPINE,
TESTS_COUNT,
};
@ -165,7 +167,8 @@ const std::string g_aTestNames[TESTS_COUNT] = {
#if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE)
"ClippingNodeTest",
#endif
"FileUtilsTest"
"FileUtilsTest",
"SpineTest"
};
#endif

View File

@ -0,0 +1 @@
c22eca8f608170bab4ceb0086e48999fb2e3d32b

View File

@ -1 +1 @@
7bd1abbd3c1270c95196be7965f911815e7ba4c4
655a6ce855dabb133120b19537ed3879b2fc8194