mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-12 18:18:43 +08:00
C runtime works!
This commit is contained in:
parent
9a0085c36b
commit
6765ec4235
@ -53,7 +53,7 @@ float CurveTimeline_getCurvePercent (CurveTimeline* timeline, int frameIndex, fl
|
||||
|
||||
typedef struct BaseTimeline {
|
||||
CurveTimeline super;
|
||||
int const frameCount;
|
||||
int const framesLength;
|
||||
float* const frames; /* time, angle, ... for rotate. time, x, y, ... for translate and scale. */
|
||||
int boneIndex;
|
||||
} RotateTimeline;
|
||||
@ -82,7 +82,7 @@ void ScaleTimeline_setFrame (ScaleTimeline* timeline, int frameIndex, float time
|
||||
|
||||
typedef struct {
|
||||
CurveTimeline super;
|
||||
int const frameCount;
|
||||
int const framesLength;
|
||||
float* const frames; /* time, r, g, b, a, ... */
|
||||
int slotIndex;
|
||||
} ColorTimeline;
|
||||
@ -95,7 +95,7 @@ void ColorTimeline_setFrame (ColorTimeline* timeline, int frameIndex, float time
|
||||
|
||||
typedef struct {
|
||||
Timeline super;
|
||||
int const frameCount;
|
||||
int const framesLength;
|
||||
float* const frames; /* time, ... */
|
||||
int slotIndex;
|
||||
const char** const attachmentNames;
|
||||
|
||||
@ -6,6 +6,8 @@ namespace spine {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Slot;
|
||||
|
||||
typedef enum {
|
||||
ATTACHMENT_REGION, ATTACHMENT_REGION_SEQUENCE
|
||||
} AttachmentType;
|
||||
@ -15,11 +17,14 @@ struct Attachment {
|
||||
const char* const name;
|
||||
int type;
|
||||
|
||||
void (*_draw) (Attachment* attachment, struct Slot* slot);
|
||||
void (*_dispose) (Attachment* attachment);
|
||||
};
|
||||
|
||||
void Attachment_dispose (Attachment* attachment);
|
||||
|
||||
void Attachment_draw (Attachment* attachment, struct Slot* slot);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ extern "C" {
|
||||
|
||||
struct Skeleton;
|
||||
|
||||
typedef struct {
|
||||
typedef struct Slot {
|
||||
SlotData* const data;
|
||||
struct Skeleton* const skeleton;
|
||||
Bone* const bone;
|
||||
|
||||
@ -165,8 +165,8 @@ struct BaseTimeline* _BaseTimeline_create (int frameCount, int frameSize) {
|
||||
_CurveTimeline_init(&self->super, frameCount);
|
||||
((Timeline*)self)->_dispose = _BaseTimeline_dispose;
|
||||
|
||||
CAST(int, self->frameCount) = frameCount;
|
||||
CAST(float*, self->frames) = CALLOC(float, frameCount * frameSize)
|
||||
CAST(int, self->framesLength) = frameCount * frameSize;
|
||||
CAST(float*, self->frames) = CALLOC(float, self->framesLength)
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -183,8 +183,8 @@ void _RotateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float
|
||||
|
||||
Bone *bone = skeleton->bones[self->boneIndex];
|
||||
|
||||
if (time >= self->frames[self->frameCount - 2]) { /* Time is after last frame. */
|
||||
float amount = bone->data->rotation + self->frames[self->frameCount - 1] - bone->rotation;
|
||||
if (time >= self->frames[self->framesLength - 2]) { /* Time is after last frame. */
|
||||
float amount = bone->data->rotation + self->frames[self->framesLength - 1] - bone->rotation;
|
||||
while (amount > 180)
|
||||
amount -= 360;
|
||||
while (amount < -180)
|
||||
@ -194,7 +194,7 @@ void _RotateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float
|
||||
}
|
||||
|
||||
/* Interpolate between the last frame and the current frame. */
|
||||
int frameIndex = binarySearch(self->frames, self->frameCount, time, 2);
|
||||
int frameIndex = binarySearch(self->frames, self->framesLength, time, 2);
|
||||
float lastFrameValue = self->frames[frameIndex - 1];
|
||||
float frameTime = self->frames[frameIndex];
|
||||
float percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
|
||||
@ -238,14 +238,14 @@ void _TranslateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, flo
|
||||
|
||||
Bone *bone = skeleton->bones[self->boneIndex];
|
||||
|
||||
if (time >= self->frames[self->frameCount - 3]) { /* Time is after last frame. */
|
||||
bone->x += (bone->data->x + self->frames[self->frameCount - 2] - bone->x) * alpha;
|
||||
bone->y += (bone->data->y + self->frames[self->frameCount - 1] - bone->y) * alpha;
|
||||
if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */
|
||||
bone->x += (bone->data->x + self->frames[self->framesLength - 2] - bone->x) * alpha;
|
||||
bone->y += (bone->data->y + self->frames[self->framesLength - 1] - bone->y) * alpha;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Interpolate between the last frame and the current frame. */
|
||||
int frameIndex = binarySearch(self->frames, self->frameCount, time, 3);
|
||||
int frameIndex = binarySearch(self->frames, self->framesLength, time, 3);
|
||||
float lastFrameX = self->frames[frameIndex - 2];
|
||||
float lastFrameY = self->frames[frameIndex - 1];
|
||||
float frameTime = self->frames[frameIndex];
|
||||
@ -279,14 +279,14 @@ void _ScaleTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float t
|
||||
if (time < self->frames[0]) return; /* Time is before first frame. */
|
||||
|
||||
Bone *bone = skeleton->bones[self->boneIndex];
|
||||
if (time >= self->frames[self->frameCount - 3]) { /* Time is after last frame. */
|
||||
bone->scaleX += (bone->data->scaleX - 1 + self->frames[self->frameCount - 2] - bone->scaleX) * alpha;
|
||||
bone->scaleY += (bone->data->scaleY - 1 + self->frames[self->frameCount - 1] - bone->scaleY) * alpha;
|
||||
if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */
|
||||
bone->scaleX += (bone->data->scaleX - 1 + self->frames[self->framesLength - 2] - bone->scaleX) * alpha;
|
||||
bone->scaleY += (bone->data->scaleY - 1 + self->frames[self->framesLength - 1] - bone->scaleY) * alpha;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Interpolate between the last frame and the current frame. */
|
||||
int frameIndex = binarySearch(self->frames, self->frameCount, time, 3);
|
||||
int frameIndex = binarySearch(self->frames, self->framesLength, time, 3);
|
||||
float lastFrameX = self->frames[frameIndex - 2];
|
||||
float lastFrameY = self->frames[frameIndex - 1];
|
||||
float frameTime = self->frames[frameIndex];
|
||||
@ -324,8 +324,8 @@ void _ColorTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float t
|
||||
|
||||
Slot *slot = skeleton->slots[self->slotIndex];
|
||||
|
||||
if (time >= self->frames[self->frameCount - 5]) { /* Time is after last frame. */
|
||||
int i = self->frameCount - 1;
|
||||
if (time >= self->frames[self->framesLength - 5]) { /* Time is after last frame. */
|
||||
int i = self->framesLength - 1;
|
||||
slot->r = self->frames[i - 3];
|
||||
slot->g = self->frames[i - 2];
|
||||
slot->b = self->frames[i - 1];
|
||||
@ -334,7 +334,7 @@ void _ColorTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float t
|
||||
}
|
||||
|
||||
/* Interpolate between the last frame and the current frame. */
|
||||
int frameIndex = binarySearch(self->frames, self->frameCount, time, 5);
|
||||
int frameIndex = binarySearch(self->frames, self->framesLength, time, 5);
|
||||
float lastFrameR = self->frames[frameIndex - 4];
|
||||
float lastFrameG = self->frames[frameIndex - 3];
|
||||
float lastFrameB = self->frames[frameIndex - 2];
|
||||
@ -383,10 +383,10 @@ void _AttachmentTimeline_apply (const Timeline* timeline, Skeleton* skeleton, fl
|
||||
if (time < self->frames[0]) return; /* Time is before first frame. */
|
||||
|
||||
int frameIndex;
|
||||
if (time >= self->frames[self->frameCount - 1]) /* Time is after last frame. */
|
||||
frameIndex = self->frameCount - 1;
|
||||
if (time >= self->frames[self->framesLength - 1]) /* Time is after last frame. */
|
||||
frameIndex = self->framesLength - 1;
|
||||
else
|
||||
frameIndex = binarySearch(self->frames, self->frameCount, time, 1) - 1;
|
||||
frameIndex = binarySearch(self->frames, self->framesLength, time, 1) - 1;
|
||||
|
||||
const char* attachmentName = self->attachmentNames[frameIndex];
|
||||
Slot_setAttachment(skeleton->slots[self->slotIndex],
|
||||
@ -398,7 +398,7 @@ void _AttachmentTimeline_dispose (Timeline* timeline) {
|
||||
AttachmentTimeline* self = (AttachmentTimeline*)timeline;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < self->frameCount; ++i)
|
||||
for (i = 0; i < self->framesLength; ++i)
|
||||
FREE(self->attachmentNames[i])
|
||||
FREE(self->attachmentNames)
|
||||
|
||||
@ -412,7 +412,7 @@ AttachmentTimeline* AttachmentTimeline_create (int frameCount) {
|
||||
((Timeline*)self)->_apply = _AttachmentTimeline_apply;
|
||||
CAST(char**, self->attachmentNames) = CALLOC(char*, frameCount)
|
||||
|
||||
CAST(int, self->frameCount) = frameCount;
|
||||
CAST(int, self->framesLength) = frameCount;
|
||||
CAST(float*, self->frames) = CALLOC(float, frameCount)
|
||||
|
||||
return self;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/util.h>
|
||||
#include <spine/Slot.h>
|
||||
|
||||
void _Attachment_init (Attachment* self, const char* name, int type) {
|
||||
MALLOC_STR(self->name, name);
|
||||
@ -14,3 +15,7 @@ void _Attachment_deinit (Attachment* self) {
|
||||
void Attachment_dispose (Attachment* self) {
|
||||
self->_dispose(self);
|
||||
}
|
||||
|
||||
void Attachment_draw (Attachment* self, Slot* slot) {
|
||||
self->_draw(self, slot);
|
||||
}
|
||||
|
||||
@ -57,25 +57,25 @@ typedef struct Json {
|
||||
} Json;
|
||||
|
||||
/* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */
|
||||
extern Json* Json_create (const char* value);
|
||||
Json* Json_create (const char* value);
|
||||
|
||||
/* Delete a Json entity and all subentities. */
|
||||
extern void Json_dispose (Json* json);
|
||||
void Json_dispose (Json* json);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
extern int Json_getSize (Json* json);
|
||||
int Json_getSize (Json* json);
|
||||
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
extern Json* Json_getItemAt (Json* json, int item);
|
||||
Json* Json_getItemAt (Json* json, int item);
|
||||
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
extern Json* Json_getItem (Json* json, const char* string);
|
||||
extern const char* Json_getString (Json* json, const char* name, const char* defaultValue);
|
||||
extern float Json_getFloat (Json* json, const char* name, float defaultValue);
|
||||
extern int Json_getInt (Json* json, const char* name, int defaultValue);
|
||||
Json* Json_getItem (Json* json, const char* string);
|
||||
const char* Json_getString (Json* json, const char* name, const char* defaultValue);
|
||||
float Json_getFloat (Json* json, const char* name, float defaultValue);
|
||||
int Json_getInt (Json* json, const char* name, int defaultValue);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */
|
||||
extern const char* Json_getError (void);
|
||||
const char* Json_getError (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -41,6 +41,11 @@ void _Skeleton_init (Skeleton* self, SkeletonData* data) {
|
||||
|
||||
self->drawOrder = MALLOC(Slot*, self->slotCount)
|
||||
memcpy(self->drawOrder, self->slots, sizeof(Slot*) * self->slotCount);
|
||||
|
||||
self->r = 1;
|
||||
self->g = 1;
|
||||
self->b = 1;
|
||||
self->a = 1;
|
||||
}
|
||||
|
||||
void _Skeleton_deinit (Skeleton* self) {
|
||||
|
||||
@ -31,46 +31,41 @@ using namespace std;
|
||||
using namespace spine;
|
||||
|
||||
int main () {
|
||||
Atlas* atlas = Atlas_readAtlasFile("../data/spineboy.atlas");
|
||||
SkeletonJson* json = SkeletonJson_create(atlas);
|
||||
SkeletonData *skeletonData = SkeletonJson_readSkeletonDataFile(json, "../data/spineboy-skeleton.json");
|
||||
Animation* animation = SkeletonJson_readAnimationFile(json, "../data/spineboy-walk.json", skeletonData);
|
||||
SkeletonJson_dispose(json);
|
||||
|
||||
try {
|
||||
Atlas* atlas = Atlas_readAtlasFile("../data/spineboy.atlas");
|
||||
SkeletonJson* json = SkeletonJson_create(atlas);
|
||||
SkeletonData *skeletonData = SkeletonJson_readSkeletonDataFile(json, "../data/spineboy-skeleton.json");
|
||||
Animation* animation = SkeletonJson_readAnimationFile(json, "../data/spineboy-walk.json", skeletonData);
|
||||
SkeletonJson_dispose(json);
|
||||
Skeleton* skeleton = Skeleton_create(skeletonData);
|
||||
skeleton->flipX = false;
|
||||
skeleton->flipY = false;
|
||||
Skeleton_setToBindPose(skeleton);
|
||||
Skeleton_getRootBone(skeleton)->x = 320;
|
||||
Skeleton_getRootBone(skeleton)->y = 420;
|
||||
Skeleton_updateWorldTransform(skeleton);
|
||||
|
||||
Skeleton* skeleton = Skeleton_create(skeletonData);
|
||||
skeleton->flipX = false;
|
||||
skeleton->flipY = false;
|
||||
Skeleton_setToBindPose(skeleton);
|
||||
Skeleton_getRootBone(skeleton)->x = 320;
|
||||
Skeleton_getRootBone(skeleton)->y = 420;
|
||||
sf::RenderWindow window(sf::VideoMode(640, 480), "Spine SFML");
|
||||
window.setFramerateLimit(60);
|
||||
sf::Event event;
|
||||
sf::Clock deltaClock;
|
||||
float animationTime = 0;
|
||||
while (window.isOpen()) {
|
||||
while (window.pollEvent(event))
|
||||
if (event.type == sf::Event::Closed) window.close();
|
||||
window.clear();
|
||||
window.draw(Skeleton_getDrawable(skeleton));
|
||||
window.display();
|
||||
|
||||
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||
deltaClock.restart();
|
||||
animationTime += delta;
|
||||
|
||||
Animation_apply(animation, skeleton, animationTime, true);
|
||||
Skeleton_updateWorldTransform(skeleton);
|
||||
|
||||
sf::RenderWindow window(sf::VideoMode(640, 480), "Spine SFML");
|
||||
window.setFramerateLimit(60);
|
||||
sf::Event event;
|
||||
sf::Clock deltaClock;
|
||||
float animationTime = 0;
|
||||
while (window.isOpen()) {
|
||||
while (window.pollEvent(event))
|
||||
if (event.type == sf::Event::Closed) window.close();
|
||||
window.clear();
|
||||
window.draw(Skeleton_getDrawable(skeleton));
|
||||
window.display();
|
||||
|
||||
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||
deltaClock.restart();
|
||||
animationTime += delta;
|
||||
|
||||
Animation_apply(animation, skeleton, animationTime, true);
|
||||
Skeleton_updateWorldTransform(skeleton);
|
||||
}
|
||||
|
||||
Skeleton_dispose(skeleton);
|
||||
SkeletonData_dispose(skeletonData);
|
||||
Atlas_dispose(atlas);
|
||||
} catch (exception &ex) {
|
||||
cout << ex.what() << endl << flush;
|
||||
}
|
||||
|
||||
Skeleton_dispose(skeleton);
|
||||
SkeletonData_dispose(skeletonData);
|
||||
Atlas_dispose(atlas);
|
||||
}
|
||||
|
||||
@ -49,6 +49,8 @@ void _SfmlSkeleton_dispose (Skeleton* skeleton) {
|
||||
}
|
||||
|
||||
Skeleton* Skeleton_create (SkeletonData* data) {
|
||||
Bone_setYDown(1);
|
||||
|
||||
SfmlSkeleton* self = CALLOC(SfmlSkeleton, 1)
|
||||
_Skeleton_init(&self->super, data);
|
||||
self->super._dispose = _SfmlSkeleton_dispose;
|
||||
@ -63,15 +65,14 @@ SkeletonDrawable& Skeleton_getDrawable (const Skeleton* self) {
|
||||
return *((SfmlSkeleton*)self)->drawable;
|
||||
}
|
||||
|
||||
SkeletonDrawable::SkeletonDrawable (Skeleton* self) {
|
||||
skeleton = (SfmlSkeleton*)self;
|
||||
SkeletonDrawable::SkeletonDrawable (Skeleton* self) :
|
||||
skeleton((SfmlSkeleton*)self) {
|
||||
}
|
||||
|
||||
void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
|
||||
skeleton->vertexArray->clear();
|
||||
for (int i = 0; i < skeleton->super.slotCount; ++i)
|
||||
if (skeleton->super.slots[i]->attachment) ; //skeleton->slots[i]->attachment->draw(slots[i]);
|
||||
// BOZO - Draw the slots!
|
||||
if (skeleton->super.slots[i]->attachment) Attachment_draw(skeleton->super.slots[i]->attachment, skeleton->super.slots[i]);
|
||||
states.texture = skeleton->texture;
|
||||
target.draw(*skeleton->vertexArray, states);
|
||||
}
|
||||
@ -83,40 +84,8 @@ void _SfmlRegionAttachment_dispose (Attachment* self) {
|
||||
FREE(self)
|
||||
}
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region) {
|
||||
SfmlRegionAttachment* self = CALLOC(SfmlRegionAttachment, 1)
|
||||
_RegionAttachment_init(&self->super, name);
|
||||
self->super.super._dispose = _SfmlRegionAttachment_dispose;
|
||||
|
||||
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 &self->super;
|
||||
}
|
||||
|
||||
void _RegionAttachment_draw (SfmlRegionAttachment* self, Slot* slot) {
|
||||
void _SfmlRegionAttachment_draw (Attachment* attachment, Slot* slot) {
|
||||
SfmlRegionAttachment* self = (SfmlRegionAttachment*)attachment;
|
||||
SfmlSkeleton* skeleton = (SfmlSkeleton*)slot->skeleton;
|
||||
Uint8 r = skeleton->super.r * slot->r * 255;
|
||||
Uint8 g = skeleton->super.g * slot->g * 255;
|
||||
@ -159,4 +128,38 @@ void _RegionAttachment_draw (SfmlRegionAttachment* self, Slot* slot) {
|
||||
skeleton->vertexArray->append(vertices[3]);
|
||||
}
|
||||
|
||||
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region) {
|
||||
SfmlRegionAttachment* self = CALLOC(SfmlRegionAttachment, 1)
|
||||
_RegionAttachment_init(&self->super, name);
|
||||
self->super.super._dispose = _SfmlRegionAttachment_dispose;
|
||||
self->super.super._draw = _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 &self->super;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user