Merge pull request #13770 from geron-cn/v3

add  Frame End Call Back and Animation Clip End Call Back
This commit is contained in:
pandamicro 2015-09-19 00:24:21 +08:00
commit 6bf54a3eda
4 changed files with 189 additions and 10 deletions

View File

@ -207,6 +207,7 @@ void ActionTimeline::step(float delta)
{
_currentFrame = (int)(_time / _frameInternal);
stepToFrame(_currentFrame);
emitFrameEndCallFuncs(_currentFrame);
if (endtoffset >= 0 && _lastFrameListener != nullptr) // last frame
_lastFrameListener();
}
@ -220,6 +221,7 @@ void ActionTimeline::step(float delta)
{
_currentFrame = _endFrame;
stepToFrame(_currentFrame);
emitFrameEndCallFuncs(_currentFrame);
if (_lastFrameListener != nullptr) // last frame
_lastFrameListener();
}
@ -306,16 +308,20 @@ void ActionTimeline::addAnimationInfo(const AnimationInfo& animationInfo)
}
_animationInfos[animationInfo.name] = animationInfo;
addFrameEndCallFunc(animationInfo.endIndex, animationInfo.name, animationInfo.clipEndCallBack);
}
void ActionTimeline::removeAnimationInfo(std::string animationName)
{
if (_animationInfos.find(animationName) == _animationInfos.end())
auto clipIter = _animationInfos.find(animationName);
if (clipIter == _animationInfos.end())
{
CCLOG("AnimationInfo (%s) not exists.", animationName.c_str());
return;
}
auto clipEndCall = (*clipIter).second.clipEndCallBack;
removeFrameEndCall((*clipIter).second.endIndex, animationName);
_animationInfos.erase(animationName);
}
@ -324,11 +330,23 @@ bool ActionTimeline::IsAnimationInfoExists(const std::string& animationName)
return _animationInfos.find(animationName) != _animationInfos.end();
}
AnimationInfo ActionTimeline::getAnimationInfo(const std::string &animationName)
const AnimationInfo& ActionTimeline::getAnimationInfo(const std::string &animationName)
{
return _animationInfos.find(animationName)->second;
}
void ActionTimeline::setAnimationEndCallBack(const std::string animationName, std::function<void()> func)
{
auto clipIter = _animationInfos.find(animationName);
if (clipIter == _animationInfos.end())
{
CCLOG("AnimationInfo (%s) not exists.", animationName.c_str());
return;
}
clipIter->second.clipEndCallBack = func;
addFrameEndCallFunc(clipIter->second.endIndex, animationName, func);
}
void ActionTimeline::setFrameEventCallFunc(std::function<void(Frame *)> listener)
{
_frameEventListener = listener;
@ -357,6 +375,52 @@ void ActionTimeline::emitFrameEvent(Frame* frame)
}
}
void ActionTimeline::addFrameEndCallFunc(int frameIndex, const std::string& funcKey, std::function<void()> func)
{
if (func != nullptr)
{
_frameEndCallFuncs[frameIndex][funcKey] = func;
}
}
void ActionTimeline::removeFrameEndCall(int frameIndex, const std::string& funcKey)
{
auto endClipCallsIter = _frameEndCallFuncs.find(frameIndex);
if (endClipCallsIter != _frameEndCallFuncs.end())
{
auto funcIter = (*endClipCallsIter).second.find(funcKey);
if (funcIter != (*endClipCallsIter).second.end())
(*endClipCallsIter).second.erase(funcKey);
if ((*endClipCallsIter).second.empty())
_frameEndCallFuncs.erase(endClipCallsIter);
}
}
void ActionTimeline::removeFrameEndCall(int frameIndex)
{
auto endClipCallsIter = _frameEndCallFuncs.find(frameIndex);
if (endClipCallsIter != _frameEndCallFuncs.end())
{
_frameEndCallFuncs.erase(endClipCallsIter);
}
}
void ActionTimeline::clearFrameEndCalls()
{
_frameEndCallFuncs.clear();
}
void ActionTimeline::emitFrameEndCallFuncs(int frameIndex)
{
auto clipEndCallsIter = _frameEndCallFuncs.find(frameIndex);
if (clipEndCallsIter != _frameEndCallFuncs.end())
{
auto clipEndCalls = (*clipEndCallsIter).second;
for (auto call : clipEndCalls)
(call).second();
}
}
void ActionTimeline::gotoFrame(int frameIndex)
{
if(_target == nullptr)
@ -377,4 +441,5 @@ void ActionTimeline::stepToFrame(int frameIndex)
_timelineList.at(i)->stepToFrame(frameIndex);
}
}
NS_TIMELINE_END

View File

@ -31,19 +31,29 @@ THE SOFTWARE.
NS_TIMELINE_BEGIN
struct AnimationInfo
typedef struct AnimationInfo
{
AnimationInfo():startIndex(0),endIndex(0){}
AnimationInfo(const std::string& otherName, int otherStartIndex, int otherEndIndex)
:name(otherName),
startIndex(otherStartIndex),
endIndex(otherEndIndex)
AnimationInfo()
:startIndex(0)
,endIndex(0)
{
}
AnimationInfo(const std::string& otherName, int otherStartIndex, int otherEndIndex)
:name(otherName)
,startIndex(otherStartIndex)
,endIndex(otherEndIndex)
{
}
std::string name;
int startIndex;
int endIndex;
};
//need set call back before clip added to ActionTimeline
// or see @ActionTimeline::setAnimationEndCallBack
std::function<void()> clipEndCallBack;
} AnimationClip;
class CC_STUDIO_DLL ActionTimelineData : public cocos2d::Ref
{
@ -145,7 +155,9 @@ public:
virtual void addAnimationInfo(const AnimationInfo& animationInfo);
virtual void removeAnimationInfo(std::string animationName);
virtual bool IsAnimationInfoExists(const std::string& animationName);
virtual AnimationInfo getAnimationInfo(const std::string& animationName);
virtual const AnimationInfo& getAnimationInfo(const std::string& animationName);
// add a frame end call back to animation's end frame @addFrameEndCallFunc, make animationName as the key of func
virtual void setAnimationEndCallBack(const std::string animationName, std::function<void()> func);
/** Set ActionTimeline's frame event callback function */
void setFrameEventCallFunc(std::function<void(Frame *)> listener);
@ -155,6 +167,15 @@ public:
void setLastFrameCallFunc(std::function<void()> listener);
void clearLastFrameCallFunc();
// add a call back after played frameIndex
virtual void addFrameEndCallFunc(int frameIndex, const std::string& funcKey, std::function<void()> func);
// clear frame call back func after frameIndex
virtual void removeFrameEndCall(int frameIndex, const std::string& funcKey);
// clear frame call backs after frameIndex
virtual void removeFrameEndCall(int frameIndex);
// clear all frame call backs in this actiontimeline
virtual void clearFrameEndCalls();
/** Inherit from Action. */
/** Returns a clone of ActionTimeline */
@ -172,6 +193,9 @@ protected:
virtual void gotoFrame(int frameIndex);
virtual void stepToFrame(int frameIndex);
// emit call back after frameIndex played
virtual void emitFrameEndCallFuncs(int frameIndex);
/** emit frame event, call it when enter a frame*/
virtual void emitFrameEvent(Frame* frame);
@ -190,6 +214,7 @@ protected:
std::function<void(Frame*)> _frameEventListener;
std::function<void()> _lastFrameListener;
std::map<int, std::map<std::string, std::function<void()> > > _frameEndCallFuncs;
std::map<std::string, AnimationInfo> _animationInfos;
};

View File

@ -4,6 +4,7 @@
#include "renderer/CCCustomCommand.h"
#include "VisibleRect.h"
#include "editor-support/cocostudio/CCComExtensionData.h"
#include "ui/CocosGUI.h"
USING_NS_CC;
@ -24,6 +25,7 @@ CocoStudioActionTimelineTests::CocoStudioActionTimelineTests()
ADD_TEST_CASE(TestActionTimelineSkeleton);
ADD_TEST_CASE(TestTimelineExtensionData);
ADD_TEST_CASE(TestActionTimelineBlendFuncFrame);
ADD_TEST_CASE(TestAnimationClipEndCallBack);
}
CocoStudioActionTimelineTests::~CocoStudioActionTimelineTests()
@ -597,3 +599,81 @@ std::string TestActionTimelineBlendFuncFrame::title() const
{
return "Test ActionTimeline BlendFunc Frame";
}
//TestAnimationClipEndCallBack
void TestAnimationClipEndCallBack::onEnter()
{
ActionTimelineBaseTest::onEnter();
Node* node = CSLoader::createNode("ActionTimeline/DemoPlayer_skeleton.csb");
ActionTimeline* action = CSLoader::createTimeline("ActionTimeline/DemoPlayer_skeleton.csb");
node->runAction(action);
node->setScale(0.2f);
node->setPosition(150, 150);
// test for frame end call back
action->addFrameEndCallFunc(5, "CallBackAfterFifthFrame", [this]{
auto text = ui::Text::create();
text->setString("CallBackAfterFifthFrame");
text->setPosition(Vec2(100, 40));
text->setLocalZOrder(1000);
this->runAction(Sequence::create(
CallFunc::create([this, text]{this->addChild(text); }),
DelayTime::create(3),
CallFunc::create([text]{text->removeFromParent(); }),
nullptr));
});
action->addFrameEndCallFunc(5, "AnotherCallBackAfterFifthFrame", [this]{
auto text = ui::Text::create();
text->setString("AnotherCallBackAfterFifthFrame");
text->setPosition(Vec2(100, 70));
this->runAction(Sequence::create(
CallFunc::create([this, text]{this->addChild(text); }),
DelayTime::create(3),
CallFunc::create([text]{text->removeFromParent(); }),
nullptr));
});
action->addFrameEndCallFunc(7, "CallBackAfterSenvnthFrame", [this]{
auto text = ui::Text::create();
text->setString("CallBackAfterSenvnthFrame");
text->setPosition(Vec2(100, 100));
this->runAction(Sequence::create(
CallFunc::create([this, text]{this->addChild(text); }),
DelayTime::create(3),
CallFunc::create([text]{text->removeFromParent(); }),
nullptr));
});
// test for animation clip end call back
action->setAnimationEndCallBack("stand", [this]{
auto text = ui::Text::create();
text->setString("CallBackAfterStandAnimationClip");
text->setPosition(Vec2(100, 130));
this->runAction(Sequence::create(
CallFunc::create([this, text]{this->addChild(text); }),
DelayTime::create(3),
CallFunc::create([text]{text->removeFromParent(); }),
nullptr));
});
AnimationClip animClip("testClip", 3, 13);
animClip.clipEndCallBack = ([this,node]{
auto text = ui::Text::create();
text->setString("testClip");
text->setPosition(Vec2(100, 140));
this->runAction(Sequence::create(
CallFunc::create([this, text]{this->addChild(text); }),
DelayTime::create(3),
CallFunc::create([text]{text->removeFromParent(); }),
nullptr));
});
action->addAnimationInfo(animClip);
action->setTimeSpeed(0.2f);
addChild(node);
action->gotoFrameAndPlay(0);
}
std::string TestAnimationClipEndCallBack::title() const
{
return "Test ActionTimeline Frame End Call Back\n and Animation Clip End Call Back";
}

View File

@ -146,4 +146,13 @@ public:
virtual void onEnter() override;
virtual std::string title() const override;
};
class TestAnimationClipEndCallBack : public ActionTimelineBaseTest
{
public:
CREATE_FUNC(TestAnimationClipEndCallBack);
virtual void onEnter() override;
virtual std::string title() const override;
};
#endif // __ANIMATION_SCENE_H__