您的位置:首页 > 移动开发 > Cocos引擎

深度解析cocostudio是如何处理动作编辑器导出来的Json文件(1) (转)

2013-10-24 15:32 579 查看
转自:blog.csdn.net/eduwc/article/details/9858723

在开始解析之前,先和大家说下如何阅读本文。

1.由于涉及到一些类的跳转,所以在有出现(跳XX)的地方,大家就可以利用搜索 搜索到相应的目的地查看 如果没有在系列文章深度解析cocostudio是如何处理动作编辑器导出来的Json文件(1)中,请到深度解析cocostudio是如何处理动作编辑器导出来的Json文件(2)中查找

2.本文章都是先上代码,然后再来做具体分析(其中一些不是很重要的就直接跟写在代码后面了)

我们来看一看cocostudio如何解析动画的

首先是加载动画文件

cs::ArmatureDataManager::sharedArmatureDataManager()->addArmatureFileInfo("NewProject","", "NewProject0.png","NewProject0.plist", "NewProject.json");

ArmatureDataManager 这个就是管理动画数据的大管家了

sharedArmatureDataManager 这个是一个单例,用来创建ArmatureDataManager的

我们再来深入看下addArmatureFileInfo是如何把json的动画信息加载进来并且解析的

先上源码,再来逐步分析

void ArmatureDataManager::addArmatureFileInfo(const char *armatureName, const char *useExistFileInfo, const char *imagePath, const char *plistPath, const char *configFilePath)

{

ArmatureFileInfo *fileInfo = (ArmatureFileInfo*)m_pArmatureFileInfoDic->objectForKey(armatureName);

if(!fileInfo)

{

fileInfo = ArmatureFileInfo::create();

fileInfo->armatureName = armatureName;

fileInfo->configFilePath = configFilePath;

fileInfo->useExistFileInfo = useExistFileInfo;

if (fileInfo->useExistFileInfo.compare("") != 0)

{

fileInfo = (ArmatureFileInfo*)m_pArmatureFileInfoDic->objectForKey(fileInfo->useExistFileInfo);

}

m_pArmatureFileInfoDic->setObject(fileInfo, fileInfo->armatureName);

}

DataReaderHelper::addDataFromFile(configFilePath);

for (std::vector<ImageInfo>::iterator it = fileInfo->imageInfoVector.begin(); it != fileInfo->imageInfoVector.end(); it++)

{

if (it->imagePath.compare(imagePath) == 0)

{

return;

}

}

ImageInfo imageInfo;

imageInfo.imagePath = imagePath;

imageInfo.plistPath = plistPath;

addSpriteFrameFromFile(plistPath, imagePath);

fileInfo->imageInfoVector.push_back(imageInfo);

}

分析

1. //作者考虑的很周到,会首先判断是否加载过了你所需要的Json文件,如果加载了 就直接根据名字来调取

ArmatureFileInfo *fileInfo = (ArmatureFileInfo*)m_pArmatureFileInfoDic->objectForKey(armatureName);

2.

//这边就是是重点了 这段代码开始解析Json,并且为你整理好数据格式,方便以后使用(跳1)

DataReaderHelper::addDataFromFile(configFilePath);

--------------------------------------------------------------华丽的分割线------------------------------------------------------------------------

(跳1)我们来看看addDataFromFile的具体实现

DataReaderHelper::addDataFromFile(configFilePath);

我们打开addDataFromFile来看下

void DataReaderHelper::addDataFromFile(const char *filePath)

{

/*

* Check if file is already added to ArmatureDataManager, if then return.

*/

for(unsigned int i = 0; i<m_arrConfigFileList.size(); i++)

{

if (m_arrConfigFileList[i].compare(filePath) == 0)

{

return;

}

}

m_arrConfigFileList.push_back(filePath);

std::string filePathStr = filePath;

size_t startPos = filePathStr.find_last_of(".");

std::string str = &filePathStr[startPos];

if (str.compare(".xml") == 0)

{

#if CS_TOOL_PLATFORM

if(Game::sharedGame()->isUsePackage())

{

DataReaderHelper::addDataFromXMLPak(filePathStr.c_str());

}

else

{

DataReaderHelper::addDataFromXML(filePathStr.c_str());

}

#else

DataReaderHelper::addDataFromXML(filePathStr.c_str());

#endif

}

else if(str.compare(".json") == 0 || str.compare(".ExportJson") == 0)

{

DataReaderHelper::addDataFromJson(filePathStr.c_str());

}

}

最开始又是一段检测是否添加的检测程序

for(unsigned int i = 0; i<m_arrConfigFileList.size(); i++)

{

if (m_arrConfigFileList[i].compare(filePath) == 0)

{

return;

}

}

解析

1.查看是xml文件还是json文件 根据不同文件做不同的处理(支持dragonbones导出的xml文件和cocostudio

动作编辑器导出Json文件)

std::string filePathStr = filePath;

size_t startPos = filePathStr.find_last_of(".");

std::string str = &filePathStr[startPos];

2. 根据上面的结果下面开始分别根据xml和json来做不同的处理,由于动作编辑器使用的是Json格式的,所以我们就先来主要

看下Json格式的解析 (要用到JsonCpp了 不是很了解的同学可以网上查看下)

if (str.compare(".xml") == 0)

{

#if CS_TOOL_PLATFORM

if(Game::sharedGame()->isUsePackage())

{

DataReaderHelper::addDataFromXMLPak(filePathStr.c_str());

}

else

{

DataReaderHelper::addDataFromXML(filePathStr.c_str());

}

#else

DataReaderHelper::addDataFromXML(filePathStr.c_str());

#endif

}

else if(str.compare(".json") == 0 || str.compare(".ExportJson") == 0)

{

我们重点看下DataReaderHelper::addDataFromJson(filePathStr.c_str())是如何来解析Json的(跳2)

DataReaderHelper::addDataFromJson(filePathStr.c_str());

}

--------------------------------------------------------------华丽的分割线------------------------------------------------------------------------

(跳2)

这边不需要太多的解析,主要就是读取文件了

void DataReaderHelper::addDataFromJson(const char *filePath)

{

unsigned long size;

std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(filePath);

const char *pFileContent = (char*)CCFileUtils::sharedFileUtils()->getFileData(fullPath.c_str() , "r", &size);

//把处理后的数据加入到缓存中

addDataFromJsonCache(pFileContent);

}

我们接着看 addDataFromJsonCache

void DataReaderHelper::addDataFromJsonCache(const char *fileContent)

{

CSJsonDictionary json;

json.initWithDescription(fileContent);//此处就是解析json的地方(跳3)

// Decode armatures

int length = json.getArrayItemCount(ARMATURE_DATA);

(跳4)

for (int i = 0; i<length; i++)

{

CSJsonDictionary *armatureDic = json.getSubItemFromArray(ARMATURE_DATA, i);

ArmatureData *armatureData = decodeArmature(*armatureDic);

ArmatureDataManager::sharedArmatureDataManager()->addArmatureData(armatureData->name.c_str(), armatureData);

}

// Decode animations

length = json.getArrayItemCount(ANIMATION_DATA);

for (int i = 0; i<length; i++)

{

CSJsonDictionary *animationDic = json.getSubItemFromArray(ANIMATION_DATA, i);

AnimationData *animationData = decodeAnimation(*animationDic);

ArmatureDataManager::sharedArmatureDataManager()->addAnimationData(animationData->name.c_str(), animationData);

}

// Decode textures

length = json.getArrayItemCount(TEXTURE_DATA);

for (int i = 0; i<length; i++)

{

CSJsonDictionary *textureDic = json.getSubItemFromArray(TEXTURE_DATA, i);

TextureData *textureData = decodeTexture(*textureDic);

ArmatureDataManager::sharedArmatureDataManager()->addTextureData(textureData->name.c_str(), textureData);

}

}

(跳3)

void CSJsonDictionary::initWithDescription(const char *pszDescription)

{

Json::Reader cReader;

m_cValue.clear();

if (pszDescription && *pszDescription)

{

std::string strValue = pszDescription;

//开始调用jsoncpp来解析json

cReader.parse(strValue, m_cValue, false);

}

}

解析 cReader.parse(strValue, m_cValue, false);

strValue 这个是要解析的字符串

m_cValue用来保存结果的 Json::Value 类型的变量

false 这个参数是用来决定是否要把注释也加进去的

按照官方的解释是

* \param collectComments \c true to collect comment and allow writing them back during

* serialization, \c false to discard comments.

* This parameter is ignored if Features::allowComments_

* is \c false.

下面来翻译下(英文不好 大家不要见怪啊)

如果设置成ture,就是可以再序列化的时候把注释也加进去

如果设置成false, 就是不添加注释

这个参数,如果在Features::allowComments_设置成false的时候就忽略

我们接着看parse 又嵌套了一层...水好深

bool

Reader::parse( const std::string &document,

Value &root,

bool collectComments )

{

document_ = document;

const char *begin = document_.c_str();//获取json内容

const char *end = begin + document_.length();//或者最后一个字符"\0"

return parse( begin, end, root, collectComments );

}

接着看return parse( begin, end, root, collectComments );

bool

Reader::parse( const char *beginDoc, const char *endDoc,

Value &root,

bool collectComments )

{

if ( !features_.allowComments_ )

{

collectComments = false;

}

begin_ = beginDoc;

end_ = endDoc;

collectComments_ = collectComments;

current_ = begin_;

lastValueEnd_ = 0;

lastValue_ = 0;

commentsBefore_ = "";

errors_.clear();

while ( !nodes_.empty() )

nodes_.pop();

nodes_.push( &root );

bool successful = readValue();

Token token;

skipCommentTokens( token );

if ( collectComments_ && !commentsBefore_.empty() )

root.setComment( commentsBefore_, commentAfter );

if ( features_.strictRoot_ )

{

if ( !root.isArray() && !root.isObject() )

{

// Set error location to start of doc, ideally should be first token found in doc

token.type_ = tokenError;

token.start_ = beginDoc;

token.end_ = endDoc;

addError( "A valid JSON document must be either an array or an object value.",

token );

return false;

}

}

return successful;

}

我们下节继续

--------------------------------------------------------------华丽的分割线------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: