2014-06-11 11:10:07 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2013 cocos2d-x.org
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
#include "CCActionTimeline.h"
|
2014-06-11 11:10:07 +08:00
|
|
|
|
2014-06-13 18:51:32 +08:00
|
|
|
USING_NS_CC;
|
2014-06-11 11:10:07 +08:00
|
|
|
|
2014-06-13 18:51:32 +08:00
|
|
|
NS_TIMELINE_BEGIN
|
2014-06-11 11:10:07 +08:00
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
// ActionTimelineData
|
|
|
|
ActionTimelineData* ActionTimelineData::create(int actionTag)
|
2014-06-13 13:36:01 +08:00
|
|
|
{
|
2014-08-28 07:31:57 +08:00
|
|
|
ActionTimelineData * ret = new (std::nothrow) ActionTimelineData();
|
2014-06-13 13:36:01 +08:00
|
|
|
if (ret && ret->init(actionTag))
|
|
|
|
{
|
|
|
|
ret->autorelease();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CC_SAFE_DELETE(ret);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
ActionTimelineData::ActionTimelineData()
|
2014-06-13 13:36:01 +08:00
|
|
|
: _actionTag(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
bool ActionTimelineData::init(int actionTag)
|
2014-06-13 13:36:01 +08:00
|
|
|
{
|
|
|
|
_actionTag = actionTag;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
// ActionTimeline
|
|
|
|
ActionTimeline* ActionTimeline::create()
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-08-28 07:31:57 +08:00
|
|
|
ActionTimeline* object = new (std::nothrow) ActionTimeline();
|
2014-06-11 11:10:07 +08:00
|
|
|
if (object && object->init())
|
|
|
|
{
|
|
|
|
object->autorelease();
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(object);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
ActionTimeline::ActionTimeline()
|
2014-06-11 11:10:07 +08:00
|
|
|
: _duration(0)
|
|
|
|
, _time(0)
|
|
|
|
, _timeSpeed(1)
|
|
|
|
, _frameInternal(1/60.0f)
|
|
|
|
, _playing(false)
|
|
|
|
, _currentFrame(0)
|
2014-06-17 11:45:57 +08:00
|
|
|
, _startFrame(0)
|
2014-06-11 11:10:07 +08:00
|
|
|
, _endFrame(0)
|
|
|
|
, _frameEventListener(nullptr)
|
2014-10-23 17:38:04 +08:00
|
|
|
, _lastFrameListener(nullptr)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
ActionTimeline::~ActionTimeline()
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
bool ActionTimeline::init()
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-12-22 18:57:48 +08:00
|
|
|
void ActionTimeline::play(std::string name, bool loop)
|
|
|
|
{
|
2015-01-12 10:55:15 +08:00
|
|
|
if (_animationInfos.find(name) == _animationInfos.end())
|
2014-12-22 18:57:48 +08:00
|
|
|
{
|
2015-01-12 10:55:15 +08:00
|
|
|
CCLOG("Can't find animation info for %s", name.c_str());
|
|
|
|
return;
|
2014-12-22 18:57:48 +08:00
|
|
|
}
|
2015-01-12 10:55:15 +08:00
|
|
|
|
|
|
|
AnimationInfo& index = _animationInfos[name];
|
|
|
|
gotoFrameAndPlay(index.startIndex, index.endIndex, loop);
|
2014-12-22 18:57:48 +08:00
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::gotoFrameAndPlay(int startIndex)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
gotoFrameAndPlay(startIndex, true);
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::gotoFrameAndPlay(int startIndex, bool loop)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
gotoFrameAndPlay(startIndex, _duration, loop);
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::gotoFrameAndPlay(int startIndex, int endIndex, bool loop)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-06-30 15:53:12 +08:00
|
|
|
gotoFrameAndPlay(startIndex, endIndex, startIndex, loop);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionTimeline::gotoFrameAndPlay(int startIndex, int endIndex, int currentFrameIndex, bool loop)
|
|
|
|
{
|
|
|
|
_startFrame = startIndex;
|
|
|
|
_endFrame = endIndex;
|
|
|
|
_currentFrame = currentFrameIndex;
|
|
|
|
_loop = loop;
|
|
|
|
_time = _currentFrame*_frameInternal;
|
2014-06-11 11:10:07 +08:00
|
|
|
|
|
|
|
resume();
|
|
|
|
gotoFrame(_currentFrame);
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::gotoFrameAndPause(int startIndex)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-06-17 11:45:57 +08:00
|
|
|
_startFrame = _currentFrame = startIndex;
|
|
|
|
_time = _currentFrame * _frameInternal;
|
|
|
|
|
2014-06-11 11:10:07 +08:00
|
|
|
pause();
|
|
|
|
gotoFrame(_currentFrame);
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::pause()
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
_playing = false;
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::resume()
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
_playing = true;
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
bool ActionTimeline::isPlaying() const
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
return _playing;
|
|
|
|
}
|
|
|
|
|
2014-06-30 15:53:12 +08:00
|
|
|
void ActionTimeline::setCurrentFrame(int frameIndex)
|
|
|
|
{
|
2014-11-24 10:49:22 +08:00
|
|
|
if (frameIndex >= _startFrame && frameIndex <= _endFrame)
|
2014-06-30 15:53:12 +08:00
|
|
|
{
|
|
|
|
_currentFrame = frameIndex;
|
|
|
|
_time = _currentFrame*_frameInternal;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CCLOG("frame index is not between start frame and end frame");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
ActionTimeline* ActionTimeline::clone() const
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-06-13 16:03:03 +08:00
|
|
|
ActionTimeline* newAction = ActionTimeline::create();
|
2014-06-11 11:10:07 +08:00
|
|
|
newAction->setDuration(_duration);
|
|
|
|
newAction->setTimeSpeed(_timeSpeed);
|
|
|
|
|
|
|
|
for (auto timelines : _timelineMap)
|
|
|
|
{
|
|
|
|
for(auto timeline : timelines.second)
|
|
|
|
{
|
|
|
|
Timeline* newTimeline = timeline->clone();
|
|
|
|
newAction->addTimeline(newTimeline);
|
|
|
|
}
|
|
|
|
}
|
2015-01-27 12:04:14 +08:00
|
|
|
|
|
|
|
for( auto info : _animationInfos)
|
|
|
|
{
|
|
|
|
newAction->addAnimationInfo(info.second);
|
|
|
|
}
|
2014-06-11 11:10:07 +08:00
|
|
|
return newAction;
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::step(float delta)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
if (!_playing || _timelineMap.size() == 0 || _duration == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_time += delta * _timeSpeed;
|
2014-06-18 11:22:38 +08:00
|
|
|
_currentFrame = (int)(_time / _frameInternal);
|
|
|
|
|
|
|
|
stepToFrame(_currentFrame);
|
2014-06-11 11:10:07 +08:00
|
|
|
|
2014-06-17 11:45:57 +08:00
|
|
|
if(_time > _endFrame * _frameInternal)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-10-23 17:38:04 +08:00
|
|
|
if(_lastFrameListener != nullptr)
|
|
|
|
_lastFrameListener();
|
|
|
|
|
2014-06-11 11:10:07 +08:00
|
|
|
_playing = _loop;
|
|
|
|
if(!_playing)
|
2014-06-17 11:45:57 +08:00
|
|
|
_time = _endFrame * _frameInternal;
|
2014-06-11 11:10:07 +08:00
|
|
|
else
|
2014-06-20 11:23:26 +08:00
|
|
|
gotoFrameAndPlay(_startFrame, _endFrame, _loop);
|
2014-06-11 11:10:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef std::function<void(Node*)> tCallBack;
|
|
|
|
void foreachNodeDescendant(Node* parent, tCallBack callback)
|
|
|
|
{
|
|
|
|
callback(parent);
|
|
|
|
|
2014-12-21 01:03:30 +08:00
|
|
|
auto& children = parent->getChildren();
|
2014-06-11 11:10:07 +08:00
|
|
|
for (auto child : children)
|
|
|
|
{
|
|
|
|
foreachNodeDescendant(child, callback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::startWithTarget(Node *target)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
Action::startWithTarget(target);
|
2014-10-16 18:14:58 +08:00
|
|
|
this->setTag(target->getTag());
|
2014-06-11 11:10:07 +08:00
|
|
|
|
|
|
|
foreachNodeDescendant(target,
|
|
|
|
[this, target](Node* child)
|
|
|
|
{
|
2014-06-13 16:03:03 +08:00
|
|
|
ActionTimelineData* data = dynamic_cast<ActionTimelineData*>(child->getUserObject());
|
2014-07-21 17:45:56 +08:00
|
|
|
|
|
|
|
if(data)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-07-21 17:45:56 +08:00
|
|
|
int actionTag = data->getActionTag();
|
|
|
|
if(_timelineMap.find(actionTag) != _timelineMap.end())
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-07-21 17:45:56 +08:00
|
|
|
auto timelines = this->_timelineMap[actionTag];
|
|
|
|
for (auto timeline : timelines)
|
|
|
|
{
|
|
|
|
timeline->setNode(child);
|
|
|
|
}
|
2014-06-11 11:10:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::addTimeline(Timeline* timeline)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
int tag = timeline->getActionTag();
|
|
|
|
if (_timelineMap.find(tag) == _timelineMap.end())
|
|
|
|
{
|
2014-06-13 13:36:01 +08:00
|
|
|
_timelineMap[tag] = Vector<Timeline*>();
|
2014-06-11 11:10:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!_timelineMap[tag].contains(timeline))
|
|
|
|
{
|
|
|
|
_timelineList.pushBack(timeline);
|
|
|
|
_timelineMap[tag].pushBack(timeline);
|
2014-06-13 16:03:03 +08:00
|
|
|
timeline->setActionTimeline(this);
|
2014-06-11 11:10:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::removeTimeline(Timeline* timeline)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
int tag = timeline->getActionTag();
|
|
|
|
if (_timelineMap.find(tag) != _timelineMap.end())
|
|
|
|
{
|
|
|
|
if(_timelineMap[tag].contains(timeline))
|
|
|
|
{
|
|
|
|
_timelineMap[tag].eraseObject(timeline);
|
|
|
|
_timelineList.eraseObject(timeline);
|
2014-06-13 16:03:03 +08:00
|
|
|
timeline->setActionTimeline(nullptr);
|
2014-06-11 11:10:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-12 10:55:15 +08:00
|
|
|
|
|
|
|
void ActionTimeline::addAnimationInfo(const AnimationInfo& animationInfo)
|
2014-12-22 18:57:48 +08:00
|
|
|
{
|
2015-01-12 10:55:15 +08:00
|
|
|
if (_animationInfos.find(animationInfo.name) != _animationInfos.end())
|
2014-12-22 18:57:48 +08:00
|
|
|
{
|
2015-01-12 10:55:15 +08:00
|
|
|
CCLOG("Animation (%s) already exists.", animationInfo.name.c_str());
|
2014-12-22 18:57:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2015-01-12 10:55:15 +08:00
|
|
|
|
|
|
|
_animationInfos[animationInfo.name] = animationInfo;
|
2014-12-22 18:57:48 +08:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:55:15 +08:00
|
|
|
void ActionTimeline::removeAnimationInfo(std::string animationName)
|
2014-12-22 18:57:48 +08:00
|
|
|
{
|
2015-01-12 10:55:15 +08:00
|
|
|
if (_animationInfos.find(animationName) == _animationInfos.end())
|
2014-12-22 18:57:48 +08:00
|
|
|
{
|
2015-01-12 10:55:15 +08:00
|
|
|
CCLOG("AnimationInfo (%s) not exists.", animationName.c_str());
|
2014-12-22 18:57:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2015-01-12 10:55:15 +08:00
|
|
|
|
|
|
|
_animationInfos.erase(animationName);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ActionTimeline::IsAnimationInfoExists(const std::string& animationName)
|
|
|
|
{
|
|
|
|
return _animationInfos.find(animationName) != _animationInfos.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
AnimationInfo ActionTimeline::getAnimationInfo(const std::string &animationName)
|
|
|
|
{
|
|
|
|
return _animationInfos.find(animationName)->second;
|
2014-12-22 18:57:48 +08:00
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::setFrameEventCallFunc(std::function<void(Frame *)> listener)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
_frameEventListener = listener;
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::clearFrameEventCallFunc()
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
_frameEventListener = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-23 17:38:04 +08:00
|
|
|
void ActionTimeline::setLastFrameCallFunc(std::function<void()> listener)
|
|
|
|
{
|
|
|
|
_lastFrameListener = listener;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActionTimeline::clearLastFrameCallFunc()
|
|
|
|
{
|
|
|
|
_lastFrameListener = nullptr;
|
|
|
|
}
|
2014-06-11 11:10:07 +08:00
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::emitFrameEvent(Frame* frame)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
if(_frameEventListener)
|
|
|
|
{
|
|
|
|
_frameEventListener(frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::gotoFrame(int frameIndex)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-10-23 17:38:04 +08:00
|
|
|
if(_target == nullptr)
|
|
|
|
return;
|
|
|
|
|
2014-07-09 00:09:35 +08:00
|
|
|
ssize_t size = _timelineList.size();
|
|
|
|
for(ssize_t i = 0; i < size; i++)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
_timelineList.at(i)->gotoFrame(frameIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-13 16:03:03 +08:00
|
|
|
void ActionTimeline::stepToFrame(int frameIndex)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
2014-07-09 00:09:35 +08:00
|
|
|
ssize_t size = _timelineList.size();
|
|
|
|
for(ssize_t i = 0; i < size; i++)
|
2014-06-11 11:10:07 +08:00
|
|
|
{
|
|
|
|
_timelineList.at(i)->stepToFrame(frameIndex);
|
|
|
|
}
|
|
|
|
}
|
2014-06-13 18:51:32 +08:00
|
|
|
NS_TIMELINE_END
|