// // REDBatchNode.cpp // cocos2d_libs // // Created by xiao鱼哥 on 2023/2/2. // #include "REDBatchNode.h" #include "base/CCDirector.h" #include "2d/CCSprite.h" #include "2d/CCSpriteFrame.h" #include "2d/CCNode.h" #include "REDAnimationManager.h" #include "2d/CCParticleSystemQuad.h" #include "base/CCEventDispatcher.h" #include "base/CCEventCustom.h" #include "base/CCEventListenerCustom.h" #include "2d/CCProgressTimer.h" #include "REDBatchNodeManager.h" using namespace cocos2d; namespace redream { REDBatchNode::REDBatchNode(){ } REDBatchNode::~REDBatchNode(){ REDBatchNodeManager::getInstance()->removeListener(_redreamName, this); } void REDBatchNode::setBatchPlistSpriteNames(REDPlistPic & SpNames){ _needBatchPlistSpriteNames = SpNames; } void REDBatchNode::setRootNode(Node* node,REDAnimationManager* animMgr){ if (_rootNode) { CCASSERT(0, "不允许再次设置"); return; } _rootNode = node; _animMgr = animMgr; _redreamName = _animMgr->getREDFileName(); REDBatchNodeManager::getInstance()->addListener(_redreamName, this); } void REDBatchNode::onListener(){ mergeFinish(); } void REDBatchNode::mergeFinish() { batchEnd(_rootNode); //重置一下帧动画, _animMgr->resetSpriteFrameOfAllChildrenAnimtion(); }; ///更新自己的frame ///@return true记录,下次快速访问 bool REDBatchNode::resetSprite(Sprite* sp){ ///获取SF,肯定会有.不会为空 SpriteFrame* sf = sp->getSpriteFrame(); string sfName = sf->getSpriteFrameName(); if (sfName.empty()) { ///如果是空,说明是单图,暂时不处理 ///为什么是空,是单图==> SpriteFrame的创建有2中方式,单图和plist, ///如果是plist则在添加到FrameCache时也会设置SpriteFrameName这个属性, ///如果是单图,也可能会有 _textureFilename这个属性,也可能没有. ///通过creat(filename...这样创建的就有,否则没有. } else{ unordered_set plist = _animMgr->getRepleacePlistSt(); SpriteFrameCache* sfc = SpriteFrameCache::getInstance(); SpriteFrame* nsf = sfc->getSpriteFrameByName(sfName,plist); if (nsf) { sp->setSpriteFrame(nsf); sp->setDirty(true); } else{ // CCLOG("合批之后,有图没有找到 %s/%s",plist.c_str(),sfName.c_str()); // CCASSERT(false, Str); } return true; } return false; } ///重置当前node,更加node的实际类型,做对应的操作. ///@return true 是否记录,下次快速访问使用 bool REDBatchNode::resetNode(Node* node){ ///Scale9Sprite 一样处理 ///ControlButton中也是创建了Sprite作为child加入的. Sprite* sp = dynamic_cast(node); if (sp) {//进入sprite的逻辑 BlendFunc blendFunc = sp->getBlendFunc(); if (resetSprite(sp)) { sp->setBlendFunc(blendFunc); return true; } return false; } ProgressTimer* pt = dynamic_cast(node); if (pt) {//进入 ProgressTimer 的逻辑 Sprite* sp1 = pt->getSprite(); if (sp1) { BlendFunc blendFunc = sp1->getBlendFunc(); if (resetSprite(sp1)) { pt->resetBySpriteFrame(); pt->setPercentage(pt->getPercentage()); sp1->setBlendFunc(blendFunc); return true; } } return false; } //粒子特效.从CCB加载过程,会记录纹理Texture,这个纹理 可能是从Plist读的,也可能是单图. //如果是plist读的,则需要记住 frameName,需要改粒子的加载过程中的 //如果是单图,也需要记录当时的路径,但是Texture2d里面的filepath已经是处理的路径,所以也需要记住单独的文件. //所以 如果需要支持所有的例子效果.需要改动的地方比较多. ZMLCCParticleSystemQuad* psq = dynamic_cast(node); if (psq) { BlendFunc blendFunc = psq->getBlendFunc(); psq->resetTextureByKeyInfo(_animMgr->getRepleacePlistSt()); psq->setBlendFunc(blendFunc); return true; } ParticleSystemQuad* ccpsq = dynamic_cast(node); if (ccpsq) { BlendFunc blendFunc = ccpsq->getBlendFunc(); ccpsq->resetTextureByKeyInfo(_animMgr->getRepleacePlistSt()); ccpsq->setBlendFunc(blendFunc); return true; } return false; } void REDBatchNode::batchEnd(Node* node){ resetNode(node); cocos2d::Vector& children = node->getChildren(); for( const auto &child: children){ if (child->getBatchNode() == nullptr) {//子类不是batchNode的才进入. batchEnd(child); } else{ CCLOG("这是一个嵌套的batchredream,不需要父节点处理,他自己去处理吧!"); } } }; bool REDBatchNode::init(){ return true; } REDBatchNode *REDBatchNode::create() { REDBatchNode *ret = new (std::nothrow) REDBatchNode(); if (ret && ret->init()) { ret->autorelease(); return ret; } else { CC_SAFE_DELETE(ret); return nullptr; } } }