mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 23:34:53 +08:00
Better AnimationState listeners, including on a TrackEntry.
This commit is contained in:
parent
cd7538d6a1
commit
7199d22417
@ -57,6 +57,8 @@ struct spTrackEntry {
|
||||
float delay, time, lastTime, endTime, timeScale;
|
||||
spAnimationStateListener listener;
|
||||
float mixTime, mixDuration, mix;
|
||||
|
||||
void* rendererObject;
|
||||
};
|
||||
|
||||
struct spAnimationState {
|
||||
|
||||
@ -74,6 +74,7 @@
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/SkinnedMeshAttachment.h>
|
||||
#include <spine/BoundingBoxAttachment.h>
|
||||
#include <spine/AnimationState.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -86,6 +87,8 @@ extern "C" {
|
||||
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path);
|
||||
void _spAtlasPage_disposeTexture (spAtlasPage* self);
|
||||
char* _spUtil_readFile (const char* path, int* length);
|
||||
spTrackEntry* _spAnimationState_createTrackEntry (spAnimationState* self);
|
||||
void _spAnimationState_disposeTrackEntry (spAnimationState* self, spTrackEntry* entry);
|
||||
|
||||
#ifdef SPINE_SHORT_NAMES
|
||||
#define _AtlasPage_createTexture(...) _spAtlasPage_createTexture(__VA_ARGS__)
|
||||
@ -109,6 +112,11 @@ char* _readFile (const char* path, int* length);
|
||||
|
||||
/**/
|
||||
|
||||
spTrackEntry* _spTrackEntry_create ();
|
||||
void _spTrackEntry_dispose (spTrackEntry* entry);
|
||||
|
||||
/**/
|
||||
|
||||
void _spAttachmentLoader_init (spAttachmentLoader* self, /**/
|
||||
void (*dispose) (spAttachmentLoader* self), /**/
|
||||
spAttachment* (*newAttachment) (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name,
|
||||
|
||||
@ -45,14 +45,6 @@ void _spTrackEntry_dispose (spTrackEntry* entry) {
|
||||
FREE(entry);
|
||||
}
|
||||
|
||||
void _spTrackEntry_disposeAll (spTrackEntry* entry) {
|
||||
while (entry) {
|
||||
spTrackEntry* next = entry->next;
|
||||
_spTrackEntry_dispose(entry);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
typedef struct {
|
||||
@ -71,12 +63,20 @@ spAnimationState* spAnimationState_create (spAnimationStateData* data) {
|
||||
return self;
|
||||
}
|
||||
|
||||
void _spAnimationState_disposeAllEntries (spAnimationState* self, spTrackEntry* entry) {
|
||||
while (entry) {
|
||||
spTrackEntry* next = entry->next;
|
||||
_spAnimationState_disposeTrackEntry(self, entry);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
void spAnimationState_dispose (spAnimationState* self) {
|
||||
int i;
|
||||
_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
|
||||
FREE(internal->events);
|
||||
for (i = 0; i < self->trackCount; ++i)
|
||||
_spTrackEntry_disposeAll(self->tracks[i]);
|
||||
_spAnimationState_disposeAllEntries(self, self->tracks[i]);
|
||||
FREE(self->tracks);
|
||||
FREE(self);
|
||||
}
|
||||
@ -140,7 +140,7 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
|
||||
|
||||
if (alpha >= 1) {
|
||||
alpha = 1;
|
||||
_spTrackEntry_dispose(current->previous);
|
||||
_spAnimationState_disposeTrackEntry(self, current->previous);
|
||||
current->previous = 0;
|
||||
}
|
||||
spAnimation_mix(current->animation, skeleton, current->lastTime, time,
|
||||
@ -203,8 +203,8 @@ void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) {
|
||||
|
||||
self->tracks[trackIndex] = 0;
|
||||
|
||||
if (current->previous) _spTrackEntry_dispose(current->previous);
|
||||
_spTrackEntry_disposeAll(current);
|
||||
if (current->previous) _spAnimationState_disposeTrackEntry(self, current->previous);
|
||||
_spAnimationState_disposeAllEntries(self, current);
|
||||
}
|
||||
|
||||
spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index) {
|
||||
@ -237,9 +237,9 @@ void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEnt
|
||||
} else
|
||||
entry->previous = current;
|
||||
} else
|
||||
_spTrackEntry_dispose(current);
|
||||
_spAnimationState_disposeTrackEntry(self, current);
|
||||
|
||||
if (previous) _spTrackEntry_dispose(previous);
|
||||
if (previous) _spAnimationState_disposeTrackEntry(self, previous);
|
||||
}
|
||||
|
||||
self->tracks[index] = entry;
|
||||
@ -260,9 +260,9 @@ spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int t
|
||||
spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop) {
|
||||
spTrackEntry* entry;
|
||||
spTrackEntry* current = _spAnimationState_expandToIndex(self, trackIndex);
|
||||
if (current) _spTrackEntry_disposeAll(current->next);
|
||||
if (current) _spAnimationState_disposeAllEntries(self, current->next);
|
||||
|
||||
entry = _spTrackEntry_create();
|
||||
entry = _spAnimationState_createTrackEntry(self);
|
||||
entry->animation = animation;
|
||||
entry->loop = loop;
|
||||
entry->endTime = animation->duration;
|
||||
@ -280,7 +280,7 @@ spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIn
|
||||
float delay) {
|
||||
spTrackEntry* last;
|
||||
|
||||
spTrackEntry* entry = _spTrackEntry_create();
|
||||
spTrackEntry* entry = _spAnimationState_createTrackEntry(self);
|
||||
entry->animation = animation;
|
||||
entry->loop = loop;
|
||||
entry->endTime = animation->duration;
|
||||
|
||||
@ -47,16 +47,34 @@ bool ExampleLayer::init () {
|
||||
if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false;
|
||||
|
||||
skeletonNode = SkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas", 0.6f);
|
||||
skeletonNode->setMix("walk", "jump", 0.2f);
|
||||
skeletonNode->setMix("jump", "run", 0.2f);
|
||||
skeletonNode->setAnimationListener(&ExampleLayer::animationStateEvent, this);
|
||||
// skeletonNode->timeScale = 0.3f;
|
||||
skeletonNode->debugBones = true;
|
||||
|
||||
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);
|
||||
skeletonNode->addAnimation(0, "jump", false, 3);
|
||||
spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 3);
|
||||
skeletonNode->addAnimation(0, "run", true);
|
||||
|
||||
skeletonNode->setStartListener(jumpEntry, [](int trackIndex) {
|
||||
log("jumped!", trackIndex);
|
||||
});
|
||||
|
||||
// skeletonNode->addAnimation(1, "test", true);
|
||||
// skeletonNode->runAction(RepeatForever::create(Sequence::create(FadeOut::create(1), FadeIn::create(1), DelayTime::create(5), NULL)));
|
||||
|
||||
@ -73,24 +91,3 @@ void ExampleLayer::update (float deltaTime) {
|
||||
// Test releasing memory.
|
||||
// Director::getInstance()->replaceScene(ExampleLayer::scene());
|
||||
}
|
||||
|
||||
void ExampleLayer::animationStateEvent (SkeletonAnimation* node, int trackIndex, spEventType type, spEvent* event, int loopCount) {
|
||||
spTrackEntry* entry = spAnimationState_getCurrent(node->state, trackIndex);
|
||||
const char* animationName = (entry && entry->animation) ? entry->animation->name : 0;
|
||||
|
||||
switch (type) {
|
||||
case SP_ANIMATION_START:
|
||||
log("%d start: %s", trackIndex, animationName);
|
||||
break;
|
||||
case SP_ANIMATION_END:
|
||||
log("%d end: %s", trackIndex, animationName);
|
||||
break;
|
||||
case SP_ANIMATION_COMPLETE:
|
||||
log("%d complete: %s, %d", trackIndex, animationName, loopCount);
|
||||
break;
|
||||
case SP_ANIMATION_EVENT:
|
||||
log("%d event: %s, %s: %d, %f, %s", trackIndex, animationName, event->data->name, event->intValue, event->floatValue, event->stringValue);
|
||||
break;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
@ -44,8 +44,6 @@ public:
|
||||
CREATE_FUNC (ExampleLayer);
|
||||
private:
|
||||
spine::SkeletonAnimation* skeletonNode;
|
||||
|
||||
void animationStateEvent (spine::SkeletonAnimation* node, int trackIndex, spEventType type, spEvent* event, int loopCount);
|
||||
};
|
||||
|
||||
#endif // _EXAMPLELAYER_H_
|
||||
@ -40,8 +40,12 @@ using std::vector;
|
||||
|
||||
namespace spine {
|
||||
|
||||
static void callback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) {
|
||||
((SkeletonAnimation*)state->context)->onAnimationStateEvent(trackIndex, type, event, loopCount);
|
||||
static void animationCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) {
|
||||
((SkeletonAnimation*)state->rendererObject)->onAnimationStateEvent(trackIndex, type, event, loopCount);
|
||||
}
|
||||
|
||||
static void trackEntryCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) {
|
||||
((SkeletonAnimation*)state->rendererObject)->onTrackEntryEvent(trackIndex, type, event, loopCount);
|
||||
}
|
||||
|
||||
SkeletonAnimation* SkeletonAnimation::createWithData (spSkeletonData* skeletonData) {
|
||||
@ -65,8 +69,8 @@ SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFi
|
||||
void SkeletonAnimation::initialize () {
|
||||
ownsAnimationStateData = true;
|
||||
state = spAnimationState_create(spAnimationStateData_create(skeleton->data));
|
||||
state->context = this;
|
||||
state->listener = callback;
|
||||
state->rendererObject = this;
|
||||
state->listener = animationCallback;
|
||||
}
|
||||
|
||||
SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData)
|
||||
@ -106,8 +110,8 @@ void SkeletonAnimation::setAnimationStateData (spAnimationStateData* stateData)
|
||||
|
||||
ownsAnimationStateData = false;
|
||||
state = spAnimationState_create(stateData);
|
||||
state->context = this;
|
||||
state->listener = callback;
|
||||
state->rendererObject = this;
|
||||
state->listener = animationCallback;
|
||||
}
|
||||
|
||||
void SkeletonAnimation::setMix (const char* fromAnimation, const char* toAnimation, float duration) {
|
||||
@ -145,7 +149,64 @@ void SkeletonAnimation::clearTrack (int trackIndex) {
|
||||
}
|
||||
|
||||
void SkeletonAnimation::onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) {
|
||||
if (listener) listener(this, trackIndex, type, event, 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;
|
||||
}
|
||||
}
|
||||
|
||||
static _TrackEntryListeners* getListeners (spTrackEntry* entry) {
|
||||
if (!entry->rendererObject) {
|
||||
entry->rendererObject = NEW(spine::_TrackEntryListeners);
|
||||
entry->listener = trackEntryCallback;
|
||||
}
|
||||
return (_TrackEntryListeners*)entry->rendererObject;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -37,8 +37,17 @@
|
||||
|
||||
namespace spine {
|
||||
|
||||
class SkeletonAnimation;
|
||||
typedef std::function<void(spine::SkeletonAnimation* node, int trackIndex, spEventType type, spEvent* event, int loopCount)> AnimationStateListener;
|
||||
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;
|
||||
|
||||
typedef struct _TrackEntryListeners {
|
||||
StartListener startListener;
|
||||
EndListener endListener;
|
||||
CompleteListener completeListener;
|
||||
EventListener eventListener;
|
||||
} _TrackEntryListeners;
|
||||
|
||||
/** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be
|
||||
* played later. */
|
||||
@ -61,25 +70,29 @@ public:
|
||||
void setAnimationStateData (spAnimationStateData* stateData);
|
||||
void setMix (const char* fromAnimation, const char* toAnimation, float duration);
|
||||
|
||||
template<class _Rx, class _Farg0, class _Arg0> void setAnimationListener (_Rx _Farg0::* const type, _Arg0&& target) {
|
||||
using namespace std::placeholders;
|
||||
this->listener = std::bind(type, target, _1, _2, _3, _4, _5);
|
||||
}
|
||||
|
||||
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;
|
||||
AnimationStateListener listener;
|
||||
bool ownsAnimationStateData;
|
||||
|
||||
void initialize ();
|
||||
|
||||
@ -55,8 +55,19 @@ char* _spUtil_readFile (const char* path, int* length) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
spTrackEntry* _spAnimationState_createTrackEntry (spAnimationState* self) {
|
||||
return _spTrackEntry_create();
|
||||
}
|
||||
|
||||
void _spAnimationState_disposeTrackEntry (spAnimationState* self, spTrackEntry* entry) {
|
||||
if (entry->rendererObject) FREE(entry->rendererObject);
|
||||
_spTrackEntry_dispose(entry);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
namespace spine {
|
||||
|
||||
void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, V3F_C4B_T2F_Quad* quad, bool premultipliedAlpha) {
|
||||
float vertices[8];
|
||||
spRegionAttachment_computeWorldVertices(self, slot->skeleton->x, slot->skeleton->y, slot->bone, vertices);
|
||||
@ -106,3 +117,5 @@ void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, V3F_
|
||||
quad->br.texCoords.u = self->uvs[SP_VERTEX_X4];
|
||||
quad->br.texCoords.v = self->uvs[SP_VERTEX_Y4];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -36,6 +36,10 @@
|
||||
#include <spine/SkeletonRenderer.h>
|
||||
#include <spine/SkeletonAnimation.h>
|
||||
|
||||
namespace spine {
|
||||
|
||||
void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, cocos2d::V3F_C4B_T2F_Quad* quad, bool premultiplied = false);
|
||||
|
||||
}
|
||||
|
||||
#endif /* SPINE_COCOS2DX_H_ */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user