• 从零开始のcocos2dx生活(九)CCBReader


    NodeLoaderLibrary是用来存储节点加载器类型的类,通过registerDefaultNodeLoaders()可以注册所有默认类型的加载器
    在CocosBuilder的使用手册中:
    1、如果要使用自定义的加载器

    //创建一个默认的节点加载器库对象
    CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary(); 
    
    //使用自己的节点加载器,第一个参数是节点加载器的名字,第二个参数是节点加载器的加载函数
    ccNodeLoaderLibrary->registerCCNodeLoader("HelloCocosBuilderLayer", HelloCocosBuilderLayerLoader::loader());
    

    我们来看一看第一个方法中中做了什么操作:

    NodeLoaderLibrary * NodeLoaderLibrary::newDefaultNodeLoaderLibrary() {
    	//先是调用了librayr方法,但进去之后发现只是一行宏定义
    	//CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(NodeLoaderLibrary, library);
    	//再调到这个方法中,发现这是一个类似于create()的方法,用来创建NodeLoaderLibrary对象
    	//并将这个对象加入到内存自动管理中
        NodeLoaderLibrary * ccNodeLoaderLibrary = NodeLoaderLibrary::library();
        //给创建的对象注册一堆默认的节点加载器,放在下面一段代码中了
        ccNodeLoaderLibrary->registerDefaultNodeLoaders();
        //最后返回带了各种加载器的节点加载库对象
        return ccNodeLoaderLibrary;
    }
    
    void NodeLoaderLibrary::registerDefaultNodeLoaders() {
        this->registerNodeLoader("CCNode", NodeLoader::loader());
        this->registerNodeLoader("CCLayer", LayerLoader::loader());
        this->registerNodeLoader("CCLayerColor", LayerColorLoader::loader());
        this->registerNodeLoader("CCLayerGradient", LayerGradientLoader::loader());
        this->registerNodeLoader("CCSprite", SpriteLoader::loader());
        this->registerNodeLoader("CCLabelBMFont", LabelBMFontLoader::loader());
        this->registerNodeLoader("CCLabelTTF", LabelTTFLoader::loader());
        this->registerNodeLoader("CCScale9Sprite", Scale9SpriteLoader::loader());
        this->registerNodeLoader("CCScrollView", ScrollViewLoader::loader());
        this->registerNodeLoader("CCBFile", CCBFileLoader::loader());
        this->registerNodeLoader("CCMenu", MenuLoader::loader());
        this->registerNodeLoader("CCMenuItemImage", MenuItemImageLoader::loader());
        this->registerNodeLoader("CCControlButton", ControlButtonLoader::loader());
        this->registerNodeLoader("CCParticleSystemQuad", ParticleSystemQuadLoader::loader());
    }
    

    再看看第二个方法:

    void NodeLoaderLibrary::registerNodeLoader(const char * pClassName, NodeLoader * pNodeLoader) {
    	//先将加载器hold住
        pNodeLoader->retain();
        //将加载器以(加载器名,加载器)的格式存储在_nodeLoaders中
        //_nodeLoaders是一张map,在.h文件中可以看到如下的定义,存储了所有的加载器
        //typedef std::map<std::string, NodeLoader *> NodeLoaderMap;
        this->_nodeLoaders.insert(NodeLoaderMapEntry(pClassName, pNodeLoader));
    }
    

    2、如果不使用自定义的加载器,只需要一行代码就可以创建默认的加载器对象了

     CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();
    

    以上是创建加载器的对象的方法

    如果需要加载ccbi文件,那么需要知道ccbi文件中的根节点是什么类型的对象,以及想要返回的值类型,选择合适的类型来定义加载ccbi文件,如下使用了粒子系统来定义加载的ccbi文件

    CCParticleSystem* myParticles = (CCParticleSystem*) ccbReader->readNodeGraphFromFile("MyParticleSystem.ccbi");
    

    .ccb文件是CCB项目的原始文件。是map键值对的形式,保存了项目中所有Node的信息。

    .ccbi文件是CCB项目发布后的生成的二进制文件。CCBReader可以快速通过该二进制文件,读取并设置CCB项目内容到引擎中。
    .ccbi文件是.ccb文件的精简,专门提供给CCBReader类进行解析。通过CCBReader,把项目中的Node和Node属性在引擎中新建Node并设置属性,从而把这些Node添加到Scene或Layer中。

    //加载ccb文件
    Node* CCBReader::readNodeGraphFromFile(const char *pCCBFileName)
    {
        return this->readNodeGraphFromFile(pCCBFileName, nullptr);
    }
    
    Node* CCBReader::readNodeGraphFromFile(const char* pCCBFileName, Ref* pOwner) 
    {
        return this->readNodeGraphFromFile(pCCBFileName, pOwner, Director::getInstance()->getWinSize());
    }
    //最后都调用这个方法
    Node* CCBReader::readNodeGraphFromFile(const char *pCCBFileName, Ref *pOwner, const Size &parentSize)
    {
        if (nullptr == pCCBFileName || strlen(pCCBFileName) == 0)
        {
            return nullptr;
        }
    
        std::string strCCBFileName(pCCBFileName);  //获取ccb文件的名字
        std::string strSuffix(".ccb*i");  // 格式字符
        // Add ccbi suffix
        // 判断文件名没有.ccbi的后缀,如果没有就加上
        if (!CCBReader::endsWith(strCCBFileName.c_str(), strSuffix.c_str()))
        {
            strCCBFileName += strSuffix;
        }
        //获取ccb文件的完整地址
        std::string strPath = FileUtils::getInstance()->fullPathForFilename(strCCBFileName);
        
        //将ccb文件完整地址转型为Data
        auto dataPtr = std::make_shared<Data>(FileUtils::getInstance()->getDataFromFile(strPath));
        
        //调用readNodeGraphFromData,下面一段
        Node *ret =  this->readNodeGraphFromData(dataPtr, pOwner, parentSize);
        
        return ret;
    }
    
    Node* CCBReader::readNodeGraphFromDDData(std::shared_ptr<cocos2d::Data> data, Ref *pOwner, const Size &parentSize)
    {
        _data = data; //ccb完整路径
        _bytes =_data->getBytes(); //将文件路径转换成char字符
        _currentByte = 0;
        _currentBit = 0;
        _owner = pOwner; //跳转了几个函数没发现有什么用法,因为是Ref类型,猜测是可自定义参数
        CC_SAFE_RETAIN(_owner);
        
        
        _animationManager->setRootContainerSize(parentSize);
        _animationManager->_owner = _owner;
        
        //
        Node *pNodeGraph = readFileWithCleanUp(true, std::make_shared<CCBAnimationManagerMap>());
        
        //
        if (pNodeGraph && _animationManager->getAutoPlaySequenceId() != -1)
        {
            // Auto play animations
            _animationManager->runAnimationsForSequenceIdTweenDuration(_animationManager->getAutoPlaySequenceId(), 0);
        }
        
        // Assign actionManagers to userObject
        for (auto iter = _animationManagers->begin(); iter != _animationManagers->end(); ++iter)
        {
            Node* pNode = iter->first;
            CCBAnimationManager* manager = iter->second;
            
            //
            pNode->setUserObject(manager);
            
            //不使用
            if (_jsControlled)
            {
                _nodesWithAnimationManagers.pushBack(pNode);
                _animationManagersForNodes.pushBack(manager);
            }
        }
        
        return pNodeGraph;
    }
    
    Node* CCBReader::readFileWithCleanUp(bool bCleanUp, CCBAnimationManagerMapPtr am)
    {
        if (! readHeader())
        {
            return nullptr;
        }
        
        if (! readStringCache())
        {
            return nullptr;
        }
        
        if (! readSequences())
        {
            return nullptr;
        }
        
        
        //
        setAnimationManagers(am);
        //
        Node *pNode = readNodeGraph(nullptr);
        //
        _animationManagers->insert(pNode, _animationManager);
    
        
        
        if (bCleanUp)
        {
            cleanUpNodeGraph(pNode);
        }
        
        return pNode;
    }
    
    bool CCBReader::readStringCache() {
        int numStrings = this->readInt(false);
    
        for(int i = 0; i < numStrings; i++) {
            this->_stringCache.push_back(this->readUTF8());
        }
    
        return true;
    }
    
    bool CCBReader::readSequences()
    {
        auto& sequences = _animationManager->getSequences();
        
        int numSeqs = readInt(false);
        
        for (int i = 0; i < numSeqs; i++)
        {
            CCBSequence *seq = new (std::nothrow) CCBSequence();
            seq->autorelease();
            
            seq->setDuration(readFloat());
            seq->setName(readCachedString().c_str());
            seq->setSequenceId(readInt(false));
            seq->setChainedSequenceId(readInt(true));
            
            if(!readCallbackKeyframesForSeq(seq)) return false;
            if(!readSoundKeyframesForSeq(seq)) return false;
            
            sequences.pushBack(seq);
        }
        
        _animationManager->setAutoPlaySequenceId(readInt(true));
        return true;
    }
    
    //解析头部字节
    bool CCBReader::readHeader()
    {
        /* If no bytes loaded, don't crash about it. */
        if(this->_bytes == nullptr) {
            return false;
        }
    
        /* Read magic bytes */
        int magicBytes = *((int*)(this->_bytes + this->_currentByte));
        this->_currentByte += 4;
    
        if(CC_SWAP_INT32_BIG_TO_HOST(magicBytes) != (*reinterpret_cast<const int*>("ccbi"))) {
            return false; 
        }
    
        /* Read version. */
        int version = this->readInt(false);
        if(version != CCB_VERSION) {
            log("WARNING! Incompatible ccbi file version (file: %d reader: %d)", version, CCB_VERSION);
            return false;
        }
    
        // Read JS check
        _jsControlled = this->readBool();
        _animationManager->_jsControlled = _jsControlled;
    
        return true;
    }
    

    暂存

  • 相关阅读:
    【U-Boot】建立U-Boot编译环境
    【电路】JTAG下载器研究
    【FPGA】Xilinx-7系的时钟资源与DDR3配置
    【电路】KiCad-Pcbnew-建BGA形式的Footprint
    【电路】KiCad-Eeschema-建BGA形式的Symbol
    【电路】差分接口互连(二)
    【电路】差分接口互连(一)
    【电路】pmic芯片设计细节
    【电路】PADS建库细节
    【电路】SPI接口细化&控制
  • 原文地址:https://www.cnblogs.com/sakuraneo/p/11992044.html
Copyright © 2020-2023  润新知