#include "editor-support/cocosbuilder/CCBAnimationManager.h" #include "editor-support/cocosbuilder/CCBReader.h" #include "editor-support/cocosbuilder/CCNode+CCBRelativePositioning.h" #include "audio/include/AudioEngine.h" #include "editor-support/cocosbuilder/CCBSelectorResolver.h" #include #include #include #include "common/CocosConfig.h" using namespace cocos2d; using namespace std; using namespace cocos2d::extension; using namespace experimental; namespace cocosbuilder { // Implementation of CCBAinmationManager CCBAnimationManager::CCBAnimationManager() : _jsControlled(false) , _owner(nullptr) , _autoPlaySequenceId(0) , _rootNode(nullptr) , _rootContainerSize(Size::ZERO) , _delegate(nullptr) , _runningSequence(nullptr) , _speed(1.0f) { 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& CCBAnimationManager::getSequences() { return _sequences; } void CCBAnimationManager::setSequences(const Vector& 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(eventType))); } ValueVector& CCBAnimationManager::getDocumentCallbackNames() { return _documentCallbackNames; } Vector& 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& 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(_delegate)); _delegate = pDelegate; CC_SAFE_RETAIN(dynamic_cast(_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>& 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; } std::string CCBAnimationManager::getCCBFileName(){ return _ccbFileName; } void CCBAnimationManager::setCCBFileName(std::string filename){ _ccbFileName = filename; } 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(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 if (propName == "frameIndex") { return CCBFrameIndexTo::create(duration, pKeyframe0->getValue().asByte(), pKeyframe1->getValue().asByte()); } else if (propName == "posVar"){ //粒子发射器大小 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticlePosVarTo::create(duration, Vec2(x,y)); } else if (propName == "gravity"){ // 粒子重力 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBGravityTo::create(duration, Vec2(x,y)); } else if(propName == "speed"){ // 粒子速度 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleSpeedTo::create(duration, Vec2(x,y)); } else if(propName == "life"){ // 粒子生命 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleLifeTo::create(duration, Vec2(x,y)); } else if(propName == "startSize"){ // 初始尺寸 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleStartSizeTo::create(duration, Vec2(x,y)); } else if(propName == "endSize"){ // 结束尺寸 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleEndSizeTo::create(duration, Vec2(x,y)); } else if(propName == "startSpin"){ // 开始旋转角度: auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleStartSpinTo::create(duration, Vec2(x,y)); } else if(propName == "endSpin"){ // 结束旋转角度 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleEndSpinTo::create(duration, Vec2(x,y)); } else if(propName == "angle"){ // 发射角度 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleAngleTo::create(duration, Vec2(x,y)); } else if(propName == "tangentialAccel"){ // 切向加速度 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleTangentialAccelTo::create(duration, Vec2(x,y)); } else if(propName == "radialAccel"){ // 径向加速度: auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleRadialAccelTo::create(duration, Vec2(x,y)); } else if(propName == "startRadius"){ // 开始半径: auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleStartRadiusTo::create(duration, Vec2(x,y)); } else if(propName == "endRadius"){ // 结束半径 auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleEndRadiusTo::create(duration, Vec2(x,y)); } else if(propName == "rotatePerSecond"){ // 旋转: auto& value = pKeyframe1->getValue().asValueVector(); float x = value[0].asFloat(); float y = value[1].asFloat(); return CCBParticleRotatePerSecondTo::create(duration, Vec2(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(pNode)->setSpriteFrame(static_cast(obj)); }else if(propName == "progressFrame"){ static_cast(pNode)->setSpriteFrame(static_cast(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 if (propName == "frameIndex") { unsigned char frameIndex = value.asByte(); static_cast(pNode)->setFrameIndex(frameIndex); } else if (propName == "posVar"){ // 粒子发射器尺寸 auto& valueVector = value.asValueVector(); float gx = valueVector[0].asFloat(); float gy = valueVector[1].asFloat(); static_cast(pNode)->setPosVar(Vec2(gx, gy)); } else if (propName == "gravity") { // 粒子重力 auto& valueVector = value.asValueVector(); float gx = valueVector[0].asFloat(); float gy = valueVector[1].asFloat(); static_cast(pNode)->setGravity(Vec2(gx, gy)); } else if (propName == "speed") { // 粒子速度 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setSpeed(speed); static_cast(pNode)->setSpeedVar(speedVar); } else if(propName == "life"){ // 粒子生命 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setLife(speed); static_cast(pNode)->setLifeVar(speedVar); } else if(propName == "startSize"){ // 初始尺寸 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setStartSize(speed); static_cast(pNode)->setStartSizeVar(speedVar); } else if(propName == "endSize"){ // 结束尺寸 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setEndSize(speed); static_cast(pNode)->setEndSizeVar(speedVar); } else if(propName == "startSpin"){ // 开始旋转角度: auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setStartSpin(speed); static_cast(pNode)->setStartSpinVar(speedVar); } else if(propName == "endSpin"){ // 结束旋转角度 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setEndSpin(speed); static_cast(pNode)->setEndSpinVar(speedVar); } else if(propName == "angle"){ // 发射角度 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setAngle(speed); static_cast(pNode)->setAngleVar(speedVar); } else if(propName == "tangentialAccel"){ // 切向加速度 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setTangentialAccel(speed); static_cast(pNode)->setTangentialAccelVar(speedVar); } else if(propName == "radialAccel"){ // 径向加速度: auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setRadialAccel(speed); static_cast(pNode)->setRadialAccelVar(speedVar); } else if(propName == "startRadius"){ // 开始半径: auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setStartSpin(speed); static_cast(pNode)->setStartSpinVar(speedVar); } else if(propName == "endRadius"){ // 结束半径 auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setEndRadius(speed); static_cast(pNode)->setEndRadiusVar(speedVar); } else if(propName == "rotatePerSecond"){ // 旋转: auto& valueVector = value.asValueVector(); float speed = valueVector[0].asFloat(); float speedVar = valueVector[1].asFloat(); static_cast(pNode)->setRotatePerSecond(speed); static_cast(pNode)->setRotatePerSecondVar(speedVar); } 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(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(easingType)); return pAction; } } Sequence* CCBAnimationManager::actionForCallbackChannel(CCBSequenceProperty* channel) { float lastKeyframeTime = 0; Vector 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(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(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>(); 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 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 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); } } //add song auto seq = Sequence::create(actions); auto speed = Speed::create(seq, _speed); speed->setTag(101); pNode->runAction(speed); } } void CCBAnimationManager::updateSpeed(float speed, Node* node) { std::vector actions; _rootNode->getActionManager()->getActionsByTag(101, node, actions); std::vector::iterator iter = actions.begin(); while (iter != actions.end()) { Speed* sp = dynamic_cast(*iter); if (sp != nullptr) { sp->setSpeed(_speed); } iter ++; } Vector children = node->getChildren(); Vector::iterator iter2 = children.begin(); while (iter2 != children.end()) { updateSpeed(speed, *iter2); iter2 ++; } } void CCBAnimationManager::updateSpeed(float speed) { _speed = speed; updateSpeed(speed, _rootNode); } const std::unordered_map>> & CCBAnimationManager::getNodeSequences(){ return _nodeSequences; } 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 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); if (seq == nullptr) { CCASSERT(false, "Sequence id couldn't be found"); return; } ActionInterval *completeAction = Sequence::createWithTwoActions(DelayTime::create((seq->getDuration() + fTweenDuration)), CallFunc::create( CC_CALLBACK_0(CCBAnimationManager::sequenceCompleted,this))); auto speed = Speed::create(completeAction, _speed); speed->setTag(101); _rootNode->runAction(speed); // 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); } //add by djd Spawn* CCBAnimationManager::getNodeAniByName(const char *pName, Node* pNode,Vec2 orginPos){ Spawn *tAction = nullptr; int nSeqId = getSequenceId(pName); for (auto nodeSeqIter = _nodeSequences.begin(); nodeSeqIter != _nodeSequences.end(); ++nodeSeqIter) { Node *node = nodeSeqIter->first; if (node != pNode) { continue; } // Refer to CCBReader::readKeyframe() for the real type of value auto seqs = nodeSeqIter->second; auto seqNodeProps = seqs[nSeqId]; if (!seqNodeProps.empty()) { // Reset nodes that have sequence node properties, and run actions on them Vector seqList; for (auto iter = seqNodeProps.begin(); iter != seqNodeProps.end(); ++iter) { const std::string propName = iter->first; CCBSequenceProperty *pSeqProp = iter->second; auto& keyframes = pSeqProp->getKeyframes(); ssize_t numKeyframes = keyframes.size(); if (numKeyframes > 1) { // Make an animation! Vector actions; CCBKeyframe *keyframeFirst = keyframes.at(0); float timeFirst = keyframeFirst->getTime(); 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 = nullptr; //重写position if (strcmp(pSeqProp->getName(), "position") == 0) { float duration = kf1->getTime() - (kf0 ? kf0->getTime() : 0); // Get position type auto& array = getBaseValue(pNode, propName).asValueVector(); CCBReader::PositionType type = (CCBReader::PositionType)array[2].asInt(); // Get relative position auto value = kf1->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); action = MoveTo::create(duration, Vec2(absPos.x + orginPos.x, absPos.y + orginPos.y)); }else{ 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); seqList.pushBack(seq); } } tAction = Spawn::create(seqList); } break; } return tAction; } int CCBAnimationManager::runAnimationsForSequenceNamedTweenDuration(const char *pName, float fTweenDuration) { int seqId = getSequenceId(pName); if (seqId != -1) { runAnimationsForSequenceIdTweenDuration(seqId, fTweenDuration); } else { // logCppErrMsg("ACT:%s", pName); return -1; } return 0; } int CCBAnimationManager::runAnimationsForSequenceNamed(const char *pName) { return 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) { ActionInstant::update(time); static_cast(_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) { ActionInstant::update(time); if (!CocosConfig::getCCBAudioEnable()) return; string efx = CocosConfig::getCcbEfxPrefix() + _soundFile; CCLOG("playEffect:%s",efx.c_str()); int soundId = AudioEngine::play2d(efx); if (CocosConfig::pushNotificationWhenCCBSoundPlayed()) { __Integer *i = __Integer::create(soundId); __NotificationCenter::getInstance()->postNotification("CCB_PLAY_SOUND", i); } } /************************************************************ 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)); } /************************************************************ CCBFrameIndexTo ************************************************************/ CCBFrameIndexTo* CCBFrameIndexTo::create(float fDuration, int startIndex, int endIndex) { CCBFrameIndexTo *ret = new (std::nothrow) CCBFrameIndexTo(); if (ret) { if (ret->initWithDuration(fDuration, startIndex, endIndex)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBFrameIndexTo::initWithDuration(float fDuration, int startIndex, int endIndex) { if (ActionInterval::initWithDuration(fDuration)) { _startIndex = startIndex; _endIndex = endIndex; return true; } else { return false; } } CCBFrameIndexTo* CCBFrameIndexTo::clone() const { auto a = new (std::nothrow) CCBFrameIndexTo(); a->initWithDuration(_duration, _startIndex, _endIndex); a->autorelease(); return a; } CCBFrameIndexTo* CCBFrameIndexTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBFrameIndexTo"); return nullptr; } void CCBFrameIndexTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); _diffIndex = _endIndex - _startIndex; } void CCBFrameIndexTo::update(float time) { auto fasp = dynamic_cast(_target); CCASSERT(fasp != nullptr, "CCBFrameIndexTo 只支持 ZGFrameActionSprite类型的图片"); auto frameIndex = (int)(_startIndex + (_diffIndex * time)); fasp->setFrameIndex(frameIndex); } /************************************************************ CCBParticlePosVarTo ************************************************************/ CCBParticlePosVarTo* CCBParticlePosVarTo::create(float fDuration, cocos2d::Vec2 pos){ CCBParticlePosVarTo *ret = new (std::nothrow) CCBParticlePosVarTo(); if (ret) { if (ret->initWithDuration(fDuration, pos)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticlePosVarTo::initWithDuration(float fDuration, cocos2d::Vec2 pos){ if (ActionInterval::initWithDuration(fDuration)) { _endGravity = pos; return true; } else { return false; } } CCBParticlePosVarTo* CCBParticlePosVarTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticlePosVarTo(); a->initWithDuration(_duration, _endGravity); a->autorelease(); return a; } CCBParticlePosVarTo* CCBParticlePosVarTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticlePosVarTo"); return nullptr; } void CCBParticlePosVarTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); _startGravity = dynamic_cast(pNode)->getPosVar(); _diffGravity = _endGravity - _startGravity; } void CCBParticlePosVarTo::update(float time){ auto fasp = dynamic_cast(_target); CCASSERT(fasp != nullptr, "CCBGravityTo 只支持 ParticleSystem"); auto gravity = _startGravity + (_diffGravity * time); fasp->setPosVar(gravity); } /************************************************************ CCBGravityTo ************************************************************/ CCBGravityTo* CCBGravityTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBGravityTo *ret = new (std::nothrow) CCBGravityTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBGravityTo::initWithDuration(float fDuration, cocos2d::Vec2 gravity){ if (ActionInterval::initWithDuration(fDuration)) { _endGravity = gravity; return true; } else { return false; } } CCBGravityTo* CCBGravityTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBGravityTo(); a->initWithDuration(_duration, _endGravity); a->autorelease(); return a; } CCBGravityTo* CCBGravityTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBGravityTo"); return nullptr; } void CCBGravityTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); _startGravity = dynamic_cast(pNode)->getGravity(); _diffGravity = _endGravity - _startGravity; } void CCBGravityTo::update(float time){ auto fasp = dynamic_cast(_target); CCASSERT(fasp != nullptr, "CCBGravityTo 只支持 ParticleSystem"); auto gravity = _startGravity + (_diffGravity * time); fasp->setGravity(gravity); } /************************************************************ CCBParticleSpeedTo ************************************************************/ //粒子速度 CCBParticleSpeedTo* CCBParticleSpeedTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBParticleSpeedTo *ret = new (std::nothrow) CCBParticleSpeedTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleSpeedTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleSpeedTo* CCBParticleSpeedTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleSpeedTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleSpeedTo* CCBParticleSpeedTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleSpeedTo"); return nullptr; } void CCBParticleSpeedTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getSpeed(); float aVar = dynamic_cast(pNode)->getSpeedVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleSpeedTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setSpeed(floatVar.x); par->setSpeedVar(floatVar.y); } /************************************************************ CCBParticleLifeTo ************************************************************/ //粒子生命 CCBParticleLifeTo* CCBParticleLifeTo::create(float fDuration, cocos2d::Vec2 folatVar){ CCBParticleLifeTo *ret = new (std::nothrow) CCBParticleLifeTo(); if (ret) { if (ret->initWithDuration(fDuration, folatVar)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleLifeTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleLifeTo* CCBParticleLifeTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleLifeTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleLifeTo* CCBParticleLifeTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleLifeTo"); return nullptr; } void CCBParticleLifeTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getLife(); float aVar = dynamic_cast(pNode)->getLifeVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleLifeTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setLife(floatVar.x); par->setLifeVar(floatVar.y); } /************************************************************ CCBParticleStartSizeTo ************************************************************/ //粒子初始尺寸 CCBParticleStartSizeTo* CCBParticleStartSizeTo::create(float fDuration, cocos2d::Vec2 folatVar){ CCBParticleStartSizeTo *ret = new (std::nothrow) CCBParticleStartSizeTo(); if (ret) { if (ret->initWithDuration(fDuration, folatVar)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleStartSizeTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleStartSizeTo* CCBParticleStartSizeTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleStartSizeTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleStartSizeTo* CCBParticleStartSizeTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleStartSizeTo"); return nullptr; } void CCBParticleStartSizeTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getStartSize(); float aVar = dynamic_cast(pNode)->getStartSizeVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleStartSizeTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setStartSize(floatVar.x); par->setStartSizeVar(floatVar.y); } /************************************************************ CCBParticleEndSizeTo ************************************************************/ //粒子结束时的尺寸大小 CCBParticleEndSizeTo* CCBParticleEndSizeTo::create(float fDuration, cocos2d::Vec2 folatVar){ CCBParticleEndSizeTo *ret = new (std::nothrow) CCBParticleEndSizeTo(); if (ret) { if (ret->initWithDuration(fDuration, folatVar)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleEndSizeTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleEndSizeTo* CCBParticleEndSizeTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleEndSizeTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleEndSizeTo* CCBParticleEndSizeTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleEndSizeTo"); return nullptr; } void CCBParticleEndSizeTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getEndSize(); float aVar = dynamic_cast(pNode)->getEndSizeVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleEndSizeTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setEndSize(floatVar.x); par->setEndSizeVar(floatVar.y); } /************************************************************ CCBParticleStartSpinTo ************************************************************/ //粒子速度 CCBParticleStartSpinTo* CCBParticleStartSpinTo::create(float fDuration, cocos2d::Vec2 folatVar){ CCBParticleStartSpinTo *ret = new (std::nothrow) CCBParticleStartSpinTo(); if (ret) { if (ret->initWithDuration(fDuration, folatVar)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleStartSpinTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleStartSpinTo* CCBParticleStartSpinTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleStartSpinTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleStartSpinTo* CCBParticleStartSpinTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleStartSpinTo"); return nullptr; } void CCBParticleStartSpinTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getStartSpin(); float aVar = dynamic_cast(pNode)->getStartSpinVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleStartSpinTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setStartSpin(floatVar.x); par->setStartSpinVar(floatVar.y); } /************************************************************ CCBParticleEndSpinTo ************************************************************/ //粒子结束角度 CCBParticleEndSpinTo* CCBParticleEndSpinTo::create(float fDuration, cocos2d::Vec2 folatVar){ CCBParticleEndSpinTo *ret = new (std::nothrow) CCBParticleEndSpinTo(); if (ret) { if (ret->initWithDuration(fDuration, folatVar)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleEndSpinTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleEndSpinTo* CCBParticleEndSpinTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleEndSpinTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleEndSpinTo* CCBParticleEndSpinTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleEndSpinTo"); return nullptr; } void CCBParticleEndSpinTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getEndSpin(); float aVar = dynamic_cast(pNode)->getEndSpinVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleEndSpinTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setEndSpin(floatVar.x); par->setEndSpinVar(floatVar.y); } /************************************************************ CCBParticleAngleTo ************************************************************/ //粒子发射角度 CCBParticleAngleTo* CCBParticleAngleTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBParticleAngleTo *ret = new (std::nothrow) CCBParticleAngleTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleAngleTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleAngleTo* CCBParticleAngleTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleAngleTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleAngleTo* CCBParticleAngleTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleAngleTo"); return nullptr; } void CCBParticleAngleTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getAngle(); float aVar = dynamic_cast(pNode)->getAngleVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleAngleTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setAngle(floatVar.x); par->setAngleVar(floatVar.y); } /************************************************************ CCBParticleTangentialAccelTo ************************************************************/ //粒子重力模式切向加速度 CCBParticleTangentialAccelTo* CCBParticleTangentialAccelTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBParticleTangentialAccelTo *ret = new (std::nothrow) CCBParticleTangentialAccelTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleTangentialAccelTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleTangentialAccelTo* CCBParticleTangentialAccelTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleTangentialAccelTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleTangentialAccelTo* CCBParticleTangentialAccelTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleTangentialAccelTo"); return nullptr; } void CCBParticleTangentialAccelTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getTangentialAccel(); float aVar = dynamic_cast(pNode)->getTangentialAccelVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleTangentialAccelTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setTangentialAccel(floatVar.x); par->setTangentialAccelVar(floatVar.y); } /************************************************************ CCBParticleRadialAccelTo ************************************************************/ //粒子径向加速度 CCBParticleRadialAccelTo* CCBParticleRadialAccelTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBParticleRadialAccelTo *ret = new (std::nothrow) CCBParticleRadialAccelTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleRadialAccelTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleRadialAccelTo* CCBParticleRadialAccelTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleRadialAccelTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleRadialAccelTo* CCBParticleRadialAccelTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleRadialAccelTo"); return nullptr; } void CCBParticleRadialAccelTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getRadialAccel(); float aVar = dynamic_cast(pNode)->getRadialAccelVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleRadialAccelTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setRadialAccel(floatVar.x); par->setRadialAccelVar(floatVar.y); } /************************************************************ CCBParticleStartRadiusTo ************************************************************/ //粒子半径模式开始半径 CCBParticleStartRadiusTo* CCBParticleStartRadiusTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBParticleStartRadiusTo *ret = new (std::nothrow) CCBParticleStartRadiusTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleStartRadiusTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleStartRadiusTo* CCBParticleStartRadiusTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleStartRadiusTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleStartRadiusTo* CCBParticleStartRadiusTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleStartRadiusTo"); return nullptr; } void CCBParticleStartRadiusTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getStartRadius(); float aVar = dynamic_cast(pNode)->getStartRadiusVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleStartRadiusTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setStartRadius(floatVar.x); par->setStartRadiusVar(floatVar.y); } /************************************************************ CCBParticleEndRadiusTo ************************************************************/ //粒子半径模式结束半径 CCBParticleEndRadiusTo* CCBParticleEndRadiusTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBParticleEndRadiusTo *ret = new (std::nothrow) CCBParticleEndRadiusTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleEndRadiusTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleEndRadiusTo* CCBParticleEndRadiusTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleEndRadiusTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleEndRadiusTo* CCBParticleEndRadiusTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleEndRadiusTo"); return nullptr; } void CCBParticleEndRadiusTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getEndRadius(); float aVar = dynamic_cast(pNode)->getEndRadiusVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleEndRadiusTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setEndRadius(floatVar.x); par->setEndRadiusVar(floatVar.y); } /************************************************************ CCBParticleRotatePerSecondTo ************************************************************/ //粒子速度 CCBParticleRotatePerSecondTo* CCBParticleRotatePerSecondTo::create(float fDuration, cocos2d::Vec2 gravity){ CCBParticleRotatePerSecondTo *ret = new (std::nothrow) CCBParticleRotatePerSecondTo(); if (ret) { if (ret->initWithDuration(fDuration, gravity)) { ret->autorelease(); } else { CC_SAFE_DELETE(ret); } } return ret; } bool CCBParticleRotatePerSecondTo::initWithDuration(float fDuration, cocos2d::Vec2 folatVar){ if (ActionInterval::initWithDuration(fDuration)) { _endFloatVar = folatVar; return true; } else { return false; } } CCBParticleRotatePerSecondTo* CCBParticleRotatePerSecondTo::clone() const { // no copy constructor auto a = new (std::nothrow) CCBParticleRotatePerSecondTo(); a->initWithDuration(_duration, _endFloatVar); a->autorelease(); return a; } CCBParticleRotatePerSecondTo* CCBParticleRotatePerSecondTo::reverse() const { CCASSERT(false, "reverse() is not supported in CCBParticleSpeedTo"); return nullptr; } void CCBParticleRotatePerSecondTo::startWithTarget(cocos2d::Node *pNode) { ActionInterval::startWithTarget(pNode); float a = dynamic_cast(pNode)->getRotatePerSecond(); float aVar = dynamic_cast(pNode)->getRotatePerSecondVar(); _startFloatVar = Vec2(a, aVar); _diffFloatVar = _endFloatVar - _startFloatVar; } void CCBParticleRotatePerSecondTo::update(float time){ auto par = dynamic_cast(_target); CCASSERT(par != nullptr, "CCBParticleSpeedTo 只支持 ParticleSystem"); auto floatVar = _startFloatVar + (_diffFloatVar * time); par->setRotatePerSecond(floatVar.x); par->setRotatePerSecondVar(floatVar.y); } /************************************************************ 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); } } }