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;
}

暂存

从零开始のcocos2dx生活(九)CCBReader的更多相关文章

  1. 从零开始のcocos2dx生活(七)ParticleSystem

    CCParticleSystem是用来设置粒子效果的类 1.粒子分为两种模式:重力模式 和 半径模式 重力模式独占属性: gravity 重力方向,Vec2类型,可以分别指定不同方向的重力大小 spe ...

  2. 从零开始のcocos2dx生活(二)Node

    节点 Node 文章目录 节点 Node 前言 变量初始化 创建一个节点对象 获取节点依赖的计数器 获取节点的描述(获取节点的Tag) 节点的局部层顺序值(LocalZOrder) 设置节点的Loca ...

  3. 从零开始のcocos2dx生活(十一)TableView

    目录 简述 主要变量 主要方法 setVerticalFillOrder reloadData cellAtIndex updateCellAtIndex insertCellAtIndex remo ...

  4. 从零开始のcocos2dx生活(十)ScrollView

    目录 简介 基础变量 ScrollViewDelegate Direction _dragging _container _touchMoved _bounceable _touchLength 方法 ...

  5. 从零开始のcocos2dx生活(八)ParticleSystemQuad

    https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/#_1 写的真的非常好-最近没时间拜读,只看 ...

  6. 从零开始のcocos2dx生活(六)EventDispatcher

    EventDispatcher可能是所有的里面比较不容易理解也不容易看的 我说自己的理解可能会误导到你们-[索了你们看不下去>< 我写了几乎所有的代码的注释,有的是废话跳过就好 主要的代码 ...

  7. 从零开始のcocos2dx生活(一)内存管理

    cocos中所有的对象都是继承自Ref基类,Ref的职责就是对对象进行引用计数管理 内存管理中最重要的是三个方法retain().release().autorelease() 在cocos中创建对象 ...

  8. 从零开始のcocos2dx生活(五)ActionEase

    文章目录 sineEaseIn sineEaseOut sineEaseInOut expoEaseIn expoEaseOut expoEaseInOut easeIn easeOut easeIn ...

  9. 从零开始のcocos2dx生活(四)ActionManager

    文章目录 初始化构造函数 析构函数 删除哈希元素 分配存放动作对象的空间 通过索引移除动作 暂停动作 恢复动作 暂停所有的动作 恢复所有的动作 添加动作 移除所有的动作 移除target中的所有动作 ...

随机推荐

  1. 2018-7-29-C#-强转会不会抛出异常

    title author date CreateTime categories C# 强转会不会抛出异常 lindexi 2018-7-29 14:24:1 +0800 2018-4-4 16:24: ...

  2. js循环遍历数组(对象)

    1,for循环 对于循环应该是最常用的一种遍历方式了,通常用来遍历数组结构. let arr = [a,b,d];for (let i=0; i<arr.length; i++){ consol ...

  3. C# POST 表单发送文件

    表单提交协议规定:要先将 HTTP 要求的 Content-Type 设为 multipart/form-data,而且要设定一个 boundary 参数,这个参数是由应用程序自行产生,它会用来识别每 ...

  4. 2019-11-17-dotnet-C#-获取本机外网-IP-地址

    title author date CreateTime categories dotnet C# 获取本机外网 IP 地址 lindexi 2019-11-17 16:38:10 +0800 201 ...

  5. 队列&优先队列

    1.队列 普通的队列都是先进先出,元素从队尾添加,从队头删除. function queue(){ var arr=[]; this.enqueue=function(item){ arr.push( ...

  6. JS遍历数组

    for 如果用var会造成变量声明提前等问题for(var i = 1; i <= arr.length; i++){ console.log(arr[i - 1]);} for(let i = ...

  7. 运行项目npm run dev时报错: ~Error: Cannot find module 'webpack-cli/bin/config-yargs', 原因是

    webpack@3.X运行项目npm run dev时报错: ~Error: Cannot find module 'webpack-cli/bin/config-yargs' 我的原因是:  web ...

  8. linux kdb 内核调试器

    许多读者可能奇怪为什么内核没有建立更多高级的调试特性在里面.答案, 非常简单, 是 Linus 不相信交互式的调试器. 他担心它们会导致不好的修改, 这些修改给问题打了补丁 而不是找到问题的真正原因. ...

  9. maven仓库总结,maven私服搭建,批量mvn eclipse:eclipse

    配置pom.xml依赖包时在这里找包的描述: http://search.maven.org/#browse 以java为根目录. mvn archtype:generate -DgroupId=zt ...

  10. Linux 内核 ksets 之上的操作

    对于初始化和设置, ksets 有一个接口非常类似于 kobjects. 下列函数存在: void kset_init(struct kset *kset); int kset_add(struct ...