mirror of https://github.com/axmolengine/axmol.git
308 lines
7.6 KiB
C++
308 lines
7.6 KiB
C++
/****************************************************************************
|
|
Copyright (c) 2013-2017 Chukong Technologies Inc.
|
|
|
|
https://axmolengine.github.io/
|
|
|
|
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.
|
|
****************************************************************************/
|
|
|
|
#include "ActionObject.h"
|
|
#include "CocoLoader.h"
|
|
|
|
#include "base/Director.h"
|
|
#include "base/Scheduler.h"
|
|
#include "2d/ActionInstant.h"
|
|
#include "base/Utils.h"
|
|
|
|
USING_NS_AX;
|
|
|
|
namespace cocostudio
|
|
{
|
|
|
|
ActionObject::ActionObject()
|
|
: _name("")
|
|
, _loop(false)
|
|
, _bPause(false)
|
|
, _bPlaying(false)
|
|
, _fUnitTime(0.1f)
|
|
, _currentTime(0.0f)
|
|
, _pScheduler(nullptr)
|
|
, _CallBack(nullptr)
|
|
, _fTotalTime(0.0f)
|
|
{
|
|
_pScheduler = Director::getInstance()->getScheduler();
|
|
AX_SAFE_RETAIN(_pScheduler);
|
|
}
|
|
|
|
ActionObject::~ActionObject()
|
|
{
|
|
_loop = false;
|
|
_pScheduler->unscheduleAllForTarget(this);
|
|
_actionNodeList.clear();
|
|
AX_SAFE_RELEASE(_pScheduler);
|
|
AX_SAFE_RELEASE(_CallBack);
|
|
}
|
|
|
|
void ActionObject::setName(const char* name)
|
|
{
|
|
_name.assign(name);
|
|
}
|
|
const char* ActionObject::getName()
|
|
{
|
|
return _name.c_str();
|
|
}
|
|
|
|
void ActionObject::setLoop(bool bLoop)
|
|
{
|
|
_loop = bLoop;
|
|
}
|
|
bool ActionObject::getLoop()
|
|
{
|
|
return _loop;
|
|
}
|
|
|
|
void ActionObject::setUnitTime(float fTime)
|
|
{
|
|
_fUnitTime = fTime;
|
|
for (const auto& e : _actionNodeList)
|
|
{
|
|
e->setUnitTime(_fUnitTime);
|
|
}
|
|
}
|
|
float ActionObject::getUnitTime()
|
|
{
|
|
return _fUnitTime;
|
|
}
|
|
|
|
float ActionObject::getCurrentTime()
|
|
{
|
|
return _currentTime;
|
|
}
|
|
|
|
void ActionObject::setCurrentTime(float fTime)
|
|
{
|
|
_currentTime = fTime;
|
|
}
|
|
|
|
float ActionObject::getTotalTime()
|
|
{
|
|
return _fTotalTime;
|
|
}
|
|
bool ActionObject::isPlaying()
|
|
{
|
|
return _bPlaying;
|
|
}
|
|
|
|
void ActionObject::initWithDictionary(const rapidjson::Value& dic, Ref* root)
|
|
{
|
|
setName(DICTOOL->getStringValue_json(dic, "name"));
|
|
setLoop(DICTOOL->getBooleanValue_json(dic, "loop"));
|
|
setUnitTime(DICTOOL->getFloatValue_json(dic, "unittime"));
|
|
int actionNodeCount = DICTOOL->getArrayCount_json(dic, "actionnodelist");
|
|
int maxLength = 0;
|
|
for (int i = 0; i < actionNodeCount; i++)
|
|
{
|
|
ActionNode* actionNode = new ActionNode();
|
|
actionNode->autorelease();
|
|
const rapidjson::Value& actionNodeDic = DICTOOL->getDictionaryFromArray_json(dic, "actionnodelist", i);
|
|
actionNode->initWithDictionary(actionNodeDic, root);
|
|
actionNode->setUnitTime(getUnitTime());
|
|
_actionNodeList.pushBack(actionNode);
|
|
|
|
int length = actionNode->getLastFrameIndex() - actionNode->getFirstFrameIndex();
|
|
if (length > maxLength)
|
|
maxLength = length;
|
|
}
|
|
_fTotalTime = maxLength * _fUnitTime;
|
|
}
|
|
|
|
void ActionObject::initWithBinary(CocoLoader* cocoLoader, stExpCocoNode* cocoNode, ax::Ref* root)
|
|
{
|
|
stExpCocoNode* stChildNode = cocoNode->GetChildArray(cocoLoader);
|
|
stExpCocoNode* actionNodeList = nullptr;
|
|
int count = cocoNode->GetChildNum();
|
|
for (int i = 0; i < count; ++i)
|
|
{
|
|
std::string key = stChildNode[i].GetName(cocoLoader);
|
|
std::string value = stChildNode[i].GetValue(cocoLoader);
|
|
if (key == "name")
|
|
{
|
|
setName(value.c_str());
|
|
}
|
|
else if (key == "loop")
|
|
{
|
|
setLoop(valueToBool(value));
|
|
}
|
|
else if (key == "unittime")
|
|
{
|
|
setUnitTime(valueToFloat(value));
|
|
}
|
|
else if (key == "actionnodelist")
|
|
{
|
|
actionNodeList = &stChildNode[i];
|
|
}
|
|
}
|
|
|
|
if (nullptr != actionNodeList)
|
|
{
|
|
int actionNodeCount = actionNodeList->GetChildNum();
|
|
stExpCocoNode* actionNodeArray = actionNodeList->GetChildArray(cocoLoader);
|
|
int maxLength = 0;
|
|
for (int i = 0; i < actionNodeCount; i++)
|
|
{
|
|
ActionNode* actionNode = new ActionNode();
|
|
actionNode->autorelease();
|
|
|
|
actionNode->initWithBinary(cocoLoader, &actionNodeArray[i], root);
|
|
|
|
actionNode->setUnitTime(getUnitTime());
|
|
|
|
_actionNodeList.pushBack(actionNode);
|
|
|
|
int length = actionNode->getLastFrameIndex() - actionNode->getFirstFrameIndex();
|
|
if (length > maxLength)
|
|
maxLength = length;
|
|
}
|
|
|
|
_fTotalTime = maxLength * _fUnitTime;
|
|
}
|
|
}
|
|
|
|
int ActionObject::valueToInt(std::string_view value)
|
|
{
|
|
return atoi(value.data());
|
|
}
|
|
bool ActionObject::valueToBool(std::string_view value)
|
|
{
|
|
int intValue = valueToInt(value);
|
|
if (1 == intValue)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
float ActionObject::valueToFloat(std::string_view value)
|
|
{
|
|
return utils::atof(value.data());
|
|
}
|
|
|
|
void ActionObject::addActionNode(ActionNode* node)
|
|
{
|
|
if (node == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
_actionNodeList.pushBack(node);
|
|
node->setUnitTime(_fUnitTime);
|
|
}
|
|
void ActionObject::removeActionNode(ActionNode* node)
|
|
{
|
|
if (node == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
_actionNodeList.eraseObject(node);
|
|
}
|
|
|
|
void ActionObject::play()
|
|
{
|
|
stop();
|
|
this->updateToFrameByTime(0.0f);
|
|
for (const auto& e : _actionNodeList)
|
|
{
|
|
e->playAction();
|
|
}
|
|
if (_loop)
|
|
{
|
|
_pScheduler->schedule(AX_SCHEDULE_SELECTOR(ActionObject::simulationActionUpdate), this, 0.0f, AX_REPEAT_FOREVER,
|
|
0.0f, false);
|
|
}
|
|
else
|
|
{
|
|
_pScheduler->schedule(AX_SCHEDULE_SELECTOR(ActionObject::simulationActionUpdate), this, 0.0f, false);
|
|
}
|
|
}
|
|
|
|
void ActionObject::play(CallFunc* func)
|
|
{
|
|
this->play();
|
|
this->_CallBack = func;
|
|
AX_SAFE_RETAIN(_CallBack);
|
|
}
|
|
void ActionObject::pause()
|
|
{
|
|
_bPause = true;
|
|
_bPlaying = false;
|
|
}
|
|
|
|
void ActionObject::stop()
|
|
{
|
|
for (const auto& e : _actionNodeList)
|
|
{
|
|
e->stopAction();
|
|
}
|
|
_bPlaying = false;
|
|
_pScheduler->unschedule(AX_SCHEDULE_SELECTOR(ActionObject::simulationActionUpdate), this);
|
|
_bPause = false;
|
|
}
|
|
|
|
void ActionObject::updateToFrameByTime(float fTime)
|
|
{
|
|
_currentTime = fTime;
|
|
for (const auto& e : _actionNodeList)
|
|
{
|
|
e->updateActionToTimeLine(fTime);
|
|
}
|
|
}
|
|
|
|
void ActionObject::simulationActionUpdate(float /*dt*/)
|
|
{
|
|
bool isEnd = true;
|
|
|
|
for (const auto& e : _actionNodeList)
|
|
{
|
|
if (!e->isActionDoneOnce())
|
|
{
|
|
isEnd = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isEnd)
|
|
{
|
|
if (_CallBack != nullptr)
|
|
{
|
|
_CallBack->execute();
|
|
}
|
|
if (_loop)
|
|
{
|
|
this->play();
|
|
}
|
|
else
|
|
{
|
|
_bPlaying = false;
|
|
_pScheduler->unschedule(AX_SCHEDULE_SELECTOR(ActionObject::simulationActionUpdate), this);
|
|
}
|
|
}
|
|
}
|
|
} // namespace cocostudio
|