瀏覽代碼

Better AnimationState listeners, including on a TrackEntry.

NathanSweet 11 年之前
父節點
當前提交
7199d22417

+ 2 - 0
spine-c/include/spine/AnimationState.h

@@ -57,6 +57,8 @@ struct spTrackEntry {
 	float delay, time, lastTime, endTime, timeScale;
 	float delay, time, lastTime, endTime, timeScale;
 	spAnimationStateListener listener;
 	spAnimationStateListener listener;
 	float mixTime, mixDuration, mix;
 	float mixTime, mixDuration, mix;
+
+	void* rendererObject;
 };
 };
 
 
 struct spAnimationState {
 struct spAnimationState {

+ 8 - 0
spine-c/include/spine/extension.h

@@ -74,6 +74,7 @@
 #include <spine/MeshAttachment.h>
 #include <spine/MeshAttachment.h>
 #include <spine/SkinnedMeshAttachment.h>
 #include <spine/SkinnedMeshAttachment.h>
 #include <spine/BoundingBoxAttachment.h>
 #include <spine/BoundingBoxAttachment.h>
+#include <spine/AnimationState.h>
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
@@ -86,6 +87,8 @@ extern "C" {
 void _spAtlasPage_createTexture (spAtlasPage* self, const char* path);
 void _spAtlasPage_createTexture (spAtlasPage* self, const char* path);
 void _spAtlasPage_disposeTexture (spAtlasPage* self);
 void _spAtlasPage_disposeTexture (spAtlasPage* self);
 char* _spUtil_readFile (const char* path, int* length);
 char* _spUtil_readFile (const char* path, int* length);
+spTrackEntry* _spAnimationState_createTrackEntry (spAnimationState* self);
+void _spAnimationState_disposeTrackEntry (spAnimationState* self, spTrackEntry* entry);
 
 
 #ifdef SPINE_SHORT_NAMES
 #ifdef SPINE_SHORT_NAMES
 #define _AtlasPage_createTexture(...) _spAtlasPage_createTexture(__VA_ARGS__)
 #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 _spAttachmentLoader_init (spAttachmentLoader* self, /**/
 void (*dispose) (spAttachmentLoader* self), /**/
 void (*dispose) (spAttachmentLoader* self), /**/
 		spAttachment* (*newAttachment) (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name,
 		spAttachment* (*newAttachment) (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name,

+ 17 - 17
spine-c/src/spine/AnimationState.c

@@ -45,14 +45,6 @@ void _spTrackEntry_dispose (spTrackEntry* entry) {
 	FREE(entry);
 	FREE(entry);
 }
 }
 
 
-void _spTrackEntry_disposeAll (spTrackEntry* entry) {
-	while (entry) {
-		spTrackEntry* next = entry->next;
-		_spTrackEntry_dispose(entry);
-		entry = next;
-	}
-}
-
 /**/
 /**/
 
 
 typedef struct {
 typedef struct {
@@ -71,12 +63,20 @@ spAnimationState* spAnimationState_create (spAnimationStateData* data) {
 	return self;
 	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) {
 void spAnimationState_dispose (spAnimationState* self) {
 	int i;
 	int i;
 	_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
 	_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
 	FREE(internal->events);
 	FREE(internal->events);
 	for (i = 0; i < self->trackCount; ++i)
 	for (i = 0; i < self->trackCount; ++i)
-		_spTrackEntry_disposeAll(self->tracks[i]);
+		_spAnimationState_disposeAllEntries(self, self->tracks[i]);
 	FREE(self->tracks);
 	FREE(self->tracks);
 	FREE(self);
 	FREE(self);
 }
 }
@@ -140,7 +140,7 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
 
 
 			if (alpha >= 1) {
 			if (alpha >= 1) {
 				alpha = 1;
 				alpha = 1;
-				_spTrackEntry_dispose(current->previous);
+				_spAnimationState_disposeTrackEntry(self, current->previous);
 				current->previous = 0;
 				current->previous = 0;
 			}
 			}
 			spAnimation_mix(current->animation, skeleton, current->lastTime, time,
 			spAnimation_mix(current->animation, skeleton, current->lastTime, time,
@@ -203,8 +203,8 @@ void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) {
 
 
 	self->tracks[trackIndex] = 0;
 	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) {
 spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index) {
@@ -237,9 +237,9 @@ void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEnt
 			} else
 			} else
 				entry->previous = current;
 				entry->previous = current;
 		} else
 		} else
-			_spTrackEntry_dispose(current);
+			_spAnimationState_disposeTrackEntry(self, current);
 
 
-		if (previous) _spTrackEntry_dispose(previous);
+		if (previous) _spAnimationState_disposeTrackEntry(self, previous);
 	}
 	}
 
 
 	self->tracks[index] = entry;
 	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* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop) {
 	spTrackEntry* entry;
 	spTrackEntry* entry;
 	spTrackEntry* current = _spAnimationState_expandToIndex(self, trackIndex);
 	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->animation = animation;
 	entry->loop = loop;
 	entry->loop = loop;
 	entry->endTime = animation->duration;
 	entry->endTime = animation->duration;
@@ -280,7 +280,7 @@ spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIn
 		float delay) {
 		float delay) {
 	spTrackEntry* last;
 	spTrackEntry* last;
 
 
-	spTrackEntry* entry = _spTrackEntry_create();
+	spTrackEntry* entry = _spAnimationState_createTrackEntry(self);
 	entry->animation = animation;
 	entry->animation = animation;
 	entry->loop = loop;
 	entry->loop = loop;
 	entry->endTime = animation->duration;
 	entry->endTime = animation->duration;

+ 22 - 25
spine-cocos2dx/example/Classes/ExampleLayer.cpp

@@ -47,16 +47,34 @@ bool ExampleLayer::init () {
 	if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false;
 	if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false;
 
 
 	skeletonNode = SkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas", 0.6f);
 	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->timeScale = 0.3f;
 	skeletonNode->debugBones = true;
 	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->setAnimation(0, "walk", true);
-	skeletonNode->addAnimation(0, "jump", false, 3);
+	spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 3);
 	skeletonNode->addAnimation(0, "run", true);
 	skeletonNode->addAnimation(0, "run", true);
 
 
+	skeletonNode->setStartListener(jumpEntry, [](int trackIndex) {
+		log("jumped!", trackIndex);
+	});
+
 	// skeletonNode->addAnimation(1, "test", true);
 	// skeletonNode->addAnimation(1, "test", true);
 	// skeletonNode->runAction(RepeatForever::create(Sequence::create(FadeOut::create(1), FadeIn::create(1), DelayTime::create(5), NULL)));
 	// 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.
 	// Test releasing memory.
 	// Director::getInstance()->replaceScene(ExampleLayer::scene());
 	// 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);
-}

+ 0 - 2
spine-cocos2dx/example/Classes/ExampleLayer.h

@@ -44,8 +44,6 @@ public:
 	CREATE_FUNC (ExampleLayer);
 	CREATE_FUNC (ExampleLayer);
 private:
 private:
 	spine::SkeletonAnimation* skeletonNode;
 	spine::SkeletonAnimation* skeletonNode;
-
-	void animationStateEvent (spine::SkeletonAnimation* node, int trackIndex, spEventType type, spEvent* event, int loopCount);
 };
 };
 
 
 #endif // _EXAMPLELAYER_H_
 #endif // _EXAMPLELAYER_H_

+ 68 - 7
spine-cocos2dx/src/spine/SkeletonAnimation.cpp

@@ -40,8 +40,12 @@ using std::vector;
 
 
 namespace spine {
 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) {
 SkeletonAnimation* SkeletonAnimation::createWithData (spSkeletonData* skeletonData) {
@@ -65,8 +69,8 @@ SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFi
 void SkeletonAnimation::initialize () {
 void SkeletonAnimation::initialize () {
 	ownsAnimationStateData = true;
 	ownsAnimationStateData = true;
 	state = spAnimationState_create(spAnimationStateData_create(skeleton->data));
 	state = spAnimationState_create(spAnimationStateData_create(skeleton->data));
-	state->context = this;
-	state->listener = callback;
+	state->rendererObject = this;
+	state->listener = animationCallback;
 }
 }
 
 
 SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData)
 SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData)
@@ -106,8 +110,8 @@ void SkeletonAnimation::setAnimationStateData (spAnimationStateData* stateData)
 
 
 	ownsAnimationStateData = false;
 	ownsAnimationStateData = false;
 	state = spAnimationState_create(stateData);
 	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) {
 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) {
 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;
 }
 }
 
 
 }
 }

+ 21 - 8
spine-cocos2dx/src/spine/SkeletonAnimation.h

@@ -37,8 +37,17 @@
 
 
 namespace spine {
 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
 /** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be
   * played later. */
   * played later. */
@@ -61,25 +70,29 @@ public:
 	void setAnimationStateData (spAnimationStateData* stateData);
 	void setAnimationStateData (spAnimationStateData* stateData);
 	void setMix (const char* fromAnimation, const char* toAnimation, float duration);
 	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* setAnimation (int trackIndex, const char* name, bool loop);
 	spTrackEntry* addAnimation (int trackIndex, const char* name, bool loop, float delay = 0);
 	spTrackEntry* addAnimation (int trackIndex, const char* name, bool loop, float delay = 0);
 	spTrackEntry* getCurrent (int trackIndex = 0);
 	spTrackEntry* getCurrent (int trackIndex = 0);
 	void clearTracks ();
 	void clearTracks ();
 	void clearTrack (int trackIndex = 0);
 	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 onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
+	virtual void onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
 
 
 protected:
 protected:
 	SkeletonAnimation ();
 	SkeletonAnimation ();
 
 
 private:
 private:
 	typedef SkeletonRenderer super;
 	typedef SkeletonRenderer super;
-	AnimationStateListener listener;
 	bool ownsAnimationStateData;
 	bool ownsAnimationStateData;
 
 
 	void initialize ();
 	void initialize ();

+ 13 - 0
spine-cocos2dx/src/spine/spine-cocos2dx.cpp

@@ -55,8 +55,19 @@ char* _spUtil_readFile (const char* path, int* length) {
 	return bytes;
 	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) {
 void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, V3F_C4B_T2F_Quad* quad, bool premultipliedAlpha) {
 	float vertices[8];
 	float vertices[8];
 	spRegionAttachment_computeWorldVertices(self, slot->skeleton->x, slot->skeleton->y, slot->bone, vertices);
 	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.u = self->uvs[SP_VERTEX_X4];
 	quad->br.texCoords.v = self->uvs[SP_VERTEX_Y4];
 	quad->br.texCoords.v = self->uvs[SP_VERTEX_Y4];
 }
 }
+
+}

+ 4 - 0
spine-cocos2dx/src/spine/spine-cocos2dx.h

@@ -36,6 +36,10 @@
 #include <spine/SkeletonRenderer.h>
 #include <spine/SkeletonRenderer.h>
 #include <spine/SkeletonAnimation.h>
 #include <spine/SkeletonAnimation.h>
 
 
+namespace spine {
+
 void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, cocos2d::V3F_C4B_T2F_Quad* quad, bool premultiplied = false);
 void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, cocos2d::V3F_C4B_T2F_Quad* quad, bool premultiplied = false);
 
 
+}
+
 #endif /* SPINE_COCOS2DX_H_ */
 #endif /* SPINE_COCOS2DX_H_ */