mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
Refactoring to make extension easier.
Much less weird OOP needed. Rendering is separate from data objects. cocos2d-iphone and cocos2d-x support for multi page atlases.
This commit is contained in:
parent
3defbc4132
commit
2bc3f511a1
@ -7,86 +7,15 @@
|
||||
|
||||
/**/
|
||||
|
||||
typedef struct {
|
||||
AtlasPage super;
|
||||
int extraData;
|
||||
} ExampleAtlasPage;
|
||||
|
||||
void _ExampleAtlasPage_dispose (AtlasPage* page) {
|
||||
ExampleAtlasPage* self = SUB_CAST(ExampleAtlasPage, page);
|
||||
_AtlasPage_deinit(SUPER(self));
|
||||
|
||||
self->extraData = 0;
|
||||
|
||||
FREE(self);
|
||||
void _AtlasPage_createTexture (AtlasPage* self, const char* path) {
|
||||
self->texture = 0;
|
||||
self->width = 123;
|
||||
self->height = 456;
|
||||
}
|
||||
|
||||
AtlasPage* AtlasPage_create (const char* name, const char* path) {
|
||||
ExampleAtlasPage* self = NEW(ExampleAtlasPage);
|
||||
_AtlasPage_init(SUPER(self), name, _ExampleAtlasPage_dispose);
|
||||
|
||||
self->extraData = 123;
|
||||
|
||||
return SUPER(self);
|
||||
void _AtlasPage_disposeTexture (AtlasPage* self) {
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
typedef struct {
|
||||
Skeleton super;
|
||||
int extraData;
|
||||
} ExampleSkeleton;
|
||||
|
||||
void _ExampleSkeleton_dispose (Skeleton* skeleton) {
|
||||
ExampleSkeleton* self = SUB_CAST(ExampleSkeleton, skeleton);
|
||||
_Skeleton_deinit(SUPER(self));
|
||||
|
||||
self->extraData = 0;
|
||||
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
Skeleton* Skeleton_create (SkeletonData* data) {
|
||||
ExampleSkeleton* self = NEW(ExampleSkeleton);
|
||||
_Skeleton_init(SUPER(self), data, _ExampleSkeleton_dispose);
|
||||
|
||||
self->extraData = 789;
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
typedef struct {
|
||||
RegionAttachment super;
|
||||
int extraData;
|
||||
} ExampleRegionAttachment;
|
||||
|
||||
void _ExampleRegionAttachment_dispose (Attachment* attachment) {
|
||||
ExampleRegionAttachment* self = SUB_CAST(ExampleRegionAttachment, attachment);
|
||||
_RegionAttachment_deinit(SUPER(self));
|
||||
|
||||
self->extraData = 0;
|
||||
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
void _ExampleRegionAttachment_draw (Attachment* attachment, Slot* slot) {
|
||||
/* ExampleRegionAttachment* self = (ExampleRegionAttachment*)attachment;
|
||||
Draw or queue region for drawing. */
|
||||
}
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region) {
|
||||
ExampleRegionAttachment* self = NEW(ExampleRegionAttachment);
|
||||
_RegionAttachment_init(SUPER(self), name, _ExampleRegionAttachment_dispose, _ExampleRegionAttachment_draw);
|
||||
|
||||
self->extraData = 456;
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
return _readFile(path, length);
|
||||
}
|
||||
@ -96,7 +25,7 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
int main (void) {
|
||||
Atlas* atlas = Atlas_readAtlasFile("data/spineboy.atlas");
|
||||
printf("First region name: %s, x: %d, y: %d\n", atlas->regions->name, atlas->regions->x, atlas->regions->y);
|
||||
printf("First page name: %s, extraData: %d\n", atlas->pages->name, ((ExampleAtlasPage*)atlas->pages)->extraData);
|
||||
printf("First page name: %s, size: %d, %d\n", atlas->pages->name, atlas->pages->width, atlas->pages->height);
|
||||
|
||||
SkeletonJson* json = SkeletonJson_create(atlas);
|
||||
SkeletonData *skeletonData = SkeletonJson_readSkeletonDataFile(json, "data/spineboy.json");
|
||||
@ -104,7 +33,6 @@ int main (void) {
|
||||
printf("Default skin name: %s\n", skeletonData->defaultSkin->name);
|
||||
|
||||
Skeleton* skeleton = Skeleton_create(skeletonData);
|
||||
printf("Skeleton extraData: %d\n", ((ExampleSkeleton*)skeleton)->extraData);
|
||||
|
||||
Animation* animation = SkeletonData_findAnimation(skeletonData, "walk");
|
||||
if (!animation) printf("Error: %s\n", json->error);
|
||||
|
||||
@ -55,12 +55,14 @@ struct AtlasPage {
|
||||
AtlasFormat format;
|
||||
AtlasFilter minFilter, magFilter;
|
||||
AtlasWrap uWrap, vWrap;
|
||||
AtlasPage* next;
|
||||
|
||||
const void* const vtable;
|
||||
void* texture;
|
||||
int width, height;
|
||||
|
||||
AtlasPage* next;
|
||||
};
|
||||
|
||||
AtlasPage* AtlasPage_create (const char* name, const char* path);
|
||||
AtlasPage* AtlasPage_create (const char* name);
|
||||
void AtlasPage_dispose (AtlasPage* self);
|
||||
|
||||
/**/
|
||||
@ -69,6 +71,7 @@ typedef struct AtlasRegion AtlasRegion;
|
||||
struct AtlasRegion {
|
||||
const char* name;
|
||||
int x, y, width, height;
|
||||
float u, v, u2, v2;
|
||||
float offsetX, offsetY;
|
||||
int originalWidth, originalHeight;
|
||||
int index;
|
||||
@ -76,7 +79,9 @@ struct AtlasRegion {
|
||||
int/*bool*/flip;
|
||||
int* splits;
|
||||
int* pads;
|
||||
|
||||
AtlasPage* page;
|
||||
|
||||
AtlasRegion* next;
|
||||
};
|
||||
|
||||
@ -90,7 +95,7 @@ typedef struct {
|
||||
AtlasRegion* regions;
|
||||
} Atlas;
|
||||
|
||||
/* Image files referenced in the atlas file will be prefixed dir. */
|
||||
/* Image files referenced in the atlas file will be prefixed with dir. */
|
||||
Atlas* Atlas_readAtlas (const char* data, int length, const char* dir);
|
||||
/* Image files referenced in the atlas file will be prefixed with the directory containing the atlas file. */
|
||||
Atlas* Atlas_readAtlasFile (const char* path);
|
||||
|
||||
@ -47,8 +47,6 @@ struct Attachment {
|
||||
|
||||
void Attachment_dispose (Attachment* self);
|
||||
|
||||
void Attachment_draw (Attachment* self, struct Slot* slot);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,22 +28,31 @@
|
||||
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/Atlas.h>
|
||||
#include <spine/Slot.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace spine {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
VERTEX_X1 = 0, VERTEX_Y1, VERTEX_X2, VERTEX_Y2, VERTEX_X3, VERTEX_Y3, VERTEX_X4, VERTEX_Y4
|
||||
} VertexIndex;
|
||||
|
||||
typedef struct RegionAttachment RegionAttachment;
|
||||
struct RegionAttachment {
|
||||
Attachment super;
|
||||
float x, y, scaleX, scaleY, rotation, width, height;
|
||||
AtlasRegion* region;
|
||||
float offset[8];
|
||||
float vertices[8];
|
||||
float uvs[8];
|
||||
};
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region);
|
||||
RegionAttachment* RegionAttachment_create (const char* name);
|
||||
|
||||
void RegionAttachment_updateOffset (RegionAttachment* self);
|
||||
void RegionAttachment_updateVertices (RegionAttachment* self, Slot* slot);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -51,10 +51,9 @@ struct Skeleton {
|
||||
float r, g, b, a;
|
||||
float time;
|
||||
int/*bool*/flipX, flipY;
|
||||
|
||||
const void* const vtable;
|
||||
};
|
||||
|
||||
Skeleton* Skeleton_create (SkeletonData* data);
|
||||
void Skeleton_dispose (Skeleton* self);
|
||||
|
||||
void Skeleton_updateWorldTransform (const Skeleton* self);
|
||||
|
||||
@ -28,10 +28,11 @@
|
||||
|
||||
- An OOP style is used where each "class" is made up of a struct and a number of functions prefixed with the struct name.
|
||||
|
||||
- struct fields that are const are readonly. Either they are set in a constructor and can never be changed, or they can only be
|
||||
changed by calling a function.
|
||||
- struct fields that are const are readonly. Either they are set in a create function and can never be changed, or they can only
|
||||
be changed by calling a function.
|
||||
|
||||
- Inheritance is done using a struct field named "super" as the first field, allowing the struct to be cast to its "super class".
|
||||
This works because a pointer to a struct is guaranteed to be a pointer to the first struct field.
|
||||
|
||||
- Classes intended for inheritance provide init/deinit functions which subclasses must call in their create/dispose functions.
|
||||
|
||||
@ -73,10 +74,10 @@
|
||||
/* Gets the vtable for the specified type. Not type safe, use with care. */
|
||||
#define VTABLE(TYPE,VALUE) ((_##TYPE##Vtable*)((TYPE*)VALUE)->vtable)
|
||||
|
||||
/* Frees memory. Can be used on const. */
|
||||
/* Frees memory. Can be used on const types. */
|
||||
#define FREE(VALUE) _free((void*)VALUE)
|
||||
|
||||
/* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const. */
|
||||
/* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const types. */
|
||||
#define MALLOC_STR(TO,FROM) strcpy(CONST_CAST(char*, TO) = (char*)malloc(strlen(FROM) + 1), FROM)
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -96,10 +97,8 @@ extern "C" {
|
||||
* Functions that must be implemented:
|
||||
*/
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region);
|
||||
|
||||
AtlasPage* AtlasPage_create (const char* name, const char* path);
|
||||
|
||||
void _AtlasPage_createTexture (AtlasPage* self, const char* path);
|
||||
void _AtlasPage_disposeTexture (AtlasPage* self);
|
||||
char* _Util_readFile (const char* path, int* length);
|
||||
|
||||
/*
|
||||
@ -117,26 +116,21 @@ char* _readFile (const char* path, int* length);
|
||||
|
||||
/**/
|
||||
|
||||
void _Skeleton_init (Skeleton* self, SkeletonData* data, //
|
||||
void (*dispose) (Skeleton* skeleton));
|
||||
void _Skeleton_deinit (Skeleton* self);
|
||||
void _AttachmentLoader_init (AttachmentLoader* self, //
|
||||
void (*dispose) (AttachmentLoader* self), //
|
||||
Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name));
|
||||
void _AttachmentLoader_deinit (AttachmentLoader* self);
|
||||
void _AttachmentLoader_setError (AttachmentLoader* self, const char* error1, const char* error2);
|
||||
void _AttachmentLoader_setUnknownTypeError (AttachmentLoader* self, AttachmentType type);
|
||||
|
||||
/**/
|
||||
|
||||
void _Attachment_init (Attachment* self, const char* name, AttachmentType type, //
|
||||
void (*dispose) (Attachment* self), //
|
||||
void (*draw) (Attachment* self, struct Slot* slot));
|
||||
void (*dispose) (Attachment* self));
|
||||
void _Attachment_deinit (Attachment* self);
|
||||
|
||||
/**/
|
||||
|
||||
void _RegionAttachment_init (RegionAttachment* self, const char* name, //
|
||||
void (*dispose) (Attachment* self), //
|
||||
void (*draw) (Attachment* self, struct Slot* slot));
|
||||
void _RegionAttachment_deinit (RegionAttachment* self);
|
||||
|
||||
/**/
|
||||
|
||||
void _Timeline_init (Timeline* self, //
|
||||
void (*dispose) (Timeline* self), //
|
||||
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha));
|
||||
@ -149,21 +143,6 @@ void _CurveTimeline_init (CurveTimeline* self, int frameCount, //
|
||||
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha));
|
||||
void _CurveTimeline_deinit (CurveTimeline* self);
|
||||
|
||||
/**/
|
||||
|
||||
void _AtlasPage_init (AtlasPage* self, const char* name, //
|
||||
void (*dispose) (AtlasPage* self));
|
||||
void _AtlasPage_deinit (AtlasPage* self);
|
||||
|
||||
/**/
|
||||
|
||||
void _AttachmentLoader_init (AttachmentLoader* self, //
|
||||
void (*dispose) (AttachmentLoader* self), //
|
||||
Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name));
|
||||
void _AttachmentLoader_deinit (AttachmentLoader* self);
|
||||
void _AttachmentLoader_setError (AttachmentLoader* self, const char* error1, const char* error2);
|
||||
void _AttachmentLoader_setUnknownTypeError (AttachmentLoader* self, AttachmentType type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,8 +70,8 @@ typedef struct _TimelineVtable {
|
||||
void (*dispose) (Timeline* self);
|
||||
} _TimelineVtable;
|
||||
|
||||
void _Timeline_init (Timeline* self, /**/
|
||||
void (*dispose) (Timeline* self), /**/
|
||||
void _Timeline_init (Timeline* self, //
|
||||
void (*dispose) (Timeline* self), //
|
||||
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) {
|
||||
CONST_CAST(_TimelineVtable*, self->vtable) = NEW(_TimelineVtable);
|
||||
VTABLE(Timeline, self) ->dispose = dispose;
|
||||
@ -96,8 +96,8 @@ static const float CURVE_LINEAR = 0;
|
||||
static const float CURVE_STEPPED = -1;
|
||||
static const int CURVE_SEGMENTS = 10;
|
||||
|
||||
void _CurveTimeline_init (CurveTimeline* self, int frameCount, /**/
|
||||
void (*dispose) (Timeline* self), /**/
|
||||
void _CurveTimeline_init (CurveTimeline* self, int frameCount, //
|
||||
void (*dispose) (Timeline* self), //
|
||||
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) {
|
||||
_Timeline_init(SUPER(self), dispose, apply);
|
||||
self->curves = CALLOC(float, (frameCount - 1) * 6);
|
||||
@ -203,7 +203,7 @@ void _BaseTimeline_dispose (Timeline* timeline) {
|
||||
}
|
||||
|
||||
/* Many timelines have structure identical to struct BaseTimeline and extend CurveTimeline. **/
|
||||
struct BaseTimeline* _BaseTimeline_create (int frameCount, int frameSize, /**/
|
||||
struct BaseTimeline* _BaseTimeline_create (int frameCount, int frameSize, //
|
||||
void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) {
|
||||
|
||||
struct BaseTimeline* self = NEW(struct BaseTimeline);
|
||||
|
||||
@ -35,20 +35,15 @@ typedef struct _AtlasPageVtable {
|
||||
void (*dispose) (AtlasPage* self);
|
||||
} _AtlasPageVtable;
|
||||
|
||||
void _AtlasPage_init (AtlasPage* self, const char* name, /**/
|
||||
void (*dispose) (AtlasPage* self)) {
|
||||
CONST_CAST(_AtlasPageVtable*, self->vtable) = NEW(_AtlasPageVtable);
|
||||
VTABLE(AtlasPage, self) ->dispose = dispose;
|
||||
AtlasPage* AtlasPage_create (const char* name) {
|
||||
AtlasPage* self = NEW(AtlasPage);
|
||||
MALLOC_STR(self->name, name);
|
||||
}
|
||||
|
||||
void _AtlasPage_deinit (AtlasPage* self) {
|
||||
FREE(self->vtable);
|
||||
FREE(self->name);
|
||||
return self;
|
||||
}
|
||||
|
||||
void AtlasPage_dispose (AtlasPage* self) {
|
||||
VTABLE(AtlasPage, self) ->dispose(self);
|
||||
FREE(self->name);
|
||||
_AtlasPage_disposeTexture(self);
|
||||
}
|
||||
|
||||
/**/
|
||||
@ -200,16 +195,14 @@ Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) {
|
||||
if (needsSlash) path[dirLength] = '/';
|
||||
strcpy(path + dirLength + needsSlash, name);
|
||||
|
||||
page = AtlasPage_create(name, path);
|
||||
page = AtlasPage_create(name);
|
||||
FREE(name);
|
||||
if (lastPage)
|
||||
lastPage->next = page;
|
||||
else
|
||||
self->pages = page;
|
||||
lastPage = page;
|
||||
|
||||
FREE(name);
|
||||
FREE(path);
|
||||
|
||||
if (!readValue(end, &str)) return abortAtlas(self);
|
||||
page->format = (AtlasFormat)indexOf(formatNames, 7, &str);
|
||||
|
||||
@ -222,6 +215,9 @@ Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) {
|
||||
page->uWrap = *str.begin == 'x' ? ATLAS_REPEAT : (*str.begin == 'y' ? ATLAS_CLAMPTOEDGE : ATLAS_REPEAT);
|
||||
page->vWrap = *str.begin == 'x' ? ATLAS_CLAMPTOEDGE : (*str.begin == 'y' ? ATLAS_REPEAT : ATLAS_REPEAT);
|
||||
}
|
||||
|
||||
_AtlasPage_createTexture(page, path);
|
||||
FREE(path);
|
||||
} else {
|
||||
AtlasRegion *region = AtlasRegion_create();
|
||||
if (lastRegion)
|
||||
@ -244,6 +240,11 @@ Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) {
|
||||
region->width = toInt(tuple);
|
||||
region->height = toInt(tuple + 1);
|
||||
|
||||
region->u = region->x / (float)page->width;
|
||||
region->v = region->y / (float)page->height;
|
||||
region->u2 = (region->x + region->width) / (float)page->width;
|
||||
region->v2 = (region->y + region->height) / (float)page->height;
|
||||
|
||||
int count;
|
||||
if (!(count = readTuple(end, tuple))) return abortAtlas(self);
|
||||
if (count == 4) { /* split is optional */
|
||||
|
||||
@ -39,7 +39,9 @@ Attachment* _AtlasAttachmentLoader_newAttachment (AttachmentLoader* loader, Skin
|
||||
_AttachmentLoader_setError(loader, "Region not found: ", name);
|
||||
return 0;
|
||||
}
|
||||
return SUPER_CAST(Attachment, RegionAttachment_create(name, region)) ;
|
||||
RegionAttachment* attachment = RegionAttachment_create(name);
|
||||
attachment->region = region;
|
||||
return SUPER(attachment);
|
||||
}
|
||||
default:
|
||||
_AttachmentLoader_setUnknownTypeError(loader, type);
|
||||
|
||||
@ -32,17 +32,14 @@ namespace spine {
|
||||
#endif
|
||||
|
||||
typedef struct _AttachmentVtable {
|
||||
void (*draw) (Attachment* self, struct Slot* slot);
|
||||
void (*dispose) (Attachment* self);
|
||||
} _AttachmentVtable;
|
||||
|
||||
void _Attachment_init (Attachment* self, const char* name, AttachmentType type, /**/
|
||||
void (*dispose) (Attachment* self), /**/
|
||||
void (*draw) (Attachment* self, struct Slot* slot)) {
|
||||
void _Attachment_init (Attachment* self, const char* name, AttachmentType type, //
|
||||
void (*dispose) (Attachment* self)) {
|
||||
|
||||
CONST_CAST(_AttachmentVtable*, self->vtable) = NEW(_AttachmentVtable);
|
||||
VTABLE(Attachment, self) ->dispose = dispose;
|
||||
VTABLE(Attachment, self) ->draw = draw;
|
||||
|
||||
MALLOC_STR(self->name, name);
|
||||
self->type = type;
|
||||
@ -57,10 +54,6 @@ void Attachment_dispose (Attachment* self) {
|
||||
VTABLE(Attachment, self) ->dispose(self);
|
||||
}
|
||||
|
||||
void Attachment_draw (Attachment* self, Slot* slot) {
|
||||
VTABLE(Attachment, self) ->draw(self, slot);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -36,8 +36,8 @@ typedef struct _AttachmentLoaderVtable {
|
||||
void (*dispose) (AttachmentLoader* self);
|
||||
} _AttachmentLoaderVtable;
|
||||
|
||||
void _AttachmentLoader_init (AttachmentLoader* self, /**/
|
||||
void (*dispose) (AttachmentLoader* self), /**/
|
||||
void _AttachmentLoader_init (AttachmentLoader* self, //
|
||||
void (*dispose) (AttachmentLoader* self), //
|
||||
Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name)) {
|
||||
CONST_CAST(_AttachmentLoaderVtable*, self->vtable) = NEW(_AttachmentLoaderVtable);
|
||||
VTABLE(AttachmentLoader, self) ->dispose = dispose;
|
||||
|
||||
@ -31,16 +31,12 @@
|
||||
namespace spine {
|
||||
#endif
|
||||
|
||||
void _RegionAttachment_init (RegionAttachment* self, const char* name, /**/
|
||||
void (*dispose) (Attachment* self), /**/
|
||||
void (*draw) (Attachment* self, struct Slot* slot)) {
|
||||
RegionAttachment* RegionAttachment_create (const char* name) {
|
||||
RegionAttachment* self = NEW(RegionAttachment);
|
||||
self->scaleX = 1;
|
||||
self->scaleY = 1;
|
||||
_Attachment_init(SUPER(self), name, ATTACHMENT_REGION, dispose, draw);
|
||||
}
|
||||
|
||||
void _RegionAttachment_deinit (RegionAttachment* self) {
|
||||
_Attachment_deinit(SUPER(self));
|
||||
_Attachment_init(SUPER(self), name, ATTACHMENT_REGION, _Attachment_deinit);
|
||||
return self;
|
||||
}
|
||||
|
||||
void RegionAttachment_updateOffset (RegionAttachment* self) {
|
||||
@ -63,14 +59,27 @@ void RegionAttachment_updateOffset (RegionAttachment* self) {
|
||||
float localX2Sin = localX2 * sine;
|
||||
float localY2Cos = localY2 * cosine + self->y;
|
||||
float localY2Sin = localY2 * sine;
|
||||
self->offset[0] = localXCos - localYSin;
|
||||
self->offset[1] = localYCos + localXSin;
|
||||
self->offset[2] = localXCos - localY2Sin;
|
||||
self->offset[3] = localY2Cos + localXSin;
|
||||
self->offset[4] = localX2Cos - localY2Sin;
|
||||
self->offset[5] = localY2Cos + localX2Sin;
|
||||
self->offset[6] = localX2Cos - localYSin;
|
||||
self->offset[7] = localYCos + localX2Sin;
|
||||
self->offset[VERTEX_X1] = localXCos - localYSin;
|
||||
self->offset[VERTEX_Y1] = localYCos + localXSin;
|
||||
self->offset[VERTEX_X2] = localXCos - localY2Sin;
|
||||
self->offset[VERTEX_Y2] = localY2Cos + localXSin;
|
||||
self->offset[VERTEX_X3] = localX2Cos - localY2Sin;
|
||||
self->offset[VERTEX_Y3] = localY2Cos + localX2Sin;
|
||||
self->offset[VERTEX_X4] = localX2Cos - localYSin;
|
||||
self->offset[VERTEX_Y4] = localYCos + localX2Sin;
|
||||
}
|
||||
|
||||
void RegionAttachment_updateVertices (RegionAttachment* self, Slot* slot) {
|
||||
float* offset = self->offset;
|
||||
Bone* bone = slot->bone;
|
||||
self->vertices[VERTEX_X1] = offset[VERTEX_X1] * bone->m00 + offset[VERTEX_Y1] * bone->m01 + bone->worldX;
|
||||
self->vertices[VERTEX_Y1] = offset[VERTEX_X1] * bone->m10 + offset[VERTEX_Y1] * bone->m11 + bone->worldY;
|
||||
self->vertices[VERTEX_X2] = offset[VERTEX_X2] * bone->m00 + offset[VERTEX_Y2] * bone->m01 + bone->worldX;
|
||||
self->vertices[VERTEX_Y2] = offset[VERTEX_X2] * bone->m10 + offset[VERTEX_Y2] * bone->m11 + bone->worldY;
|
||||
self->vertices[VERTEX_X3] = offset[VERTEX_X3] * bone->m00 + offset[VERTEX_Y3] * bone->m01 + bone->worldX;
|
||||
self->vertices[VERTEX_Y3] = offset[VERTEX_X3] * bone->m10 + offset[VERTEX_Y3] * bone->m11 + bone->worldY;
|
||||
self->vertices[VERTEX_X4] = offset[VERTEX_X4] * bone->m00 + offset[VERTEX_Y4] * bone->m01 + bone->worldX;
|
||||
self->vertices[VERTEX_Y4] = offset[VERTEX_X4] * bone->m10 + offset[VERTEX_Y4] * bone->m11 + bone->worldY;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -31,16 +31,10 @@
|
||||
namespace spine {
|
||||
#endif
|
||||
|
||||
typedef struct _SkeletonVtable {
|
||||
void (*dispose) (Skeleton* skeleton);
|
||||
} _SkeletonVtable;
|
||||
|
||||
void _Skeleton_init (Skeleton* self, SkeletonData* data, void (*dispose) (Skeleton* skeleton)) {
|
||||
Skeleton* Skeleton_create (SkeletonData* data) {
|
||||
Skeleton* self = NEW(Skeleton);
|
||||
CONST_CAST(SkeletonData*, self->data) = data;
|
||||
|
||||
CONST_CAST(_SkeletonVtable*, self->vtable) = NEW(_SkeletonVtable);
|
||||
VTABLE(Skeleton, self) ->dispose = dispose;
|
||||
|
||||
self->boneCount = self->data->boneCount;
|
||||
self->bones = MALLOC(Bone*, self->boneCount);
|
||||
int i, ii;
|
||||
@ -84,11 +78,11 @@ void _Skeleton_init (Skeleton* self, SkeletonData* data, void (*dispose) (Skelet
|
||||
self->g = 1;
|
||||
self->b = 1;
|
||||
self->a = 1;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void _Skeleton_deinit (Skeleton* self) {
|
||||
FREE(self->vtable);
|
||||
|
||||
void Skeleton_dispose (Skeleton* self) {
|
||||
int i;
|
||||
for (i = 0; i < self->boneCount; ++i)
|
||||
Bone_dispose(self->bones[i]);
|
||||
@ -101,10 +95,6 @@ void _Skeleton_deinit (Skeleton* self) {
|
||||
FREE(self->drawOrder);
|
||||
}
|
||||
|
||||
void Skeleton_dispose (Skeleton* self) {
|
||||
VTABLE(Skeleton, self) ->dispose(self);
|
||||
}
|
||||
|
||||
void Skeleton_updateWorldTransform (const Skeleton* self) {
|
||||
int i;
|
||||
for (i = 0; i < self->boneCount; ++i)
|
||||
|
||||
@ -29,22 +29,6 @@
|
||||
#include <spine/spine.h>
|
||||
#include "cocos2d.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace spine {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ccV3F_C4B_T2F_Quad* RegionAttachment_updateQuad (Attachment* self, Slot* slot);
|
||||
ccV3F_C4B_T2F_Quad* RegionAttachment_getQuad (RegionAttachment* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
using namespace spine;
|
||||
#endif
|
||||
|
||||
/**/
|
||||
|
||||
@interface CCSkeleton : CCNodeRGBA<CCBlendProtocol> {
|
||||
@private
|
||||
bool ownsSkeleton;
|
||||
@ -58,9 +42,6 @@ using namespace spine;
|
||||
bool debugSlots;
|
||||
bool debugBones;
|
||||
|
||||
CCTextureAtlas* textureAtlas; // All region attachments for a skeleton must use the same texture.
|
||||
unsigned int quadCount;
|
||||
|
||||
ccBlendFunc blendFunc;
|
||||
}
|
||||
|
||||
@ -109,4 +90,19 @@ using namespace spine;
|
||||
|
||||
@end
|
||||
|
||||
/**/
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace spine {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_T2F_Quad* quad);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
using namespace spine;
|
||||
#endif
|
||||
|
||||
#endif /* SPINE_COCOS2D_H_ */
|
||||
|
||||
@ -30,77 +30,33 @@
|
||||
namespace spine {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
AtlasPage super;
|
||||
CCTexture2D* texture;
|
||||
CCTextureAtlas* textureAtlas;
|
||||
} Cocos2dAtlasPage;
|
||||
|
||||
void _Cocos2dAtlasPage_dispose (AtlasPage* page) {
|
||||
Cocos2dAtlasPage* self = SUB_CAST(Cocos2dAtlasPage, page);
|
||||
_AtlasPage_deinit(SUPER(self));
|
||||
|
||||
[self->texture release];
|
||||
[self->textureAtlas release];
|
||||
|
||||
FREE(page);
|
||||
void _AtlasPage_createTexture (AtlasPage* self, const char* path) {
|
||||
CCTexture2D* texture = [[CCTextureCache sharedTextureCache] addImage:@(path)];
|
||||
CCTextureAtlas* textureAtlas = [[CCTextureAtlas alloc] initWithTexture:texture capacity:4];
|
||||
[textureAtlas retain];
|
||||
self->texture = textureAtlas;
|
||||
CGSize size = texture.contentSizeInPixels;
|
||||
self->width = size.width;
|
||||
self->height = size.height;
|
||||
}
|
||||
|
||||
AtlasPage* AtlasPage_create (const char* name, const char* path) {
|
||||
Cocos2dAtlasPage* self = NEW(Cocos2dAtlasPage);
|
||||
_AtlasPage_init(SUPER(self), name, _Cocos2dAtlasPage_dispose);
|
||||
void _AtlasPage_disposeTexture (AtlasPage* self) {
|
||||
[(CCTextureAtlas*)self->texture release];
|
||||
}
|
||||
|
||||
self->texture = [[CCTextureCache sharedTextureCache] addImage:@(path)];
|
||||
[self->texture retain];
|
||||
self->textureAtlas = [[CCTextureAtlas alloc] initWithTexture:self->texture capacity:4];
|
||||
[self->textureAtlas retain];
|
||||
|
||||
return SUPER(self);
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
return _readFile([[[CCFileUtils sharedFileUtils] fullPathForFilename:@(path)] UTF8String], length);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
typedef struct {
|
||||
Skeleton super;
|
||||
CCSkeleton* node;
|
||||
} Cocos2dSkeleton;
|
||||
void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_T2F_Quad* quad) {
|
||||
RegionAttachment_updateVertices(self, slot);
|
||||
|
||||
void _Cocos2dSkeleton_dispose (Skeleton* self) {
|
||||
_Skeleton_deinit(self);
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
Skeleton* _Cocos2dSkeleton_create (SkeletonData* data, CCSkeleton* node) {
|
||||
Cocos2dSkeleton* self = NEW(Cocos2dSkeleton);
|
||||
_Skeleton_init(SUPER(self), data, _Cocos2dSkeleton_dispose);
|
||||
|
||||
self->node = node;
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
typedef struct {
|
||||
RegionAttachment super;
|
||||
ccV3F_C4B_T2F_Quad quad;
|
||||
CCTextureAtlas* textureAtlas;
|
||||
} Cocos2dRegionAttachment;
|
||||
|
||||
void _Cocos2dRegionAttachment_dispose (Attachment* self) {
|
||||
_RegionAttachment_deinit(SUB_CAST(RegionAttachment, self) );
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
ccV3F_C4B_T2F_Quad* RegionAttachment_updateQuad (Attachment* attachment, Slot* slot) {
|
||||
Cocos2dRegionAttachment* self = SUB_CAST(Cocos2dRegionAttachment, attachment);
|
||||
Cocos2dSkeleton* skeleton = SUB_CAST(Cocos2dSkeleton, slot->skeleton);
|
||||
|
||||
GLubyte r = SUPER(skeleton)->r * slot->r * 255;
|
||||
GLubyte g = SUPER(skeleton)->g * slot->g * 255;
|
||||
GLubyte b = SUPER(skeleton)->b * slot->b * 255;
|
||||
GLubyte a = SUPER(skeleton)->a * slot->a * 255;
|
||||
ccV3F_C4B_T2F_Quad* quad = &self->quad;
|
||||
GLubyte r = slot->skeleton->r * slot->r * 255;
|
||||
GLubyte g = slot->skeleton->g * slot->g * 255;
|
||||
GLubyte b = slot->skeleton->b * slot->b * 255;
|
||||
GLubyte a = slot->skeleton->a * slot->a * 255;
|
||||
quad->bl.colors.r = r;
|
||||
quad->bl.colors.g = g;
|
||||
quad->bl.colors.b = b;
|
||||
@ -118,82 +74,35 @@ ccV3F_C4B_T2F_Quad* RegionAttachment_updateQuad (Attachment* attachment, Slot* s
|
||||
quad->br.colors.b = b;
|
||||
quad->br.colors.a = a;
|
||||
|
||||
float* offset = SUPER(self)->offset;
|
||||
quad->bl.vertices.x = offset[0] * slot->bone->m00 + offset[1] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->bl.vertices.y = offset[0] * slot->bone->m10 + offset[1] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tl.vertices.x = offset[2] * slot->bone->m00 + offset[3] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tl.vertices.y = offset[2] * slot->bone->m10 + offset[3] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tr.vertices.x = offset[4] * slot->bone->m00 + offset[5] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tr.vertices.y = offset[4] * slot->bone->m10 + offset[5] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->br.vertices.x = offset[6] * slot->bone->m00 + offset[7] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->br.vertices.y = offset[6] * slot->bone->m10 + offset[7] * slot->bone->m11 + slot->bone->worldY;
|
||||
float* offset = self->offset;
|
||||
quad->bl.vertices.x = offset[VERTEX_X1] * slot->bone->m00 + offset[VERTEX_Y1] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->bl.vertices.y = offset[VERTEX_X1] * slot->bone->m10 + offset[VERTEX_Y1] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tl.vertices.x = offset[VERTEX_X2] * slot->bone->m00 + offset[VERTEX_Y2] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tl.vertices.y = offset[VERTEX_X2] * slot->bone->m10 + offset[VERTEX_Y2] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tr.vertices.x = offset[VERTEX_X3] * slot->bone->m00 + offset[VERTEX_Y3] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tr.vertices.y = offset[VERTEX_X3] * slot->bone->m10 + offset[VERTEX_Y3] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->br.vertices.x = offset[VERTEX_X4] * slot->bone->m00 + offset[VERTEX_Y4] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->br.vertices.y = offset[VERTEX_X4] * slot->bone->m10 + offset[VERTEX_Y4] * slot->bone->m11 + slot->bone->worldY;
|
||||
|
||||
return quad;
|
||||
}
|
||||
|
||||
void _Cocos2dRegionAttachment_draw (Attachment* attachment, Slot* slot) {
|
||||
RegionAttachment_updateQuad(attachment, slot);
|
||||
|
||||
Cocos2dRegionAttachment* self = SUB_CAST(Cocos2dRegionAttachment, attachment);
|
||||
Cocos2dSkeleton* skeleton = SUB_CAST(Cocos2dSkeleton, slot->skeleton);
|
||||
|
||||
// Cocos2d doesn't handle batching for us, so we'll just force a single texture per skeleton.
|
||||
skeleton->node->textureAtlas = self->textureAtlas;
|
||||
while (self->textureAtlas.capacity <= skeleton->node->quadCount) {
|
||||
if (![self->textureAtlas resizeCapacity:self->textureAtlas.capacity * 2]) return;
|
||||
}
|
||||
[self->textureAtlas updateQuad:&self->quad atIndex:skeleton->node->quadCount++];
|
||||
}
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region) {
|
||||
Cocos2dRegionAttachment* self = NEW(Cocos2dRegionAttachment);
|
||||
_RegionAttachment_init(SUPER(self), name, _Cocos2dRegionAttachment_dispose, _Cocos2dRegionAttachment_draw);
|
||||
|
||||
Cocos2dAtlasPage* page = SUB_CAST(Cocos2dAtlasPage, region->page);
|
||||
self->textureAtlas = page->textureAtlas;
|
||||
CGSize size = page->texture.contentSizeInPixels;
|
||||
float u = region->x / size.width;
|
||||
float u2 = (region->x + region->width) / size.width;
|
||||
float v = region->y / size.height;
|
||||
float v2 = (region->y + region->height) / size.height;
|
||||
ccV3F_C4B_T2F_Quad* quad = &self->quad;
|
||||
if (region->rotate) {
|
||||
quad->tl.texCoords.u = u;
|
||||
quad->tl.texCoords.v = v2;
|
||||
quad->tr.texCoords.u = u;
|
||||
quad->tr.texCoords.v = v;
|
||||
quad->br.texCoords.u = u2;
|
||||
quad->br.texCoords.v = v;
|
||||
quad->bl.texCoords.u = u2;
|
||||
quad->bl.texCoords.v = v2;
|
||||
if (self->region->rotate) {
|
||||
quad->tl.texCoords.u = self->region->u;
|
||||
quad->tl.texCoords.v = self->region->v2;
|
||||
quad->tr.texCoords.u = self->region->u;
|
||||
quad->tr.texCoords.v = self->region->v;
|
||||
quad->br.texCoords.u = self->region->u2;
|
||||
quad->br.texCoords.v = self->region->v;
|
||||
quad->bl.texCoords.u = self->region->u2;
|
||||
quad->bl.texCoords.v = self->region->v2;
|
||||
} else {
|
||||
quad->bl.texCoords.u = u;
|
||||
quad->bl.texCoords.v = v2;
|
||||
quad->tl.texCoords.u = u;
|
||||
quad->tl.texCoords.v = v;
|
||||
quad->tr.texCoords.u = u2;
|
||||
quad->tr.texCoords.v = v;
|
||||
quad->br.texCoords.u = u2;
|
||||
quad->br.texCoords.v = v2;
|
||||
quad->bl.texCoords.u = self->region->u;
|
||||
quad->bl.texCoords.v = self->region->v2;
|
||||
quad->tl.texCoords.u = self->region->u;
|
||||
quad->tl.texCoords.v = self->region->v;
|
||||
quad->tr.texCoords.u = self->region->u2;
|
||||
quad->tr.texCoords.v = self->region->v;
|
||||
quad->br.texCoords.u = self->region->u2;
|
||||
quad->br.texCoords.v = self->region->v2;
|
||||
}
|
||||
|
||||
quad->bl.vertices.z = 0;
|
||||
quad->tl.vertices.z = 0;
|
||||
quad->tr.vertices.z = 0;
|
||||
quad->br.vertices.z = 0;
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
|
||||
ccV3F_C4B_T2F_Quad* RegionAttachment_getQuad (RegionAttachment* attachment) {
|
||||
Cocos2dRegionAttachment* self = SUB_CAST(Cocos2dRegionAttachment, attachment);
|
||||
return &self->quad;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
return _readFile([[[CCFileUtils sharedFileUtils] fullPathForFilename:@(path)] UTF8String], length);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -211,11 +120,13 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
+ (CCSkeleton*) create:(NSString*)skeletonDataFile atlas:(Atlas*)atlas scale:(float)scale {
|
||||
NSAssert(skeletonDataFile, @"skeletonDataFile cannot be nil.");
|
||||
NSAssert(atlas, @"atlas cannot be nil.");
|
||||
|
||||
SkeletonJson* json = SkeletonJson_create(atlas);
|
||||
json->scale = scale;
|
||||
SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, [skeletonDataFile UTF8String]);
|
||||
NSAssert(skeletonData, ([NSString stringWithFormat:@"Error reading skeleton data file: %@\nError: %s", skeletonDataFile, json->error]));
|
||||
SkeletonJson_dispose(json);
|
||||
|
||||
CCSkeleton* node = skeletonData ? [CCSkeleton create:skeletonData] : 0;
|
||||
node->ownsSkeleton = true;
|
||||
return node;
|
||||
@ -228,9 +139,11 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
+ (CCSkeleton*) create:(NSString*)skeletonDataFile atlasFile:(NSString*)atlasFile scale:(float)scale {
|
||||
NSAssert(skeletonDataFile, @"skeletonDataFile cannot be nil.");
|
||||
NSAssert(atlasFile, @"atlasFile cannot be nil.");
|
||||
|
||||
Atlas* atlas = Atlas_readAtlasFile([atlasFile UTF8String]);
|
||||
NSAssert(atlas, ([NSString stringWithFormat:@"Error reading atlas file: %@", atlasFile]));
|
||||
if (!atlas) return 0;
|
||||
|
||||
SkeletonJson* json = SkeletonJson_create(atlas);
|
||||
json->scale = scale;
|
||||
SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, [skeletonDataFile UTF8String]);
|
||||
@ -240,6 +153,7 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
Atlas_dispose(atlas);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CCSkeleton* node = [CCSkeleton create:skeletonData];
|
||||
node->ownsSkeleton = true;
|
||||
node->atlas = atlas;
|
||||
@ -264,7 +178,7 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
self = [super init];
|
||||
if (!self) return nil;
|
||||
|
||||
CONST_CAST(Skeleton*, skeleton) = _Cocos2dSkeleton_create(skeletonData, self);
|
||||
CONST_CAST(Skeleton*, skeleton) = Skeleton_create(skeletonData);
|
||||
|
||||
if (!stateData) {
|
||||
stateData = AnimationStateData_create(skeletonData);
|
||||
@ -308,23 +222,43 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
skeleton->b = color.b / (float)255;
|
||||
skeleton->a = self.opacity / (float)255;
|
||||
|
||||
quadCount = 0;
|
||||
for (int i = 0, n = skeleton->slotCount; i < n; ++i)
|
||||
if (skeleton->slots[i]->attachment) Attachment_draw(skeleton->slots[i]->attachment, skeleton->slots[i]);
|
||||
if (textureAtlas) [textureAtlas drawNumberOfQuads:quadCount];
|
||||
CCTextureAtlas* textureAtlas = 0;
|
||||
int quadCount = 0;
|
||||
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
|
||||
Slot* slot = skeleton->slots[i];
|
||||
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
|
||||
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
|
||||
CCTextureAtlas* regionTextureAtlas = (CCTextureAtlas*)attachment->region->page->texture;
|
||||
if (regionTextureAtlas != textureAtlas) {
|
||||
if (textureAtlas) {
|
||||
[textureAtlas drawNumberOfQuads:quadCount];
|
||||
quadCount = 0;
|
||||
}
|
||||
}
|
||||
textureAtlas = regionTextureAtlas;
|
||||
if (textureAtlas.capacity == quadCount && ![textureAtlas resizeCapacity:quadCount * 2]) return;
|
||||
RegionAttachment_updateQuad(attachment, slot, &textureAtlas.quads[quadCount++]);
|
||||
}
|
||||
if (textureAtlas) {
|
||||
[textureAtlas drawNumberOfQuads:quadCount];
|
||||
quadCount = 0;
|
||||
}
|
||||
|
||||
if (debugSlots) {
|
||||
// Slots.
|
||||
ccDrawColor4B(0, 0, 255, 255);
|
||||
glLineWidth(1);
|
||||
CGPoint points[4];
|
||||
for (int i = 0, n = skeleton->slotCount; i < n; ++i) {
|
||||
if (!skeleton->slots[i]->attachment) continue;
|
||||
ccV3F_C4B_T2F_Quad* quad = &((Cocos2dRegionAttachment*)skeleton->slots[i]->attachment)->quad;
|
||||
points[0] = ccp(quad->bl.vertices.x, quad->bl.vertices.y);
|
||||
points[1] = ccp(quad->br.vertices.x, quad->br.vertices.y);
|
||||
points[2] = ccp(quad->tr.vertices.x, quad->tr.vertices.y);
|
||||
points[3] = ccp(quad->tl.vertices.x, quad->tl.vertices.y);
|
||||
ccV3F_C4B_T2F_Quad quad;
|
||||
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
|
||||
Slot* slot = skeleton->slots[i];
|
||||
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
|
||||
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
|
||||
RegionAttachment_updateQuad(attachment, slot, &quad);
|
||||
points[0] = ccp(quad.bl.vertices.x, quad.bl.vertices.y);
|
||||
points[1] = ccp(quad.br.vertices.x, quad.br.vertices.y);
|
||||
points[2] = ccp(quad.tr.vertices.x, quad.tr.vertices.y);
|
||||
points[3] = ccp(quad.tl.vertices.x, quad.tl.vertices.y);
|
||||
ccDrawPoly(points, 4, true);
|
||||
}
|
||||
}
|
||||
@ -332,7 +266,7 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
// 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->boneCount; i < n; i++) {
|
||||
Bone *bone = skeleton->bones[i];
|
||||
float x = bone->data->length * bone->m00 + bone->worldX;
|
||||
float y = bone->data->length * bone->m10 + bone->worldY;
|
||||
@ -341,7 +275,7 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
// 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->boneCount; i < n; i++) {
|
||||
Bone *bone = skeleton->bones[i];
|
||||
ccDrawPoint(ccp(bone->worldX, bone->worldY));
|
||||
if (i == 0) ccDrawColor4B(0, 255, 0, 255);
|
||||
@ -353,27 +287,28 @@ char* _Util_readFile (const char* path, int* length) {
|
||||
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
|
||||
float scaleX = self.scaleX;
|
||||
float scaleY = self.scaleY;
|
||||
ccV3F_C4B_T2F_Quad quad;
|
||||
for (int i = 0; i < skeleton->slotCount; ++i) {
|
||||
Slot* slot = skeleton->slots[i];
|
||||
Attachment* attachment = slot->attachment;
|
||||
if (!attachment || attachment->type != ATTACHMENT_REGION) continue;
|
||||
Cocos2dRegionAttachment* regionAttachment = SUB_CAST(Cocos2dRegionAttachment, attachment);
|
||||
minX = fmin(minX, regionAttachment->quad.bl.vertices.x * scaleX);
|
||||
minY = fmin(minY, regionAttachment->quad.bl.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, regionAttachment->quad.bl.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, regionAttachment->quad.bl.vertices.y * scaleY);
|
||||
minX = fmin(minX, regionAttachment->quad.br.vertices.x * scaleX);
|
||||
minY = fmin(minY, regionAttachment->quad.br.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, regionAttachment->quad.br.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, regionAttachment->quad.br.vertices.y * scaleY);
|
||||
minX = fmin(minX, regionAttachment->quad.tl.vertices.x * scaleX);
|
||||
minY = fmin(minY, regionAttachment->quad.tl.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, regionAttachment->quad.tl.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, regionAttachment->quad.tl.vertices.y * scaleY);
|
||||
minX = fmin(minX, regionAttachment->quad.tr.vertices.x * scaleX);
|
||||
minY = fmin(minY, regionAttachment->quad.tr.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, regionAttachment->quad.tr.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, regionAttachment->quad.tr.vertices.y * scaleY);
|
||||
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
|
||||
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
|
||||
RegionAttachment_updateQuad(attachment, slot, &quad);
|
||||
minX = fmin(minX, quad.bl.vertices.x * scaleX);
|
||||
minY = fmin(minY, quad.bl.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, quad.bl.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, quad.bl.vertices.y * scaleY);
|
||||
minX = fmin(minX, quad.br.vertices.x * scaleX);
|
||||
minY = fmin(minY, quad.br.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, quad.br.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, quad.br.vertices.y * scaleY);
|
||||
minX = fmin(minX, quad.tl.vertices.x * scaleX);
|
||||
minY = fmin(minY, quad.tl.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, quad.tl.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, quad.tl.vertices.y * scaleY);
|
||||
minX = fmin(minX, quad.tr.vertices.x * scaleX);
|
||||
minY = fmin(minY, quad.tr.vertices.y * scaleY);
|
||||
maxX = fmax(maxX, quad.tr.vertices.x * scaleX);
|
||||
maxY = fmax(maxY, quad.tr.vertices.y * scaleY);
|
||||
}
|
||||
minX = self.position.x + minX;
|
||||
minY = self.position.y + minY;
|
||||
|
||||
@ -31,43 +31,85 @@ using std::min;
|
||||
using std::max;
|
||||
namespace spine {
|
||||
|
||||
void _Cocos2dxAtlasPage_dispose (AtlasPage* page) {
|
||||
Cocos2dxAtlasPage* self = SUB_CAST(Cocos2dxAtlasPage, page);
|
||||
_AtlasPage_deinit(SUPER(self));
|
||||
|
||||
CC_SAFE_RELEASE_NULL(self->texture);
|
||||
CC_SAFE_RELEASE_NULL(self->textureAtlas);
|
||||
|
||||
FREE(page);
|
||||
void _AtlasPage_createTexture (AtlasPage* self, const char* path) {
|
||||
CCTexture2D* texture = CCTextureCache::sharedTextureCache()->addImage(path);
|
||||
CCTextureAtlas* textureAtlas = CCTextureAtlas::createWithTexture(texture, 4);
|
||||
textureAtlas->retain();
|
||||
self->texture = textureAtlas;
|
||||
self->width = texture->getPixelsWide();
|
||||
self->height = texture->getPixelsHigh();
|
||||
}
|
||||
|
||||
AtlasPage* AtlasPage_create (const char* name, const char* path) {
|
||||
Cocos2dxAtlasPage* self = NEW(Cocos2dxAtlasPage);
|
||||
_AtlasPage_init(SUPER(self), name, _Cocos2dxAtlasPage_dispose);
|
||||
void _AtlasPage_disposeTexture (AtlasPage* self) {
|
||||
((CCTextureAtlas*)self->texture)->release();
|
||||
}
|
||||
|
||||
self->texture = CCTextureCache::sharedTextureCache()->addImage(path);
|
||||
self->texture->retain();
|
||||
self->textureAtlas = CCTextureAtlas::createWithTexture(self->texture, 4);
|
||||
self->textureAtlas->retain();
|
||||
|
||||
return SUPER(self);
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
unsigned long size;
|
||||
char* data = reinterpret_cast<char*>(CCFileUtils::sharedFileUtils()->getFileData(
|
||||
CCFileUtils::sharedFileUtils()->fullPathForFilename(path).c_str(), "r", &size));
|
||||
*length = size;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
void _Cocos2dxSkeleton_dispose (Skeleton* self) {
|
||||
_Skeleton_deinit(self);
|
||||
FREE(self);
|
||||
void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_T2F_Quad* quad) {
|
||||
RegionAttachment_updateVertices(self, slot);
|
||||
|
||||
GLubyte r = slot->skeleton->r * slot->r * 255;
|
||||
GLubyte g = slot->skeleton->g * slot->g * 255;
|
||||
GLubyte b = slot->skeleton->b * slot->b * 255;
|
||||
GLubyte a = slot->skeleton->a * slot->a * 255;
|
||||
quad->bl.colors.r = r;
|
||||
quad->bl.colors.g = g;
|
||||
quad->bl.colors.b = b;
|
||||
quad->bl.colors.a = a;
|
||||
quad->tl.colors.r = r;
|
||||
quad->tl.colors.g = g;
|
||||
quad->tl.colors.b = b;
|
||||
quad->tl.colors.a = a;
|
||||
quad->tr.colors.r = r;
|
||||
quad->tr.colors.g = g;
|
||||
quad->tr.colors.b = b;
|
||||
quad->tr.colors.a = a;
|
||||
quad->br.colors.r = r;
|
||||
quad->br.colors.g = g;
|
||||
quad->br.colors.b = b;
|
||||
quad->br.colors.a = a;
|
||||
|
||||
float* offset = self->offset;
|
||||
quad->bl.vertices.x = offset[VERTEX_X1] * slot->bone->m00 + offset[VERTEX_Y1] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->bl.vertices.y = offset[VERTEX_X1] * slot->bone->m10 + offset[VERTEX_Y1] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tl.vertices.x = offset[VERTEX_X2] * slot->bone->m00 + offset[VERTEX_Y2] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tl.vertices.y = offset[VERTEX_X2] * slot->bone->m10 + offset[VERTEX_Y2] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tr.vertices.x = offset[VERTEX_X3] * slot->bone->m00 + offset[VERTEX_Y3] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tr.vertices.y = offset[VERTEX_X3] * slot->bone->m10 + offset[VERTEX_Y3] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->br.vertices.x = offset[VERTEX_X4] * slot->bone->m00 + offset[VERTEX_Y4] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->br.vertices.y = offset[VERTEX_X4] * slot->bone->m10 + offset[VERTEX_Y4] * slot->bone->m11 + slot->bone->worldY;
|
||||
|
||||
if (self->region->rotate) {
|
||||
quad->tl.texCoords.u = self->region->u;
|
||||
quad->tl.texCoords.v = self->region->v2;
|
||||
quad->tr.texCoords.u = self->region->u;
|
||||
quad->tr.texCoords.v = self->region->v;
|
||||
quad->br.texCoords.u = self->region->u2;
|
||||
quad->br.texCoords.v = self->region->v;
|
||||
quad->bl.texCoords.u = self->region->u2;
|
||||
quad->bl.texCoords.v = self->region->v2;
|
||||
} else {
|
||||
quad->bl.texCoords.u = self->region->u;
|
||||
quad->bl.texCoords.v = self->region->v2;
|
||||
quad->tl.texCoords.u = self->region->u;
|
||||
quad->tl.texCoords.v = self->region->v;
|
||||
quad->tr.texCoords.u = self->region->u2;
|
||||
quad->tr.texCoords.v = self->region->v;
|
||||
quad->br.texCoords.u = self->region->u2;
|
||||
quad->br.texCoords.v = self->region->v2;
|
||||
}
|
||||
}
|
||||
|
||||
Skeleton* _Cocos2dxSkeleton_create (SkeletonData* data, CCSkeleton* node) {
|
||||
Cocos2dxSkeleton* self = NEW(Cocos2dxSkeleton);
|
||||
_Skeleton_init(SUPER(self), data, _Cocos2dxSkeleton_dispose);
|
||||
|
||||
self->node = node;
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
/**/
|
||||
|
||||
CCSkeleton* CCSkeleton::create (const char* skeletonDataFile, Atlas* atlas, float scale) {
|
||||
SkeletonJson* json = SkeletonJson_create(atlas);
|
||||
@ -105,7 +147,7 @@ CCSkeleton* CCSkeleton::create (SkeletonData* skeletonData, AnimationStateData*
|
||||
CCSkeleton::CCSkeleton (SkeletonData *skeletonData, AnimationStateData *stateData) :
|
||||
ownsSkeleton(false), ownsStateData(false), atlas(0),
|
||||
skeleton(0), state(0), debugSlots(false), debugBones(false) {
|
||||
CONST_CAST(Skeleton*, skeleton) = _Cocos2dxSkeleton_create(skeletonData, this);
|
||||
CONST_CAST(Skeleton*, skeleton) = Skeleton_create(skeletonData);
|
||||
|
||||
if (!stateData) {
|
||||
stateData = AnimationStateData_create(skeletonData);
|
||||
@ -146,23 +188,43 @@ void CCSkeleton::draw () {
|
||||
skeleton->b = color.b / (float)255;
|
||||
skeleton->a = getOpacity() / (float)255;
|
||||
|
||||
quadCount = 0;
|
||||
for (int i = 0, n = skeleton->slotCount; i < n; i++)
|
||||
if (skeleton->slots[i]->attachment) Attachment_draw(skeleton->slots[i]->attachment, skeleton->slots[i]);
|
||||
if (textureAtlas) textureAtlas->drawNumberOfQuads(quadCount);
|
||||
CCTextureAtlas* textureAtlas = 0;
|
||||
int quadCount = 0;
|
||||
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
|
||||
Slot* slot = skeleton->slots[i];
|
||||
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
|
||||
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
|
||||
CCTextureAtlas* regionTextureAtlas = (CCTextureAtlas*)attachment->region->page->texture;
|
||||
if (regionTextureAtlas != textureAtlas) {
|
||||
if (textureAtlas) {
|
||||
textureAtlas->drawNumberOfQuads(quadCount);
|
||||
quadCount = 0;
|
||||
}
|
||||
}
|
||||
textureAtlas = regionTextureAtlas;
|
||||
if (textureAtlas->getCapacity() == quadCount && !textureAtlas->resizeCapacity(quadCount * 2)) return;
|
||||
RegionAttachment_updateQuad(attachment, slot, &textureAtlas->getQuads()[quadCount++]);
|
||||
}
|
||||
if (textureAtlas) {
|
||||
textureAtlas->drawNumberOfQuads(quadCount);
|
||||
quadCount = 0;
|
||||
}
|
||||
|
||||
if (debugSlots) {
|
||||
// Slots.
|
||||
ccDrawColor4B(0, 0, 255, 255);
|
||||
glLineWidth(1);
|
||||
CCPoint points[4];
|
||||
ccV3F_C4B_T2F_Quad quad;
|
||||
for (int i = 0, n = skeleton->slotCount; i < n; i++) {
|
||||
if (!skeleton->slots[i]->attachment) continue;
|
||||
ccV3F_C4B_T2F_Quad* quad = &((Cocos2dxRegionAttachment*)skeleton->slots[i]->attachment)->quad;
|
||||
points[0] = ccp(quad->bl.vertices.x, quad->bl.vertices.y);
|
||||
points[1] = ccp(quad->br.vertices.x, quad->br.vertices.y);
|
||||
points[2] = ccp(quad->tr.vertices.x, quad->tr.vertices.y);
|
||||
points[3] = ccp(quad->tl.vertices.x, quad->tl.vertices.y);
|
||||
Slot* slot = skeleton->slots[i];
|
||||
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
|
||||
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
|
||||
RegionAttachment_updateQuad(attachment, slot, &quad);
|
||||
points[0] = ccp(quad.bl.vertices.x, quad.bl.vertices.y);
|
||||
points[1] = ccp(quad.br.vertices.x, quad.br.vertices.y);
|
||||
points[2] = ccp(quad.tr.vertices.x, quad.tr.vertices.y);
|
||||
points[3] = ccp(quad.tl.vertices.x, quad.tl.vertices.y);
|
||||
ccDrawPoly(points, 4, true);
|
||||
}
|
||||
}
|
||||
@ -191,27 +253,28 @@ CCRect CCSkeleton::boundingBox () {
|
||||
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
|
||||
float scaleX = getScaleX();
|
||||
float scaleY = getScaleY();
|
||||
ccV3F_C4B_T2F_Quad quad;
|
||||
for (int i = 0; i < skeleton->slotCount; ++i) {
|
||||
Slot* slot = skeleton->slots[i];
|
||||
Attachment* attachment = slot->attachment;
|
||||
if (!attachment || attachment->type != ATTACHMENT_REGION) continue;
|
||||
Cocos2dxRegionAttachment* regionAttachment = SUB_CAST(Cocos2dxRegionAttachment, attachment);
|
||||
minX = min(minX, regionAttachment->quad.bl.vertices.x * scaleX);
|
||||
minY = min(minY, regionAttachment->quad.bl.vertices.y * scaleY);
|
||||
maxX = max(maxX, regionAttachment->quad.bl.vertices.x * scaleX);
|
||||
maxY = max(maxY, regionAttachment->quad.bl.vertices.y * scaleY);
|
||||
minX = min(minX, regionAttachment->quad.br.vertices.x * scaleX);
|
||||
minY = min(minY, regionAttachment->quad.br.vertices.y * scaleY);
|
||||
maxX = max(maxX, regionAttachment->quad.br.vertices.x * scaleX);
|
||||
maxY = max(maxY, regionAttachment->quad.br.vertices.y * scaleY);
|
||||
minX = min(minX, regionAttachment->quad.tl.vertices.x * scaleX);
|
||||
minY = min(minY, regionAttachment->quad.tl.vertices.y * scaleY);
|
||||
maxX = max(maxX, regionAttachment->quad.tl.vertices.x * scaleX);
|
||||
maxY = max(maxY, regionAttachment->quad.tl.vertices.y * scaleY);
|
||||
minX = min(minX, regionAttachment->quad.tr.vertices.x * scaleX);
|
||||
minY = min(minY, regionAttachment->quad.tr.vertices.y * scaleY);
|
||||
maxX = max(maxX, regionAttachment->quad.tr.vertices.x * scaleX);
|
||||
maxY = max(maxY, regionAttachment->quad.tr.vertices.y * scaleY);
|
||||
if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue;
|
||||
RegionAttachment* attachment = (RegionAttachment*)slot->attachment;
|
||||
RegionAttachment_updateQuad(attachment, slot, &quad);
|
||||
minX = min(minX, quad.bl.vertices.x * scaleX);
|
||||
minY = min(minY, quad.bl.vertices.y * scaleY);
|
||||
maxX = max(maxX, quad.bl.vertices.x * scaleX);
|
||||
maxY = max(maxY, quad.bl.vertices.y * scaleY);
|
||||
minX = min(minX, quad.br.vertices.x * scaleX);
|
||||
minY = min(minY, quad.br.vertices.y * scaleY);
|
||||
maxX = max(maxX, quad.br.vertices.x * scaleX);
|
||||
maxY = max(maxY, quad.br.vertices.y * scaleY);
|
||||
minX = min(minX, quad.tl.vertices.x * scaleX);
|
||||
minY = min(minY, quad.tl.vertices.y * scaleY);
|
||||
maxX = max(maxX, quad.tl.vertices.x * scaleX);
|
||||
maxY = max(maxY, quad.tl.vertices.y * scaleY);
|
||||
minX = min(minX, quad.tr.vertices.x * scaleX);
|
||||
minY = min(minY, quad.tr.vertices.y * scaleY);
|
||||
maxX = max(maxX, quad.tr.vertices.x * scaleX);
|
||||
maxY = max(maxY, quad.tr.vertices.y * scaleY);
|
||||
}
|
||||
CCPoint position = getPosition();
|
||||
minX = position.x + minX;
|
||||
@ -283,114 +346,4 @@ void CCSkeleton::setBlendFunc (ccBlendFunc blendFunc) {
|
||||
this->blendFunc = blendFunc;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
void _Cocos2dxRegionAttachment_dispose (Attachment* self) {
|
||||
_RegionAttachment_deinit(SUB_CAST(RegionAttachment, self) );
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
ccV3F_C4B_T2F_Quad* RegionAttachment_updateQuad (Attachment* attachment, Slot* slot) {
|
||||
Cocos2dxRegionAttachment* self = SUB_CAST(Cocos2dxRegionAttachment, attachment);
|
||||
Cocos2dxSkeleton* skeleton = SUB_CAST(Cocos2dxSkeleton, slot->skeleton);
|
||||
|
||||
GLubyte r = SUPER(skeleton)->r * slot->r * 255;
|
||||
GLubyte g = SUPER(skeleton)->g * slot->g * 255;
|
||||
GLubyte b = SUPER(skeleton)->b * slot->b * 255;
|
||||
GLubyte a = SUPER(skeleton)->a * slot->a * 255;
|
||||
ccV3F_C4B_T2F_Quad* quad = &self->quad;
|
||||
quad->bl.colors.r = r;
|
||||
quad->bl.colors.g = g;
|
||||
quad->bl.colors.b = b;
|
||||
quad->bl.colors.a = a;
|
||||
quad->tl.colors.r = r;
|
||||
quad->tl.colors.g = g;
|
||||
quad->tl.colors.b = b;
|
||||
quad->tl.colors.a = a;
|
||||
quad->tr.colors.r = r;
|
||||
quad->tr.colors.g = g;
|
||||
quad->tr.colors.b = b;
|
||||
quad->tr.colors.a = a;
|
||||
quad->br.colors.r = r;
|
||||
quad->br.colors.g = g;
|
||||
quad->br.colors.b = b;
|
||||
quad->br.colors.a = a;
|
||||
|
||||
float* offset = SUPER(self)->offset;
|
||||
quad->bl.vertices.x = offset[0] * slot->bone->m00 + offset[1] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->bl.vertices.y = offset[0] * slot->bone->m10 + offset[1] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tl.vertices.x = offset[2] * slot->bone->m00 + offset[3] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tl.vertices.y = offset[2] * slot->bone->m10 + offset[3] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->tr.vertices.x = offset[4] * slot->bone->m00 + offset[5] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->tr.vertices.y = offset[4] * slot->bone->m10 + offset[5] * slot->bone->m11 + slot->bone->worldY;
|
||||
quad->br.vertices.x = offset[6] * slot->bone->m00 + offset[7] * slot->bone->m01 + slot->bone->worldX;
|
||||
quad->br.vertices.y = offset[6] * slot->bone->m10 + offset[7] * slot->bone->m11 + slot->bone->worldY;
|
||||
|
||||
return quad;
|
||||
}
|
||||
|
||||
void _Cocos2dxRegionAttachment_draw (Attachment* attachment, Slot* slot) {
|
||||
RegionAttachment_updateQuad(attachment, slot);
|
||||
|
||||
Cocos2dxRegionAttachment* self = SUB_CAST(Cocos2dxRegionAttachment, attachment);
|
||||
Cocos2dxSkeleton* skeleton = SUB_CAST(Cocos2dxSkeleton, slot->skeleton);
|
||||
|
||||
// cocos2dx doesn't handle batching for us, so we force a single texture per skeleton.
|
||||
skeleton->node->textureAtlas = self->textureAtlas;
|
||||
while (self->textureAtlas->getCapacity() <= skeleton->node->quadCount) {
|
||||
if (!self->textureAtlas->resizeCapacity(self->textureAtlas->getCapacity() * 2)) return;
|
||||
}
|
||||
self->textureAtlas->updateQuad(&self->quad, skeleton->node->quadCount++);
|
||||
}
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region) {
|
||||
Cocos2dxRegionAttachment* self = NEW(Cocos2dxRegionAttachment);
|
||||
_RegionAttachment_init(SUPER(self), name, _Cocos2dxRegionAttachment_dispose, _Cocos2dxRegionAttachment_draw);
|
||||
|
||||
Cocos2dxAtlasPage* page = SUB_CAST(Cocos2dxAtlasPage, region->page);
|
||||
self->textureAtlas = page->textureAtlas;
|
||||
const CCSize& size = page->texture->getContentSizeInPixels();
|
||||
float u = region->x / size.width;
|
||||
float u2 = (region->x + region->width) / size.width;
|
||||
float v = region->y / size.height;
|
||||
float v2 = (region->y + region->height) / size.height;
|
||||
ccV3F_C4B_T2F_Quad* quad = &self->quad;
|
||||
if (region->rotate) {
|
||||
quad->tl.texCoords.u = u;
|
||||
quad->tl.texCoords.v = v2;
|
||||
quad->tr.texCoords.u = u;
|
||||
quad->tr.texCoords.v = v;
|
||||
quad->br.texCoords.u = u2;
|
||||
quad->br.texCoords.v = v;
|
||||
quad->bl.texCoords.u = u2;
|
||||
quad->bl.texCoords.v = v2;
|
||||
} else {
|
||||
quad->bl.texCoords.u = u;
|
||||
quad->bl.texCoords.v = v2;
|
||||
quad->tl.texCoords.u = u;
|
||||
quad->tl.texCoords.v = v;
|
||||
quad->tr.texCoords.u = u2;
|
||||
quad->tr.texCoords.v = v;
|
||||
quad->br.texCoords.u = u2;
|
||||
quad->br.texCoords.v = v2;
|
||||
}
|
||||
|
||||
quad->bl.vertices.z = 0;
|
||||
quad->tl.vertices.z = 0;
|
||||
quad->tr.vertices.z = 0;
|
||||
quad->br.vertices.z = 0;
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
unsigned long size;
|
||||
char* data = reinterpret_cast<char*>(CCFileUtils::sharedFileUtils()->getFileData(
|
||||
CCFileUtils::sharedFileUtils()->fullPathForFilename(path).c_str(), "r", &size));
|
||||
*length = size;
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -31,21 +31,6 @@
|
||||
|
||||
namespace spine {
|
||||
|
||||
typedef struct {
|
||||
AtlasPage super;
|
||||
cocos2d::CCTexture2D* texture;
|
||||
cocos2d::CCTextureAtlas* textureAtlas;
|
||||
} Cocos2dxAtlasPage;
|
||||
|
||||
/**/
|
||||
|
||||
class CCSkeleton;
|
||||
|
||||
typedef struct {
|
||||
Skeleton super;
|
||||
CCSkeleton* node;
|
||||
} Cocos2dxSkeleton;
|
||||
|
||||
class CCSkeleton: public cocos2d::CCNodeRGBA, public cocos2d::CCBlendProtocol {
|
||||
private:
|
||||
bool ownsSkeleton;
|
||||
@ -59,9 +44,6 @@ public:
|
||||
bool debugSlots;
|
||||
bool debugBones;
|
||||
|
||||
cocos2d::CCTextureAtlas* textureAtlas; // All region attachments for a skeleton must use the same texture.
|
||||
unsigned int quadCount;
|
||||
|
||||
static CCSkeleton* create (const char* skeletonDataFile, Atlas* atlas, float scale = 1);
|
||||
static CCSkeleton* create (const char* skeletonDataFile, const char* atlasFile, float scale = 1);
|
||||
static CCSkeleton* create (SkeletonData* skeletonData, AnimationStateData* stateData = 0);
|
||||
@ -110,13 +92,7 @@ public:
|
||||
|
||||
/**/
|
||||
|
||||
typedef struct {
|
||||
RegionAttachment super;
|
||||
cocos2d::ccV3F_C4B_T2F_Quad quad;
|
||||
cocos2d::CCTextureAtlas* textureAtlas;
|
||||
} Cocos2dxRegionAttachment;
|
||||
|
||||
cocos2d::ccV3F_C4B_T2F_Quad* RegionAttachment_updateQuad (Attachment* self, Slot* slot);
|
||||
void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, cocos2d::ccV3F_C4B_T2F_Quad* quad);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -31,58 +31,35 @@
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <SFML/Graphics/RenderStates.hpp>
|
||||
|
||||
using sf::Quads;
|
||||
using sf::RenderTarget;
|
||||
using sf::RenderStates;
|
||||
using sf::Texture;
|
||||
using sf::Uint8;
|
||||
using sf::Vertex;
|
||||
using sf::VertexArray;
|
||||
using namespace sf;
|
||||
|
||||
namespace spine {
|
||||
|
||||
void _SfmlAtlasPage_dispose (AtlasPage* page) {
|
||||
SfmlAtlasPage* self = SUB_CAST(SfmlAtlasPage, page);
|
||||
_AtlasPage_deinit(SUPER(self));
|
||||
|
||||
delete self->texture;
|
||||
|
||||
FREE(page);
|
||||
void _AtlasPage_createTexture (AtlasPage* self, const char* path) {
|
||||
Texture* texture = new Texture();
|
||||
if (!texture->loadFromFile(path)) return;
|
||||
self->texture = texture;
|
||||
Vector2u size = texture->getSize();
|
||||
self->width = size.x;
|
||||
self->height = size.x;
|
||||
}
|
||||
|
||||
AtlasPage* AtlasPage_create (const char* name, const char* path) {
|
||||
SfmlAtlasPage* self = NEW(SfmlAtlasPage);
|
||||
_AtlasPage_init(SUPER(self), name, _SfmlAtlasPage_dispose);
|
||||
void _AtlasPage_disposeTexture (AtlasPage* self) {
|
||||
delete (Texture*)self->texture;
|
||||
}
|
||||
|
||||
self->texture = new Texture();
|
||||
self->texture->loadFromFile(path);
|
||||
|
||||
return SUPER(self);
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
return _readFile(path, length);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
void _SfmlSkeleton_dispose (Skeleton* self) {
|
||||
_Skeleton_deinit(self);
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
Skeleton* _SfmlSkeleton_create (SkeletonData* data, SkeletonDrawable* drawable) {
|
||||
Bone_setYDown(1);
|
||||
|
||||
SfmlSkeleton* self = NEW(SfmlSkeleton);
|
||||
_Skeleton_init(SUPER(self), data, _SfmlSkeleton_dispose);
|
||||
|
||||
CONST_CAST(SkeletonDrawable*, self->drawable) = drawable;
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
|
||||
SkeletonDrawable::SkeletonDrawable (SkeletonData* skeletonData, AnimationStateData* stateData) :
|
||||
timeScale(1),
|
||||
vertexArray(new VertexArray(Quads, skeletonData->boneCount * 4)),
|
||||
texture(0) {
|
||||
skeleton = _SfmlSkeleton_create(skeletonData, this);
|
||||
vertexArray(new VertexArray(Quads, skeletonData->boneCount * 4)) {
|
||||
Bone_setYDown(true);
|
||||
|
||||
skeleton = Skeleton_create(skeletonData);
|
||||
state = AnimationState_create(stateData);
|
||||
}
|
||||
|
||||
@ -101,99 +78,77 @@ void SkeletonDrawable::update (float deltaTime) {
|
||||
|
||||
void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
|
||||
vertexArray->clear();
|
||||
for (int i = 0; i < skeleton->slotCount; ++i)
|
||||
if (skeleton->slots[i]->attachment) Attachment_draw(skeleton->slots[i]->attachment, skeleton->slots[i]);
|
||||
states.texture = texture;
|
||||
for (int i = 0; i < skeleton->slotCount; ++i) {
|
||||
Slot* slot = skeleton->slots[i];
|
||||
Attachment* attachment = slot->attachment;
|
||||
if (!attachment || attachment->type != ATTACHMENT_REGION) continue;
|
||||
RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
|
||||
RegionAttachment_updateVertices(regionAttachment, slot);
|
||||
|
||||
Uint8 r = skeleton->r * slot->r * 255;
|
||||
Uint8 g = skeleton->g * slot->g * 255;
|
||||
Uint8 b = skeleton->b * slot->b * 255;
|
||||
Uint8 a = skeleton->a * slot->a * 255;
|
||||
|
||||
sf::Vertex vertices[4];
|
||||
vertices[0].color.r = r;
|
||||
vertices[0].color.g = g;
|
||||
vertices[0].color.b = b;
|
||||
vertices[0].color.a = a;
|
||||
vertices[1].color.r = r;
|
||||
vertices[1].color.g = g;
|
||||
vertices[1].color.b = b;
|
||||
vertices[1].color.a = a;
|
||||
vertices[2].color.r = r;
|
||||
vertices[2].color.g = g;
|
||||
vertices[2].color.b = b;
|
||||
vertices[2].color.a = a;
|
||||
vertices[3].color.r = r;
|
||||
vertices[3].color.g = g;
|
||||
vertices[3].color.b = b;
|
||||
vertices[3].color.a = a;
|
||||
|
||||
vertices[0].position.x = regionAttachment->vertices[VERTEX_X1];
|
||||
vertices[0].position.y = regionAttachment->vertices[VERTEX_Y1];
|
||||
vertices[1].position.x = regionAttachment->vertices[VERTEX_X2];
|
||||
vertices[1].position.y = regionAttachment->vertices[VERTEX_Y2];
|
||||
vertices[2].position.x = regionAttachment->vertices[VERTEX_X3];
|
||||
vertices[2].position.y = regionAttachment->vertices[VERTEX_Y3];
|
||||
vertices[3].position.x = regionAttachment->vertices[VERTEX_X4];
|
||||
vertices[3].position.y = regionAttachment->vertices[VERTEX_Y4];
|
||||
|
||||
int u = regionAttachment->region->x;
|
||||
int u2 = u + regionAttachment->region->width;
|
||||
int v = regionAttachment->region->y;
|
||||
int v2 = v + regionAttachment->region->height;
|
||||
if (regionAttachment->region->rotate) {
|
||||
vertices[1].texCoords.x = u;
|
||||
vertices[1].texCoords.y = v2;
|
||||
vertices[2].texCoords.x = u;
|
||||
vertices[2].texCoords.y = v;
|
||||
vertices[3].texCoords.x = u2;
|
||||
vertices[3].texCoords.y = v;
|
||||
vertices[0].texCoords.x = u2;
|
||||
vertices[0].texCoords.y = v2;
|
||||
} else {
|
||||
vertices[0].texCoords.x = u;
|
||||
vertices[0].texCoords.y = v2;
|
||||
vertices[1].texCoords.x = u;
|
||||
vertices[1].texCoords.y = v;
|
||||
vertices[2].texCoords.x = u2;
|
||||
vertices[2].texCoords.y = v;
|
||||
vertices[3].texCoords.x = u2;
|
||||
vertices[3].texCoords.y = v2;
|
||||
}
|
||||
|
||||
// SMFL doesn't handle batching for us, so we'll just force a single texture per skeleton.
|
||||
states.texture = (Texture*)regionAttachment->region->page->texture;
|
||||
vertexArray->append(vertices[0]);
|
||||
vertexArray->append(vertices[1]);
|
||||
vertexArray->append(vertices[2]);
|
||||
vertexArray->append(vertices[3]);
|
||||
}
|
||||
target.draw(*vertexArray, states);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
void _SfmlRegionAttachment_dispose (Attachment* self) {
|
||||
_RegionAttachment_deinit(SUB_CAST(RegionAttachment, self) );
|
||||
FREE(self);
|
||||
}
|
||||
|
||||
void _SfmlRegionAttachment_draw (Attachment* attachment, Slot* slot) {
|
||||
SfmlRegionAttachment* self = SUB_CAST(SfmlRegionAttachment, attachment);
|
||||
SfmlSkeleton* skeleton = (SfmlSkeleton*)slot->skeleton;
|
||||
Uint8 r = SUPER(skeleton)->r * slot->r * 255;
|
||||
Uint8 g = SUPER(skeleton)->g * slot->g * 255;
|
||||
Uint8 b = SUPER(skeleton)->b * slot->b * 255;
|
||||
Uint8 a = SUPER(skeleton)->a * slot->a * 255;
|
||||
sf::Vertex* vertices = self->vertices;
|
||||
vertices[0].color.r = r;
|
||||
vertices[0].color.g = g;
|
||||
vertices[0].color.b = b;
|
||||
vertices[0].color.a = a;
|
||||
vertices[1].color.r = r;
|
||||
vertices[1].color.g = g;
|
||||
vertices[1].color.b = b;
|
||||
vertices[1].color.a = a;
|
||||
vertices[2].color.r = r;
|
||||
vertices[2].color.g = g;
|
||||
vertices[2].color.b = b;
|
||||
vertices[2].color.a = a;
|
||||
vertices[3].color.r = r;
|
||||
vertices[3].color.g = g;
|
||||
vertices[3].color.b = b;
|
||||
vertices[3].color.a = a;
|
||||
|
||||
float* offset = SUPER(self)->offset;
|
||||
Bone* bone = slot->bone;
|
||||
vertices[0].position.x = offset[0] * bone->m00 + offset[1] * bone->m01 + bone->worldX;
|
||||
vertices[0].position.y = offset[0] * bone->m10 + offset[1] * bone->m11 + bone->worldY;
|
||||
vertices[1].position.x = offset[2] * bone->m00 + offset[3] * bone->m01 + bone->worldX;
|
||||
vertices[1].position.y = offset[2] * bone->m10 + offset[3] * bone->m11 + bone->worldY;
|
||||
vertices[2].position.x = offset[4] * bone->m00 + offset[5] * bone->m01 + bone->worldX;
|
||||
vertices[2].position.y = offset[4] * bone->m10 + offset[5] * bone->m11 + bone->worldY;
|
||||
vertices[3].position.x = offset[6] * bone->m00 + offset[7] * bone->m01 + bone->worldX;
|
||||
vertices[3].position.y = offset[6] * bone->m10 + offset[7] * bone->m11 + bone->worldY;
|
||||
|
||||
// SMFL doesn't handle batching for us, so we'll just force a single texture per skeleton.
|
||||
skeleton->drawable->texture = self->texture;
|
||||
skeleton->drawable->vertexArray->append(vertices[0]);
|
||||
skeleton->drawable->vertexArray->append(vertices[1]);
|
||||
skeleton->drawable->vertexArray->append(vertices[2]);
|
||||
skeleton->drawable->vertexArray->append(vertices[3]);
|
||||
}
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region) {
|
||||
SfmlRegionAttachment* self = NEW(SfmlRegionAttachment);
|
||||
_RegionAttachment_init(SUPER(self), name, _SfmlRegionAttachment_dispose, _SfmlRegionAttachment_draw);
|
||||
|
||||
self->texture = ((SfmlAtlasPage*)region->page)->texture;
|
||||
int u = region->x;
|
||||
int u2 = u + region->width;
|
||||
int v = region->y;
|
||||
int v2 = v + region->height;
|
||||
if (region->rotate) {
|
||||
self->vertices[1].texCoords.x = u;
|
||||
self->vertices[1].texCoords.y = v2;
|
||||
self->vertices[2].texCoords.x = u;
|
||||
self->vertices[2].texCoords.y = v;
|
||||
self->vertices[3].texCoords.x = u2;
|
||||
self->vertices[3].texCoords.y = v;
|
||||
self->vertices[0].texCoords.x = u2;
|
||||
self->vertices[0].texCoords.y = v2;
|
||||
} else {
|
||||
self->vertices[0].texCoords.x = u;
|
||||
self->vertices[0].texCoords.y = v2;
|
||||
self->vertices[1].texCoords.x = u;
|
||||
self->vertices[1].texCoords.y = v;
|
||||
self->vertices[2].texCoords.x = u2;
|
||||
self->vertices[2].texCoords.y = v;
|
||||
self->vertices[3].texCoords.x = u2;
|
||||
self->vertices[3].texCoords.y = v2;
|
||||
}
|
||||
|
||||
return SUPER(self);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
return _readFile(path, length);
|
||||
}
|
||||
|
||||
} /* namespace spine */
|
||||
|
||||
@ -52,7 +52,6 @@ public:
|
||||
AnimationState* state;
|
||||
float timeScale;
|
||||
sf::VertexArray* vertexArray;
|
||||
sf::Texture* texture; // All region attachments must use the same texture.
|
||||
|
||||
SkeletonDrawable (SkeletonData* skeleton, AnimationStateData* stateData = 0);
|
||||
~SkeletonDrawable ();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user