Merge branch 'master' of https://github.com/EsotericSoftware/spine-runtimes
Conflicts: spine-csharp/src/SkeletonJson.cs
9
.gitignore
vendored
@ -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/*
|
||||
|
||||
@ -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
|
||||
|
||||
@ -67,7 +67,7 @@ struct spAnimationState {
|
||||
float timeScale;
|
||||
spAnimationStateListener listener;
|
||||
|
||||
int trackCount;
|
||||
int tracksCount;
|
||||
spTrackEntry** tracks;
|
||||
|
||||
void* rendererObject;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_ */
|
||||
@ -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_ */
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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__)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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" />
|
||||
|
||||
@ -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>
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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];
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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];
|
||||
|
||||
133
spine-c/src/spine/IkConstraint.c
Normal 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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
@ -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_
|
||||
@ -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_ */
|
||||
@ -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;
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 239 KiB |
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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_ */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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_ */
|
||||
@ -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)
|
||||
@ -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();
|
||||
}
|
||||
@ -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_
|
||||
@ -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_ */
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
Before Width: | Height: | Size: 3.7 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 160 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 239 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 160 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 239 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 160 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 239 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 160 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 239 KiB |
@ -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();
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
#ifndef __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#endif // __MAIN_H__
|
||||
@ -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
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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_ */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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_ */
|
||||
@ -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;
|
||||
}
|
||||
@ -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_ */
|
||||
@ -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)
|
||||
@ -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();
|
||||
}
|
||||
@ -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_
|
||||
|
Before Width: | Height: | Size: 3.7 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 160 KiB |