Conflicts:
	spine-csharp/src/SkeletonJson.cs
This commit is contained in:
Fenrisul 2014-09-04 03:39:10 -07:00
commit bed13e4a36
247 changed files with 9180 additions and 15396 deletions

9
.gitignore vendored
View File

@ -25,12 +25,9 @@ spine-libgdx/libs/*
spine-cocos2dx/2/cocos2dx/
!spine-cocos2dx/2/cocos2dx/Place cocos2dx here.txt
spine-cocos2dx/2/example/proj.win32/Debug
spine-cocos2dx/3.0/cocos2dx/
!spine-cocos2dx/3.0/cocos2dx/Place cocos2dx here.txt
spine-cocos2dx/3.0/example/proj.win32/Debug
spine-cocos2dx/3.1/cocos2dx/
!spine-cocos2dx/3.1/cocos2dx/Place cocos2dx here.txt
spine-cocos2dx/3.1/example/proj.win32/Debug
spine-cocos2dx/3/cocos2dx/
!spine-cocos2dx/3/cocos2dx/Place cocos2dx here.txt
spine-cocos2dx/3/example/proj.win32/Debug
xcuserdata
spine-cocos2d-iphone/2/cocos2d/*

View File

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

View File

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

View File

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

View File

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

View File

@ -28,40 +28,46 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_POLYGONBATCH_H_
#define SPINE_POLYGONBATCH_H_
#ifndef SPINE_IKCONSTRAINT_H_
#define SPINE_IKCONSTRAINT_H_
#include "cocos2d.h"
#include <spine/IkConstraintData.h>
#include <spine/Bone.h>
namespace spine {
#ifdef __cplusplus
extern "C" {
#endif
class PolygonBatch : public cocos2d::Ref {
public:
static PolygonBatch* createWithCapacity (int capacity);
struct spSkeleton;
/** @js ctor */
PolygonBatch();
/** @js NA
* @lua NA */
virtual ~PolygonBatch();
bool initWithCapacity (int capacity);
void add (const cocos2d::Texture2D* texture,
const float* vertices, const float* uvs, int verticesCount,
const int* triangles, int trianglesCount,
cocos2d::Color4B* color);
void flush ();
private:
int capacity;
cocos2d::V2F_C4B_T2F* vertices;
int verticesCount;
GLushort* triangles;
int trianglesCount;
const cocos2d::Texture2D* texture;
typedef struct spIkConstraint spIkConstraint;
struct spIkConstraint {
spIkConstraintData* const data;
int bonesCount;
spBone** bones;
spBone* target;
int bendDirection;
float mix;
};
}
spIkConstraint* spIkConstraint_create (spIkConstraintData* data, const struct spSkeleton* skeleton);
void spIkConstraint_dispose (spIkConstraint* self);
#endif // SPINE_POLYGONBATCH_H_
void spIkConstraint_apply (spIkConstraint* self);
void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha);
void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, float alpha);
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraint IkConstraint;
#define IkConstraint_create(...) spIkConstraint_create(__VA_ARGS__)
#define IkConstraint_dispose(...) spIkConstraint_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_IKCONSTRAINT_H_ */

View File

@ -28,40 +28,38 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_POLYGONBATCH_H_
#define SPINE_POLYGONBATCH_H_
#ifndef SPINE_IKCONSTRAINTDATA_H_
#define SPINE_IKCONSTRAINTDATA_H_
#include "cocos2d.h"
#include <spine/BoneData.h>
namespace spine {
#ifdef __cplusplus
extern "C" {
#endif
class PolygonBatch : public cocos2d::Ref {
public:
static PolygonBatch* createWithCapacity (int capacity);
/** @js ctor */
PolygonBatch();
/** @js NA
* @lua NA */
virtual ~PolygonBatch();
bool initWithCapacity (int capacity);
void add (const cocos2d::Texture2D* texture,
const float* vertices, const float* uvs, int verticesCount,
const int* triangles, int trianglesCount,
cocos2d::Color4B* color);
void flush ();
private:
int capacity;
cocos2d::V2F_C4B_T2F* vertices;
int verticesCount;
GLushort* triangles;
int trianglesCount;
const cocos2d::Texture2D* texture;
typedef struct spIkConstraintData spIkConstraintData;
struct spIkConstraintData {
const char* const name;
int bonesCount;
spBoneData** bones;
spBoneData* target;
int bendDirection;
float mix;
};
}
spIkConstraintData* spIkConstraintData_create (const char* name);
void spIkConstraintData_dispose (spIkConstraintData* self);
#endif // SPINE_POLYGONBATCH_H_
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraintData IkConstraintData;
#define IkConstraintData_create(...) spIkConstraintData_create(__VA_ARGS__)
#define IkConstraintData_dispose(...) spIkConstraintData_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_IKCONSTRAINTDATA_H_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -84,6 +84,8 @@
<ClInclude Include="include\spine\Event.h" />
<ClInclude Include="include\spine\EventData.h" />
<ClInclude Include="include\spine\extension.h" />
<ClInclude Include="include\spine\IkConstraint.h" />
<ClInclude Include="include\spine\IkConstraintData.h" />
<ClInclude Include="include\spine\MeshAttachment.h" />
<ClInclude Include="include\spine\RegionAttachment.h" />
<ClInclude Include="include\spine\Skeleton.h" />
@ -111,6 +113,8 @@
<ClCompile Include="src\spine\Event.c" />
<ClCompile Include="src\spine\EventData.c" />
<ClCompile Include="src\spine\extension.c" />
<ClCompile Include="src\spine\IkConstraint.c" />
<ClCompile Include="src\spine\IkConstraintData.c" />
<ClCompile Include="src\spine\Json.c" />
<ClCompile Include="src\spine\MeshAttachment.c" />
<ClCompile Include="src\spine\RegionAttachment.c" />

View File

@ -90,6 +90,12 @@
<ClInclude Include="include\spine\spine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\spine\IkConstraint.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\spine\IkConstraintData.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\spine\Atlas.c">
@ -164,5 +170,11 @@
<ClCompile Include="src\spine\SkinnedMeshAttachment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\spine\IkConstraint.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\spine\IkConstraintData.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,133 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/IkConstraint.h>
#include <spine/Skeleton.h>
#include <spine/extension.h>
spIkConstraint* spIkConstraint_create (spIkConstraintData* data, const spSkeleton* skeleton) {
int i;
spIkConstraint* self = NEW(spIkConstraint);
CONST_CAST(spIkConstraintData*, self->data) = data;
self->bendDirection = data->bendDirection;
self->mix = data->mix;
self->bonesCount = self->data->bonesCount;
self->bones = MALLOC(spBone*, self->bonesCount);
for (i = 0; i < self->bonesCount; ++i)
self->bones[i] = spSkeleton_findBone(skeleton, self->data->bones[i]->name);
self->target = spSkeleton_findBone(skeleton, self->data->target->name);
return self;
}
void spIkConstraint_dispose (spIkConstraint* self) {
FREE(self->bones);
FREE(self);
}
void spIkConstraint_apply (spIkConstraint* self) {
switch (self->bonesCount) {
case 1:
spIkConstraint_apply1(self->bones[0], self->target->worldX, self->target->worldY, self->mix);
break;
case 2:
spIkConstraint_apply2(self->bones[0], self->bones[1], self->target->worldX, self->target->worldY, self->bendDirection,
self->mix);
break;
}
}
void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha) {
float parentRotation = (!bone->data->inheritRotation || !bone->parent) ? 0 : bone->parent->worldRotation;
float rotation = bone->rotation;
float rotationIK = ATAN2(targetY - bone->worldY, targetX - bone->worldX) * RAD_DEG - parentRotation;
bone->rotationIK = rotation + (rotationIK - rotation) * alpha;
}
void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, float alpha) {
float positionX, positionY, childX, childY, offset, len1, len2, cosDenom, cos, childAngle, adjacent, opposite, parentAngle, rotation;
spBone* parentParent;
float childRotation = child->rotation, parentRotation = parent->rotation;
if (alpha == 0) {
child->rotationIK = childRotation;
parent->rotationIK = parentRotation;
return;
}
parentParent = parent->parent;
if (parentParent) {
spBone_worldToLocal(parentParent, targetX, targetY, &positionX, &positionY);
targetX = (positionX - parent->x) * parentParent->worldScaleX;
targetY = (positionY - parent->y) * parentParent->worldScaleY;
} else {
targetX -= parent->x;
targetY -= parent->y;
}
if (child->parent == parent) {
positionX = child->x;
positionY = child->y;
} else {
spBone_localToWorld(child->parent, child->x, child->y, &positionX, &positionY);
spBone_worldToLocal(parent, positionX, positionY, &positionX, &positionY);
}
childX = positionX * parent->worldScaleX;
childY = positionY * parent->worldScaleY;
offset = ATAN2(childY, childX);
len1 = SQRT(childX * childX + childY * childY);
len2 = child->data->length * child->worldScaleX;
/* Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/ */
cosDenom = 2 * len1 * len2;
if (cosDenom < 0.0001f) {
child->rotationIK = childRotation + (ATAN2(targetY, targetX) * RAD_DEG - parentRotation - childRotation) * alpha;
return;
}
cos = (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom;
if (cos < -1)
cos = -1;
else if (cos > 1) /**/
cos = 1;
childAngle = ACOS(cos) * bendDirection;
adjacent = len1 + len2 * cos;
opposite = len2 * SIN(childAngle);
parentAngle = ATAN2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
rotation = (parentAngle - offset) * RAD_DEG - parentRotation;
if (rotation > 180)
rotation -= 360;
else if (rotation < -180) /**/
rotation += 360;
parent->rotationIK = parentRotation + rotation * alpha;
rotation = (childAngle + offset) * RAD_DEG - childRotation;
if (rotation > 180)
rotation -= 360;
else if (rotation < -180) /**/
rotation += 360;
child->rotationIK = childRotation + (rotation + parent->worldRotation - child->parent->worldRotation) * alpha;
}

View File

@ -28,21 +28,19 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef _GOBLINSEXAMPLE_H_
#define _GOBLINSEXAMPLE_H_
#include <spine/IkConstraintData.h>
#include <spine/extension.h>
#include "cocos2d.h"
#include <spine/spine-cocos2dx.h>
spIkConstraintData* spIkConstraintData_create (const char* name) {
spIkConstraintData* self = NEW(spIkConstraintData);
MALLOC_STR(self->name, name);
self->bendDirection = 1;
self->mix = 1;
return self;
}
class GoblinsExample : public cocos2d::LayerColor {
public:
static cocos2d::Scene* scene ();
virtual bool init ();
CREATE_FUNC (GoblinsExample);
private:
spine::SkeletonAnimation* skeletonNode;
};
#endif // _GOBLINSEXAMPLE_H_
void spIkConstraintData_dispose (spIkConstraintData* self) {
FREE(self->name);
FREE(self->bones);
FREE(self);
}

View File

@ -1,5 +1,6 @@
/*
Copyright (c) 2009 Dave Gamble
Copyright (c) 2009, Dave Gamble
Copyright (c) 2013, Esoteric Software
Permission is hereby granted, dispose of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -55,19 +56,19 @@ static int Json_strcasecmp (const char* s1, const char* s2) {
/* TODO we may be able to elide these NULL checks if we can prove
* the graph and input (only callsite is Json_getItem) should not have NULLs
*/
if ( s1 && s2 )
{
if (s1 && s2) {
#if defined(_WIN32)
return _stricmp( s1, s2 );
return _stricmp(s1, s2);
#else
return strcasecmp( s1, s2 );
#endif
}
else
{
if ( s1 < s2 ) return -1; /* s1 is null, s2 is not */
else if ( s1 == s2 ) return 0; /* both are null */
else return 1; /* s2 is nul s1 is not */
} else {
if (s1 < s2)
return -1; /* s1 is null, s2 is not */
else if (s1 == s2)
return 0; /* both are null */
else
return 1; /* s2 is nul s1 is not */
}
}
@ -101,29 +102,24 @@ static const char* parse_number (Json *item, const char* num) {
* We also already know that this starts with [-0-9] from parse_value.
*/
#if __STDC_VERSION__ >= 199901L
n = strtof( num, &endptr );
n = strtof(num, &endptr);
#else
n = (float)strtod( num, &endptr );
#endif
/* ignore errno's ERANGE, which returns +/-HUGE_VAL */
/* n is 0 on any other error */
if ( endptr != num )
{
if (endptr != num) {
/* Parse success, number found. */
item->valueFloat = n;
item->valueInt = (int)n;
item->type = Json_Number;
return endptr;
}
else
{
} else {
/* Parse failure, ep is set. */
ep = num;
return 0;
}
}
/* Parse the input text into an unescaped cstring, and populate item. */
@ -231,7 +227,7 @@ static const char* parse_object (Json *item, const char* value);
/* Utility to jump whitespace and cr/lf */
static const char* skip (const char* in) {
if ( !in ) return 0; /* must propagate NULL since it's often called in skip(f(...)) form */
if (!in) return 0; /* must propagate NULL since it's often called in skip(f(...)) form */
while (*in && (unsigned char)*in <= 32)
in++;
return in;
@ -262,54 +258,50 @@ static const char* parse_value (Json *item, const char* value) {
if (!value) return 0; /* Fail on null. */
#endif
switch ( *value )
{
case 'n':
{
if (!strncmp(value+1, "ull", 3)) {
item->type = Json_NULL;
return value + 4;
}
break;
switch (*value) {
case 'n': {
if (!strncmp(value + 1, "ull", 3)) {
item->type = Json_NULL;
return value + 4;
}
case 'f':
{
if (!strncmp(value+1, "alse", 4)) {
item->type = Json_False;
/* calloc prevents us needing item->type = Json_False or valueInt = 0 here */
return value + 5;
}
break;
break;
}
case 'f': {
if (!strncmp(value + 1, "alse", 4)) {
item->type = Json_False;
/* calloc prevents us needing item->type = Json_False or valueInt = 0 here */
return value + 5;
}
case 't':
{
if (!strncmp(value+1, "rue", 3)) {
item->type = Json_True;
item->valueInt = 1;
return value + 4;
}
break;
break;
}
case 't': {
if (!strncmp(value + 1, "rue", 3)) {
item->type = Json_True;
item->valueInt = 1;
return value + 4;
}
case '\"':
return parse_string(item, value);
case '[':
return parse_array(item, value);
case '{':
return parse_object(item, value);
case '-': /* fallthrough */
case '0': /* fallthrough */
case '1': /* fallthrough */
case '2': /* fallthrough */
case '3': /* fallthrough */
case '4': /* fallthrough */
case '5': /* fallthrough */
case '6': /* fallthrough */
case '7': /* fallthrough */
case '8': /* fallthrough */
case '9':
return parse_number(item, value);
default:
break;
break;
}
case '\"':
return parse_string(item, value);
case '[':
return parse_array(item, value);
case '{':
return parse_object(item, value);
case '-': /* fallthrough */
case '0': /* fallthrough */
case '1': /* fallthrough */
case '2': /* fallthrough */
case '3': /* fallthrough */
case '4': /* fallthrough */
case '5': /* fallthrough */
case '6': /* fallthrough */
case '7': /* fallthrough */
case '8': /* fallthrough */
case '9':
return parse_number(item, value);
default:
break;
}
ep = value;

View File

@ -39,7 +39,7 @@ extern "C" {
#define Json_Object 6
#ifndef SPINE_JSON_HAVE_PREV
/* Spine doesn't use the "prev" link in the Json sibling lists. */
/* Spine doesn't use the "prev" link in the Json sibling lists. */
#define SPINE_JSON_HAVE_PREV 0
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -149,14 +149,14 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
const int* triangles = 0;
int trianglesCount = 0;
float r = 0, g = 0, b = 0, a = 0;
for (int i = 0, n = _skeleton->slotCount; i < n; i++) {
for (int i = 0, n = _skeleton->slotsCount; i < n; i++) {
spSlot* slot = _skeleton->drawOrder[i];
if (!slot->attachment) continue;
CCTexture2D *texture = 0;
switch (slot->attachment->type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
texture = [self getTextureForRegion:attachment];
uvs = attachment->uvs;
verticesCount = 8;
@ -170,7 +170,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
}
case SP_ATTACHMENT_MESH: {
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
texture = [self getTextureForMesh:attachment];
uvs = attachment->uvs;
verticesCount = attachment->verticesCount;
@ -184,7 +184,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
}
case SP_ATTACHMENT_SKINNED_MESH: {
spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
texture = [self getTextureForSkinnedMesh:attachment];
uvs = attachment->uvs;
verticesCount = attachment->uvsCount;
@ -220,11 +220,11 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
ccDrawColor4B(0, 0, 255, 255);
glLineWidth(1);
CGPoint points[4];
for (int i = 0, n = _skeleton->slotCount; i < n; i++) {
for (int i = 0, n = _skeleton->slotsCount; i < n; i++) {
spSlot* slot = _skeleton->drawOrder[i];
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
points[0] = ccp(worldVertices[0], worldVertices[1]);
points[1] = ccp(worldVertices[2], worldVertices[3]);
points[2] = ccp(worldVertices[4], worldVertices[5]);
@ -236,7 +236,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
// Bone lengths.
glLineWidth(2);
ccDrawColor4B(255, 0, 0, 255);
for (int i = 0, n = _skeleton->boneCount; i < n; i++) {
for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
spBone *bone = _skeleton->bones[i];
float x = bone->data->length * bone->m00 + bone->worldX;
float y = bone->data->length * bone->m10 + bone->worldY;
@ -245,7 +245,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
// Bone origins.
ccPointSize(4);
ccDrawColor4B(0, 0, 255, 255); // Root bone is blue.
for (int i = 0, n = _skeleton->boneCount; i < n; i++) {
for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
spBone *bone = _skeleton->bones[i];
ccDrawPoint(ccp(bone->worldX, bone->worldY));
if (i == 0) ccDrawColor4B(0, 255, 0, 255);
@ -268,21 +268,21 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
- (CGRect) boundingBox {
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
float scaleX = self.scaleX, scaleY = self.scaleY;
for (int i = 0; i < _skeleton->slotCount; ++i) {
for (int i = 0; i < _skeleton->slotsCount; ++i) {
spSlot* slot = _skeleton->slots[i];
if (!slot->attachment) continue;
int verticesCount;
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
verticesCount = 8;
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
verticesCount = mesh->verticesCount;
} else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
verticesCount = mesh->uvsCount;
} else
continue;

View File

@ -147,7 +147,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
const int* triangles = 0;
int trianglesCount = 0;
float r = 0, g = 0, b = 0, a = 0;
for (int i = 0, n = _skeleton->slotCount; i < n; i++) {
for (int i = 0, n = _skeleton->slotsCount; i < n; i++) {
spSlot* slot = _skeleton->drawOrder[i];
if (!slot->attachment) continue;
@ -155,7 +155,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
switch (slot->attachment->type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
texture = [self getTextureForRegion:attachment];
uvs = attachment->uvs;
verticesCount = 8;
@ -170,7 +170,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
case SP_ATTACHMENT_MESH: {
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
texture = [self getTextureForMesh:attachment];
uvs = attachment->uvs;
verticesCount = attachment->verticesCount;
@ -185,7 +185,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
case SP_ATTACHMENT_SKINNED_MESH: {
spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
texture = [self getTextureForSkinnedMesh:attachment];
uvs = attachment->uvs;
verticesCount = attachment->uvsCount;
@ -233,11 +233,11 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
if (_debugSlots) {
// Slots.
CGPoint points[4];
for (int i = 0, n = _skeleton->slotCount; i < n; i++) {
for (int i = 0, n = _skeleton->slotsCount; i < n; i++) {
spSlot* slot = _skeleton->drawOrder[i];
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
points[0] = ccp(worldVertices[0], worldVertices[1]);
points[1] = ccp(worldVertices[2], worldVertices[3]);
points[2] = ccp(worldVertices[4], worldVertices[5]);
@ -248,7 +248,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
}
if (_debugBones) {
// Bone lengths.
for (int i = 0, n = _skeleton->boneCount; i < n; i++) {
for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
spBone *bone = _skeleton->bones[i];
float x = bone->data->length * bone->m00 + bone->worldX;
float y = bone->data->length * bone->m10 + bone->worldY;
@ -256,7 +256,7 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
}
// Bone origins.
for (int i = 0, n = _skeleton->boneCount; i < n; i++) {
for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
spBone *bone = _skeleton->bones[i];
[_drawNode drawDot:ccp(bone->worldX, bone->worldY) radius:4 color:[CCColor greenColor]];
if (i == 0) [_drawNode drawDot:ccp(bone->worldX, bone->worldY) radius:4 color:[CCColor blueColor]];
@ -279,21 +279,21 @@ static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
- (CGRect) boundingBox {
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
float scaleX = self.scaleX, scaleY = self.scaleY;
for (int i = 0; i < _skeleton->slotCount; ++i) {
for (int i = 0; i < _skeleton->slotsCount; ++i) {
spSlot* slot = _skeleton->slots[i];
if (!slot->attachment) continue;
int verticesCount;
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
verticesCount = 8;
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
verticesCount = mesh->verticesCount;
} else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
verticesCount = mesh->uvsCount;
} else
continue;

View File

@ -16,5 +16,5 @@ Alternatively, the contents of the `spine-c/src`, `spine-c/include` and `spine-c
## Examples
[Spineboy](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/2/example/Classes/SpineboyExample.cpp)
[Golbins](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/2/example/Classes/GoblinsExample.cpp)
- [Spineboy](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/2/example/Classes/SpineboyExample.cpp)
- [Golbins](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/2/example/Classes/GoblinsExample.cpp)

View File

@ -151,14 +151,14 @@ void SkeletonRenderer::draw () {
const int* triangles = nullptr;
int trianglesCount = 0;
float r = 0, g = 0, b = 0, a = 0;
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
for (int i = 0, n = skeleton->slotsCount; i < n; i++) {
spSlot* slot = skeleton->drawOrder[i];
if (!slot->attachment) continue;
CCTexture2D *texture = nullptr;
switch (slot->attachment->type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = 8;
@ -172,7 +172,7 @@ void SkeletonRenderer::draw () {
}
case SP_ATTACHMENT_MESH: {
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->verticesCount;
@ -186,7 +186,7 @@ void SkeletonRenderer::draw () {
}
case SP_ATTACHMENT_SKINNED_MESH: {
spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->uvsCount;
@ -220,11 +220,11 @@ void SkeletonRenderer::draw () {
ccDrawColor4B(0, 0, 255, 255);
glLineWidth(1);
CCPoint points[4];
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
for (int i = 0, n = skeleton->slotsCount; i < n; i++) {
spSlot* slot = skeleton->drawOrder[i];
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
points[0] = ccp(worldVertices[0], worldVertices[1]);
points[1] = ccp(worldVertices[2], worldVertices[3]);
points[2] = ccp(worldVertices[4], worldVertices[5]);
@ -236,7 +236,7 @@ void SkeletonRenderer::draw () {
// Bone lengths.
glLineWidth(2);
ccDrawColor4B(255, 0, 0, 255);
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
for (int i = 0, n = skeleton->bonesCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
float x = bone->data->length * bone->m00 + bone->worldX;
float y = bone->data->length * bone->m10 + bone->worldY;
@ -245,7 +245,7 @@ void SkeletonRenderer::draw () {
// Bone origins.
ccPointSize(4);
ccDrawColor4B(0, 0, 255, 255); // Root bone is blue.
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
for (int i = 0, n = skeleton->bonesCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
ccDrawPoint(ccp(bone->worldX, bone->worldY));
if (i == 0) ccDrawColor4B(0, 255, 0, 255);
@ -268,21 +268,21 @@ CCTexture2D* SkeletonRenderer::getTexture (spSkinnedMeshAttachment* attachment)
CCRect SkeletonRenderer::boundingBox () {
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
float scaleX = getScaleX(), scaleY = getScaleY();
for (int i = 0; i < skeleton->slotCount; ++i) {
for (int i = 0; i < skeleton->slotsCount; ++i) {
spSlot* slot = skeleton->slots[i];
if (!slot->attachment) continue;
int verticesCount;
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices);
verticesCount = 8;
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
verticesCount = mesh->verticesCount;
} else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
verticesCount = mesh->uvsCount;
} else
continue;

View File

@ -1,20 +0,0 @@
# spine-cocos2dx v3.0
The spine-cocos2dx runtime provides functionality to load, manipulate and render [Spine](http://esotericsoftware.com) skeletal animation data using [cocos2d-x](http://www.cocos2d-x.org/). spine-cocos2dx is based on [spine-c](https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine-c).
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Place the contents of a cocos2d-x version 3.0 distribution into the `spine-cocos2dx/3.0/cocos2dx` directory.
1. Open the XCode (Mac) or Visual C++ 2012 Express (Windows) project file from the `spine-cocos2dx/3.0/example` directory. Build files are also provided for Android.
Alternatively, the contents of the `spine-c/src`, `spine-c/include` and `spine-cocos2dx/3.0/src` directories can be copied into your project. Be sure your header search path will find the contents of the `spine-c/include` and `spine-cocos2dx/3.0/src` directories. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files.
## Notes
- Images are no longer premultiplied by cocos2d-x as they where in cocos2d-x v2, so the Spine atlas images *should* use premultiplied alpha.
## Examples
[Spineboy](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/3.0/example/Classes/SpineboyExample.cpp)
[Golbins](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/3.0/example/Classes/GoblinsExample.cpp)

View File

@ -1,18 +0,0 @@
#ifndef _APPDELEGATE_H_
#define _APPDELEGATE_H_
#include "cocos2d.h"
class AppDelegate: private cocos2d::CCApplication {
public:
AppDelegate ();
virtual ~AppDelegate ();
virtual bool applicationDidFinishLaunching ();
virtual void applicationDidEnterBackground ();
virtual void applicationWillEnterForeground ();
};
#endif // _APPDELEGATE_H_

View File

@ -1,61 +0,0 @@
#ifndef _APPMACROS_H_
#define _APPMACROS_H_
#include "cocos2d.h"
/* For demonstrating using one design resolution to match different resources,
or one resource to match different design resolutions.
[Situation 1] Using one design resolution to match different resources.
Please look into Appdelegate::applicationDidFinishLaunching.
We check current device frame size to decide which resource need to be selected.
So if you want to test this situation which said in title '[Situation 1]',
you should change ios simulator to different device(e.g. iphone, iphone-retina3.5, iphone-retina4.0, ipad, ipad-retina),
or change the window size in "proj.XXX/main.cpp" by "CCEGLView::setFrameSize" if you are using win32 or linux plaform
and modify "proj.mac/AppController.mm" by changing the window rectangle.
[Situation 2] Using one resource to match different design resolutions.
The coordinates in your codes is based on your current design resolution rather than resource size.
Therefore, your design resolution could be very large and your resource size could be small.
To test this, just define the marco 'TARGET_DESIGN_RESOLUTION_SIZE' to 'DESIGN_RESOLUTION_2048X1536'
and open iphone simulator or create a window of 480x320 size.
[Note] Normally, developer just need to define one design resolution(e.g. 960x640) with one or more resources.
*/
#define DESIGN_RESOLUTION_480X320 0
#define DESIGN_RESOLUTION_960x640 1
#define DESIGN_RESOLUTION_1024X768 2
#define DESIGN_RESOLUTION_2048X1536 3
/* If you want to switch design resolution, change next line */
#define TARGET_DESIGN_RESOLUTION_SIZE DESIGN_RESOLUTION_960x640
typedef struct tagResource {
cocos2d::Size size;
char directory[100];
} Resource;
static Resource smallResource = {cocos2d::Size(480, 320), "iphone"};
static Resource mediumResource = {cocos2d::Size(960, 640), "iphone-retina"};
static Resource largeResource = {cocos2d::Size(1024, 768), "ipad"};
static Resource extralargeResource = {cocos2d::Size(2048, 1536), "ipad-retina"};
#if (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_480X320)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(480, 320);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_960x640)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(960, 640);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_1024X768)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(1024, 768);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_2048X1536)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(2048, 1536);
#else
#error unknown target design resolution!
#endif
// The font size 24 is designed for small resolution, so we should change it to fit for current design resolution
#define TITLE_FONT_SIZE (cocos2d::Director::getInstance()->getOpenGLView()->getDesignResolutionSize().width / smallResource.size.width * 24)
#endif /* _APPMACROS_H_ */

View File

@ -1,73 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "GoblinsExample.h"
#include "SpineboyExample.h"
#include <iostream>
#include <fstream>
#include <string.h>
USING_NS_CC;
using namespace spine;
using namespace std;
Scene* GoblinsExample::scene () {
Scene *scene = Scene::create();
scene->addChild(GoblinsExample::create());
return scene;
}
bool GoblinsExample::init () {
if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false;
skeletonNode = SkeletonAnimation::createWithFile("goblins-ffd.json", "goblins-ffd.atlas", 1.5f);
skeletonNode->setAnimation(0, "walk", true);
skeletonNode->setSkin("goblin");
Size windowSize = Director::getInstance()->getWinSize();
skeletonNode->setPosition(Point(windowSize.width / 2, 20));
addChild(skeletonNode);
scheduleUpdate();
EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [this] (Touch* touch, Event* event) -> bool {
if (!skeletonNode->debugBones)
skeletonNode->debugBones = true;
else if (skeletonNode->timeScale == 1)
skeletonNode->timeScale = 0.3f;
else
Director::getInstance()->replaceScene(SpineboyExample::scene());
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
return true;
}

View File

@ -1,105 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "SpineboyExample.h"
#include "GoblinsExample.h"
#include <iostream>
#include <fstream>
#include <string.h>
USING_NS_CC;
using namespace spine;
using namespace std;
Scene* SpineboyExample::scene () {
Scene *scene = Scene::create();
scene->addChild(SpineboyExample::create());
return scene;
}
bool SpineboyExample::init () {
if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false;
skeletonNode = SkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas", 0.6f);
skeletonNode->startListener = [this] (int trackIndex) {
spTrackEntry* entry = spAnimationState_getCurrent(skeletonNode->state, trackIndex);
const char* animationName = (entry && entry->animation) ? entry->animation->name : 0;
log("%d start: %s", trackIndex, animationName);
};
skeletonNode->endListener = [] (int trackIndex) {
log("%d end", trackIndex);
};
skeletonNode->completeListener = [] (int trackIndex, int loopCount) {
log("%d complete: %d", trackIndex, loopCount);
};
skeletonNode->eventListener = [] (int trackIndex, spEvent* event) {
log("%d event: %s, %d, %f, %s", trackIndex, event->data->name, event->intValue, event->floatValue, event->stringValue);
};
skeletonNode->setMix("walk", "jump", 0.2f);
skeletonNode->setMix("jump", "run", 0.2f);
skeletonNode->setAnimation(0, "walk", true);
spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 3);
skeletonNode->addAnimation(0, "run", true);
skeletonNode->setStartListener(jumpEntry, [] (int trackIndex) {
log("jumped!");
});
// skeletonNode->addAnimation(1, "test", true);
// skeletonNode->runAction(RepeatForever::create(Sequence::create(FadeOut::create(1), FadeIn::create(1), DelayTime::create(5), NULL)));
Size windowSize = Director::getInstance()->getWinSize();
skeletonNode->setPosition(Point(windowSize.width / 2, 20));
addChild(skeletonNode);
scheduleUpdate();
EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [this] (Touch* touch, Event* event) -> bool {
if (!skeletonNode->debugBones)
skeletonNode->debugBones = true;
else if (skeletonNode->timeScale == 1)
skeletonNode->timeScale = 0.3f;
else
Director::getInstance()->replaceScene(GoblinsExample::scene());
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
return true;
}
void SpineboyExample::update (float deltaTime) {
// Test releasing memory.
// Director::getInstance()->replaceScene(SpineboyExample::scene());
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

View File

@ -1,112 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/PolygonBatch.h>
#include <spine/extension.h>
USING_NS_CC;
namespace spine {
PolygonBatch* PolygonBatch::createWithCapacity (int capacity) {
PolygonBatch* batch = new PolygonBatch();
batch->initWithCapacity(capacity);
batch->autorelease();
return batch;
}
PolygonBatch::PolygonBatch () :
capacity(0),
vertices(nullptr), verticesCount(0),
triangles(nullptr), trianglesCount(0),
texture(nullptr)
{}
bool PolygonBatch::initWithCapacity (int capacity) {
// 32767 is max index, so 32767 / 3 - (32767 / 3 % 3) = 10920.
CCASSERT(capacity <= 10920, "capacity cannot be > 10920");
CCASSERT(capacity >= 0, "capacity cannot be < 0");
this->capacity = capacity;
vertices = MALLOC(V2F_C4B_T2F, capacity);
triangles = MALLOC(GLushort, capacity * 3);
return true;
}
PolygonBatch::~PolygonBatch () {
FREE(vertices);
FREE(triangles);
}
void PolygonBatch::add (const Texture2D* addTexture,
const float* addVertices, const float* uvs, int addVerticesCount,
const int* addTriangles, int addTrianglesCount,
Color4B* color) {
if (
addTexture != texture
|| verticesCount + (addVerticesCount >> 1) > capacity
|| trianglesCount + addTrianglesCount > capacity * 3) {
this->flush();
texture = addTexture;
}
for (int i = 0; i < addTrianglesCount; ++i, ++trianglesCount)
triangles[trianglesCount] = addTriangles[i] + verticesCount;
for (int i = 0; i < addVerticesCount; i += 2, ++verticesCount) {
V2F_C4B_T2F* vertex = vertices + verticesCount;
vertex->vertices.x = addVertices[i];
vertex->vertices.y = addVertices[i + 1];
vertex->colors = *color;
vertex->texCoords.u = uvs[i];
vertex->texCoords.v = uvs[i + 1];
}
}
void PolygonBatch::flush () {
if (!verticesCount) return;
GL::bindTexture2D(texture->getName());
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORDS);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), &vertices[0].vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), &vertices[0].colors);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), &vertices[0].texCoords);
glDrawElements(GL_TRIANGLES, trianglesCount, GL_UNSIGNED_SHORT, triangles);
verticesCount = 0;
trianglesCount = 0;
CHECK_GL_ERROR_DEBUG();
}
}

View File

@ -1,229 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/SkeletonAnimation.h>
#include <spine/spine-cocos2dx.h>
#include <spine/extension.h>
#include <algorithm>
USING_NS_CC;
using std::min;
using std::max;
using std::vector;
namespace spine {
void animationCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) {
((SkeletonAnimation*)state->rendererObject)->onAnimationStateEvent(trackIndex, type, event, loopCount);
}
void trackEntryCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) {
((SkeletonAnimation*)state->rendererObject)->onTrackEntryEvent(trackIndex, type, event, loopCount);
}
typedef struct _TrackEntryListeners {
StartListener startListener;
EndListener endListener;
CompleteListener completeListener;
EventListener eventListener;
} _TrackEntryListeners;
static _TrackEntryListeners* getListeners (spTrackEntry* entry) {
if (!entry->rendererObject) {
entry->rendererObject = NEW(spine::_TrackEntryListeners);
entry->listener = trackEntryCallback;
}
return (_TrackEntryListeners*)entry->rendererObject;
}
void disposeTrackEntry (spTrackEntry* entry) {
if (entry->rendererObject) FREE(entry->rendererObject);
_spTrackEntry_dispose(entry);
}
//
SkeletonAnimation* SkeletonAnimation::createWithData (spSkeletonData* skeletonData) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonData);
node->autorelease();
return node;
}
SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlas, scale);
node->autorelease();
return node;
}
SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlasFile, scale);
node->autorelease();
return node;
}
void SkeletonAnimation::initialize () {
ownsAnimationStateData = true;
state = spAnimationState_create(spAnimationStateData_create(skeleton->data));
state->rendererObject = this;
state->listener = animationCallback;
_spAnimationState* stateInternal = (_spAnimationState*)state;
stateInternal->disposeTrackEntry = disposeTrackEntry;
}
SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData)
: SkeletonRenderer(skeletonData) {
initialize();
}
SkeletonAnimation::SkeletonAnimation (const char* skeletonDataFile, spAtlas* atlas, float scale)
: SkeletonRenderer(skeletonDataFile, atlas, scale) {
initialize();
}
SkeletonAnimation::SkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale)
: SkeletonRenderer(skeletonDataFile, atlasFile, scale) {
initialize();
}
SkeletonAnimation::~SkeletonAnimation () {
if (ownsAnimationStateData) spAnimationStateData_dispose(state->data);
spAnimationState_dispose(state);
}
void SkeletonAnimation::update (float deltaTime) {
super::update(deltaTime);
deltaTime *= timeScale;
spAnimationState_update(state, deltaTime);
spAnimationState_apply(state, skeleton);
spSkeleton_updateWorldTransform(skeleton);
}
void SkeletonAnimation::setAnimationStateData (spAnimationStateData* stateData) {
CCASSERT(stateData, "stateData cannot be null.");
if (ownsAnimationStateData) spAnimationStateData_dispose(state->data);
spAnimationState_dispose(state);
ownsAnimationStateData = false;
state = spAnimationState_create(stateData);
state->rendererObject = this;
state->listener = animationCallback;
}
void SkeletonAnimation::setMix (const char* fromAnimation, const char* toAnimation, float duration) {
spAnimationStateData_setMixByName(state->data, fromAnimation, toAnimation, duration);
}
spTrackEntry* SkeletonAnimation::setAnimation (int trackIndex, const char* name, bool loop) {
spAnimation* animation = spSkeletonData_findAnimation(skeleton->data, name);
if (!animation) {
log("Spine: Animation not found: %s", name);
return 0;
}
return spAnimationState_setAnimation(state, trackIndex, animation, loop);
}
spTrackEntry* SkeletonAnimation::addAnimation (int trackIndex, const char* name, bool loop, float delay) {
spAnimation* animation = spSkeletonData_findAnimation(skeleton->data, name);
if (!animation) {
log("Spine: Animation not found: %s", name);
return 0;
}
return spAnimationState_addAnimation(state, trackIndex, animation, loop, delay);
}
spTrackEntry* SkeletonAnimation::getCurrent (int trackIndex) {
return spAnimationState_getCurrent(state, trackIndex);
}
void SkeletonAnimation::clearTracks () {
spAnimationState_clearTracks(state);
}
void SkeletonAnimation::clearTrack (int trackIndex) {
spAnimationState_clearTrack(state, trackIndex);
}
void SkeletonAnimation::onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) {
switch (type) {
case SP_ANIMATION_START:
if (startListener) startListener(trackIndex);
break;
case SP_ANIMATION_END:
if (endListener) endListener(trackIndex);
break;
case SP_ANIMATION_COMPLETE:
if (completeListener) completeListener(trackIndex, loopCount);
break;
case SP_ANIMATION_EVENT:
if (eventListener) eventListener(trackIndex, event);
break;
}
}
void SkeletonAnimation::onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) {
spTrackEntry* entry = spAnimationState_getCurrent(state, trackIndex);
if (!entry->rendererObject) return;
_TrackEntryListeners* listeners = (_TrackEntryListeners*)entry->rendererObject;
switch (type) {
case SP_ANIMATION_START:
if (listeners->startListener) listeners->startListener(trackIndex);
break;
case SP_ANIMATION_END:
if (listeners->endListener) listeners->endListener(trackIndex);
break;
case SP_ANIMATION_COMPLETE:
if (listeners->completeListener) listeners->completeListener(trackIndex, loopCount);
break;
case SP_ANIMATION_EVENT:
if (listeners->eventListener) listeners->eventListener(trackIndex, event);
break;
}
}
void SkeletonAnimation::setStartListener (spTrackEntry* entry, StartListener listener) {
getListeners(entry)->startListener = listener;
}
void SkeletonAnimation::setEndListener (spTrackEntry* entry, EndListener listener) {
getListeners(entry)->endListener = listener;
}
void SkeletonAnimation::setCompleteListener (spTrackEntry* entry, CompleteListener listener) {
getListeners(entry)->completeListener = listener;
}
void SkeletonAnimation::setEventListener (spTrackEntry* entry, spine::EventListener listener) {
getListeners(entry)->eventListener = listener;
}
}

View File

@ -1,96 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_SKELETONANIMATION_H_
#define SPINE_SKELETONANIMATION_H_
#include <spine/spine.h>
#include <spine/SkeletonRenderer.h>
#include "cocos2d.h"
namespace spine {
typedef std::function<void(int trackIndex)> StartListener;
typedef std::function<void(int trackIndex)> EndListener;
typedef std::function<void(int trackIndex, int loopCount)> CompleteListener;
typedef std::function<void(int trackIndex, spEvent* event)> EventListener;
/** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be
* played later. */
class SkeletonAnimation: public SkeletonRenderer {
public:
spAnimationState* state;
static SkeletonAnimation* createWithData (spSkeletonData* skeletonData);
static SkeletonAnimation* createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonAnimation* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
SkeletonAnimation (spSkeletonData* skeletonData);
SkeletonAnimation (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
virtual ~SkeletonAnimation ();
virtual void update (float deltaTime);
void setAnimationStateData (spAnimationStateData* stateData);
void setMix (const char* fromAnimation, const char* toAnimation, float duration);
spTrackEntry* setAnimation (int trackIndex, const char* name, bool loop);
spTrackEntry* addAnimation (int trackIndex, const char* name, bool loop, float delay = 0);
spTrackEntry* getCurrent (int trackIndex = 0);
void clearTracks ();
void clearTrack (int trackIndex = 0);
StartListener startListener;
EndListener endListener;
CompleteListener completeListener;
EventListener eventListener;
void setStartListener (spTrackEntry* entry, StartListener listener);
void setEndListener (spTrackEntry* entry, EndListener listener);
void setCompleteListener (spTrackEntry* entry, CompleteListener listener);
void setEventListener (spTrackEntry* entry, EventListener listener);
virtual void onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
virtual void onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
protected:
SkeletonAnimation ();
private:
typedef SkeletonRenderer super;
bool ownsAnimationStateData;
void initialize ();
};
}
#endif /* SPINE_SKELETONANIMATION_H_ */

View File

@ -1,366 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/SkeletonRenderer.h>
#include <spine/spine-cocos2dx.h>
#include <spine/extension.h>
#include <spine/PolygonBatch.h>
#include <algorithm>
USING_NS_CC;
using std::min;
using std::max;
namespace spine {
static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData);
node->autorelease();
return node;
}
SkeletonRenderer* SkeletonRenderer::createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonDataFile, atlas, scale);
node->autorelease();
return node;
}
SkeletonRenderer* SkeletonRenderer::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonDataFile, atlasFile, scale);
node->autorelease();
return node;
}
void SkeletonRenderer::initialize () {
atlas = 0;
debugSlots = false;
debugBones = false;
timeScale = 1;
worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
batch = PolygonBatch::createWithCapacity(2000); // Max number of vertices and triangles per batch.
batch->retain();
blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
setOpacityModifyRGB(true);
setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
scheduleUpdate();
}
void SkeletonRenderer::setSkeletonData (spSkeletonData *skeletonData, bool ownsSkeletonData) {
skeleton = spSkeleton_create(skeletonData);
rootBone = skeleton->bones[0];
this->ownsSkeletonData = ownsSkeletonData;
}
SkeletonRenderer::SkeletonRenderer () {
initialize();
}
SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkeletonData) {
initialize();
setSkeletonData(skeletonData, ownsSkeletonData);
}
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, spAtlas* atlas, float scale) {
initialize();
spSkeletonJson* json = spSkeletonJson_create(atlas);
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data.");
spSkeletonJson_dispose(json);
setSkeletonData(skeletonData, true);
}
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale) {
initialize();
atlas = spAtlas_createFromFile(atlasFile, 0);
CCASSERT(atlas, "Error reading atlas file.");
spSkeletonJson* json = spSkeletonJson_create(atlas);
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file.");
spSkeletonJson_dispose(json);
setSkeletonData(skeletonData, true);
}
SkeletonRenderer::~SkeletonRenderer () {
if (ownsSkeletonData) spSkeletonData_dispose(skeleton->data);
if (atlas) spAtlas_dispose(atlas);
spSkeleton_dispose(skeleton);
batch->release();
FREE(worldVertices);
}
void SkeletonRenderer::update (float deltaTime) {
spSkeleton_update(skeleton, deltaTime * timeScale);
}
void SkeletonRenderer::draw(Renderer* renderer, const kmMat4& transform, bool transformUpdated) {
drawCommand.init(_globalZOrder);
drawCommand.func = CC_CALLBACK_0(SkeletonRenderer::drawSkeleton, this, transform, transformUpdated);
renderer->addCommand(&drawCommand);
}
void SkeletonRenderer::drawSkeleton (const kmMat4& transform, bool transformUpdated) {
getShaderProgram()->use();
getShaderProgram()->setUniformsForBuiltins(transform);
GL::bindVAO(0);
Color3B nodeColor = getColor();
skeleton->r = nodeColor.r / (float)255;
skeleton->g = nodeColor.g / (float)255;
skeleton->b = nodeColor.b / (float)255;
skeleton->a = getDisplayedOpacity() / (float)255;
int additive = -1;
Color4B color;
const float* uvs = nullptr;
int verticesCount = 0;
const int* triangles = nullptr;
int trianglesCount = 0;
float r = 0, g = 0, b = 0, a = 0;
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
spSlot* slot = skeleton->drawOrder[i];
if (!slot->attachment) continue;
Texture2D *texture = nullptr;
switch (slot->attachment->type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = 8;
triangles = quadTriangles;
trianglesCount = 6;
r = attachment->r;
g = attachment->g;
b = attachment->b;
a = attachment->a;
break;
}
case SP_ATTACHMENT_MESH: {
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->verticesCount;
triangles = attachment->triangles;
trianglesCount = attachment->trianglesCount;
r = attachment->r;
g = attachment->g;
b = attachment->b;
a = attachment->a;
break;
}
case SP_ATTACHMENT_SKINNED_MESH: {
spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->uvsCount;
triangles = attachment->triangles;
trianglesCount = attachment->trianglesCount;
r = attachment->r;
g = attachment->g;
b = attachment->b;
a = attachment->a;
break;
}
}
if (texture) {
if (slot->data->additiveBlending != additive) {
batch->flush();
GL::blendFunc(blendFunc.src, slot->data->additiveBlending ? GL_ONE : blendFunc.dst);
additive = slot->data->additiveBlending;
}
color.a = skeleton->a * slot->a * a * 255;
float multiplier = premultipliedAlpha ? color.a : 255;
color.r = skeleton->r * slot->r * r * multiplier;
color.g = skeleton->g * slot->g * g * multiplier;
color.b = skeleton->b * slot->b * b * multiplier;
batch->add(texture, worldVertices, uvs, verticesCount, triangles, trianglesCount, &color);
}
}
batch->flush();
if (debugSlots || debugBones) {
kmGLPushMatrix();
kmGLLoadMatrix(&transform);
if (debugSlots) {
// Slots.
DrawPrimitives::setDrawColor4B(0, 0, 255, 255);
glLineWidth(1);
Point points[4];
V3F_C4B_T2F_Quad quad;
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
spSlot* slot = skeleton->drawOrder[i];
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
points[0] = Point(worldVertices[0], worldVertices[1]);
points[1] = Point(worldVertices[2], worldVertices[3]);
points[2] = Point(worldVertices[4], worldVertices[5]);
points[3] = Point(worldVertices[6], worldVertices[7]);
DrawPrimitives::drawPoly(points, 4, true);
}
}
if (debugBones) {
// Bone lengths.
glLineWidth(2);
DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
float x = bone->data->length * bone->m00 + bone->worldX;
float y = bone->data->length * bone->m10 + bone->worldY;
DrawPrimitives::drawLine(Point(bone->worldX, bone->worldY), Point(x, y));
}
// Bone origins.
DrawPrimitives::setPointSize(4);
DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
DrawPrimitives::drawPoint(Point(bone->worldX, bone->worldY));
if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
}
}
kmGLPopMatrix();
}
}
Texture2D* SkeletonRenderer::getTexture (spRegionAttachment* attachment) const {
return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
}
Texture2D* SkeletonRenderer::getTexture (spMeshAttachment* attachment) const {
return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
}
Texture2D* SkeletonRenderer::getTexture (spSkinnedMeshAttachment* attachment) const {
return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
}
Rect SkeletonRenderer::getBoundingBox () const {
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
float scaleX = getScaleX(), scaleY = getScaleY();
for (int i = 0; i < skeleton->slotCount; ++i) {
spSlot* slot = skeleton->slots[i];
if (!slot->attachment) continue;
int verticesCount;
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
verticesCount = 8;
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
verticesCount = mesh->verticesCount;
} else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
verticesCount = mesh->uvsCount;
} else
continue;
for (int ii = 0; ii < verticesCount; ii += 2) {
float x = worldVertices[ii] * scaleX, y = worldVertices[ii + 1] * scaleY;
minX = min(minX, x);
minY = min(minY, y);
maxX = max(maxX, x);
maxY = max(maxY, y);
}
}
Point position = getPosition();
return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
}
// --- Convenience methods for Skeleton_* functions.
void SkeletonRenderer::updateWorldTransform () {
spSkeleton_updateWorldTransform(skeleton);
}
void SkeletonRenderer::setToSetupPose () {
spSkeleton_setToSetupPose(skeleton);
}
void SkeletonRenderer::setBonesToSetupPose () {
spSkeleton_setBonesToSetupPose(skeleton);
}
void SkeletonRenderer::setSlotsToSetupPose () {
spSkeleton_setSlotsToSetupPose(skeleton);
}
spBone* SkeletonRenderer::findBone (const char* boneName) const {
return spSkeleton_findBone(skeleton, boneName);
}
spSlot* SkeletonRenderer::findSlot (const char* slotName) const {
return spSkeleton_findSlot(skeleton, slotName);
}
bool SkeletonRenderer::setSkin (const char* skinName) {
return spSkeleton_setSkinByName(skeleton, skinName) ? true : false;
}
spAttachment* SkeletonRenderer::getAttachment (const char* slotName, const char* attachmentName) const {
return spSkeleton_getAttachmentForSlotName(skeleton, slotName, attachmentName);
}
bool SkeletonRenderer::setAttachment (const char* slotName, const char* attachmentName) {
return spSkeleton_setAttachment(skeleton, slotName, attachmentName) ? true : false;
}
// --- CCBlendProtocol
const BlendFunc& SkeletonRenderer::getBlendFunc () const {
return blendFunc;
}
void SkeletonRenderer::setBlendFunc (const BlendFunc &blendFunc) {
this->blendFunc = blendFunc;
}
void SkeletonRenderer::setOpacityModifyRGB (bool value) {
premultipliedAlpha = value;
}
bool SkeletonRenderer::isOpacityModifyRGB () {
return premultipliedAlpha;
}
}

View File

@ -1,113 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_SKELETONRENDERER_H_
#define SPINE_SKELETONRENDERER_H_
#include <spine/spine.h>
#include "cocos2d.h"
namespace spine {
class PolygonBatch;
/** Draws a skeleton. */
class SkeletonRenderer: public cocos2d::Node, public cocos2d::BlendProtocol {
public:
spSkeleton* skeleton;
spBone* rootBone;
float timeScale;
bool debugSlots;
bool debugBones;
bool premultipliedAlpha;
static SkeletonRenderer* createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
static SkeletonRenderer* createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonRenderer* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
SkeletonRenderer (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
SkeletonRenderer (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
virtual ~SkeletonRenderer ();
virtual void update (float deltaTime) override;
virtual void draw(cocos2d::Renderer* renderer, const kmMat4& transform, bool transformUpdated) override;
virtual void drawSkeleton (const kmMat4& transform, bool transformUpdated);
virtual cocos2d::Rect getBoundingBox () const override;
// --- Convenience methods for common Skeleton_* functions.
void updateWorldTransform ();
void setToSetupPose ();
void setBonesToSetupPose ();
void setSlotsToSetupPose ();
/* Returns 0 if the bone was not found. */
spBone* findBone (const char* boneName) const;
/* Returns 0 if the slot was not found. */
spSlot* findSlot (const char* slotName) const;
/* 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. Returns false if the skin was not found.
* @param skin May be 0.*/
bool setSkin (const char* skinName);
/* Returns 0 if the slot or attachment was not found. */
spAttachment* getAttachment (const char* slotName, const char* attachmentName) const;
/* Returns false if the slot or attachment was not found. */
bool setAttachment (const char* slotName, const char* attachmentName);
// --- BlendProtocol
virtual void setBlendFunc (const cocos2d::BlendFunc& blendFunc);
virtual const cocos2d::BlendFunc& getBlendFunc () const;
virtual void setOpacityModifyRGB (bool value);
virtual bool isOpacityModifyRGB ();
protected:
SkeletonRenderer ();
void setSkeletonData (spSkeletonData* skeletonData, bool ownsSkeletonData);
virtual cocos2d::Texture2D* getTexture (spRegionAttachment* attachment) const;
virtual cocos2d::Texture2D* getTexture (spMeshAttachment* attachment) const;
virtual cocos2d::Texture2D* getTexture (spSkinnedMeshAttachment* attachment) const;
private:
bool ownsSkeletonData;
spAtlas* atlas;
cocos2d::CustomCommand drawCommand;
cocos2d::BlendFunc blendFunc;
PolygonBatch* batch;
float* worldVertices;
void initialize ();
};
}
#endif /* SPINE_SKELETONRENDERER_H_ */

View File

@ -1,21 +0,0 @@
# spine-cocos2dx v3.1
The spine-cocos2dx runtime provides functionality to load, manipulate and render [Spine](http://esotericsoftware.com) skeletal animation data using [cocos2d-x](http://www.cocos2d-x.org/). spine-cocos2dx is based on [spine-c](https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine-c).
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Place the contents of a cocos2d-x version 3.1 distribution into the `spine-cocos2dx/3.1/cocos2dx` directory.
1. Run the `python download-deps.py` script in the `spine-cocos2dx/3.1/cocos2dx` directory.
1. Open the XCode (Mac) or Visual C++ 2012 Express (Windows) project file from the `spine-cocos2dx/3.1/example` directory. Build files are also provided for Android.
Alternatively, the contents of the `spine-c/src`, `spine-c/include` and `spine-cocos2dx/3.1/src` directories can be copied into your project. Be sure your header search path will find the contents of the `spine-c/include` and `spine-cocos2dx/3.1/src` directories. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files.
## Notes
- Images are no longer premultiplied by cocos2d-x as they where in cocos2d-x v2, so the Spine atlas images *should* use premultiplied alpha.
## Examples
[Spineboy](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/3.1/example/Classes/SpineboyExample.cpp)
[Golbins](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/3.1/example/Classes/GoblinsExample.cpp)

View File

@ -1,87 +0,0 @@
#include "AppDelegate.h"
#include <vector>
#include <string>
#include "SpineboyExample.h"
#include "AppMacros.h"
USING_NS_CC;
using namespace std;
AppDelegate::AppDelegate () {
}
AppDelegate::~AppDelegate () {
}
bool AppDelegate::applicationDidFinishLaunching () {
// initialize director
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
// Set the design resolution
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
// a bug in DirectX 11 level9-x on the device prevents ResolutionPolicy::NO_BORDER from working correctly
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::SHOW_ALL);
#else
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
#endif
Size frameSize = glview->getFrameSize();
vector<string> searchPath;
// In this demo, we select resource according to the frame's height.
// If the resource size is different from design resolution size, you need to set contentScaleFactor.
// We use the ratio of resource's height to the height of design resolution,
// this can make sure that the resource's height could fit for the height of design resolution.
if (frameSize.height > mediumResource.size.height) {
// if the frame's height is larger than the height of medium resource size, select large resource.
searchPath.push_back(largeResource.directory);
director->setContentScaleFactor(MIN(largeResource.size.height/designResolutionSize.height, largeResource.size.width/designResolutionSize.width));
} else if (frameSize.height > smallResource.size.height) {
// if the frame's height is larger than the height of small resource size, select medium resource.
searchPath.push_back(mediumResource.directory);
director->setContentScaleFactor(MIN(mediumResource.size.height/designResolutionSize.height, mediumResource.size.width/designResolutionSize.width));
} else {
// if the frame's height is smaller than the height of medium resource size, select small resource.
searchPath.push_back(smallResource.directory);
director->setContentScaleFactor(MIN(smallResource.size.height/designResolutionSize.height, smallResource.size.width/designResolutionSize.width));
}
searchPath.push_back("common");
// set searching path
FileUtils::getInstance()->setSearchPaths(searchPath);
// turn on display FPS
director->setDisplayStats(true);
// set FPS. the default value is 1.0/60 if you don't call this
director->setAnimationInterval(1.0 / 60);
// create a scene. it's an autorelease object
auto scene = SpineboyExample::scene();
// run
director->runWithScene(scene);
return true;
}
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground () {
Director::getInstance()->stopAnimation();
// if you use SimpleAudioEngine, it must be paused
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}
// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground () {
Director::getInstance()->startAnimation();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

View File

@ -1,18 +0,0 @@
#ifndef _APPDELEGATE_H_
#define _APPDELEGATE_H_
#include "cocos2d.h"
class AppDelegate: private cocos2d::CCApplication {
public:
AppDelegate ();
virtual ~AppDelegate ();
virtual bool applicationDidFinishLaunching ();
virtual void applicationDidEnterBackground ();
virtual void applicationWillEnterForeground ();
};
#endif // _APPDELEGATE_H_

View File

@ -1,61 +0,0 @@
#ifndef _APPMACROS_H_
#define _APPMACROS_H_
#include "cocos2d.h"
/* For demonstrating using one design resolution to match different resources,
or one resource to match different design resolutions.
[Situation 1] Using one design resolution to match different resources.
Please look into Appdelegate::applicationDidFinishLaunching.
We check current device frame size to decide which resource need to be selected.
So if you want to test this situation which said in title '[Situation 1]',
you should change ios simulator to different device(e.g. iphone, iphone-retina3.5, iphone-retina4.0, ipad, ipad-retina),
or change the window size in "proj.XXX/main.cpp" by "CCEGLView::setFrameSize" if you are using win32 or linux plaform
and modify "proj.mac/AppController.mm" by changing the window rectangle.
[Situation 2] Using one resource to match different design resolutions.
The coordinates in your codes is based on your current design resolution rather than resource size.
Therefore, your design resolution could be very large and your resource size could be small.
To test this, just define the marco 'TARGET_DESIGN_RESOLUTION_SIZE' to 'DESIGN_RESOLUTION_2048X1536'
and open iphone simulator or create a window of 480x320 size.
[Note] Normally, developer just need to define one design resolution(e.g. 960x640) with one or more resources.
*/
#define DESIGN_RESOLUTION_480X320 0
#define DESIGN_RESOLUTION_960x640 1
#define DESIGN_RESOLUTION_1024X768 2
#define DESIGN_RESOLUTION_2048X1536 3
/* If you want to switch design resolution, change next line */
#define TARGET_DESIGN_RESOLUTION_SIZE DESIGN_RESOLUTION_960x640
typedef struct tagResource {
cocos2d::Size size;
char directory[100];
} Resource;
static Resource smallResource = {cocos2d::Size(480, 320), "iphone"};
static Resource mediumResource = {cocos2d::Size(960, 640), "iphone-retina"};
static Resource largeResource = {cocos2d::Size(1024, 768), "ipad"};
static Resource extralargeResource = {cocos2d::Size(2048, 1536), "ipad-retina"};
#if (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_480X320)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(480, 320);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_960x640)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(960, 640);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_1024X768)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(1024, 768);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_2048X1536)
static cocos2d::CCSize designResolutionSize = cocos2d::Size(2048, 1536);
#else
#error unknown target design resolution!
#endif
// The font size 24 is designed for small resolution, so we should change it to fit for current design resolution
#define TITLE_FONT_SIZE (cocos2d::Director::getInstance()->getOpenGLView()->getDesignResolutionSize().width / smallResource.size.width * 24)
#endif /* _APPMACROS_H_ */

View File

@ -1,105 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "SpineboyExample.h"
#include "GoblinsExample.h"
#include <iostream>
#include <fstream>
#include <string.h>
USING_NS_CC;
using namespace spine;
using namespace std;
Scene* SpineboyExample::scene () {
Scene *scene = Scene::create();
scene->addChild(SpineboyExample::create());
return scene;
}
bool SpineboyExample::init () {
if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false;
skeletonNode = SkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas", 0.6f);
skeletonNode->startListener = [this] (int trackIndex) {
spTrackEntry* entry = spAnimationState_getCurrent(skeletonNode->state, trackIndex);
const char* animationName = (entry && entry->animation) ? entry->animation->name : 0;
log("%d start: %s", trackIndex, animationName);
};
skeletonNode->endListener = [] (int trackIndex) {
log("%d end", trackIndex);
};
skeletonNode->completeListener = [] (int trackIndex, int loopCount) {
log("%d complete: %d", trackIndex, loopCount);
};
skeletonNode->eventListener = [] (int trackIndex, spEvent* event) {
log("%d event: %s, %d, %f, %s", trackIndex, event->data->name, event->intValue, event->floatValue, event->stringValue);
};
skeletonNode->setMix("walk", "jump", 0.2f);
skeletonNode->setMix("jump", "run", 0.2f);
skeletonNode->setAnimation(0, "walk", true);
spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 3);
skeletonNode->addAnimation(0, "run", true);
skeletonNode->setStartListener(jumpEntry, [] (int trackIndex) {
log("jumped!");
});
// skeletonNode->addAnimation(1, "test", true);
// skeletonNode->runAction(RepeatForever::create(Sequence::create(FadeOut::create(1), FadeIn::create(1), DelayTime::create(5), NULL)));
Size windowSize = Director::getInstance()->getWinSize();
skeletonNode->setPosition(Vec2(windowSize.width / 2, 20));
addChild(skeletonNode);
scheduleUpdate();
EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [this] (Touch* touch, Event* event) -> bool {
if (!skeletonNode->debugBones)
skeletonNode->debugBones = true;
else if (skeletonNode->timeScale == 1)
skeletonNode->timeScale = 0.3f;
else
Director::getInstance()->replaceScene(GoblinsExample::scene());
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
return true;
}
void SpineboyExample::update (float deltaTime) {
// Test releasing memory.
// Director::getInstance()->replaceScene(SpineboyExample::scene());
}

View File

@ -1,49 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef _SPINEBOYEXAMPLE_H_
#define _SPINEBOYEXAMPLE_H_
#include "cocos2d.h"
#include <spine/spine-cocos2dx.h>
class SpineboyExample : public cocos2d::LayerColor {
public:
static cocos2d::Scene* scene ();
virtual bool init ();
virtual void update (float deltaTime);
CREATE_FUNC (SpineboyExample);
private:
spine::SkeletonAnimation* skeletonNode;
};
#endif // _SPINEBOYEXAMPLE_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,292 +0,0 @@
goblins-ffd.png
format: RGBA8888
filter: Linear,Linear
repeat: none
dagger
rotate: false
xy: 2, 28
size: 26, 108
orig: 26, 108
offset: 0, 0
index: -1
goblin/eyes-closed
rotate: false
xy: 137, 29
size: 34, 12
orig: 34, 12
offset: 0, 0
index: -1
goblin/head
rotate: false
xy: 26, 357
size: 103, 66
orig: 103, 66
offset: 0, 0
index: -1
goblin/left-arm
rotate: false
xy: 30, 28
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblin/left-foot
rotate: false
xy: 134, 260
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblin/left-hand
rotate: false
xy: 69, 25
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/left-lower-leg
rotate: false
xy: 134, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblin/left-shoulder
rotate: false
xy: 137, 43
size: 29, 44
orig: 29, 44
offset: 0, 0
index: -1
goblin/left-upper-leg
rotate: false
xy: 30, 65
size: 33, 73
orig: 33, 73
offset: 0, 0
index: -1
goblin/neck
rotate: false
xy: 201, 387
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/pelvis
rotate: false
xy: 26, 140
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblin/right-arm
rotate: false
xy: 171, 84
size: 23, 50
orig: 23, 50
offset: 0, 0
index: -1
goblin/right-foot
rotate: false
xy: 134, 225
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblin/right-hand
rotate: false
xy: 204, 258
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblin/right-lower-leg
rotate: false
xy: 201, 430
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblin/right-shoulder
rotate: false
xy: 130, 89
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblin/right-upper-leg
rotate: false
xy: 98, 214
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblin/torso
rotate: false
xy: 131, 410
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblin/undie-straps
rotate: false
xy: 2, 7
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblin/undies
rotate: false
xy: 199, 227
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
goblingirl/eyes-closed
rotate: false
xy: 59, 2
size: 37, 21
orig: 37, 21
offset: 0, 0
index: -1
goblingirl/head
rotate: false
xy: 26, 425
size: 103, 81
orig: 103, 81
offset: 0, 0
index: -1
goblingirl/left-arm
rotate: false
xy: 201, 190
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblingirl/left-foot
rotate: false
xy: 134, 192
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblingirl/left-hand
rotate: false
xy: 196, 109
size: 35, 40
orig: 35, 40
offset: 0, 0
index: -1
goblingirl/left-lower-leg
rotate: false
xy: 169, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/left-shoulder
rotate: false
xy: 107, 30
size: 28, 46
orig: 28, 46
offset: 0, 0
index: -1
goblingirl/left-upper-leg
rotate: false
xy: 65, 68
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/neck
rotate: false
xy: 204, 297
size: 35, 41
orig: 35, 41
offset: 0, 0
index: -1
goblingirl/pelvis
rotate: false
xy: 131, 365
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblingirl/right-arm
rotate: false
xy: 100, 97
size: 28, 50
orig: 28, 50
offset: 0, 0
index: -1
goblingirl/right-foot
rotate: false
xy: 134, 157
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblingirl/right-hand
rotate: false
xy: 199, 151
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblingirl/right-lower-leg
rotate: false
xy: 96, 279
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblingirl/right-shoulder
rotate: false
xy: 204, 340
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblingirl/right-upper-leg
rotate: false
xy: 98, 149
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblingirl/torso
rotate: false
xy: 26, 259
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblingirl/undie-straps
rotate: false
xy: 134, 136
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblingirl/undies
rotate: false
xy: 196, 78
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
shield
rotate: false
xy: 26, 185
size: 70, 72
orig: 70, 72
offset: 0, 0
index: -1
spear
rotate: false
xy: 2, 138
size: 22, 368
orig: 22, 368
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

View File

@ -1,194 +0,0 @@
spineboy.png
format: RGBA8888
filter: Linear,Linear
repeat: none
eye_indifferent
rotate: true
xy: 389, 5
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
eye_surprised
rotate: false
xy: 580, 34
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
front_bracer
rotate: false
xy: 732, 85
size: 35, 48
orig: 35, 48
offset: 0, 0
index: -1
front_fist_closed
rotate: false
xy: 556, 91
size: 45, 49
orig: 45, 49
offset: 0, 0
index: -1
front_fist_open
rotate: false
xy: 668, 32
size: 52, 52
orig: 52, 52
offset: 0, 0
index: -1
front_foot
rotate: false
xy: 924, 201
size: 76, 41
orig: 76, 41
offset: 0, 0
index: -1
front_foot_bend1
rotate: false
xy: 845, 200
size: 77, 42
orig: 77, 42
offset: 0, 0
index: -1
front_foot_bend2
rotate: false
xy: 778, 186
size: 65, 56
orig: 65, 56
offset: 0, 0
index: -1
front_shin
rotate: true
xy: 444, 91
size: 49, 110
orig: 49, 110
offset: 0, 0
index: -1
front_thigh
rotate: true
xy: 603, 89
size: 29, 67
orig: 29, 67
offset: 0, 0
index: -1
front_upper_arm
rotate: true
xy: 672, 86
size: 32, 58
orig: 32, 58
offset: 0, 0
index: -1
goggles
rotate: false
xy: 444, 142
size: 157, 100
orig: 157, 100
offset: 0, 0
index: -1
gun
rotate: false
xy: 603, 120
size: 126, 122
orig: 126, 122
offset: 0, 0
index: -1
head
rotate: false
xy: 279, 63
size: 163, 179
orig: 163, 179
offset: 0, 0
index: -1
mouth_grind
rotate: false
xy: 845, 163
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_oooo
rotate: false
xy: 842, 126
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_smile
rotate: false
xy: 769, 97
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
muzzle
rotate: false
xy: 2, 2
size: 275, 240
orig: 277, 240
offset: 0, 0
index: -1
neck
rotate: false
xy: 903, 173
size: 22, 25
orig: 22, 25
offset: 0, 0
index: -1
rear_bracer
rotate: false
xy: 722, 40
size: 34, 43
orig: 34, 43
offset: 0, 0
index: -1
rear_foot
rotate: false
xy: 444, 11
size: 68, 36
orig: 68, 36
offset: 0, 0
index: -1
rear_foot_bend1
rotate: false
xy: 444, 49
size: 70, 40
orig: 70, 40
offset: 0, 0
index: -1
rear_foot_bend2
rotate: false
xy: 778, 134
size: 62, 50
orig: 62, 50
offset: 0, 0
index: -1
rear_shin
rotate: false
xy: 731, 135
size: 45, 107
orig: 45, 107
offset: 0, 0
index: -1
rear_thigh
rotate: true
xy: 516, 50
size: 39, 62
orig: 39, 62
offset: 0, 0
index: -1
rear_upper_arm
rotate: false
xy: 638, 35
size: 28, 52
orig: 28, 52
offset: 0, 0
index: -1
torso
rotate: true
xy: 279, 2
size: 59, 108
orig: 59, 108
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

View File

@ -1,292 +0,0 @@
goblins-ffd.png
format: RGBA8888
filter: Linear,Linear
repeat: none
dagger
rotate: false
xy: 2, 28
size: 26, 108
orig: 26, 108
offset: 0, 0
index: -1
goblin/eyes-closed
rotate: false
xy: 137, 29
size: 34, 12
orig: 34, 12
offset: 0, 0
index: -1
goblin/head
rotate: false
xy: 26, 357
size: 103, 66
orig: 103, 66
offset: 0, 0
index: -1
goblin/left-arm
rotate: false
xy: 30, 28
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblin/left-foot
rotate: false
xy: 134, 260
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblin/left-hand
rotate: false
xy: 69, 25
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/left-lower-leg
rotate: false
xy: 134, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblin/left-shoulder
rotate: false
xy: 137, 43
size: 29, 44
orig: 29, 44
offset: 0, 0
index: -1
goblin/left-upper-leg
rotate: false
xy: 30, 65
size: 33, 73
orig: 33, 73
offset: 0, 0
index: -1
goblin/neck
rotate: false
xy: 201, 387
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/pelvis
rotate: false
xy: 26, 140
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblin/right-arm
rotate: false
xy: 171, 84
size: 23, 50
orig: 23, 50
offset: 0, 0
index: -1
goblin/right-foot
rotate: false
xy: 134, 225
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblin/right-hand
rotate: false
xy: 204, 258
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblin/right-lower-leg
rotate: false
xy: 201, 430
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblin/right-shoulder
rotate: false
xy: 130, 89
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblin/right-upper-leg
rotate: false
xy: 98, 214
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblin/torso
rotate: false
xy: 131, 410
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblin/undie-straps
rotate: false
xy: 2, 7
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblin/undies
rotate: false
xy: 199, 227
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
goblingirl/eyes-closed
rotate: false
xy: 59, 2
size: 37, 21
orig: 37, 21
offset: 0, 0
index: -1
goblingirl/head
rotate: false
xy: 26, 425
size: 103, 81
orig: 103, 81
offset: 0, 0
index: -1
goblingirl/left-arm
rotate: false
xy: 201, 190
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblingirl/left-foot
rotate: false
xy: 134, 192
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblingirl/left-hand
rotate: false
xy: 196, 109
size: 35, 40
orig: 35, 40
offset: 0, 0
index: -1
goblingirl/left-lower-leg
rotate: false
xy: 169, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/left-shoulder
rotate: false
xy: 107, 30
size: 28, 46
orig: 28, 46
offset: 0, 0
index: -1
goblingirl/left-upper-leg
rotate: false
xy: 65, 68
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/neck
rotate: false
xy: 204, 297
size: 35, 41
orig: 35, 41
offset: 0, 0
index: -1
goblingirl/pelvis
rotate: false
xy: 131, 365
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblingirl/right-arm
rotate: false
xy: 100, 97
size: 28, 50
orig: 28, 50
offset: 0, 0
index: -1
goblingirl/right-foot
rotate: false
xy: 134, 157
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblingirl/right-hand
rotate: false
xy: 199, 151
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblingirl/right-lower-leg
rotate: false
xy: 96, 279
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblingirl/right-shoulder
rotate: false
xy: 204, 340
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblingirl/right-upper-leg
rotate: false
xy: 98, 149
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblingirl/torso
rotate: false
xy: 26, 259
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblingirl/undie-straps
rotate: false
xy: 134, 136
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblingirl/undies
rotate: false
xy: 196, 78
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
shield
rotate: false
xy: 26, 185
size: 70, 72
orig: 70, 72
offset: 0, 0
index: -1
spear
rotate: false
xy: 2, 138
size: 22, 368
orig: 22, 368
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

View File

@ -1,194 +0,0 @@
spineboy.png
format: RGBA8888
filter: Linear,Linear
repeat: none
eye_indifferent
rotate: true
xy: 389, 5
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
eye_surprised
rotate: false
xy: 580, 34
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
front_bracer
rotate: false
xy: 732, 85
size: 35, 48
orig: 35, 48
offset: 0, 0
index: -1
front_fist_closed
rotate: false
xy: 556, 91
size: 45, 49
orig: 45, 49
offset: 0, 0
index: -1
front_fist_open
rotate: false
xy: 668, 32
size: 52, 52
orig: 52, 52
offset: 0, 0
index: -1
front_foot
rotate: false
xy: 924, 201
size: 76, 41
orig: 76, 41
offset: 0, 0
index: -1
front_foot_bend1
rotate: false
xy: 845, 200
size: 77, 42
orig: 77, 42
offset: 0, 0
index: -1
front_foot_bend2
rotate: false
xy: 778, 186
size: 65, 56
orig: 65, 56
offset: 0, 0
index: -1
front_shin
rotate: true
xy: 444, 91
size: 49, 110
orig: 49, 110
offset: 0, 0
index: -1
front_thigh
rotate: true
xy: 603, 89
size: 29, 67
orig: 29, 67
offset: 0, 0
index: -1
front_upper_arm
rotate: true
xy: 672, 86
size: 32, 58
orig: 32, 58
offset: 0, 0
index: -1
goggles
rotate: false
xy: 444, 142
size: 157, 100
orig: 157, 100
offset: 0, 0
index: -1
gun
rotate: false
xy: 603, 120
size: 126, 122
orig: 126, 122
offset: 0, 0
index: -1
head
rotate: false
xy: 279, 63
size: 163, 179
orig: 163, 179
offset: 0, 0
index: -1
mouth_grind
rotate: false
xy: 845, 163
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_oooo
rotate: false
xy: 842, 126
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_smile
rotate: false
xy: 769, 97
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
muzzle
rotate: false
xy: 2, 2
size: 275, 240
orig: 277, 240
offset: 0, 0
index: -1
neck
rotate: false
xy: 903, 173
size: 22, 25
orig: 22, 25
offset: 0, 0
index: -1
rear_bracer
rotate: false
xy: 722, 40
size: 34, 43
orig: 34, 43
offset: 0, 0
index: -1
rear_foot
rotate: false
xy: 444, 11
size: 68, 36
orig: 68, 36
offset: 0, 0
index: -1
rear_foot_bend1
rotate: false
xy: 444, 49
size: 70, 40
orig: 70, 40
offset: 0, 0
index: -1
rear_foot_bend2
rotate: false
xy: 778, 134
size: 62, 50
orig: 62, 50
offset: 0, 0
index: -1
rear_shin
rotate: false
xy: 731, 135
size: 45, 107
orig: 45, 107
offset: 0, 0
index: -1
rear_thigh
rotate: true
xy: 516, 50
size: 39, 62
orig: 39, 62
offset: 0, 0
index: -1
rear_upper_arm
rotate: false
xy: 638, 35
size: 28, 52
orig: 28, 52
offset: 0, 0
index: -1
torso
rotate: true
xy: 279, 2
size: 59, 108
orig: 59, 108
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

View File

@ -1,292 +0,0 @@
goblins-ffd.png
format: RGBA8888
filter: Linear,Linear
repeat: none
dagger
rotate: false
xy: 2, 28
size: 26, 108
orig: 26, 108
offset: 0, 0
index: -1
goblin/eyes-closed
rotate: false
xy: 137, 29
size: 34, 12
orig: 34, 12
offset: 0, 0
index: -1
goblin/head
rotate: false
xy: 26, 357
size: 103, 66
orig: 103, 66
offset: 0, 0
index: -1
goblin/left-arm
rotate: false
xy: 30, 28
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblin/left-foot
rotate: false
xy: 134, 260
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblin/left-hand
rotate: false
xy: 69, 25
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/left-lower-leg
rotate: false
xy: 134, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblin/left-shoulder
rotate: false
xy: 137, 43
size: 29, 44
orig: 29, 44
offset: 0, 0
index: -1
goblin/left-upper-leg
rotate: false
xy: 30, 65
size: 33, 73
orig: 33, 73
offset: 0, 0
index: -1
goblin/neck
rotate: false
xy: 201, 387
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/pelvis
rotate: false
xy: 26, 140
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblin/right-arm
rotate: false
xy: 171, 84
size: 23, 50
orig: 23, 50
offset: 0, 0
index: -1
goblin/right-foot
rotate: false
xy: 134, 225
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblin/right-hand
rotate: false
xy: 204, 258
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblin/right-lower-leg
rotate: false
xy: 201, 430
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblin/right-shoulder
rotate: false
xy: 130, 89
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblin/right-upper-leg
rotate: false
xy: 98, 214
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblin/torso
rotate: false
xy: 131, 410
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblin/undie-straps
rotate: false
xy: 2, 7
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblin/undies
rotate: false
xy: 199, 227
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
goblingirl/eyes-closed
rotate: false
xy: 59, 2
size: 37, 21
orig: 37, 21
offset: 0, 0
index: -1
goblingirl/head
rotate: false
xy: 26, 425
size: 103, 81
orig: 103, 81
offset: 0, 0
index: -1
goblingirl/left-arm
rotate: false
xy: 201, 190
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblingirl/left-foot
rotate: false
xy: 134, 192
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblingirl/left-hand
rotate: false
xy: 196, 109
size: 35, 40
orig: 35, 40
offset: 0, 0
index: -1
goblingirl/left-lower-leg
rotate: false
xy: 169, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/left-shoulder
rotate: false
xy: 107, 30
size: 28, 46
orig: 28, 46
offset: 0, 0
index: -1
goblingirl/left-upper-leg
rotate: false
xy: 65, 68
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/neck
rotate: false
xy: 204, 297
size: 35, 41
orig: 35, 41
offset: 0, 0
index: -1
goblingirl/pelvis
rotate: false
xy: 131, 365
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblingirl/right-arm
rotate: false
xy: 100, 97
size: 28, 50
orig: 28, 50
offset: 0, 0
index: -1
goblingirl/right-foot
rotate: false
xy: 134, 157
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblingirl/right-hand
rotate: false
xy: 199, 151
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblingirl/right-lower-leg
rotate: false
xy: 96, 279
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblingirl/right-shoulder
rotate: false
xy: 204, 340
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblingirl/right-upper-leg
rotate: false
xy: 98, 149
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblingirl/torso
rotate: false
xy: 26, 259
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblingirl/undie-straps
rotate: false
xy: 134, 136
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblingirl/undies
rotate: false
xy: 196, 78
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
shield
rotate: false
xy: 26, 185
size: 70, 72
orig: 70, 72
offset: 0, 0
index: -1
spear
rotate: false
xy: 2, 138
size: 22, 368
orig: 22, 368
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

View File

@ -1,194 +0,0 @@
spineboy.png
format: RGBA8888
filter: Linear,Linear
repeat: none
eye_indifferent
rotate: true
xy: 389, 5
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
eye_surprised
rotate: false
xy: 580, 34
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
front_bracer
rotate: false
xy: 732, 85
size: 35, 48
orig: 35, 48
offset: 0, 0
index: -1
front_fist_closed
rotate: false
xy: 556, 91
size: 45, 49
orig: 45, 49
offset: 0, 0
index: -1
front_fist_open
rotate: false
xy: 668, 32
size: 52, 52
orig: 52, 52
offset: 0, 0
index: -1
front_foot
rotate: false
xy: 924, 201
size: 76, 41
orig: 76, 41
offset: 0, 0
index: -1
front_foot_bend1
rotate: false
xy: 845, 200
size: 77, 42
orig: 77, 42
offset: 0, 0
index: -1
front_foot_bend2
rotate: false
xy: 778, 186
size: 65, 56
orig: 65, 56
offset: 0, 0
index: -1
front_shin
rotate: true
xy: 444, 91
size: 49, 110
orig: 49, 110
offset: 0, 0
index: -1
front_thigh
rotate: true
xy: 603, 89
size: 29, 67
orig: 29, 67
offset: 0, 0
index: -1
front_upper_arm
rotate: true
xy: 672, 86
size: 32, 58
orig: 32, 58
offset: 0, 0
index: -1
goggles
rotate: false
xy: 444, 142
size: 157, 100
orig: 157, 100
offset: 0, 0
index: -1
gun
rotate: false
xy: 603, 120
size: 126, 122
orig: 126, 122
offset: 0, 0
index: -1
head
rotate: false
xy: 279, 63
size: 163, 179
orig: 163, 179
offset: 0, 0
index: -1
mouth_grind
rotate: false
xy: 845, 163
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_oooo
rotate: false
xy: 842, 126
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_smile
rotate: false
xy: 769, 97
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
muzzle
rotate: false
xy: 2, 2
size: 275, 240
orig: 277, 240
offset: 0, 0
index: -1
neck
rotate: false
xy: 903, 173
size: 22, 25
orig: 22, 25
offset: 0, 0
index: -1
rear_bracer
rotate: false
xy: 722, 40
size: 34, 43
orig: 34, 43
offset: 0, 0
index: -1
rear_foot
rotate: false
xy: 444, 11
size: 68, 36
orig: 68, 36
offset: 0, 0
index: -1
rear_foot_bend1
rotate: false
xy: 444, 49
size: 70, 40
orig: 70, 40
offset: 0, 0
index: -1
rear_foot_bend2
rotate: false
xy: 778, 134
size: 62, 50
orig: 62, 50
offset: 0, 0
index: -1
rear_shin
rotate: false
xy: 731, 135
size: 45, 107
orig: 45, 107
offset: 0, 0
index: -1
rear_thigh
rotate: true
xy: 516, 50
size: 39, 62
orig: 39, 62
offset: 0, 0
index: -1
rear_upper_arm
rotate: false
xy: 638, 35
size: 28, 52
orig: 28, 52
offset: 0, 0
index: -1
torso
rotate: true
xy: 279, 2
size: 59, 108
orig: 59, 108
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

View File

@ -1,292 +0,0 @@
goblins-ffd.png
format: RGBA8888
filter: Linear,Linear
repeat: none
dagger
rotate: false
xy: 2, 28
size: 26, 108
orig: 26, 108
offset: 0, 0
index: -1
goblin/eyes-closed
rotate: false
xy: 137, 29
size: 34, 12
orig: 34, 12
offset: 0, 0
index: -1
goblin/head
rotate: false
xy: 26, 357
size: 103, 66
orig: 103, 66
offset: 0, 0
index: -1
goblin/left-arm
rotate: false
xy: 30, 28
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblin/left-foot
rotate: false
xy: 134, 260
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblin/left-hand
rotate: false
xy: 69, 25
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/left-lower-leg
rotate: false
xy: 134, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblin/left-shoulder
rotate: false
xy: 137, 43
size: 29, 44
orig: 29, 44
offset: 0, 0
index: -1
goblin/left-upper-leg
rotate: false
xy: 30, 65
size: 33, 73
orig: 33, 73
offset: 0, 0
index: -1
goblin/neck
rotate: false
xy: 201, 387
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/pelvis
rotate: false
xy: 26, 140
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblin/right-arm
rotate: false
xy: 171, 84
size: 23, 50
orig: 23, 50
offset: 0, 0
index: -1
goblin/right-foot
rotate: false
xy: 134, 225
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblin/right-hand
rotate: false
xy: 204, 258
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblin/right-lower-leg
rotate: false
xy: 201, 430
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblin/right-shoulder
rotate: false
xy: 130, 89
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblin/right-upper-leg
rotate: false
xy: 98, 214
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblin/torso
rotate: false
xy: 131, 410
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblin/undie-straps
rotate: false
xy: 2, 7
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblin/undies
rotate: false
xy: 199, 227
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
goblingirl/eyes-closed
rotate: false
xy: 59, 2
size: 37, 21
orig: 37, 21
offset: 0, 0
index: -1
goblingirl/head
rotate: false
xy: 26, 425
size: 103, 81
orig: 103, 81
offset: 0, 0
index: -1
goblingirl/left-arm
rotate: false
xy: 201, 190
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblingirl/left-foot
rotate: false
xy: 134, 192
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblingirl/left-hand
rotate: false
xy: 196, 109
size: 35, 40
orig: 35, 40
offset: 0, 0
index: -1
goblingirl/left-lower-leg
rotate: false
xy: 169, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/left-shoulder
rotate: false
xy: 107, 30
size: 28, 46
orig: 28, 46
offset: 0, 0
index: -1
goblingirl/left-upper-leg
rotate: false
xy: 65, 68
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/neck
rotate: false
xy: 204, 297
size: 35, 41
orig: 35, 41
offset: 0, 0
index: -1
goblingirl/pelvis
rotate: false
xy: 131, 365
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblingirl/right-arm
rotate: false
xy: 100, 97
size: 28, 50
orig: 28, 50
offset: 0, 0
index: -1
goblingirl/right-foot
rotate: false
xy: 134, 157
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblingirl/right-hand
rotate: false
xy: 199, 151
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblingirl/right-lower-leg
rotate: false
xy: 96, 279
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblingirl/right-shoulder
rotate: false
xy: 204, 340
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblingirl/right-upper-leg
rotate: false
xy: 98, 149
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblingirl/torso
rotate: false
xy: 26, 259
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblingirl/undie-straps
rotate: false
xy: 134, 136
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblingirl/undies
rotate: false
xy: 196, 78
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
shield
rotate: false
xy: 26, 185
size: 70, 72
orig: 70, 72
offset: 0, 0
index: -1
spear
rotate: false
xy: 2, 138
size: 22, 368
orig: 22, 368
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

View File

@ -1,194 +0,0 @@
spineboy.png
format: RGBA8888
filter: Linear,Linear
repeat: none
eye_indifferent
rotate: true
xy: 389, 5
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
eye_surprised
rotate: false
xy: 580, 34
size: 56, 53
orig: 56, 53
offset: 0, 0
index: -1
front_bracer
rotate: false
xy: 732, 85
size: 35, 48
orig: 35, 48
offset: 0, 0
index: -1
front_fist_closed
rotate: false
xy: 556, 91
size: 45, 49
orig: 45, 49
offset: 0, 0
index: -1
front_fist_open
rotate: false
xy: 668, 32
size: 52, 52
orig: 52, 52
offset: 0, 0
index: -1
front_foot
rotate: false
xy: 924, 201
size: 76, 41
orig: 76, 41
offset: 0, 0
index: -1
front_foot_bend1
rotate: false
xy: 845, 200
size: 77, 42
orig: 77, 42
offset: 0, 0
index: -1
front_foot_bend2
rotate: false
xy: 778, 186
size: 65, 56
orig: 65, 56
offset: 0, 0
index: -1
front_shin
rotate: true
xy: 444, 91
size: 49, 110
orig: 49, 110
offset: 0, 0
index: -1
front_thigh
rotate: true
xy: 603, 89
size: 29, 67
orig: 29, 67
offset: 0, 0
index: -1
front_upper_arm
rotate: true
xy: 672, 86
size: 32, 58
orig: 32, 58
offset: 0, 0
index: -1
goggles
rotate: false
xy: 444, 142
size: 157, 100
orig: 157, 100
offset: 0, 0
index: -1
gun
rotate: false
xy: 603, 120
size: 126, 122
orig: 126, 122
offset: 0, 0
index: -1
head
rotate: false
xy: 279, 63
size: 163, 179
orig: 163, 179
offset: 0, 0
index: -1
mouth_grind
rotate: false
xy: 845, 163
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_oooo
rotate: false
xy: 842, 126
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
mouth_smile
rotate: false
xy: 769, 97
size: 56, 35
orig: 56, 35
offset: 0, 0
index: -1
muzzle
rotate: false
xy: 2, 2
size: 275, 240
orig: 277, 240
offset: 0, 0
index: -1
neck
rotate: false
xy: 903, 173
size: 22, 25
orig: 22, 25
offset: 0, 0
index: -1
rear_bracer
rotate: false
xy: 722, 40
size: 34, 43
orig: 34, 43
offset: 0, 0
index: -1
rear_foot
rotate: false
xy: 444, 11
size: 68, 36
orig: 68, 36
offset: 0, 0
index: -1
rear_foot_bend1
rotate: false
xy: 444, 49
size: 70, 40
orig: 70, 40
offset: 0, 0
index: -1
rear_foot_bend2
rotate: false
xy: 778, 134
size: 62, 50
orig: 62, 50
offset: 0, 0
index: -1
rear_shin
rotate: false
xy: 731, 135
size: 45, 107
orig: 45, 107
offset: 0, 0
index: -1
rear_thigh
rotate: true
xy: 516, 50
size: 39, 62
orig: 39, 62
offset: 0, 0
index: -1
rear_upper_arm
rotate: false
xy: 638, 35
size: 28, 52
orig: 28, 52
offset: 0, 0
index: -1
torso
rotate: true
xy: 279, 2
size: 59, 108
orig: 59, 108
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

View File

@ -1,22 +0,0 @@
#include "main.h"
#include "../Classes/AppDelegate.h"
USING_NS_CC;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
auto director = Director::getInstance();
auto glview = GLView::create("Spine Example");
glview->setFrameSize(960, 640);
director->setOpenGLView(glview);
return Application::getInstance()->run();
}

View File

@ -1,9 +0,0 @@
#ifndef __MAIN_H__
#define __MAIN_H__
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#endif // __MAIN_H__

View File

@ -1,53 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2012 for Windows Desktop
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spine-cocos2dx", "spine-cocos2dx.vcxproj", "{DB4C84B9-AC6D-46A1-B7E6-A77FE4515ACF}"
ProjectSection(ProjectDependencies) = postProject
{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} = {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcocos2d", "..\..\cocos2dx\cocos\2d\cocos2d.vcxproj", "{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchipmunk", "..\..\cocos2dx\external\chipmunk\proj.win32\chipmunk.vcxproj", "{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spine-c", "..\..\..\..\spine-c\spine-c.vcxproj", "{5D74934A-7512-45EE-8402-7B95D3642E85}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DB4C84B9-AC6D-46A1-B7E6-A77FE4515ACF}.Debug|Win32.ActiveCfg = Debug|Win32
{DB4C84B9-AC6D-46A1-B7E6-A77FE4515ACF}.Debug|Win32.Build.0 = Debug|Win32
{DB4C84B9-AC6D-46A1-B7E6-A77FE4515ACF}.Release|Win32.ActiveCfg = Release|Win32
{DB4C84B9-AC6D-46A1-B7E6-A77FE4515ACF}.Release|Win32.Build.0 = Release|Win32
{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.ActiveCfg = Debug|Win32
{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.Build.0 = Debug|Win32
{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.ActiveCfg = Release|Win32
{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.Build.0 = Release|Win32
{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.ActiveCfg = Debug|Win32
{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.Build.0 = Debug|Win32
{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.ActiveCfg = Release|Win32
{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.Build.0 = Release|Win32
{5D74934A-7512-45EE-8402-7B95D3642E85}.Debug|Win32.ActiveCfg = Debug|Win32
{5D74934A-7512-45EE-8402-7B95D3642E85}.Debug|Win32.Build.0 = Debug|Win32
{5D74934A-7512-45EE-8402-7B95D3642E85}.Release|Win32.ActiveCfg = Release|Win32
{5D74934A-7512-45EE-8402-7B95D3642E85}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(DPCodeReviewSolutionGUID) = preSolution
DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}
EndGlobalSection
GlobalSection(DPCodeReviewSolutionGUID) = preSolution
DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}
EndGlobalSection
GlobalSection(DPCodeReviewSolutionGUID) = preSolution
DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}
EndGlobalSection
GlobalSection(DPCodeReviewSolutionGUID) = preSolution
DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}
EndGlobalSection
EndGlobal

View File

@ -1,171 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{DB4C84B9-AC6D-46A1-B7E6-A77FE4515ACF}</ProjectGuid>
<RootNamespace>spine</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>spine-cocos2dx</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '10.0'">v100</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '11.0'">v110</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '11.0' and exists('$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A')">v110_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '10.0'">v100</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '11.0'">v110</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '11.0' and exists('$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A')">v110_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\cocos2dx\cocos\2d\cocos2dx.props" />
<Import Project="..\..\cocos2dx\cocos\2d\cocos2d_headers.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\cocos2dx\cocos\2d\cocos2dx.props" />
<Import Project="..\..\cocos2dx\cocos\2d\cocos2d_headers.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration).win32\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration).win32\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration).win32\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration).win32\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\Classes;$(ProjectDir)..\..\src;$(ProjectDir)..\..\..\..\spine-c\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;COCOS2D_DEBUG=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4267;4251;4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<CompileAs>CompileAsCpp</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<EntryPointSymbol>
</EntryPointSymbol>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<IgnoreSpecificDefaultLibraries>libcmt.lib;msvcrt.lib;libcmtd.lib</IgnoreSpecificDefaultLibraries>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\cocos2dx;$(ProjectDir)..\..\..\..\cocos2dx\include;$(ProjectDir)..\..\..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\..\..\cocos2dx\platform\third_party\win32\OGLES;..\Classes;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4267;4251;4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>opengl32.lib;glew32.lib;libcocos2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\src\spine\PolygonBatch.h" />
<ClInclude Include="..\..\src\spine\SkeletonAnimation.h" />
<ClInclude Include="..\..\src\spine\SkeletonRenderer.h" />
<ClInclude Include="..\..\src\spine\spine-cocos2dx.h" />
<ClInclude Include="..\Classes\AppDelegate.h" />
<ClInclude Include="..\Classes\AppMacros.h" />
<ClInclude Include="..\Classes\GoblinsExample.h" />
<ClInclude Include="..\Classes\SpineboyExample.h" />
<ClInclude Include="main.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\spine\PolygonBatch.cpp" />
<ClCompile Include="..\..\src\spine\SkeletonAnimation.cpp" />
<ClCompile Include="..\..\src\spine\SkeletonRenderer.cpp" />
<ClCompile Include="..\..\src\spine\spine-cocos2dx.cpp" />
<ClCompile Include="..\Classes\AppDelegate.cpp" />
<ClCompile Include="..\Classes\GoblinsExample.cpp" />
<ClCompile Include="..\Classes\SpineboyExample.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\spine-c\spine-c.vcxproj">
<Project>{5d74934a-7512-45ee-8402-7b95d3642e85}</Project>
</ProjectReference>
<ProjectReference Include="..\..\cocos2dx\cocos\2d\cocos2d.vcxproj">
<Project>{98a51ba8-fc3a-415b-ac8f-8c7bd464e93e}</Project>
<Private>false</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
<ProjectReference Include="..\..\cocos2dx\external\chipmunk\proj.win32\chipmunk.vcxproj">
<Project>{207bc7a9-ccf1-4f2f-a04d-45f72242ae25}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="win32">
<UniqueIdentifier>{ef769de4-53ac-449d-92e6-e67ec8d7414e}</UniqueIdentifier>
</Filter>
<Filter Include="Classes">
<UniqueIdentifier>{0dcd52ca-d521-4ba1-a1fa-c0d58a2df402}</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{54b66b2b-0990-4335-a821-332c44b6f83e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h">
<Filter>win32</Filter>
</ClInclude>
<ClInclude Include="..\Classes\AppDelegate.h">
<Filter>Classes</Filter>
</ClInclude>
<ClInclude Include="..\Classes\AppMacros.h">
<Filter>Classes</Filter>
</ClInclude>
<ClInclude Include="..\..\src\spine\SkeletonRenderer.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\src\spine\spine-cocos2dx.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\src\spine\SkeletonAnimation.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\src\spine\PolygonBatch.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\Classes\SpineboyExample.h">
<Filter>Classes</Filter>
</ClInclude>
<ClInclude Include="..\Classes\GoblinsExample.h">
<Filter>Classes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>win32</Filter>
</ClCompile>
<ClCompile Include="..\Classes\AppDelegate.cpp">
<Filter>Classes</Filter>
</ClCompile>
<ClCompile Include="..\..\src\spine\SkeletonRenderer.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\spine\spine-cocos2dx.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\spine\SkeletonAnimation.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\spine\PolygonBatch.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\Classes\SpineboyExample.cpp">
<Filter>Classes</Filter>
</ClCompile>
<ClCompile Include="..\Classes\GoblinsExample.cpp">
<Filter>Classes</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,112 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/PolygonBatch.h>
#include <spine/extension.h>
USING_NS_CC;
namespace spine {
PolygonBatch* PolygonBatch::createWithCapacity (int capacity) {
PolygonBatch* batch = new PolygonBatch();
batch->initWithCapacity(capacity);
batch->autorelease();
return batch;
}
PolygonBatch::PolygonBatch () :
capacity(0),
vertices(nullptr), verticesCount(0),
triangles(nullptr), trianglesCount(0),
texture(nullptr)
{}
bool PolygonBatch::initWithCapacity (int capacity) {
// 32767 is max index, so 32767 / 3 - (32767 / 3 % 3) = 10920.
CCASSERT(capacity <= 10920, "capacity cannot be > 10920");
CCASSERT(capacity >= 0, "capacity cannot be < 0");
this->capacity = capacity;
vertices = MALLOC(V2F_C4B_T2F, capacity);
triangles = MALLOC(GLushort, capacity * 3);
return true;
}
PolygonBatch::~PolygonBatch () {
FREE(vertices);
FREE(triangles);
}
void PolygonBatch::add (const Texture2D* addTexture,
const float* addVertices, const float* uvs, int addVerticesCount,
const int* addTriangles, int addTrianglesCount,
Color4B* color) {
if (
addTexture != texture
|| verticesCount + (addVerticesCount >> 1) > capacity
|| trianglesCount + addTrianglesCount > capacity * 3) {
this->flush();
texture = addTexture;
}
for (int i = 0; i < addTrianglesCount; ++i, ++trianglesCount)
triangles[trianglesCount] = addTriangles[i] + verticesCount;
for (int i = 0; i < addVerticesCount; i += 2, ++verticesCount) {
V2F_C4B_T2F* vertex = vertices + verticesCount;
vertex->vertices.x = addVertices[i];
vertex->vertices.y = addVertices[i + 1];
vertex->colors = *color;
vertex->texCoords.u = uvs[i];
vertex->texCoords.v = uvs[i + 1];
}
}
void PolygonBatch::flush () {
if (!verticesCount) return;
GL::bindTexture2D(texture->getName());
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORDS);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), &vertices[0].vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), &vertices[0].colors);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), &vertices[0].texCoords);
glDrawElements(GL_TRIANGLES, trianglesCount, GL_UNSIGNED_SHORT, triangles);
verticesCount = 0;
trianglesCount = 0;
CHECK_GL_ERROR_DEBUG();
}
}

View File

@ -1,229 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/SkeletonAnimation.h>
#include <spine/spine-cocos2dx.h>
#include <spine/extension.h>
#include <algorithm>
USING_NS_CC;
using std::min;
using std::max;
using std::vector;
namespace spine {
void animationCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) {
((SkeletonAnimation*)state->rendererObject)->onAnimationStateEvent(trackIndex, type, event, loopCount);
}
void trackEntryCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) {
((SkeletonAnimation*)state->rendererObject)->onTrackEntryEvent(trackIndex, type, event, loopCount);
}
typedef struct _TrackEntryListeners {
StartListener startListener;
EndListener endListener;
CompleteListener completeListener;
EventListener eventListener;
} _TrackEntryListeners;
static _TrackEntryListeners* getListeners (spTrackEntry* entry) {
if (!entry->rendererObject) {
entry->rendererObject = NEW(spine::_TrackEntryListeners);
entry->listener = trackEntryCallback;
}
return (_TrackEntryListeners*)entry->rendererObject;
}
void disposeTrackEntry (spTrackEntry* entry) {
if (entry->rendererObject) FREE(entry->rendererObject);
_spTrackEntry_dispose(entry);
}
//
SkeletonAnimation* SkeletonAnimation::createWithData (spSkeletonData* skeletonData) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonData);
node->autorelease();
return node;
}
SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlas, scale);
node->autorelease();
return node;
}
SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlasFile, scale);
node->autorelease();
return node;
}
void SkeletonAnimation::initialize () {
ownsAnimationStateData = true;
state = spAnimationState_create(spAnimationStateData_create(skeleton->data));
state->rendererObject = this;
state->listener = animationCallback;
_spAnimationState* stateInternal = (_spAnimationState*)state;
stateInternal->disposeTrackEntry = disposeTrackEntry;
}
SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData)
: SkeletonRenderer(skeletonData) {
initialize();
}
SkeletonAnimation::SkeletonAnimation (const char* skeletonDataFile, spAtlas* atlas, float scale)
: SkeletonRenderer(skeletonDataFile, atlas, scale) {
initialize();
}
SkeletonAnimation::SkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale)
: SkeletonRenderer(skeletonDataFile, atlasFile, scale) {
initialize();
}
SkeletonAnimation::~SkeletonAnimation () {
if (ownsAnimationStateData) spAnimationStateData_dispose(state->data);
spAnimationState_dispose(state);
}
void SkeletonAnimation::update (float deltaTime) {
super::update(deltaTime);
deltaTime *= timeScale;
spAnimationState_update(state, deltaTime);
spAnimationState_apply(state, skeleton);
spSkeleton_updateWorldTransform(skeleton);
}
void SkeletonAnimation::setAnimationStateData (spAnimationStateData* stateData) {
CCASSERT(stateData, "stateData cannot be null.");
if (ownsAnimationStateData) spAnimationStateData_dispose(state->data);
spAnimationState_dispose(state);
ownsAnimationStateData = false;
state = spAnimationState_create(stateData);
state->rendererObject = this;
state->listener = animationCallback;
}
void SkeletonAnimation::setMix (const char* fromAnimation, const char* toAnimation, float duration) {
spAnimationStateData_setMixByName(state->data, fromAnimation, toAnimation, duration);
}
spTrackEntry* SkeletonAnimation::setAnimation (int trackIndex, const char* name, bool loop) {
spAnimation* animation = spSkeletonData_findAnimation(skeleton->data, name);
if (!animation) {
log("Spine: Animation not found: %s", name);
return 0;
}
return spAnimationState_setAnimation(state, trackIndex, animation, loop);
}
spTrackEntry* SkeletonAnimation::addAnimation (int trackIndex, const char* name, bool loop, float delay) {
spAnimation* animation = spSkeletonData_findAnimation(skeleton->data, name);
if (!animation) {
log("Spine: Animation not found: %s", name);
return 0;
}
return spAnimationState_addAnimation(state, trackIndex, animation, loop, delay);
}
spTrackEntry* SkeletonAnimation::getCurrent (int trackIndex) {
return spAnimationState_getCurrent(state, trackIndex);
}
void SkeletonAnimation::clearTracks () {
spAnimationState_clearTracks(state);
}
void SkeletonAnimation::clearTrack (int trackIndex) {
spAnimationState_clearTrack(state, trackIndex);
}
void SkeletonAnimation::onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) {
switch (type) {
case SP_ANIMATION_START:
if (startListener) startListener(trackIndex);
break;
case SP_ANIMATION_END:
if (endListener) endListener(trackIndex);
break;
case SP_ANIMATION_COMPLETE:
if (completeListener) completeListener(trackIndex, loopCount);
break;
case SP_ANIMATION_EVENT:
if (eventListener) eventListener(trackIndex, event);
break;
}
}
void SkeletonAnimation::onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) {
spTrackEntry* entry = spAnimationState_getCurrent(state, trackIndex);
if (!entry->rendererObject) return;
_TrackEntryListeners* listeners = (_TrackEntryListeners*)entry->rendererObject;
switch (type) {
case SP_ANIMATION_START:
if (listeners->startListener) listeners->startListener(trackIndex);
break;
case SP_ANIMATION_END:
if (listeners->endListener) listeners->endListener(trackIndex);
break;
case SP_ANIMATION_COMPLETE:
if (listeners->completeListener) listeners->completeListener(trackIndex, loopCount);
break;
case SP_ANIMATION_EVENT:
if (listeners->eventListener) listeners->eventListener(trackIndex, event);
break;
}
}
void SkeletonAnimation::setStartListener (spTrackEntry* entry, StartListener listener) {
getListeners(entry)->startListener = listener;
}
void SkeletonAnimation::setEndListener (spTrackEntry* entry, EndListener listener) {
getListeners(entry)->endListener = listener;
}
void SkeletonAnimation::setCompleteListener (spTrackEntry* entry, CompleteListener listener) {
getListeners(entry)->completeListener = listener;
}
void SkeletonAnimation::setEventListener (spTrackEntry* entry, spine::EventListener listener) {
getListeners(entry)->eventListener = listener;
}
}

View File

@ -1,96 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_SKELETONANIMATION_H_
#define SPINE_SKELETONANIMATION_H_
#include <spine/spine.h>
#include <spine/SkeletonRenderer.h>
#include "cocos2d.h"
namespace spine {
typedef std::function<void(int trackIndex)> StartListener;
typedef std::function<void(int trackIndex)> EndListener;
typedef std::function<void(int trackIndex, int loopCount)> CompleteListener;
typedef std::function<void(int trackIndex, spEvent* event)> EventListener;
/** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be
* played later. */
class SkeletonAnimation: public SkeletonRenderer {
public:
spAnimationState* state;
static SkeletonAnimation* createWithData (spSkeletonData* skeletonData);
static SkeletonAnimation* createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonAnimation* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
SkeletonAnimation (spSkeletonData* skeletonData);
SkeletonAnimation (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
virtual ~SkeletonAnimation ();
virtual void update (float deltaTime);
void setAnimationStateData (spAnimationStateData* stateData);
void setMix (const char* fromAnimation, const char* toAnimation, float duration);
spTrackEntry* setAnimation (int trackIndex, const char* name, bool loop);
spTrackEntry* addAnimation (int trackIndex, const char* name, bool loop, float delay = 0);
spTrackEntry* getCurrent (int trackIndex = 0);
void clearTracks ();
void clearTrack (int trackIndex = 0);
StartListener startListener;
EndListener endListener;
CompleteListener completeListener;
EventListener eventListener;
void setStartListener (spTrackEntry* entry, StartListener listener);
void setEndListener (spTrackEntry* entry, EndListener listener);
void setCompleteListener (spTrackEntry* entry, CompleteListener listener);
void setEventListener (spTrackEntry* entry, EventListener listener);
virtual void onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
virtual void onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
protected:
SkeletonAnimation ();
private:
typedef SkeletonRenderer super;
bool ownsAnimationStateData;
void initialize ();
};
}
#endif /* SPINE_SKELETONANIMATION_H_ */

View File

@ -1,369 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/SkeletonRenderer.h>
#include <spine/spine-cocos2dx.h>
#include <spine/extension.h>
#include <spine/PolygonBatch.h>
#include <algorithm>
USING_NS_CC;
using std::min;
using std::max;
namespace spine {
static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData);
node->autorelease();
return node;
}
SkeletonRenderer* SkeletonRenderer::createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonDataFile, atlas, scale);
node->autorelease();
return node;
}
SkeletonRenderer* SkeletonRenderer::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonDataFile, atlasFile, scale);
node->autorelease();
return node;
}
void SkeletonRenderer::initialize () {
atlas = 0;
debugSlots = false;
debugBones = false;
timeScale = 1;
worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
batch = PolygonBatch::createWithCapacity(2000); // Max number of vertices and triangles per batch.
batch->retain();
blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
setOpacityModifyRGB(true);
setGLProgram(ShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
scheduleUpdate();
}
void SkeletonRenderer::setSkeletonData (spSkeletonData *skeletonData, bool ownsSkeletonData) {
skeleton = spSkeleton_create(skeletonData);
rootBone = skeleton->bones[0];
this->ownsSkeletonData = ownsSkeletonData;
}
SkeletonRenderer::SkeletonRenderer () {
initialize();
}
SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkeletonData) {
initialize();
setSkeletonData(skeletonData, ownsSkeletonData);
}
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, spAtlas* atlas, float scale) {
initialize();
spSkeletonJson* json = spSkeletonJson_create(atlas);
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data.");
spSkeletonJson_dispose(json);
setSkeletonData(skeletonData, true);
}
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale) {
initialize();
atlas = spAtlas_createFromFile(atlasFile, 0);
CCASSERT(atlas, "Error reading atlas file.");
spSkeletonJson* json = spSkeletonJson_create(atlas);
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file.");
spSkeletonJson_dispose(json);
setSkeletonData(skeletonData, true);
}
SkeletonRenderer::~SkeletonRenderer () {
if (ownsSkeletonData) spSkeletonData_dispose(skeleton->data);
if (atlas) spAtlas_dispose(atlas);
spSkeleton_dispose(skeleton);
batch->release();
FREE(worldVertices);
}
void SkeletonRenderer::update (float deltaTime) {
spSkeleton_update(skeleton, deltaTime * timeScale);
}
void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, bool transformUpdated) {
drawCommand.init(_globalZOrder);
drawCommand.func = CC_CALLBACK_0(SkeletonRenderer::drawSkeleton, this, transform, transformUpdated);
renderer->addCommand(&drawCommand);
}
void SkeletonRenderer::drawSkeleton (const Mat4 &transform, bool transformUpdated) {
getGLProgram()->use();
getGLProgram()->setUniformsForBuiltins(transform);
GL::bindVAO(0);
Color3B nodeColor = getColor();
skeleton->r = nodeColor.r / (float)255;
skeleton->g = nodeColor.g / (float)255;
skeleton->b = nodeColor.b / (float)255;
skeleton->a = getDisplayedOpacity() / (float)255;
int additive = -1;
Color4B color;
const float* uvs = nullptr;
int verticesCount = 0;
const int* triangles = nullptr;
int trianglesCount = 0;
float r = 0, g = 0, b = 0, a = 0;
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
spSlot* slot = skeleton->drawOrder[i];
if (!slot->attachment) continue;
Texture2D *texture = nullptr;
switch (slot->attachment->type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = 8;
triangles = quadTriangles;
trianglesCount = 6;
r = attachment->r;
g = attachment->g;
b = attachment->b;
a = attachment->a;
break;
}
case SP_ATTACHMENT_MESH: {
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->verticesCount;
triangles = attachment->triangles;
trianglesCount = attachment->trianglesCount;
r = attachment->r;
g = attachment->g;
b = attachment->b;
a = attachment->a;
break;
}
case SP_ATTACHMENT_SKINNED_MESH: {
spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->uvsCount;
triangles = attachment->triangles;
trianglesCount = attachment->trianglesCount;
r = attachment->r;
g = attachment->g;
b = attachment->b;
a = attachment->a;
break;
}
default: ;
}
if (texture) {
if (slot->data->additiveBlending != additive) {
batch->flush();
GL::blendFunc(blendFunc.src, slot->data->additiveBlending ? GL_ONE : blendFunc.dst);
additive = slot->data->additiveBlending;
}
color.a = skeleton->a * slot->a * a * 255;
float multiplier = premultipliedAlpha ? color.a : 255;
color.r = skeleton->r * slot->r * r * multiplier;
color.g = skeleton->g * slot->g * g * multiplier;
color.b = skeleton->b * slot->b * b * multiplier;
batch->add(texture, worldVertices, uvs, verticesCount, triangles, trianglesCount, &color);
}
}
batch->flush();
if (debugSlots || debugBones) {
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
if (debugSlots) {
// Slots.
DrawPrimitives::setDrawColor4B(0, 0, 255, 255);
glLineWidth(1);
Vec2 points[4];
V3F_C4B_T2F_Quad quad;
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
spSlot* slot = skeleton->drawOrder[i];
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
points[0] = Vec2(worldVertices[0], worldVertices[1]);
points[1] = Vec2(worldVertices[2], worldVertices[3]);
points[2] = Vec2(worldVertices[4], worldVertices[5]);
points[3] = Vec2(worldVertices[6], worldVertices[7]);
DrawPrimitives::drawPoly(points, 4, true);
}
}
if (debugBones) {
// Bone lengths.
glLineWidth(2);
DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
float x = bone->data->length * bone->m00 + bone->worldX;
float y = bone->data->length * bone->m10 + bone->worldY;
DrawPrimitives::drawLine(Vec2(bone->worldX, bone->worldY), Vec2(x, y));
}
// Bone origins.
DrawPrimitives::setPointSize(4);
DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
DrawPrimitives::drawPoint(Vec2(bone->worldX, bone->worldY));
if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
}
}
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
}
Texture2D* SkeletonRenderer::getTexture (spRegionAttachment* attachment) const {
return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
}
Texture2D* SkeletonRenderer::getTexture (spMeshAttachment* attachment) const {
return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
}
Texture2D* SkeletonRenderer::getTexture (spSkinnedMeshAttachment* attachment) const {
return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
}
Rect SkeletonRenderer::getBoundingBox () const {
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
float scaleX = getScaleX(), scaleY = getScaleY();
for (int i = 0; i < skeleton->slotCount; ++i) {
spSlot* slot = skeleton->slots[i];
if (!slot->attachment) continue;
int verticesCount;
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
verticesCount = 8;
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
verticesCount = mesh->verticesCount;
} else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
verticesCount = mesh->uvsCount;
} else
continue;
for (int ii = 0; ii < verticesCount; ii += 2) {
float x = worldVertices[ii] * scaleX, y = worldVertices[ii + 1] * scaleY;
minX = min(minX, x);
minY = min(minY, y);
maxX = max(maxX, x);
maxY = max(maxY, y);
}
}
Vec2 position = getPosition();
return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
}
// --- Convenience methods for Skeleton_* functions.
void SkeletonRenderer::updateWorldTransform () {
spSkeleton_updateWorldTransform(skeleton);
}
void SkeletonRenderer::setToSetupPose () {
spSkeleton_setToSetupPose(skeleton);
}
void SkeletonRenderer::setBonesToSetupPose () {
spSkeleton_setBonesToSetupPose(skeleton);
}
void SkeletonRenderer::setSlotsToSetupPose () {
spSkeleton_setSlotsToSetupPose(skeleton);
}
spBone* SkeletonRenderer::findBone (const char* boneName) const {
return spSkeleton_findBone(skeleton, boneName);
}
spSlot* SkeletonRenderer::findSlot (const char* slotName) const {
return spSkeleton_findSlot(skeleton, slotName);
}
bool SkeletonRenderer::setSkin (const char* skinName) {
return spSkeleton_setSkinByName(skeleton, skinName) ? true : false;
}
spAttachment* SkeletonRenderer::getAttachment (const char* slotName, const char* attachmentName) const {
return spSkeleton_getAttachmentForSlotName(skeleton, slotName, attachmentName);
}
bool SkeletonRenderer::setAttachment (const char* slotName, const char* attachmentName) {
return spSkeleton_setAttachment(skeleton, slotName, attachmentName) ? true : false;
}
// --- CCBlendProtocol
const BlendFunc& SkeletonRenderer::getBlendFunc () const {
return blendFunc;
}
void SkeletonRenderer::setBlendFunc (const BlendFunc &blendFunc) {
this->blendFunc = blendFunc;
}
void SkeletonRenderer::setOpacityModifyRGB (bool value) {
premultipliedAlpha = value;
}
bool SkeletonRenderer::isOpacityModifyRGB () {
return premultipliedAlpha;
}
}

View File

@ -1,113 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_SKELETONRENDERER_H_
#define SPINE_SKELETONRENDERER_H_
#include <spine/spine.h>
#include "cocos2d.h"
namespace spine {
class PolygonBatch;
/** Draws a skeleton. */
class SkeletonRenderer: public cocos2d::Node, public cocos2d::BlendProtocol {
public:
spSkeleton* skeleton;
spBone* rootBone;
float timeScale;
bool debugSlots;
bool debugBones;
bool premultipliedAlpha;
static SkeletonRenderer* createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
static SkeletonRenderer* createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonRenderer* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
SkeletonRenderer (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
SkeletonRenderer (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
virtual ~SkeletonRenderer ();
virtual void update (float deltaTime) override;
virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, bool transformUpdated) override;
virtual void drawSkeleton (const cocos2d::Mat4& transform, bool transformUpdated);
virtual cocos2d::Rect getBoundingBox () const override;
// --- Convenience methods for common Skeleton_* functions.
void updateWorldTransform ();
void setToSetupPose ();
void setBonesToSetupPose ();
void setSlotsToSetupPose ();
/* Returns 0 if the bone was not found. */
spBone* findBone (const char* boneName) const;
/* Returns 0 if the slot was not found. */
spSlot* findSlot (const char* slotName) const;
/* 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. Returns false if the skin was not found.
* @param skin May be 0.*/
bool setSkin (const char* skinName);
/* Returns 0 if the slot or attachment was not found. */
spAttachment* getAttachment (const char* slotName, const char* attachmentName) const;
/* Returns false if the slot or attachment was not found. */
bool setAttachment (const char* slotName, const char* attachmentName);
// --- BlendProtocol
virtual void setBlendFunc (const cocos2d::BlendFunc& blendFunc);
virtual const cocos2d::BlendFunc& getBlendFunc () const;
virtual void setOpacityModifyRGB (bool value);
virtual bool isOpacityModifyRGB ();
protected:
SkeletonRenderer ();
void setSkeletonData (spSkeletonData* skeletonData, bool ownsSkeletonData);
virtual cocos2d::Texture2D* getTexture (spRegionAttachment* attachment) const;
virtual cocos2d::Texture2D* getTexture (spMeshAttachment* attachment) const;
virtual cocos2d::Texture2D* getTexture (spSkinnedMeshAttachment* attachment) const;
private:
bool ownsSkeletonData;
spAtlas* atlas;
cocos2d::CustomCommand drawCommand;
cocos2d::BlendFunc blendFunc;
PolygonBatch* batch;
float* worldVertices;
void initialize ();
};
}
#endif /* SPINE_SKELETONRENDERER_H_ */

View File

@ -1,55 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/spine-cocos2dx.h>
#include <spine/extension.h>
USING_NS_CC;
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path) {
Texture2D* texture = Director::getInstance()->getTextureCache()->addImage(path);
texture->retain();
self->rendererObject = texture;
self->width = texture->getPixelsWide();
self->height = texture->getPixelsHigh();
}
void _spAtlasPage_disposeTexture (spAtlasPage* self) {
((Texture2D*)self->rendererObject)->release();
}
char* _spUtil_readFile (const char* path, int* length) {
Data data = FileUtils::getInstance()->getDataFromFile(
FileUtils::getInstance()->fullPathForFilename(path).c_str());
*length = data.getSize();
char* bytes = MALLOC(char, *length);
memcpy(bytes, data.getBytes(), *length);
return bytes;
}

View File

@ -1,39 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_COCOS2DX_H_
#define SPINE_COCOS2DX_H_
#include <spine/spine.h>
#include "cocos2d.h"
#include <spine/SkeletonRenderer.h>
#include <spine/SkeletonAnimation.h>
#endif /* SPINE_COCOS2DX_H_ */

View File

@ -1,21 +0,0 @@
# spine-cocos2dx v3.2
The spine-cocos2dx runtime provides functionality to load, manipulate and render [Spine](http://esotericsoftware.com) skeletal animation data using [cocos2d-x](http://www.cocos2d-x.org/). spine-cocos2dx is based on [spine-c](https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine-c).
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Place the contents of a cocos2d-x version 3.2 distribution into the `spine-cocos2dx/3.2/cocos2dx` directory.
1. Run the `python download-deps.py` script in the `spine-cocos2dx/3.2/cocos2dx` directory.
1. Open the XCode (Mac) or Visual C++ 2012 Express (Windows) project file from the `spine-cocos2dx/3.2/example` directory. Build files are also provided for Android.
Alternatively, the contents of the `spine-c/src`, `spine-c/include` and `spine-cocos2dx/3.2/src` directories can be copied into your project. Be sure your header search path will find the contents of the `spine-c/include` and `spine-cocos2dx/3.1/src` directories. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files.
## Notes
- Images are no longer premultiplied by cocos2d-x as they where in cocos2d-x v2, so the Spine atlas images *should* use premultiplied alpha.
## Examples
[Spineboy](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/3.2/example/Classes/SpineboyExample.cpp)
[Golbins](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-cocos2dx/3.2/example/Classes/GoblinsExample.cpp)

View File

@ -1,91 +0,0 @@
#include "AppDelegate.h"
#include <vector>
#include <string>
#include "SpineboyExample.h"
#include "AppMacros.h"
USING_NS_CC;
using namespace std;
AppDelegate::AppDelegate () {
}
AppDelegate::~AppDelegate () {
}
bool AppDelegate::applicationDidFinishLaunching () {
// initialize director
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if(!glview) {
glview = GLView::create("Spine Example");
director->setOpenGLView(glview);
}
// Set the design resolution
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
// a bug in DirectX 11 level9-x on the device prevents ResolutionPolicy::NO_BORDER from working correctly
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::SHOW_ALL);
#else
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
#endif
Size frameSize = glview->getFrameSize();
vector<string> searchPath;
// In this demo, we select resource according to the frame's height.
// If the resource size is different from design resolution size, you need to set contentScaleFactor.
// We use the ratio of resource's height to the height of design resolution,
// this can make sure that the resource's height could fit for the height of design resolution.
if (frameSize.height > mediumResource.size.height) {
// if the frame's height is larger than the height of medium resource size, select large resource.
searchPath.push_back(largeResource.directory);
director->setContentScaleFactor(MIN(largeResource.size.height/designResolutionSize.height, largeResource.size.width/designResolutionSize.width));
} else if (frameSize.height > smallResource.size.height) {
// if the frame's height is larger than the height of small resource size, select medium resource.
searchPath.push_back(mediumResource.directory);
director->setContentScaleFactor(MIN(mediumResource.size.height/designResolutionSize.height, mediumResource.size.width/designResolutionSize.width));
} else {
// if the frame's height is smaller than the height of medium resource size, select small resource.
searchPath.push_back(smallResource.directory);
director->setContentScaleFactor(MIN(smallResource.size.height/designResolutionSize.height, smallResource.size.width/designResolutionSize.width));
}
searchPath.push_back("common");
// set searching path
FileUtils::getInstance()->setSearchPaths(searchPath);
// turn on display FPS
director->setDisplayStats(true);
// set FPS. the default value is 1.0/60 if you don't call this
director->setAnimationInterval(1.0 / 60);
// create a scene. it's an autorelease object
auto scene = SpineboyExample::scene();
// run
director->runWithScene(scene);
return true;
}
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground () {
Director::getInstance()->stopAnimation();
// if you use SimpleAudioEngine, it must be paused
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}
// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground () {
Director::getInstance()->startAnimation();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

View File

@ -1,49 +0,0 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef _SPINEBOYEXAMPLE_H_
#define _SPINEBOYEXAMPLE_H_
#include "cocos2d.h"
#include <spine/spine-cocos2dx.h>
class SpineboyExample : public cocos2d::LayerColor {
public:
static cocos2d::Scene* scene ();
virtual bool init ();
virtual void update (float deltaTime);
CREATE_FUNC (SpineboyExample);
private:
spine::SkeletonAnimation* skeletonNode;
};
#endif // _SPINEBOYEXAMPLE_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,292 +0,0 @@
goblins-ffd.png
format: RGBA8888
filter: Linear,Linear
repeat: none
dagger
rotate: false
xy: 2, 28
size: 26, 108
orig: 26, 108
offset: 0, 0
index: -1
goblin/eyes-closed
rotate: false
xy: 137, 29
size: 34, 12
orig: 34, 12
offset: 0, 0
index: -1
goblin/head
rotate: false
xy: 26, 357
size: 103, 66
orig: 103, 66
offset: 0, 0
index: -1
goblin/left-arm
rotate: false
xy: 30, 28
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblin/left-foot
rotate: false
xy: 134, 260
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblin/left-hand
rotate: false
xy: 69, 25
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/left-lower-leg
rotate: false
xy: 134, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblin/left-shoulder
rotate: false
xy: 137, 43
size: 29, 44
orig: 29, 44
offset: 0, 0
index: -1
goblin/left-upper-leg
rotate: false
xy: 30, 65
size: 33, 73
orig: 33, 73
offset: 0, 0
index: -1
goblin/neck
rotate: false
xy: 201, 387
size: 36, 41
orig: 36, 41
offset: 0, 0
index: -1
goblin/pelvis
rotate: false
xy: 26, 140
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblin/right-arm
rotate: false
xy: 171, 84
size: 23, 50
orig: 23, 50
offset: 0, 0
index: -1
goblin/right-foot
rotate: false
xy: 134, 225
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblin/right-hand
rotate: false
xy: 204, 258
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblin/right-lower-leg
rotate: false
xy: 201, 430
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblin/right-shoulder
rotate: false
xy: 130, 89
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblin/right-upper-leg
rotate: false
xy: 98, 214
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblin/torso
rotate: false
xy: 131, 410
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblin/undie-straps
rotate: false
xy: 2, 7
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblin/undies
rotate: false
xy: 199, 227
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
goblingirl/eyes-closed
rotate: false
xy: 59, 2
size: 37, 21
orig: 37, 21
offset: 0, 0
index: -1
goblingirl/head
rotate: false
xy: 26, 425
size: 103, 81
orig: 103, 81
offset: 0, 0
index: -1
goblingirl/left-arm
rotate: false
xy: 201, 190
size: 37, 35
orig: 37, 35
offset: 0, 0
index: -1
goblingirl/left-foot
rotate: false
xy: 134, 192
size: 65, 31
orig: 65, 31
offset: 0, 0
index: -1
goblingirl/left-hand
rotate: false
xy: 196, 109
size: 35, 40
orig: 35, 40
offset: 0, 0
index: -1
goblingirl/left-lower-leg
rotate: false
xy: 169, 293
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/left-shoulder
rotate: false
xy: 107, 30
size: 28, 46
orig: 28, 46
offset: 0, 0
index: -1
goblingirl/left-upper-leg
rotate: false
xy: 65, 68
size: 33, 70
orig: 33, 70
offset: 0, 0
index: -1
goblingirl/neck
rotate: false
xy: 204, 297
size: 35, 41
orig: 35, 41
offset: 0, 0
index: -1
goblingirl/pelvis
rotate: false
xy: 131, 365
size: 62, 43
orig: 62, 43
offset: 0, 0
index: -1
goblingirl/right-arm
rotate: false
xy: 100, 97
size: 28, 50
orig: 28, 50
offset: 0, 0
index: -1
goblingirl/right-foot
rotate: false
xy: 134, 157
size: 63, 33
orig: 63, 33
offset: 0, 0
index: -1
goblingirl/right-hand
rotate: false
xy: 199, 151
size: 36, 37
orig: 36, 37
offset: 0, 0
index: -1
goblingirl/right-lower-leg
rotate: false
xy: 96, 279
size: 36, 76
orig: 36, 76
offset: 0, 0
index: -1
goblingirl/right-shoulder
rotate: false
xy: 204, 340
size: 39, 45
orig: 39, 45
offset: 0, 0
index: -1
goblingirl/right-upper-leg
rotate: false
xy: 98, 149
size: 34, 63
orig: 34, 63
offset: 0, 0
index: -1
goblingirl/torso
rotate: false
xy: 26, 259
size: 68, 96
orig: 68, 96
offset: 0, 0
index: -1
goblingirl/undie-straps
rotate: false
xy: 134, 136
size: 55, 19
orig: 55, 19
offset: 0, 0
index: -1
goblingirl/undies
rotate: false
xy: 196, 78
size: 36, 29
orig: 36, 29
offset: 0, 0
index: -1
shield
rotate: false
xy: 26, 185
size: 70, 72
orig: 70, 72
offset: 0, 0
index: -1
spear
rotate: false
xy: 2, 138
size: 22, 368
orig: 22, 368
offset: 0, 0
index: -1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Some files were not shown because too many files have changed in this diff Show More