axmol/cocos/editor-support/cocosbuilder/CCBAnimationManager.cpp

1339 lines
36 KiB
C++

/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
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.
****************************************************************************/
#include "editor-support/cocosbuilder/CCBAnimationManager.h"
#include "editor-support/cocosbuilder/CCBReader.h"
#include "editor-support/cocosbuilder/CCNode+CCBRelativePositioning.h"
#include "audio/include/SimpleAudioEngine.h"
#include "editor-support/cocosbuilder/CCBSelectorResolver.h"
#include <string>
#include <sstream>
#include <set>
using namespace cocos2d;
using namespace std;
using namespace cocos2d::extension;
namespace cocosbuilder {
// Implementation of CCBAinmationManager
CCBAnimationManager::CCBAnimationManager()
: _jsControlled(false)
, _owner(nullptr)
, _autoPlaySequenceId(0)
, _rootNode(nullptr)
, _rootContainerSize(Size::ZERO)
, _delegate(nullptr)
, _runningSequence(nullptr)
{
init();
}
bool CCBAnimationManager::init()
{
_target = nullptr;
_animationCompleteCallbackFunc = nullptr;
return true;
}
CCBAnimationManager::~CCBAnimationManager()
{
// DictElement *pElement = nullptr;
// CCDICT_FOREACH(_nodeSequences, pElement)
// {
// Node *node = (Node*)pElement->getIntKey();
// node->release();
// }
//
// CCDICT_FOREACH(_baseValues, pElement)
// {
// Node *node = (Node*)pElement->getIntKey();
// node->release();
// }
if (_rootNode)
{
_rootNode->stopAllActions();
}
setRootNode(nullptr);
setDelegate(nullptr);
for (auto iter = _objects.begin(); iter != _objects.end(); ++iter)
{
for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2)
{
iter2->second->release();
}
}
CC_SAFE_RELEASE(_target);
}
Vector<CCBSequence*>& CCBAnimationManager::getSequences()
{
return _sequences;
}
void CCBAnimationManager::setSequences(const Vector<CCBSequence*>& seq)
{
_sequences = seq;
}
int CCBAnimationManager::getAutoPlaySequenceId()
{
return _autoPlaySequenceId;
}
void CCBAnimationManager::setAutoPlaySequenceId(int autoPlaySequenceId)
{
_autoPlaySequenceId = autoPlaySequenceId;
}
Node* CCBAnimationManager::getRootNode()
{
return _rootNode;
}
void CCBAnimationManager::setRootNode(Node *pRootNode)
{
_rootNode = pRootNode;
}
void CCBAnimationManager::setDocumentControllerName(const std::string &name)
{
_documentControllerName = name;
}
std::string CCBAnimationManager::getDocumentControllerName()
{
return _documentControllerName;
}
void CCBAnimationManager::addDocumentCallbackNode(Node *node)
{
_documentCallbackNodes.pushBack(node);
}
void CCBAnimationManager::addDocumentCallbackName(std::string name)
{
_documentCallbackNames.push_back(Value(name));
}
void CCBAnimationManager::addDocumentCallbackControlEvents(Control::EventType eventType)
{
_documentCallbackControlEvents.push_back(Value(static_cast<int>(eventType)));
}
ValueVector& CCBAnimationManager::getDocumentCallbackNames()
{
return _documentCallbackNames;
}
Vector<Node*>& CCBAnimationManager::getDocumentCallbackNodes()
{
return _documentCallbackNodes;
}
ValueVector& CCBAnimationManager::getDocumentCallbackControlEvents()
{
return _documentCallbackControlEvents;
}
void CCBAnimationManager::addDocumentOutletNode(Node *node)
{
_documentOutletNodes.pushBack(node);
}
void CCBAnimationManager::addDocumentOutletName(std::string name)
{
_documentOutletNames.push_back(Value(name));
}
ValueVector& CCBAnimationManager::getDocumentOutletNames()
{
return _documentOutletNames;
}
Vector<Node*>& CCBAnimationManager::getDocumentOutletNodes()
{
return _documentOutletNodes;
}
std::string CCBAnimationManager::getLastCompletedSequenceName()
{
return _lastCompletedSequenceName;
}
ValueVector& CCBAnimationManager::getKeyframeCallbacks()
{
return _keyframeCallbacks;
}
const Size& CCBAnimationManager::getRootContainerSize()
{
return _rootContainerSize;
}
void CCBAnimationManager::setRootContainerSize(const Size &rootContainerSize)
{
_rootContainerSize.setSize(rootContainerSize.width, rootContainerSize.height);
}
CCBAnimationManagerDelegate* CCBAnimationManager::getDelegate()
{
return _delegate;
}
void CCBAnimationManager::setDelegate(CCBAnimationManagerDelegate *pDelegate)
{
CC_SAFE_RELEASE(dynamic_cast<Ref*>(_delegate));
_delegate = pDelegate;
CC_SAFE_RETAIN(dynamic_cast<Ref*>(_delegate));
}
const char* CCBAnimationManager::getRunningSequenceName()
{
if (_runningSequence)
{
return _runningSequence->getName();
}
return nullptr;
}
const Size& CCBAnimationManager::getContainerSize(Node *pNode)
{
if (pNode)
{
return pNode->getContentSize();
}
else
{
return _rootContainerSize;
}
}
// refer to CCBReader::readNodeGraph() for data structure of pSeq
void CCBAnimationManager::addNode(Node *pNode, const std::unordered_map<int, Map<std::string, CCBSequenceProperty*>>& seq)
{
// pNode->retain();
_nodeSequences[pNode] = seq;
}
void CCBAnimationManager::setBaseValue(const Value& value, Node *pNode, const std::string& propName)
{
auto& props = _baseValues[pNode];
props[propName] = value;
}
const Value& CCBAnimationManager::getBaseValue(Node *pNode, const std::string& propName)
{
auto& props = _baseValues[pNode];
return props[propName];
}
void CCBAnimationManager::setObject(Ref* obj, Node *pNode, const std::string& propName)
{
auto& props = _objects[pNode];
auto iter = props.find(propName);
if (iter != props.end())
iter->second->release();
props[propName] = obj;
obj->retain();
}
Ref* CCBAnimationManager::getObject(Node *pNode, const std::string& propName)
{
auto& props = _objects[pNode];
auto iter = props.find(propName);
if (iter != props.end())
return iter->second;
return nullptr;
}
int CCBAnimationManager::getSequenceId(const char* pSequenceName)
{
string seqName(pSequenceName);
for (auto& seq : _sequences)
{
if (seqName.compare(seq->getName()) == 0)
{
return seq->getSequenceId();
}
}
return -1;
}
CCBSequence* CCBAnimationManager::getSequence(int nSequenceId)
{
for (auto& seq : _sequences)
{
if (seq->getSequenceId() == nSequenceId)
{
return seq;
}
}
return nullptr;
}
float CCBAnimationManager::getSequenceDuration(const char *pSequenceName)
{
int id = getSequenceId(pSequenceName);
if (id != -1)
return getSequence(id)->getDuration();
return 0;
}
void CCBAnimationManager::moveAnimationsFromNode(Node* fromNode, Node* toNode)
{
// Move base values
auto baseValueIter = _baseValues.find(fromNode);
if(baseValueIter != _baseValues.end())
{
_baseValues[toNode] = baseValueIter->second;
_baseValues.erase(baseValueIter);
// fromNode->release();
// toNode->retain();
}
auto objIter = _objects.find(fromNode);
if (objIter != _objects.end())
{
_objects[toNode] = objIter->second;
_objects.erase(objIter);
}
// Move seqs
auto seqsIter = _nodeSequences.find(fromNode);
if (seqsIter != _nodeSequences.end())
{
_nodeSequences[toNode] = seqsIter->second;
_nodeSequences.erase(seqsIter);
// fromNode->release();
// toNode->retain();
}
}
// Refer to CCBReader::readKeyframe() for the real type of value
ActionInterval* CCBAnimationManager::getAction(CCBKeyframe *pKeyframe0, CCBKeyframe *pKeyframe1, const std::string& propName, Node *pNode)
{
float duration = pKeyframe1->getTime() - (pKeyframe0 ? pKeyframe0->getTime() : 0);
if (propName == "rotationX")
{
return CCBRotateXTo::create(duration, pKeyframe1->getValue().asFloat());
}
else if (propName == "rotationY")
{
return CCBRotateYTo::create(duration, pKeyframe1->getValue().asFloat());
}
else if (propName == "rotation")
{
return CCBRotateTo::create(duration, pKeyframe1->getValue().asFloat());
}
else if (propName == "opacity")
{
return FadeTo::create(duration, pKeyframe1->getValue().asByte());
}
else if (propName == "color")
{
auto c = pKeyframe1->getValue().asValueMap();
unsigned char r = c["r"].asByte();
unsigned char g = c["g"].asByte();
unsigned char b = c["b"].asByte();
return TintTo::create(duration, r, g, b);
}
else if (propName == "visible")
{
if (pKeyframe1->getValue().asBool())
{
return Sequence::createWithTwoActions(DelayTime::create(duration), Show::create());
}
else
{
return Sequence::createWithTwoActions(DelayTime::create(duration), Hide::create());
}
}
else if (propName == "displayFrame")
{
return Sequence::createWithTwoActions(DelayTime::create(duration),
CCBSetSpriteFrame::create(static_cast<SpriteFrame*>(pKeyframe1->getObject())));
}
else if (propName == "position")
{
// Get position type
auto& array = getBaseValue(pNode, propName).asValueVector();
CCBReader::PositionType type = (CCBReader::PositionType)array[2].asInt();
// Get relative position
auto value = pKeyframe1->getValue().asValueVector();
float x = value[0].asFloat();
float y = value[1].asFloat();
Size containerSize = getContainerSize(pNode->getParent());
Vec2 absPos = getAbsolutePosition(Vec2(x,y), type, containerSize, propName);
return MoveTo::create(duration, absPos);
}
else if (propName == "scale")
{
// Get position type
auto& array = getBaseValue(pNode, propName).asValueVector();
CCBReader::ScaleType type = (CCBReader::ScaleType)array[2].asInt();
// Get relative scale
auto value = pKeyframe1->getValue().asValueVector();
float x = value[0].asFloat();
float y = value[1].asFloat();
if (type == CCBReader::ScaleType::MULTIPLY_RESOLUTION)
{
float resolutionScale = CCBReader::getResolutionScale();
x *= resolutionScale;
y *= resolutionScale;
}
return ScaleTo::create(duration, x, y);
}
else if (propName == "skew")
{
// Get relative skew
auto& value = pKeyframe1->getValue().asValueVector();
float x = value[0].asFloat();
float y = value[1].asFloat();
return SkewTo::create(duration, x, y);
}
else
{
log("CCBReader: Failed to create animation for property: %s", propName.c_str());
}
return nullptr;
}
void CCBAnimationManager::setAnimatedProperty(const std::string& propName, Node *pNode, const Value& value, Ref* obj, float fTweenDuration)
{
if (fTweenDuration > 0)
{
// Create a fake keyframe to generate the action from
CCBKeyframe *kf1 = new (std::nothrow) CCBKeyframe();
kf1->autorelease();
kf1->setObject(obj);
kf1->setValue(value);
kf1->setTime(fTweenDuration);
kf1->setEasingType(CCBKeyframe::EasingType::LINEAR);
// Animate
ActionInterval *tweenAction = getAction(nullptr, kf1, propName, pNode);
pNode->runAction(tweenAction);
}
else
{
// Just set the value
if (propName == "position")
{
// Get position type
auto& array = getBaseValue(pNode, propName).asValueVector();
CCBReader::PositionType type = (CCBReader::PositionType)array[2].asInt();
// Get relative position
auto& valueVector = value.asValueVector();
float x = valueVector[0].asFloat();
float y = valueVector[1].asFloat();
pNode->setPosition(getAbsolutePosition(Vec2(x,y), type, getContainerSize(pNode->getParent()), propName));
}
else if (propName == "scale")
{
// Get scale type
auto& array = getBaseValue(pNode, propName).asValueVector();
CCBReader::ScaleType type = (CCBReader::ScaleType)array[2].asInt();
// Get relative scale
auto& valueVector = value.asValueVector();
float x = valueVector[0].asFloat();
float y = valueVector[1].asFloat();
setRelativeScale(pNode, x, y, type, propName);
}
else if(propName == "skew")
{
// Get relative scale
auto& valueVector = value.asValueVector();
float x = valueVector[0].asFloat();
float y = valueVector[1].asFloat();
pNode->setSkewX(x);
pNode->setSkewY(y);
}
else
{
// [node setValue:value forKey:name];
// TODO: only handle rotation, opacity, displayFrame, color
if (propName == "rotation")
{
float rotate = value.asFloat();
pNode->setRotation(rotate);
} else if(propName == "rotationX")
{
float rotate = value.asFloat();
pNode->setRotationSkewX(rotate);
}else if(propName == "rotationY")
{
float rotate = value.asFloat();
pNode->setRotationSkewY(rotate);
}
else if (propName == "opacity")
{
unsigned char opacity = value.asByte();
pNode->setOpacity(opacity);
}
else if (propName == "displayFrame")
{
static_cast<Sprite*>(pNode)->setSpriteFrame(static_cast<SpriteFrame*>(obj));
}
else if (propName == "color")
{
auto c = value.asValueMap();
unsigned char r = c["r"].asByte();
unsigned char g = c["g"].asByte();
unsigned char b = c["b"].asByte();
pNode->setColor(Color3B(r, g, b));
}
else if (propName == "visible")
{
bool visible = value.asBool();
pNode->setVisible(visible);
}
else
{
log("unsupported property name is %s", propName.c_str());
CCASSERT(false, "unsupported property now");
}
}
}
}
void CCBAnimationManager::setFirstFrame(Node *pNode, CCBSequenceProperty *pSeqProp, float fTweenDuration)
{
auto& keyframes = pSeqProp->getKeyframes();
if (keyframes.empty())
{
// Use base value (no animation)
auto& baseValue = getBaseValue(pNode, pSeqProp->getName());
auto obj = getObject(pNode, pSeqProp->getName());
CCASSERT(!baseValue.isNull(), "No baseValue found for property");
setAnimatedProperty(pSeqProp->getName(), pNode, baseValue, obj, fTweenDuration);
}
else
{
// Use first keyframe
CCBKeyframe *keyframe = keyframes.at(0);
setAnimatedProperty(pSeqProp->getName(), pNode, keyframe->getValue(), keyframe->getObject(), fTweenDuration);
}
}
ActionInterval* CCBAnimationManager::getEaseAction(ActionInterval *pAction, CCBKeyframe::EasingType easingType, float fEasingOpt)
{
if (dynamic_cast<Sequence*>(pAction))
{
return pAction;
}
if (easingType == CCBKeyframe::EasingType::LINEAR)
{
return pAction;
}
else if (easingType == CCBKeyframe::EasingType::INSTANT)
{
return CCBEaseInstant::create(pAction);
}
else if (easingType == CCBKeyframe::EasingType::CUBIC_IN)
{
return EaseIn::create(pAction, fEasingOpt);
}
else if (easingType == CCBKeyframe::EasingType::CUBIC_OUT)
{
return EaseOut::create(pAction, fEasingOpt);
}
else if (easingType == CCBKeyframe::EasingType::CUBIC_INOUT)
{
return EaseInOut::create(pAction, fEasingOpt);
}
else if (easingType == CCBKeyframe::EasingType::BACK_IN)
{
return EaseBackIn::create(pAction);
}
else if (easingType == CCBKeyframe::EasingType::BACK_OUT)
{
return EaseBackOut::create(pAction);
}
else if (easingType == CCBKeyframe::EasingType::BACK_INOUT)
{
return EaseBackInOut::create(pAction);
}
else if (easingType == CCBKeyframe::EasingType::BOUNCE_IN)
{
return EaseBounceIn::create(pAction);
}
else if (easingType == CCBKeyframe::EasingType::BOUNCE_OUT)
{
return EaseBounceOut::create(pAction);
}
else if (easingType == CCBKeyframe::EasingType::BOUNCE_INOUT)
{
return EaseBounceInOut::create(pAction);
}
else if (easingType == CCBKeyframe::EasingType::ELASTIC_IN)
{
return EaseElasticIn::create(pAction, fEasingOpt);
}
else if (easingType == CCBKeyframe::EasingType::ELASTIC_OUT)
{
return EaseElasticOut::create(pAction, fEasingOpt);
}
else if (easingType == CCBKeyframe::EasingType::ELASTIC_INOUT)
{
return EaseElasticInOut::create(pAction, fEasingOpt);
}
else
{
log("CCBReader: Unknown easing type %d", static_cast<int>(easingType));
return pAction;
}
}
Sequence* CCBAnimationManager::actionForCallbackChannel(CCBSequenceProperty* channel) {
float lastKeyframeTime = 0;
Vector<FiniteTimeAction*> actions;
auto& keyframes = channel->getKeyframes();
ssize_t numKeyframes = keyframes.size();
for (long i = 0; i < numKeyframes; ++i)
{
CCBKeyframe *keyframe = keyframes.at(i);
float timeSinceLastKeyframe = keyframe->getTime() - lastKeyframeTime;
lastKeyframeTime = keyframe->getTime();
if(timeSinceLastKeyframe > 0) {
actions.pushBack(DelayTime::create(timeSinceLastKeyframe));
}
auto& keyVal = keyframe->getValue().asValueVector();
std::string selectorName = keyVal[0].asString();
CCBReader::TargetType selectorTarget = (CCBReader::TargetType)keyVal[1].asInt();
if(_jsControlled) {
std::stringstream callbackName;
callbackName << static_cast<int>(selectorTarget);
callbackName << ":" + selectorName;
auto callback = _keyframeCallFuncs.at(callbackName.str());
if (nullptr != callback)
{
CallFunc* callbackClone = callback->clone();
if (callbackClone != nullptr)
{
actions.pushBack(callbackClone);
}
}
}
else
{
Ref* target = nullptr;
if(selectorTarget == CCBReader::TargetType::DOCUMENT_ROOT)
target = _rootNode;
else if (selectorTarget == CCBReader::TargetType::OWNER)
target = _owner;
if(target != nullptr)
{
if(!selectorName.empty())
{
SEL_CallFuncN selCallFunc = 0;
CCBSelectorResolver* targetAsCCBSelectorResolver = dynamic_cast<CCBSelectorResolver *>(target);
if(targetAsCCBSelectorResolver != nullptr)
{
selCallFunc = targetAsCCBSelectorResolver->onResolveCCBCCCallFuncSelector(target, selectorName.c_str ());
}
if(selCallFunc == 0)
{
CCLOG("Skipping selector '%s' since no CCBSelectorResolver is present.", selectorName.c_str());
}
else
{
auto savedTarget = std::make_shared<Vector<Ref*>>();
savedTarget->pushBack(target);
auto callback = CallFuncN::create([savedTarget, selCallFunc](Node* sender){
auto t = savedTarget->at(0);
(t->*selCallFunc)(sender);
});
actions.pushBack(callback);
}
}
else
{
CCLOG("Unexpected empty selector.");
}
}
}
}
if(actions.size() < 1) return nullptr;
return Sequence::create(actions);
}
Sequence* CCBAnimationManager::actionForSoundChannel(CCBSequenceProperty* channel) {
float lastKeyframeTime = 0;
Vector<FiniteTimeAction*> actions;
auto& keyframes = channel->getKeyframes();
ssize_t numKeyframes = keyframes.size();
for (int i = 0; i < numKeyframes; ++i)
{
CCBKeyframe *keyframe = keyframes.at(i);
float timeSinceLastKeyframe = keyframe->getTime() - lastKeyframeTime;
lastKeyframeTime = keyframe->getTime();
if(timeSinceLastKeyframe > 0) {
actions.pushBack(DelayTime::create(timeSinceLastKeyframe));
}
stringstream ss (stringstream::in | stringstream::out);
auto& keyVal = keyframe->getValue().asValueVector();
std::string soundFile = keyVal[0].asString();
float pitch = 0.0f, pan = 0.0f, gain = 0.0f;
ss << keyVal[1].asString();
ss >> pitch;
ss.flush();
ss << keyVal[2].asString();
ss >> pan;
ss.flush();
ss << keyVal[3].asString();
ss >> gain;
ss.flush();
actions.pushBack(CCBSoundEffect::actionWithSoundFile(soundFile, pitch, pan, gain));
}
if(actions.size() < 1) return nullptr;
return Sequence::create(actions);
}
void CCBAnimationManager::runAction(Node *pNode, CCBSequenceProperty *pSeqProp, float fTweenDuration)
{
auto& keyframes = pSeqProp->getKeyframes();
ssize_t numKeyframes = keyframes.size();
if (numKeyframes > 1)
{
// Make an animation!
Vector<FiniteTimeAction*> actions;
CCBKeyframe *keyframeFirst = keyframes.at(0);
float timeFirst = keyframeFirst->getTime() + fTweenDuration;
if (timeFirst > 0)
{
actions.pushBack(DelayTime::create(timeFirst));
}
for (ssize_t i = 0; i < numKeyframes - 1; ++i)
{
CCBKeyframe *kf0 = keyframes.at(i);
CCBKeyframe *kf1 = keyframes.at(i+1);
ActionInterval *action = getAction(kf0, kf1, pSeqProp->getName(), pNode);
if (action)
{
// Apply easing
action = getEaseAction(action, kf0->getEasingType(), kf0->getEasingOpt());
actions.pushBack(action);
}
}
auto seq = Sequence::create(actions);
pNode->runAction(seq);
}
}
void CCBAnimationManager::runAnimations(const char *pName, float fTweenDuration)
{
runAnimationsForSequenceNamedTweenDuration(pName, fTweenDuration);
}
void CCBAnimationManager::runAnimations(const char *pName)
{
runAnimationsForSequenceNamed(pName);
}
void CCBAnimationManager::runAnimations(int nSeqId, float fTweenDuraiton)
{
runAnimationsForSequenceIdTweenDuration(nSeqId, fTweenDuraiton);
}
void CCBAnimationManager::runAnimationsForSequenceIdTweenDuration(int nSeqId, float fTweenDuration)
{
CCASSERT(nSeqId != -1, "Sequence id couldn't be found");
_rootNode->stopAllActions();
for (auto nodeSeqIter = _nodeSequences.begin(); nodeSeqIter != _nodeSequences.end(); ++nodeSeqIter)
{
Node *node = nodeSeqIter->first;
node->stopAllActions();
// Refer to CCBReader::readKeyframe() for the real type of value
auto seqs = nodeSeqIter->second;
auto seqNodeProps = seqs[nSeqId];
std::set<std::string> seqNodePropNames;
if (!seqNodeProps.empty())
{
// Reset nodes that have sequence node properties, and run actions on them
for (auto iter = seqNodeProps.begin(); iter != seqNodeProps.end(); ++iter)
{
const std::string propName = iter->first;
CCBSequenceProperty *seqProp = iter->second;
seqNodePropNames.insert(propName);
setFirstFrame(node, seqProp, fTweenDuration);
runAction(node, seqProp, fTweenDuration);
}
}
// Reset the nodes that may have been changed by other timelines
auto& nodeBaseValues = _baseValues[node];
if (!nodeBaseValues.empty())
{
for (auto iter = nodeBaseValues.begin(); iter != nodeBaseValues.end(); ++iter)
{
if (seqNodePropNames.find(iter->first) == seqNodePropNames.end())
{
setAnimatedProperty(iter->first, node, iter->second, nullptr, fTweenDuration);
}
}
}
auto& nodeObject = _objects[node];
if (!nodeObject.empty())
{
for (auto iter = nodeObject.begin(); iter != nodeObject.end(); ++iter)
{
if (seqNodePropNames.find(iter->first) == seqNodePropNames.end())
{
setAnimatedProperty(iter->first, node, Value(), iter->second, fTweenDuration);
}
}
}
}
// Make callback at end of sequence
CCBSequence *seq = getSequence(nSeqId);
Action *completeAction = Sequence::createWithTwoActions(DelayTime::create(seq->getDuration() + fTweenDuration),
CallFunc::create( CC_CALLBACK_0(CCBAnimationManager::sequenceCompleted,this)));
_rootNode->runAction(completeAction);
// Set the running scene
if(seq->getCallbackChannel() != nullptr) {
Action* action = (Action *)actionForCallbackChannel(seq->getCallbackChannel());
if(action != nullptr) {
_rootNode->runAction(action);
}
}
if(seq->getSoundChannel() != nullptr) {
Action* action = (Action *)actionForSoundChannel(seq->getSoundChannel());
if(action != nullptr) {
_rootNode->runAction(action);
}
}
_runningSequence = getSequence(nSeqId);
}
void CCBAnimationManager::runAnimationsForSequenceNamedTweenDuration(const char *pName, float fTweenDuration)
{
int seqId = getSequenceId(pName);
runAnimationsForSequenceIdTweenDuration(seqId, fTweenDuration);
}
void CCBAnimationManager::runAnimationsForSequenceNamed(const char *pName)
{
runAnimationsForSequenceNamedTweenDuration(pName, 0);
}
void CCBAnimationManager::debug()
{
}
void CCBAnimationManager::setAnimationCompletedCallback(Ref *target, SEL_CallFunc callbackFunc) {
if (target)
{
target->retain();
}
if (_target)
{
_target->release();
}
_target = target;
_animationCompleteCallbackFunc = callbackFunc;
}
void CCBAnimationManager::setCallFunc(CallFunc* callFunc, const std::string &callbackNamed)
{
_keyframeCallFuncs.insert(callbackNamed, callFunc);
}
void CCBAnimationManager::sequenceCompleted()
{
const char *runningSequenceName = _runningSequence->getName();
int nextSeqId = _runningSequence->getChainedSequenceId();
_runningSequence = nullptr;
if(_lastCompletedSequenceName != runningSequenceName) {
_lastCompletedSequenceName = runningSequenceName;
}
if (nextSeqId != -1)
{
runAnimationsForSequenceIdTweenDuration(nextSeqId, 0);
}
if (_delegate)
{
// There may be another runAnimation() call in this delegate method
// which will assign _runningSequence
_delegate->completedAnimationSequenceNamed(runningSequenceName);
}
if (_target && _animationCompleteCallbackFunc) {
(_target->*_animationCompleteCallbackFunc)();
}
}
// Custom actions
/************************************************************
CCBSetSpriteFrame
************************************************************/
CCBSetSpriteFrame* CCBSetSpriteFrame::create(SpriteFrame *pSpriteFrame)
{
CCBSetSpriteFrame *ret = new (std::nothrow) CCBSetSpriteFrame();
if (ret)
{
if (ret->initWithSpriteFrame(pSpriteFrame))
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE(ret);
}
}
return ret;
}
bool CCBSetSpriteFrame::initWithSpriteFrame(SpriteFrame *pSpriteFrame)
{
_spriteFrame = pSpriteFrame;
CC_SAFE_RETAIN(_spriteFrame);
return true;
}
CCBSetSpriteFrame::~CCBSetSpriteFrame()
{
CC_SAFE_RELEASE_NULL(_spriteFrame);
}
CCBSetSpriteFrame* CCBSetSpriteFrame::clone() const
{
// no copy constructor
auto a = new (std::nothrow) CCBSetSpriteFrame();
a->initWithSpriteFrame(_spriteFrame);
a->autorelease();
return a;
}
CCBSetSpriteFrame* CCBSetSpriteFrame::reverse() const
{
// returns a copy of itself
return this->clone();
}
void CCBSetSpriteFrame::update(float /*time*/)
{
static_cast<Sprite*>(_target)->setSpriteFrame(_spriteFrame);
}
/************************************************************
CCBSoundEffect
************************************************************/
CCBSoundEffect* CCBSoundEffect::actionWithSoundFile(const std::string &filename, float pitch, float pan, float gain) {
CCBSoundEffect* pRet = new (std::nothrow) CCBSoundEffect();
if (pRet != nullptr && pRet->initWithSoundFile(filename, pitch, pan, gain))
{
pRet->autorelease();
}
else
{
CC_SAFE_DELETE(pRet);
}
return pRet;
}
CCBSoundEffect::~CCBSoundEffect()
{
}
bool CCBSoundEffect::initWithSoundFile(const std::string &filename, float pitch, float pan, float gain) {
_soundFile = filename;
_pitch = pitch;
_pan = pan;
_gain = gain;
return true;
}
CCBSoundEffect* CCBSoundEffect::clone() const
{
// no copy constructor
auto a = new (std::nothrow) CCBSoundEffect();
a->initWithSoundFile(_soundFile, _pitch, _pan, _gain);
a->autorelease();
return a;
}
CCBSoundEffect* CCBSoundEffect::reverse() const
{
// returns a copy of itself
return this->clone();
}
void CCBSoundEffect::update(float /*time*/)
{
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(_soundFile.c_str());
}
/************************************************************
CCBRotateTo
************************************************************/
CCBRotateTo* CCBRotateTo::create(float fDuration, float fAngle)
{
CCBRotateTo *ret = new (std::nothrow) CCBRotateTo();
if (ret)
{
if (ret->initWithDuration(fDuration, fAngle))
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE(ret);
}
}
return ret;
}
bool CCBRotateTo::initWithDuration(float fDuration, float fAngle)
{
if (ActionInterval::initWithDuration(fDuration))
{
_dstAngle = fAngle;
return true;
}
else
{
return false;
}
}
CCBRotateTo* CCBRotateTo::clone() const
{
// no copy constructor
auto a = new (std::nothrow) CCBRotateTo();
a->initWithDuration(_duration, _dstAngle);
a->autorelease();
return a;
}
CCBRotateTo* CCBRotateTo::reverse() const
{
CCASSERT(false, "reverse() is not supported in CCBRotateTo");
return nullptr;
}
void CCBRotateTo::startWithTarget(Node *pNode)
{
ActionInterval::startWithTarget(pNode);
_startAngle = _target->getRotation();
_diffAngle = _dstAngle - _startAngle;
}
void CCBRotateTo::update(float time)
{
_target->setRotation(_startAngle + (_diffAngle * time))
;
}
/************************************************************
CCBRotateXTO
************************************************************/
CCBRotateXTo* CCBRotateXTo::create(float fDuration, float fAngle)
{
CCBRotateXTo *ret = new (std::nothrow) CCBRotateXTo();
if (ret)
{
if (ret->initWithDuration(fDuration, fAngle))
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE(ret);
}
}
return ret;
}
bool CCBRotateXTo::initWithDuration(float fDuration, float fAngle)
{
if (ActionInterval::initWithDuration(fDuration))
{
_dstAngle = fAngle;
return true;
}
else
{
return false;
}
}
void CCBRotateXTo::startWithTarget(Node *pNode)
{
//CCActionInterval::startWithTarget(pNode);
_originalTarget = pNode;
_target = pNode;
_elapsed = 0.0f;
_firstTick = true;
_startAngle = _target->getRotationSkewX();
_diffAngle = _dstAngle - _startAngle;
}
CCBRotateXTo* CCBRotateXTo::clone() const
{
// no copy constructor
auto a = new (std::nothrow) CCBRotateXTo();
a->initWithDuration(_duration, _dstAngle);
a->autorelease();
return a;
}
CCBRotateXTo* CCBRotateXTo::reverse() const
{
CCASSERT(false, "reverse() is not supported in CCBRotateXTo");
return nullptr;
}
void CCBRotateXTo::update(float time)
{
_target->setRotationSkewX(_startAngle + (_diffAngle * time));
}
/************************************************************
CCBRotateYTO
************************************************************/
CCBRotateYTo* CCBRotateYTo::create(float fDuration, float fAngle)
{
CCBRotateYTo *ret = new (std::nothrow) CCBRotateYTo();
if (ret)
{
if (ret->initWithDuration(fDuration, fAngle))
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE(ret);
}
}
return ret;
}
bool CCBRotateYTo::initWithDuration(float fDuration, float fAngle)
{
if (ActionInterval::initWithDuration(fDuration))
{
_dstAngle = fAngle;
return true;
}
else
{
return false;
}
}
CCBRotateYTo* CCBRotateYTo::clone() const
{
// no copy constructor
auto a = new (std::nothrow) CCBRotateYTo();
a->initWithDuration(_duration, _dstAngle);
a->autorelease();
return a;
}
CCBRotateYTo* CCBRotateYTo::reverse() const
{
CCASSERT(false, "reverse() is not supported in CCBRotateXTo");
return nullptr;
}
void CCBRotateYTo::startWithTarget(Node *pNode)
{
// ActionInterval::startWithTarget(pNode);
_originalTarget = pNode;
_target = pNode;
_elapsed = 0.0f;
_firstTick = true;
_startAngle = _target->getRotationSkewY();
_diffAngle = _dstAngle - _startAngle;
}
void CCBRotateYTo::update(float time)
{
_target->setRotationSkewY(_startAngle + (_diffAngle * time));
}
/************************************************************
CCBEaseInstant
************************************************************/
CCBEaseInstant* CCBEaseInstant::create(ActionInterval *pAction)
{
CCBEaseInstant *pRet = new (std::nothrow) CCBEaseInstant();
if (pRet && pRet->initWithAction(pAction))
{
pRet->autorelease();
}
else
{
CC_SAFE_RELEASE_NULL(pRet);
}
return pRet;
}
CCBEaseInstant* CCBEaseInstant::clone() const
{
// no copy constructor
auto a = new (std::nothrow) CCBEaseInstant();
a->initWithAction(_inner);
a->autorelease();
return a;
}
CCBEaseInstant* CCBEaseInstant::reverse() const
{
return CCBEaseInstant::create(_inner->reverse());
}
void CCBEaseInstant::update(float dt)
{
if (dt < 0)
{
_inner->update(0);
}
else
{
_inner->update(1);
}
}
}