#include "CCBAnimationManager.h" #include "CCBSequence.h" #include "CCBSequenceProperty.h" #include "CCBReader.h" #include "CCBKeyframe.h" #include "CCNode+CCBRelativePositioning.h" #include #include #include "SimpleAudioEngine.h" #include "CCBSelectorResolver.h" using namespace cocos2d; using namespace std; NS_CC_EXT_BEGIN // Implementation of CCBAinmationManager CCBAnimationManager::CCBAnimationManager() : mSequences(NULL) , mNodeSequences(NULL) , mBaseValues(NULL) , mAutoPlaySequenceId(0) , mRootNode(NULL) , mRootContainerSize(Size::ZERO) , mDelegate(NULL) , mRunningSequence(NULL) , jsControlled(false) , mOwner(NULL) { init(); } bool CCBAnimationManager::init() { mSequences = new Array(); mNodeSequences = new Dictionary(); mBaseValues = new Dictionary(); mDocumentOutletNames = new Array(); mDocumentOutletNodes = new Array(); mDocumentCallbackNames = new Array(); mDocumentCallbackNodes = new Array(); mKeyframeCallbacks = new Array(); mKeyframeCallFuncs = new Dictionary(); mTarget = NULL; mAnimationCompleteCallbackFunc = NULL; return true; } CCBAnimationManager::~CCBAnimationManager() { // DictElement *pElement = NULL; // CCDICT_FOREACH(mNodeSequences, pElement) // { // Node *node = (Node*)pElement->getIntKey(); // node->release(); // } // // CCDICT_FOREACH(mBaseValues, pElement) // { // Node *node = (Node*)pElement->getIntKey(); // node->release(); // } mNodeSequences->release(); mBaseValues->release(); mSequences->release(); setRootNode(NULL); setDelegate(NULL); CC_SAFE_RELEASE(mDocumentOutletNames); CC_SAFE_RELEASE(mDocumentOutletNodes); CC_SAFE_RELEASE(mDocumentCallbackNames); CC_SAFE_RELEASE(mDocumentCallbackNodes); CC_SAFE_RELEASE(mKeyframeCallFuncs); CC_SAFE_RELEASE(mKeyframeCallbacks); CC_SAFE_RELEASE(mTarget); } Array* CCBAnimationManager::getSequences() { return mSequences; } void CCBAnimationManager::setSequences(Array* seq) { mSequences = seq; } int CCBAnimationManager::getAutoPlaySequenceId() { return mAutoPlaySequenceId; } void CCBAnimationManager::setAutoPlaySequenceId(int autoPlaySequenceId) { mAutoPlaySequenceId = autoPlaySequenceId; } Node* CCBAnimationManager::getRootNode() { return mRootNode; } void CCBAnimationManager::setRootNode(Node *pRootNode) { mRootNode = pRootNode; } void CCBAnimationManager::setDocumentControllerName(const std::string &name) { mDocumentControllerName = name; } std::string CCBAnimationManager::getDocumentControllerName() { return mDocumentControllerName; } void CCBAnimationManager::addDocumentCallbackNode(Node *node) { mDocumentCallbackNodes->addObject(node); } void CCBAnimationManager::addDocumentCallbackName(std::string name) { String *tmpName = String::create(name); mDocumentCallbackNames->addObject(tmpName); } Array* CCBAnimationManager::getDocumentCallbackNames() { return mDocumentCallbackNames; } Array* CCBAnimationManager::getDocumentCallbackNodes() { return mDocumentCallbackNodes; } void CCBAnimationManager::addDocumentOutletNode(Node *node) { mDocumentOutletNodes->addObject(node); } void CCBAnimationManager::addDocumentOutletName(std::string name) { mDocumentOutletNames->addObject(String::create(name)); } Array* CCBAnimationManager::getDocumentOutletNames() { return mDocumentOutletNames; } Array* CCBAnimationManager::getDocumentOutletNodes() { return mDocumentOutletNodes; } std::string CCBAnimationManager::getLastCompletedSequenceName() { return lastCompletedSequenceName; } Array* CCBAnimationManager::getKeyframeCallbacks() { return mKeyframeCallbacks; } const Size& CCBAnimationManager::getRootContainerSize() { return mRootContainerSize; } void CCBAnimationManager::setRootContainerSize(const Size &rootContainerSize) { mRootContainerSize.setSize(rootContainerSize.width, rootContainerSize.height); } CCBAnimationManagerDelegate* CCBAnimationManager::getDelegate() { return mDelegate; } void CCBAnimationManager::setDelegate(CCBAnimationManagerDelegate *pDelegate) { CC_SAFE_RELEASE(dynamic_cast(mDelegate)); mDelegate = pDelegate; CC_SAFE_RETAIN(dynamic_cast(mDelegate)); } const char* CCBAnimationManager::getRunningSequenceName() { if (mRunningSequence) { return mRunningSequence->getName(); } return NULL; } const Size& CCBAnimationManager::getContainerSize(Node *pNode) { if (pNode) { return pNode->getContentSize(); } else { return mRootContainerSize; } } // refer to CCBReader::readNodeGraph() for data structure of pSeq void CCBAnimationManager::addNode(Node *pNode, Dictionary *pSeq) { // pNode->retain(); mNodeSequences->setObject(pSeq, (intptr_t)pNode); } void CCBAnimationManager::setBaseValue(Object *pValue, Node *pNode, const char *pPropName) { Dictionary *props = (Dictionary*)mBaseValues->objectForKey((intptr_t)pNode); if (! props) { props = Dictionary::create(); mBaseValues->setObject(props, (intptr_t)pNode); // pNode->retain(); } props->setObject(pValue, pPropName); } Object* CCBAnimationManager::getBaseValue(Node *pNode, const char* pPropName) { Dictionary *props = (Dictionary*)mBaseValues->objectForKey((intptr_t)pNode); return props->objectForKey(pPropName); } int CCBAnimationManager::getSequenceId(const char* pSequenceName) { Object *pElement = NULL; string seqName(pSequenceName); CCARRAY_FOREACH(mSequences, pElement) { CCBSequence *seq = static_cast(pElement); if (seqName.compare(seq->getName()) == 0) { return seq->getSequenceId(); } } return -1; } CCBSequence* CCBAnimationManager::getSequence(int nSequenceId) { Object *pElement = NULL; CCARRAY_FOREACH(mSequences, pElement) { CCBSequence *seq = static_cast(pElement); if (seq->getSequenceId() == nSequenceId) { return seq; } } return NULL; } void CCBAnimationManager::moveAnimationsFromNode(Node* fromNode, Node* toNode) { // Move base values Object* baseValue = mBaseValues->objectForKey((intptr_t)fromNode); if(baseValue) { mBaseValues->setObject(baseValue, (intptr_t)toNode); mBaseValues->removeObjectForKey((intptr_t)fromNode); // fromNode->release(); // toNode->retain(); } // Move seqs Object *seqs = mNodeSequences->objectForKey((intptr_t)fromNode); if(seqs) { mNodeSequences->setObject(seqs, (intptr_t)toNode); mNodeSequences->removeObjectForKey((intptr_t)fromNode); // fromNode->release(); // toNode->retain(); } } // Refer to CCBReader::readKeyframe() for the real type of value ActionInterval* CCBAnimationManager::getAction(CCBKeyframe *pKeyframe0, CCBKeyframe *pKeyframe1, const char *pPropName, Node *pNode) { float duration = pKeyframe1->getTime() - (pKeyframe0 ? pKeyframe0->getTime() : 0); if (strcmp(pPropName, "rotationX") == 0) { CCBValue *value = (CCBValue*)pKeyframe1->getValue(); return CCBRotateXTo::create(duration, value->getFloatValue()); } else if(strcmp(pPropName, "rotationY") == 0) { CCBValue *value = (CCBValue*)pKeyframe1->getValue(); return CCBRotateYTo::create(duration, value->getFloatValue()); } else if (strcmp(pPropName, "rotation") == 0) { CCBValue *value = (CCBValue*)pKeyframe1->getValue(); return CCBRotateTo::create(duration, value->getFloatValue()); } else if (strcmp(pPropName, "opacity") == 0) { CCBValue *value = (CCBValue*)pKeyframe1->getValue(); return FadeTo::create(duration, value->getByteValue()); } else if (strcmp(pPropName, "color") == 0) { Color3BWapper* color = (Color3BWapper*)pKeyframe1->getValue(); Color3B c = color->getColor(); return TintTo::create(duration, c.r, c.g, c.b); } else if (strcmp(pPropName, "visible") == 0) { CCBValue *value = (CCBValue*)pKeyframe1->getValue(); if (value->getBoolValue()) { return Sequence::createWithTwoActions(DelayTime::create(duration), Show::create()); } else { return Sequence::createWithTwoActions(DelayTime::create(duration), Hide::create()); } } else if (strcmp(pPropName, "displayFrame") == 0) { return Sequence::createWithTwoActions(DelayTime::create(duration), CCBSetSpriteFrame::create((SpriteFrame *)pKeyframe1->getValue())); } else if (strcmp(pPropName, "position") == 0) { // Get position type Array *array = (Array*)getBaseValue(pNode, pPropName); int type = ((CCBValue*)array->objectAtIndex(2))->getIntValue(); // Get relative position Array *value = (Array*)pKeyframe1->getValue(); float x = ((CCBValue*)value->objectAtIndex(0))->getFloatValue(); float y = ((CCBValue*)value->objectAtIndex(1))->getFloatValue(); Size containerSize = getContainerSize(pNode->getParent()); Point absPos = getAbsolutePosition(Point(x,y), type, containerSize, pPropName); return MoveTo::create(duration, absPos); } else if (strcmp(pPropName, "scale") == 0) { // Get position type Array *array = (Array*)getBaseValue(pNode, pPropName); int type = ((CCBValue*)array->objectAtIndex(2))->getIntValue(); // Get relative scale Array *value = (Array*)pKeyframe1->getValue(); float x = ((CCBValue*)value->objectAtIndex(0))->getFloatValue(); float y = ((CCBValue*)value->objectAtIndex(1))->getFloatValue(); if (type == kCCBScaleTypeMultiplyResolution) { float resolutionScale = CCBReader::getResolutionScale(); x *= resolutionScale; y *= resolutionScale; } return ScaleTo::create(duration, x, y); } else if(strcmp(pPropName, "skew") == 0) { // Get relative skew Array *value = (Array*)pKeyframe1->getValue(); float x = ((CCBValue*)value->objectAtIndex(0))->getFloatValue(); float y = ((CCBValue*)value->objectAtIndex(1))->getFloatValue(); return SkewTo::create(duration, x, y); } else { CCLog("CCBReader: Failed to create animation for property: %s", pPropName); } return NULL; } void CCBAnimationManager::setAnimatedProperty(const char *pPropName, Node *pNode, Object *pValue, float fTweenDuration) { if (fTweenDuration > 0) { // Create a fake keyframe to generate the action from CCBKeyframe *kf1 = new CCBKeyframe(); kf1->autorelease(); kf1->setValue(pValue); kf1->setTime(fTweenDuration); kf1->setEasingType(kCCBKeyframeEasingLinear); // Animate ActionInterval *tweenAction = getAction(NULL, kf1, pPropName, pNode); pNode->runAction(tweenAction); } else { // Just set the value if (strcmp(pPropName, "position") == 0) { // Get position type Array *array = (Array*)getBaseValue(pNode, pPropName); int type = ((CCBValue*)array->objectAtIndex(2))->getIntValue(); // Get relative position Array *value = (Array*)pValue; float x = ((CCBValue*)value->objectAtIndex(0))->getFloatValue(); float y = ((CCBValue*)value->objectAtIndex(1))->getFloatValue(); pNode->setPosition(getAbsolutePosition(Point(x,y), type, getContainerSize(pNode->getParent()), pPropName)); } else if (strcmp(pPropName, "scale") == 0) { // Get scale type Array *array = (Array*)getBaseValue(pNode, pPropName); int type = ((CCBValue*)array->objectAtIndex(2))->getIntValue(); // Get relative scale Array *value = (Array*)pValue; float x = ((CCBValue*)value->objectAtIndex(0))->getFloatValue(); float y = ((CCBValue*)value->objectAtIndex(1))->getFloatValue(); setRelativeScale(pNode, x, y, type, pPropName); } else if(strcmp(pPropName, "skew") == 0) { // Get relative scale Array *value = (Array*)pValue; float x = ((CCBValue*)value->objectAtIndex(0))->getFloatValue(); float y = ((CCBValue*)value->objectAtIndex(1))->getFloatValue(); pNode->setSkewX(x); pNode->setSkewY(y); } else { // [node setValue:value forKey:name]; // TODO only handle rotation, opacity, displayFrame, color if (strcmp(pPropName, "rotation") == 0) { float rotate = ((CCBValue*)pValue)->getFloatValue(); pNode->setRotation(rotate); } else if(strcmp(pPropName, "rotationX") == 0) { float rotate = ((CCBValue*)pValue)->getFloatValue(); pNode->setRotationX(rotate); }else if(strcmp(pPropName, "rotationY") == 0) { float rotate = ((CCBValue*)pValue)->getFloatValue(); pNode->setRotationY(rotate); } else if (strcmp(pPropName, "opacity") == 0) { int opacity = ((CCBValue*)pValue)->getByteValue(); (dynamic_cast(pNode))->setOpacity(opacity); } else if (strcmp(pPropName, "displayFrame") == 0) { ((Sprite*)pNode)->setDisplayFrame((SpriteFrame*)pValue); } else if (strcmp(pPropName, "color") == 0) { Color3BWapper *color = (Color3BWapper*)pValue; (dynamic_cast(pNode))->setColor(color->getColor()); } else if (strcmp(pPropName, "visible") == 0) { bool visible = ((CCBValue*)pValue)->getBoolValue(); pNode->setVisible(visible); } else { CCLog("unsupported property name is %s", pPropName); CCASSERT(false, "unsupported property now"); } } } } void CCBAnimationManager::setFirstFrame(Node *pNode, CCBSequenceProperty *pSeqProp, float fTweenDuration) { Array *keyframes = pSeqProp->getKeyframes(); if (keyframes->count() == 0) { // Use base value (no animation) Object *baseValue = getBaseValue(pNode, pSeqProp->getName()); CCASSERT(baseValue, "No baseValue found for property"); setAnimatedProperty(pSeqProp->getName(), pNode, baseValue, fTweenDuration); } else { // Use first keyframe CCBKeyframe *keyframe = (CCBKeyframe*)keyframes->objectAtIndex(0); setAnimatedProperty(pSeqProp->getName(), pNode, keyframe->getValue(), fTweenDuration); } } ActionInterval* CCBAnimationManager::getEaseAction(ActionInterval *pAction, int nEasingType, float fEasingOpt) { if (dynamic_cast(pAction)) { return pAction; } if (nEasingType == kCCBKeyframeEasingLinear) { return pAction; } else if (nEasingType == kCCBKeyframeEasingInstant) { return CCBEaseInstant::create(pAction); } else if (nEasingType == kCCBKeyframeEasingCubicIn) { return EaseIn::create(pAction, fEasingOpt); } else if (nEasingType == kCCBKeyframeEasingCubicOut) { return EaseOut::create(pAction, fEasingOpt); } else if (nEasingType == kCCBKeyframeEasingCubicInOut) { return EaseInOut::create(pAction, fEasingOpt); } else if (nEasingType == kCCBKeyframeEasingBackIn) { return EaseBackIn::create(pAction); } else if (nEasingType == kCCBKeyframeEasingBackOut) { return EaseBackOut::create(pAction); } else if (nEasingType == kCCBKeyframeEasingBackInOut) { return EaseBackInOut::create(pAction); } else if (nEasingType == kCCBKeyframeEasingBounceIn) { return EaseBounceIn::create(pAction); } else if (nEasingType == kCCBKeyframeEasingBounceOut) { return EaseBounceOut::create(pAction); } else if (nEasingType == kCCBKeyframeEasingBounceInOut) { return EaseBounceInOut::create(pAction); } else if (nEasingType == kCCBKeyframeEasingElasticIn) { return EaseElasticIn::create(pAction, fEasingOpt); } else if (nEasingType == kCCBKeyframeEasingElasticOut) { return EaseElasticOut::create(pAction, fEasingOpt); } else if (nEasingType == kCCBKeyframeEasingElasticInOut) { return EaseElasticInOut::create(pAction, fEasingOpt); } else { CCLog("CCBReader: Unkown easing type %d", nEasingType); return pAction; } } Object* CCBAnimationManager::actionForCallbackChannel(CCBSequenceProperty* channel) { float lastKeyframeTime = 0; Array *actions = Array::create(); Array *keyframes = channel->getKeyframes(); int numKeyframes = keyframes->count(); for (int i = 0; i < numKeyframes; ++i) { CCBKeyframe *keyframe = (CCBKeyframe*)keyframes->objectAtIndex(i); float timeSinceLastKeyframe = keyframe->getTime() - lastKeyframeTime; lastKeyframeTime = keyframe->getTime(); if(timeSinceLastKeyframe > 0) { actions->addObject(DelayTime::create(timeSinceLastKeyframe)); } Array* keyVal = (Array *)keyframe->getValue(); std::string selectorName = ((String *)keyVal->objectAtIndex(0))->getCString(); int selectorTarget = atoi(((String *)keyVal->objectAtIndex(1))->getCString()); if(jsControlled) { String* callbackName = String::createWithFormat("%d:%s", selectorTarget, selectorName.c_str()); CallFunc *callback = ((CallFunc*)(mKeyframeCallFuncs->objectForKey(callbackName->getCString())))->clone(); if(callback != NULL) { actions->addObject(callback); } } else { Object* target = NULL; if(selectorTarget == kCCBTargetTypeDocumentRoot) target = mRootNode; else if (selectorTarget == kCCBTargetTypeOwner) target = mOwner; if(target != NULL) { if(selectorName.length() > 0) { SEL_CallFuncN selCallFunc = 0; CCBSelectorResolver* targetAsCCBSelectorResolver = dynamic_cast(target); if(targetAsCCBSelectorResolver != NULL) { selCallFunc = targetAsCCBSelectorResolver->onResolveCCBCallFuncSelector(target, selectorName.c_str ()); } if(selCallFunc == 0) { CCLOG("Skipping selector '%s' since no CCBSelectorResolver is present.", selectorName.c_str()); } else { CallFuncN *callback = CallFuncN::create(target, selCallFunc); actions->addObject(callback); } } else { CCLOG("Unexpected empty selector."); } } } } if(actions->count() < 1) return NULL; return (Object *) Sequence::create(actions); } Object* CCBAnimationManager::actionForSoundChannel(CCBSequenceProperty* channel) { float lastKeyframeTime = 0; Array *actions = Array::create(); Array *keyframes = channel->getKeyframes(); int numKeyframes = keyframes->count(); for (int i = 0; i < numKeyframes; ++i) { CCBKeyframe *keyframe = (CCBKeyframe*)keyframes->objectAtIndex(i); float timeSinceLastKeyframe = keyframe->getTime() - lastKeyframeTime; lastKeyframeTime = keyframe->getTime(); if(timeSinceLastKeyframe > 0) { actions->addObject(DelayTime::create(timeSinceLastKeyframe)); } stringstream ss (stringstream::in | stringstream::out); Array* keyVal = (Array*)keyframe->getValue(); std::string soundFile = ((String *)keyVal->objectAtIndex(0))->getCString(); float pitch, pan, gain; ss << ((String *)keyVal->objectAtIndex(1))->getCString(); ss >> pitch; ss.flush(); ss << ((String *)keyVal->objectAtIndex(2))->getCString(); ss >> pan; ss.flush(); ss << ((String *)keyVal->objectAtIndex(3))->getCString(); ss >> gain; ss.flush(); actions->addObject(CCBSoundEffect::actionWithSoundFile(soundFile, pitch, pan, gain)); } if(actions->count() < 1) return NULL; return (Object *) Sequence::create(actions); } void CCBAnimationManager::runAction(Node *pNode, CCBSequenceProperty *pSeqProp, float fTweenDuration) { Array *keyframes = pSeqProp->getKeyframes(); int numKeyframes = keyframes->count(); if (numKeyframes > 1) { // Make an animation! Array *actions = Array::create(); CCBKeyframe *keyframeFirst = (CCBKeyframe*)keyframes->objectAtIndex(0); float timeFirst = keyframeFirst->getTime() + fTweenDuration; if (timeFirst > 0) { actions->addObject(DelayTime::create(timeFirst)); } for (int i = 0; i < numKeyframes - 1; ++i) { CCBKeyframe *kf0 = (CCBKeyframe*)keyframes->objectAtIndex(i); CCBKeyframe *kf1 = (CCBKeyframe*)keyframes->objectAtIndex(i+1); ActionInterval *action = getAction(kf0, kf1, pSeqProp->getName(), pNode); if (action) { // Apply easing action = getEaseAction(action, kf0->getEasingType(), kf0->getEasingOpt()); actions->addObject(action); } } FiniteTimeAction *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"); mRootNode->stopAllActions(); DictElement* pElement = NULL; CCDICT_FOREACH(mNodeSequences, pElement) { Node *node = reinterpret_cast(pElement->getIntKey()); node->stopAllActions(); // Refer to CCBReader::readKeyframe() for the real type of value Dictionary *seqs = (Dictionary*)pElement->getObject(); Dictionary *seqNodeProps = (Dictionary*)seqs->objectForKey(nSeqId); set seqNodePropNames; if (seqNodeProps) { // Reset nodes that have sequence node properties, and run actions on them DictElement* pElement1 = NULL; CCDICT_FOREACH(seqNodeProps, pElement1) { const char *propName = pElement1->getStrKey(); CCBSequenceProperty *seqProp = static_cast(seqNodeProps->objectForKey(propName)); seqNodePropNames.insert(propName); setFirstFrame(node, seqProp, fTweenDuration); runAction(node, seqProp, fTweenDuration); } } // Reset the nodes that may have been changed by other timelines Dictionary *nodeBaseValues = (Dictionary*)mBaseValues->objectForKey(pElement->getIntKey()); if (nodeBaseValues) { DictElement* pElement2 = NULL; CCDICT_FOREACH(nodeBaseValues, pElement2) { if (seqNodePropNames.find(pElement2->getStrKey()) == seqNodePropNames.end()) { Object *value = pElement2->getObject(); if (value) { setAnimatedProperty(pElement2->getStrKey(), node, value, 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))); mRootNode->runAction(completeAction); // Set the running scene if(seq->getCallbackChannel() != NULL) { Action* action = (Action *)actionForCallbackChannel(seq->getCallbackChannel()); if(action != NULL) { mRootNode->runAction(action); } } if(seq->getSoundChannel() != NULL) { Action* action = (Action *)actionForSoundChannel(seq->getSoundChannel()); if(action != NULL) { mRootNode->runAction(action); } } mRunningSequence = 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(Object *target, SEL_CallFunc callbackFunc) { if (target) { target->retain(); } if (mTarget) { mTarget->release(); } mTarget = target; mAnimationCompleteCallbackFunc = callbackFunc; } void CCBAnimationManager::setCallFunc(CallFunc* callFunc, const std::string &callbackNamed) { mKeyframeCallFuncs->setObject((Object*)callFunc, callbackNamed); } void CCBAnimationManager::sequenceCompleted() { const char *runningSequenceName = mRunningSequence->getName(); int nextSeqId = mRunningSequence->getChainedSequenceId(); mRunningSequence = NULL; if(lastCompletedSequenceName != runningSequenceName) { lastCompletedSequenceName = runningSequenceName; } if (mDelegate) { // There may be another runAnimation() call in this delegate method // which will assign mRunningSequence mDelegate->completedAnimationSequenceNamed(runningSequenceName); } if (mTarget && mAnimationCompleteCallbackFunc) { (mTarget->*mAnimationCompleteCallbackFunc)(); } if (nextSeqId != -1) { runAnimationsForSequenceIdTweenDuration(nextSeqId, 0); } } // Custom actions /************************************************************ CCBSetSpriteFrame ************************************************************/ CCBSetSpriteFrame* CCBSetSpriteFrame::create(SpriteFrame *pSpriteFrame) { CCBSetSpriteFrame *ret = new CCBSetSpriteFrame(); if (ret) { if (ret->initWithSpriteFrame(pSpriteFrame)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBSetSpriteFrame::initWithSpriteFrame(SpriteFrame *pSpriteFrame) { mSpriteFrame = pSpriteFrame; CC_SAFE_RETAIN(mSpriteFrame); return true; } CCBSetSpriteFrame::~CCBSetSpriteFrame() { CC_SAFE_RELEASE_NULL(mSpriteFrame); } CCBSetSpriteFrame* CCBSetSpriteFrame::clone() const { // no copy constructor auto a = new CCBSetSpriteFrame(); a->initWithSpriteFrame(mSpriteFrame); a->autorelease(); return a; } CCBSetSpriteFrame* CCBSetSpriteFrame::reverse() const { // returns a copy of itself return this->clone(); } void CCBSetSpriteFrame::update(float time) { ((Sprite*)_target)->setDisplayFrame(mSpriteFrame); } /************************************************************ CCBSoundEffect ************************************************************/ CCBSoundEffect* CCBSoundEffect::actionWithSoundFile(const std::string &filename, float pitch, float pan, float gain) { CCBSoundEffect* pRet = new CCBSoundEffect(); if (pRet != NULL && 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) { mSoundFile = filename; mPitch = pitch; mPan = pan; mGain = gain; return true; } CCBSoundEffect* CCBSoundEffect::clone() const { // no copy constructor auto a = new CCBSoundEffect(); a->initWithSoundFile(mSoundFile, mPitch, mPan, mGain); 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(mSoundFile.c_str()); } /************************************************************ CCBRotateTo ************************************************************/ CCBRotateTo* CCBRotateTo::create(float fDuration, float fAngle) { CCBRotateTo *ret = new 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)) { mDstAngle = fAngle; return true; } else { return false; } } CCBRotateTo* CCBRotateTo::clone() const { // no copy constructor auto a = new CCBRotateTo(); a->initWithDuration(_duration, mDstAngle); 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); mStartAngle = _target->getRotation(); mDiffAngle = mDstAngle - mStartAngle; } void CCBRotateTo::update(float time) { _target->setRotation(mStartAngle + (mDiffAngle * time)) ; } /************************************************************ CCBRotateXTO ************************************************************/ CCBRotateXTo* CCBRotateXTo::create(float fDuration, float fAngle) { CCBRotateXTo *ret = new 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)) { mDstAngle = fAngle; return true; } else { return false; } } void CCBRotateXTo::startWithTarget(Node *pNode) { //CCActionInterval::startWithTarget(pNode); _originalTarget = pNode; _target = pNode; _elapsed = 0.0f; _firstTick = true; mStartAngle = _target->getRotationX(); mDiffAngle = mDstAngle - mStartAngle; } CCBRotateXTo* CCBRotateXTo::clone() const { // no copy constructor auto a = new CCBRotateXTo(); a->initWithDuration(_duration, mDstAngle); a->autorelease(); return a; } CCBRotateXTo* CCBRotateXTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBRotateXTo"); return nullptr; } void CCBRotateXTo::update(float time) { _target->setRotationX(mStartAngle + (mDiffAngle * time)) ; } /************************************************************ CCBRotateYTO ************************************************************/ CCBRotateYTo* CCBRotateYTo::create(float fDuration, float fAngle) { CCBRotateYTo *ret = new 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)) { mDstAngle = fAngle; return true; } else { return false; } } CCBRotateYTo* CCBRotateYTo::clone() const { // no copy constructor auto a = new CCBRotateYTo(); a->initWithDuration(_duration, mDstAngle); 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; mStartAngle = _target->getRotationY(); mDiffAngle = mDstAngle - mStartAngle; } void CCBRotateYTo::update(float time) { _target->setRotationY(mStartAngle + (mDiffAngle * time)) ; } /************************************************************ CCBEaseInstant ************************************************************/ CCBEaseInstant* CCBEaseInstant::create(ActionInterval *pAction) { CCBEaseInstant *pRet = new 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 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); } } NS_CC_EXT_END