zoukankan      html  css  js  c++  java
  • 从零开始の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;
    }
    

    暂存

  • 相关阅读:
    LeetCode Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/sakuraneo/p/11992044.html
Copyright © 2011-2022 走看看