#include #include #include "base/CCDirector.h" #include "platform/CCFileUtils.h" #include "2d/CCScene.h" #include "2d/CCSpriteFrameCache.h" #include "renderer/CCTextureCache.h" #include "REDReader.h" #include "CCNodeLoader.h" #include "CCNodeLoaderLibrary.h" #include "CCNodeLoaderListener.h" #include "REDMemberVariableAssigner.h" #include "REDSelectorResolver.h" #include "REDAnimationManager.h" #include "REDSequenceProperty.h" #include "REDKeyframe.h" #include #include "common/CocosConfig.h" #include "ReboltRedManager.h" #include "REDBatchNode.h" using namespace cocos2d; using namespace cocos2d::extension; namespace redream { /************************************************************************* Implementation of REDFile *************************************************************************/ //add by yutao std::unordered_map> s_ccbFileCacheMap; std::shared_ptr REDReader::getBytesFromREDFileByName(std::string ccbFullFilePath) { std::string ccbfileStr(ccbFullFilePath); auto p = s_ccbFileCacheMap.find(ccbfileStr); if( p != s_ccbFileCacheMap.end()) { //CCLOG("从缓存中读ccb文件%s",ccbfileStr.c_str()); return p->second; } else { auto data = std::make_shared(FileUtils::getInstance()->getDataFromFile(ccbFullFilePath)); s_ccbFileCacheMap.insert(make_pair(ccbfileStr, data)); //CCLOG("从文件读ccb文件%s",ccbfileStr.c_str()); return data; } } void REDReader::releaseAllREDFileCache() { s_ccbFileCacheMap.erase(s_ccbFileCacheMap.begin(),s_ccbFileCacheMap.end()); } REDFile::REDFile():_REDFileNode(nullptr) {} REDFile* REDFile::create() { REDFile *ret = new (std::nothrow) REDFile(); if (ret) { ret->autorelease(); } return ret; } Node* REDFile::getREDFileNode() { return _REDFileNode; } void REDFile::setREDFileNode(Node *pNode) { CC_SAFE_RELEASE(_REDFileNode); _REDFileNode = pNode; CC_SAFE_RETAIN(_REDFileNode); } /************************************************************************* Implementation of REDReader *************************************************************************/ REDReader::REDReader(NodeLoaderLibrary * pNodeLoaderLibrary, REDMemberVariableAssigner * pREDMemberVariableAssigner, REDSelectorResolver * pREDSelectorResolver, NodeLoaderListener * pNodeLoaderListener) : _data(nullptr) , _bytes(nullptr) , _currentByte(-1) , _currentBit(-1) , _owner(nullptr) , _animationManager(nullptr) , _animatedProps(nullptr) , _redFileProtobuf(nullptr) , _isReboltNode(false) , _reboltRedManager(nullptr) { this->_nodeLoaderLibrary = pNodeLoaderLibrary; this->_nodeLoaderLibrary->retain(); this->_REDMemberVariableAssigner = pREDMemberVariableAssigner; this->_REDSelectorResolver = pREDSelectorResolver; this->_nodeLoaderListener = pNodeLoaderListener; init(); } REDReader::REDReader(REDReader * ccbReader) : _data(nullptr) , _bytes(nullptr) , _currentByte(-1) , _currentBit(-1) , _owner(nullptr) , _animationManager(nullptr) , _animatedProps(nullptr) , _isReboltNode(false) , _reboltRedManager(nullptr) { this->_loadedSpriteSheets = ccbReader->_loadedSpriteSheets; this->_nodeLoaderLibrary = ccbReader->_nodeLoaderLibrary; this->_nodeLoaderLibrary->retain(); this->_REDMemberVariableAssigner = ccbReader->_REDMemberVariableAssigner; this->_REDSelectorResolver = ccbReader->_REDSelectorResolver; this->_nodeLoaderListener = ccbReader->_nodeLoaderListener; this->_REDRootPath = ccbReader->getREDRootPath(); init(); } REDReader::REDReader() : _data(nullptr) , _bytes(nullptr) , _currentByte(-1) , _currentBit(-1) , _owner(nullptr) , _animationManager(nullptr) , _nodeLoaderLibrary(nullptr) , _nodeLoaderListener(nullptr) , _REDMemberVariableAssigner(nullptr) , _REDSelectorResolver(nullptr) , _isReboltNode(false) , _reboltRedManager(nullptr) { init(); } REDReader::~REDReader() { CC_SAFE_RELEASE_NULL(_owner); CC_SAFE_DELETE(_animatedProps); this->_nodeLoaderLibrary->release(); _ownerOutletNames.clear(); _ownerCallbackNames.clear(); // Clear string cache. this->_stringCache.clear(); setAnimationManager(nullptr); setReboltRedManager(nullptr); } void REDReader::setREDRootPath(const char* ccbRootPath) { CCASSERT(ccbRootPath != nullptr, "ccbRootPath can't be nullptr!"); _REDRootPath = ccbRootPath; getAnimationManager()->setREDRootPath(_REDRootPath); } void REDReader::setPlist(std::unordered_set plistSt,std::unordered_set replacePlistSt){ _plistSt = plistSt; getAnimationManager()->setReaderPlist(plistSt,replacePlistSt); } const std::string& REDReader::getREDRootPath() const { return _REDRootPath; } bool REDReader::init() { // Setup action manager REDAnimationManager *pActionManager = new (std::nothrow) REDAnimationManager(); setAnimationManager(pActionManager); pActionManager->release(); // Setup resolution scale and container size _animationManager->setRootContainerSize(Director::getInstance()->getWinSize()); return true; } REDAnimationManager* REDReader::getAnimationManager() { return _animationManager; } void REDReader::setAnimationManager(REDAnimationManager *pAnimationManager) { CC_SAFE_RELEASE(_animationManager); _animationManager = pAnimationManager; CC_SAFE_RETAIN(_animationManager); } REDReader::REDAnimationManagerMapPtr REDReader::getAnimationManagers() { return _animationManagers; } void REDReader::setAnimationManagers(REDAnimationManagerMapPtr x) { _animationManagers = x; } void REDReader::setReboltRedManager(ReboltRedManager* rrm){ CC_SAFE_RELEASE(_reboltRedManager); _reboltRedManager = rrm; CC_SAFE_RETAIN(_reboltRedManager); } ReboltRedManager* REDReader::getReboltRedManager(){ return _reboltRedManager; } REDReader::ReboltRedManagerMapPtr REDReader::getReboltRedManagerMapPtr(){ return _reboltRedManagers; } void REDReader::setReboltRedManagerMapPtr(ReboltRedManagerMapPtr x){ _reboltRedManagers = x; } REDMemberVariableAssigner * REDReader::getREDMemberVariableAssigner() { return this->_REDMemberVariableAssigner; } bool REDReader::isReboltNode(){ return _isReboltNode; } REDSelectorResolver * REDReader::getREDSelectorResolver() { return this->_REDSelectorResolver; } std::set* REDReader::getAnimatedProperties() { return _animatedProps; } std::set& REDReader::getLoadedSpriteSheet() { return _loadedSpriteSheets; } Ref* REDReader::getOwner() { return _owner; } Node* REDReader::readNodeGraphFromFile(const char *pREDFileName) { return this->readNodeGraphFromFile(pREDFileName, nullptr); } Node* REDReader::readNodeGraphFromFile(const char* pREDFileName, Ref* pOwner) { return this->readNodeGraphFromFile(pREDFileName, pOwner, Director::getInstance()->getWinSize()); } Node* REDReader::readNodeGraphFromFile(const char *pREDFileName, Ref *pOwner, const Size &parentSize) { if (nullptr == pREDFileName || strlen(pREDFileName) == 0) { return nullptr; } std::string strREDFileName(pREDFileName); size_t pos = strREDFileName.rfind("."); if (pos == string::npos) { strREDFileName += ".redream"; } else { std::string strSuffix(".batchredream"); std::string endSuffix = strREDFileName.substr(pos); if (endSuffix == strSuffix) {//如果后缀名是batchredream _isBatchNode = true; } } this->getAnimationManager()->setREDFileName(strREDFileName); std::string strPath = FileUtils::getInstance()->fullPathForFilename(strREDFileName); // auto dataPtr = std::make_shared(FileUtils::getInstance()->getDataFromFile(strPath)); auto dataPtr = this->getBytesFromREDFileByName(strPath); Node *ret = this->readNodeGraphFromData(dataPtr, pOwner, parentSize); return ret; } Node* REDReader::readNodeGraphFromData(std::shared_ptr data, Ref *pOwner, const Size &parentSize) { _data = data; _currentByte = 0; _currentBit = 0; _owner = pOwner; CC_SAFE_RETAIN(_owner); _animationManager->setRootContainerSize(parentSize); _animationManager->_owner = _owner; Node *pNodeGraph = readFileWithCleanUp(true, std::make_shared(), std::make_shared()); int id = _animationManager->getAutoPlaySequenceId(); // log("error_getAutoPlaySequenceId:%d", id); // log("error_getReferenceCount:%d", _animationManager->getReferenceCount()); if(_animationManager->getReferenceCount()<=1){ return nullptr; } // Assign actionManagers to userObject for (auto iter = _animationManagers->begin(); iter != _animationManagers->end(); ++iter) { Node* pNode = iter->first; REDAnimationManager* manager = iter->second; pNode->setUserObject(manager); } if (pNodeGraph && id != -1) { // Auto play animations _animationManager->runAnimationsForSequenceIdTweenDuration(id, 0); } return pNodeGraph; } Scene* REDReader::createSceneWithNodeGraphFromFile(const char *pREDFileName) { return createSceneWithNodeGraphFromFile(pREDFileName, nullptr); } Scene* REDReader::createSceneWithNodeGraphFromFile(const char *pREDFileName, Ref *pOwner) { return createSceneWithNodeGraphFromFile(pREDFileName, pOwner, Director::getInstance()->getWinSize()); } Scene* REDReader::createSceneWithNodeGraphFromFile(const char *pREDFileName, Ref *pOwner, const Size &parentSize) { Node *pNode = readNodeGraphFromFile(pREDFileName, pOwner, parentSize); Scene *pScene = Scene::create(); pScene->addChild(pNode); return pScene; } void REDReader::cleanUpNodeGraph(Node *node) { node->setUserObject(nullptr); auto& children = node->getChildren(); for(const auto &obj : children) { cleanUpNodeGraph(obj); } } Node* REDReader::readFileWithCleanUp(bool bCleanUp, REDAnimationManagerMapPtr am, ReboltRedManagerMapPtr rm, std::function callback) { _redFileProtobuf = new RedreamInfo::RedFile(); bool isSuccess = _redFileProtobuf->ParseFromArray(_data->getBytes(), (int)_data->getSize());//获取到所有的字符串,然后创建内容 if(!isSuccess) { CC_SAFE_DELETE(_redFileProtobuf); return nullptr; } if (! readHeader()) { CC_SAFE_DELETE(_redFileProtobuf); return nullptr; } if (! readSequences()) { CC_SAFE_DELETE(_redFileProtobuf); return nullptr; } setAnimationManagers(am); if (_isBatchNode) { readFrameNames(); } setReboltRedManagerMapPtr(rm); readFileRedream(_redFileProtobuf->rebolt()); //TODO: 需要在这里处理rebolt逻辑,暂时先用回调的方式处理 if(callback){ callback(); } Node *pNode = readNodeGraph(nullptr, _redFileProtobuf->root()); _animationManagers->insert(pNode, _animationManager); if (bCleanUp) { cleanUpNodeGraph(pNode); } CC_SAFE_DELETE(_redFileProtobuf); if(_isReboltNode){ _reboltRedManager->parseTreeMapAndStartUpdate(); } return pNode; } void REDReader::readFileRedream(const RedreamInfo::Rebolt& reboltBuf){ _isReboltNode = reboltBuf.isrebolted(); if(_isReboltNode || _reboltRedManagers->size() > 0){ //有rebolt逻辑,或者有父节点存在rebolt逻辑才会创建 _reboltRedManager auto reboltRedManager = new (std::nothrow) ReboltRedManager(); setReboltRedManager(reboltRedManager); reboltRedManager->release(); reboltRedManager->setREDAnimationManager(getAnimationManager()); } if(_isReboltNode){ // 如果自己有rebolt逻辑才会加载或许逻辑 // 解析别名和树的关系 // <树类型,<树名字,树randomId>> std::map> typeBtMap; auto treeIndexesProto = reboltBuf.rebolttrees(); for(auto it = treeIndexesProto.begin(); it != treeIndexesProto.end(); ++it){ string treeRandomId = it->first; auto reboltBt = it->second; string treeName = reboltBt.treename(); string treeType = reboltBt.treetype(); typeBtMap[treeType][treeName] = treeRandomId; // CCLOG("RedSenceReader::readReboltSceneMangerFromFile: %s, %s, %s",treeType.c_str(), treeName.c_str(), treeRandomId.c_str()); } _reboltRedManager->setTreeTypeNameMap(typeBtMap); // <函数id,<参数类型key,[参数列表string]>> std::map>> funParam; auto funcParamIndexsProro = reboltBuf.funcparamindexs(); for(auto it = funcParamIndexsProro.begin(); it != funcParamIndexsProro.end(); it++){ string funId = it->first; RedreamInfo::Rebolt_FuncParamInfo funcParamInfo = it->second; std::vector boolKeysVec; auto boolKeysBuf = funcParamInfo.boolkeys(); for(int i = 0; i < boolKeysBuf.size(); i++){ string boolKey = boolKeysBuf.at(i); boolKeysVec.push_back(boolKey); } funParam[funId]["boolKeys"] = boolKeysVec; std::vector stringKeysVec; auto stringKeysBuf = funcParamInfo.stringkeys(); for(int i = 0; i < stringKeysBuf.size(); i++){ string stringKey = stringKeysBuf.at(i); stringKeysVec.push_back(stringKey); } funParam[funId]["stringKeys"] = stringKeysVec; } _reboltRedManager->setFunParam(funParam); } } bool REDReader::readHeader() { /* Read version. */ int version = _redFileProtobuf->version(); if(version != RED_VERSION) { // log("WARNING! Incompatible ccbi file version (file: %d reader: %d)", version, RED_VERSION); // return false; } return true; } const std::string& REDReader::readCachedString(int idx ) { return this->_redFileProtobuf->stringcache(idx); } void REDReader::setRootNodeForOrtherManger(Node* node){ // Set root node if (! _animationManager->getRootNode()){ if (_isBatchNode) { REDBatchNode * bthNode = REDBatchNode::create(); bthNode->setRootNode(node,_animationManager); node->setBatchNode(bthNode); bthNode->setBatchPlistSpriteNames(_batchPlistFrameNames); } _animationManager->setRootNode(node); } if(_reboltRedManager && !_reboltRedManager->getRootNode()){ _reboltRedManager->setRootNode(node); if(_isReboltNode){ Node* reboltRootNode = _reboltRedManager->getRootNode(); if(_reboltRedManagers->find(reboltRootNode) == _reboltRedManagers->end()){ _reboltRedManagers->insert(reboltRootNode, _reboltRedManager); } vector selfRootReboltMangetVec = _reboltRedManager->getRootRedMangers(); RootReboltManger retRrm; retRrm.rootRedManger = _reboltRedManager; retRrm.selfPath = ""; selfRootReboltMangetVec.push_back(retRrm); _reboltRedManager->setRootRedMangers(selfRootReboltMangetVec); } } } void REDReader::readAnimatedProperties(Node* node, const RedreamInfo::Node& nodeProtobuf){ //MARK: Read animated properties std::unordered_map> seqs; CC_SAFE_DELETE(_animatedProps); // 这个破玩意在后面读节点属性的时候也会用的到,所以只能在下次用之前和析构的时候进行删除操作 _animatedProps = new std::set(); int numSequence = nodeProtobuf.sequences_size(); for (int i = 0; i < numSequence; ++i) { auto& sequencePropertyMap = nodeProtobuf.sequences(i); int seqId = sequencePropertyMap.seqid(); Map seqNodeProps; int numProps = sequencePropertyMap.props_size(); for (int j = 0; j < numProps; ++j) { auto& sequenceProperty = sequencePropertyMap.props(j); REDSequenceProperty *seqProp = new (std::nothrow) REDSequenceProperty(); seqProp->autorelease(); seqProp->setName(readCachedString(sequenceProperty.name()).c_str()); seqProp->setType(sequenceProperty.type()); _animatedProps->insert(seqProp->getName()); int numKeyframes = sequenceProperty.keyframes_size(); for (int k = 0; k < numKeyframes; ++k) { auto& keyframeProtobuf = sequenceProperty.keyframes(k); PropertyType pt = static_cast(seqProp->getType()); REDKeyframe *keyframe = readKeyframe(pt, keyframeProtobuf); seqProp->getKeyframes().pushBack(keyframe); if (_isBatchNode && pt==PropertyType::SPRITEFRAME ) { _animationManager->addDisplayFrameKeykframe(keyframe); } } seqNodeProps.insert(seqProp->getName(), seqProp); } seqs[seqId] = seqNodeProps; } if (!seqs.empty()) { _animationManager->addNode(node, seqs); } } void REDReader::assignReboltName(const std::string& reboltName, const std::string& reboltId, cocos2d::Node* node){ if(_reboltRedManager){ _reboltRedManager->onAssignREDReboltRedManagerReboltName(_reboltRedManager, reboltName.c_str(), reboltId.c_str(), node); } } void REDReader::assignREDMemberVariable(TargetType memberVarAssignmentType, std::string memberVarAssignmentName, std::string className, Node* node){ // TargetType memberVarAssignmentType = static_cast(nodeProtobuf.membervarassignmenttype()); // std::string memberVarAssignmentName; // if(memberVarAssignmentType != TargetType::NONE) // { // memberVarAssignmentName = this->readCachedString(nodeProtobuf.membervarassignmentname()); // } if (memberVarAssignmentType != TargetType::NONE) { Ref* target = nullptr; if(memberVarAssignmentType == TargetType::DOCUMENT_ROOT) { target = _animationManager->getRootNode(); } else if(memberVarAssignmentType == TargetType::OWNER) { target = this->_owner; } if(target != nullptr) { REDMemberVariableAssigner * targetAsREDMemberVariableAssigner = dynamic_cast(target); bool assigned = false; if (memberVarAssignmentType != TargetType::NONE) { if(targetAsREDMemberVariableAssigner != nullptr) { assigned = targetAsREDMemberVariableAssigner->onAssignREDMemberVariable(target, memberVarAssignmentName.c_str(), node); targetAsREDMemberVariableAssigner->onAssignREDMemberVariableWithClass(target, memberVarAssignmentName.c_str(), node, className); } if(!assigned && this->_REDMemberVariableAssigner != nullptr) { assigned = this->_REDMemberVariableAssigner->onAssignREDMemberVariable(target, memberVarAssignmentName.c_str(), node); this->_REDMemberVariableAssigner->onAssignREDMemberVariableWithClass(target, memberVarAssignmentName.c_str(), node, className); } } } } } void REDReader::assignCustomProperty(NodeLoader* ccNodeLoader, Node* node){ // Assign custom properties. if (!ccNodeLoader->getCustomProperties().empty()) { bool customAssigned = false; Ref* target = node; if(target != nullptr) { REDMemberVariableAssigner * targetAsREDMemberVariableAssigner = dynamic_cast(target); auto& customPropeties = ccNodeLoader->getCustomProperties(); for (auto iter = customPropeties.begin(); iter != customPropeties.end(); ++iter) { if (targetAsREDMemberVariableAssigner) { customAssigned = targetAsREDMemberVariableAssigner->onAssignREDCustomProperty(target, iter->first.c_str(), iter->second); } if(!customAssigned && this->_REDMemberVariableAssigner) { customAssigned = this->_REDMemberVariableAssigner->onAssignREDCustomProperty(target, iter->first.c_str(), iter->second); } } } } } Node * REDReader::readNodeGraph(Node * pParent, const RedreamInfo::Node& nodeProtobuf) { //MARK: create NodeLoader std::string className = this->readCachedString(nodeProtobuf.classname()); NodeLoader* ccNodeLoader = this->_nodeLoaderLibrary->getNodeLoader(className.c_str()); TargetType memberVarAssignmentType = static_cast(nodeProtobuf.membervarassignmenttype()); std::string memberVarAssignmentName; if(memberVarAssignmentType != TargetType::NONE) { memberVarAssignmentName = this->readCachedString(nodeProtobuf.membervarassignmentname()); } int reboltnameIndx = nodeProtobuf.reboltname(); //Add by zml rebolt 解析使用 string reboltName = ""; reboltName = this->readCachedString(reboltnameIndx); int reboltIdIndx = nodeProtobuf.reboltid(); string reboltId = this->readCachedString(reboltIdIndx); if (!ccNodeLoader) { string redFileName = getAnimationManager()->getREDFileName(); string err = StringUtils::format("文件【%s】节点名字【%s】reboltName【%s】没有找到Node解析器【%s】",redFileName.c_str(), memberVarAssignmentName.c_str(), reboltName.c_str(), className.c_str()); // throw err; CCLOG("%s", err.c_str()); CCLOG("!!!注意,解析器替换为默认的节点类型了!!!"); // 如果没有获取到ccNodeLoader,则去按照默认的节点类型(baseName)去查找ccNodeLoader std::string baseName = this->readCachedString(nodeProtobuf.baseclassname()); ccNodeLoader = this->_nodeLoaderLibrary->getNodeLoader(baseName.c_str()); if(!ccNodeLoader){ return nullptr; } } Node *node = ccNodeLoader->loadNode(pParent, this); setRootNodeForOrtherManger(node); readAnimatedProperties(node, nodeProtobuf); //MARK: Read properties ccNodeLoader->parseProperties(node, pParent, this, nodeProtobuf, reboltName, reboltId); //MARK: bool isREDFileNode = (nullptr == dynamic_cast(node)) ? false : true; // Handle sub ccb files (remove middle node) if (isREDFileNode) { REDFile *ccbFileNode = (REDFile*)node; Node *embeddedNode = ccbFileNode->getREDFileNode(); if (embeddedNode == nullptr) { CCLOG("ERROR embedded node: ReboltName", reboltName.c_str()); string redFileName = getAnimationManager()->getREDFileName(); string err = StringUtils::format("文件【%s】节点名字【%s】reboltName【%s】加载失败了",redFileName.c_str(), memberVarAssignmentName.c_str(), reboltName.c_str()); throw err; } else { embeddedNode->setPosition(ccbFileNode->getPosition()); embeddedNode->setRotation(ccbFileNode->getRotation()); embeddedNode->setScaleX(ccbFileNode->getScaleX()); embeddedNode->setScaleY(ccbFileNode->getScaleY()); embeddedNode->setTag(ccbFileNode->getTag()); embeddedNode->setVisible(ccbFileNode->isVisible()); //TODO: 斜切、透明、颜色都没设置?? //embeddedNode->setIgnoreAnchorPointForPosition(ccbFileNode->isIgnoreAnchorPointForPosition()); _animationManager->moveAnimationsFromNode(ccbFileNode, embeddedNode); ccbFileNode->setREDFileNode(nullptr); node = embeddedNode; } } //设置透明度穿透 by zml node->setCascadeOpacityEnabled(true); if(reboltName != ""){ assignReboltName(reboltName, reboltId, node); } assignREDMemberVariable(memberVarAssignmentType, memberVarAssignmentName, className, node); assignCustomProperty(ccNodeLoader, node); /* Read and add children. */ int numChildren = nodeProtobuf.child_size(); for(int i = 0; i < numChildren; i++) { auto& childProtoBuf = nodeProtobuf.child(i); Node * child = this->readNodeGraph(node, childProtoBuf); node->addChild(child); } // FIX ISSUE #1860: "onNodeLoaded will be called twice if ccb was added as a REDFile". // If it's a sub-ccb node, skip notification to NodeLoaderListener since it will be // notified at LINE #734: Node * child = this->readNodeGraph(node); if (!isREDFileNode) { // Call onNodeLoaded NodeLoaderListener * nodeAsNodeLoaderListener = dynamic_cast(node); if(nodeAsNodeLoaderListener != nullptr) { nodeAsNodeLoaderListener->onNodeLoaded(node, ccNodeLoader); } else if(this->_nodeLoaderListener != nullptr) { this->_nodeLoaderListener->onNodeLoaded(node, ccNodeLoader); } } return node; } REDKeyframe* REDReader::readKeyframe(PropertyType type, const RedreamInfo::Keyframe& keyframeProtobuf) { REDKeyframe *keyframe = new (std::nothrow) REDKeyframe(); keyframe->autorelease(); int equalPointsCount = keyframeProtobuf.equalpoints_size(); std::vector equalPoints = {}; for (int i = 0; i < equalPointsCount; ++i) { equalPoints.push_back(Vec2(keyframeProtobuf.equalpoints(i).x(), keyframeProtobuf.equalpoints(i).y())); } keyframe->setEqualPoints(equalPoints); // keyframe->setTime(readFloat()); keyframe->setTime(keyframeProtobuf.time()); // REDKeyframe::EasingType easingType = static_cast(readInt(false)); RedreamInfo::Easing easing = keyframeProtobuf.easing(); REDKeyframe::EasingType easingType = static_cast(easing.type()); float *easingOpt = (float*)malloc(4 * sizeof(float));; Value value; if (easingType == REDKeyframe::EasingType::CUBIC_IN || easingType == REDKeyframe::EasingType::CUBIC_OUT || easingType == REDKeyframe::EasingType::CUBIC_INOUT || easingType == REDKeyframe::EasingType::ELASTIC_IN || easingType == REDKeyframe::EasingType::ELASTIC_OUT || easingType == REDKeyframe::EasingType::ELASTIC_INOUT) { // *easingOpt = readFloat(); *easingOpt = easing.opt().easing1fopt().x(); } if(easingType == REDKeyframe::EasingType::Custom){ // easingOpt[0] = readFloat(); // easingOpt[1] = readFloat(); // easingOpt[2] = readFloat(); // easingOpt[3] = readFloat(); RedreamInfo::Easing4fOpt opt4f = easing.opt().easing4fopt(); easingOpt[0] = opt4f.x(); easingOpt[1] = opt4f.y(); easingOpt[2] = opt4f.z(); easingOpt[3] = opt4f.w(); } keyframe->setEasingType(easingType); keyframe->setEasingOpt(easingOpt); CC_SAFE_FREE(easingOpt); RedreamInfo::Value valueProtobuf = keyframeProtobuf.value(); if (type == PropertyType::CHECK) { value = valueProtobuf.boolvalue(); // value = readBool(); } else if (type == PropertyType::BYTE) { // value = readByte(); value = valueProtobuf.intvalue(); } else if (type == PropertyType::COLOR3) { // unsigned char r = readByte(); // unsigned char g = readByte(); // unsigned char b = readByte(); RedreamInfo::Color3 color3 = valueProtobuf.color3(); unsigned char r = color3.r(); unsigned char g = color3.g(); unsigned char b = color3.b(); ValueMap colorMap; colorMap["r"] = r; colorMap["g"] = g; colorMap["b"] = b; value = colorMap; } else if (type == PropertyType::COLOR4F_VAR) { RedreamInfo::Color4FVar color4FVar = valueProtobuf.color4fvar(); // float red = readFloat(); // float green = readFloat(); // float blue = readFloat(); // float alpha = readFloat(); // float redVar = readFloat(); // float greenVar = readFloat(); // float blueVar = readFloat(); // float alphaVar = readFloat(); float red = color4FVar.red(); float green = color4FVar.green(); float blue = color4FVar.blue(); float alpha = color4FVar.alpha(); float redVar = color4FVar.redvar(); float greenVar = color4FVar.greenvar(); float blueVar = color4FVar.bluevar(); float alphaVar = color4FVar.alphavar(); } else if (type == PropertyType::DEGREES) { // value = readFloat(); value = valueProtobuf.floatvalue(); } else if (type == PropertyType::SCALE_LOCK || type == PropertyType::POSITION || type == PropertyType::FLOAT_XY || type == PropertyType::POINT || type == PropertyType::FLOAT_VAR) { // float a = readFloat(); // float b = readFloat(); RedreamInfo::Vec2 vec2 = valueProtobuf.vec2(); float a = vec2.x(); float b = vec2.y(); ValueVector ab; ab.push_back(Value(a)); ab.push_back(Value(b)); value = ab; } else if (type == PropertyType::SPRITEFRAME) { // std::string spriteSheet = readCachedString(); // std::string spriteFile = readCachedString(); RedreamInfo::SpriteFrame spriteFramProtobuf = valueProtobuf.spriteframe(); std::string spriteSheet = readCachedString(spriteFramProtobuf.spritesheet()); std::string spriteFile = readCachedString(spriteFramProtobuf.spritefile()); SpriteFrame* spriteFrame = getSpriteFrameByName(spriteFile, spriteSheet,true); //add by songqingyu 记录信息,重置用 ValueVector vv = {Value(spriteSheet),Value(spriteFile)}; value = Value(vv); keyframe->setObject(spriteFrame); }else if (type == PropertyType::SPINE_SKELFRAME) { // std::string animation = readCachedString(); // float progress = readFloat(); // bool isLoop = readBool(); RedreamInfo::SkelFrame skelFrame = valueProtobuf.skelframe(); std::string animation = readCachedString(skelFrame.animation()); float progress = skelFrame.progress(); bool isLoop = skelFrame.loop(); ValueMap frameMap; frameMap["animation"] = animation; frameMap["progress"] = progress; frameMap["loop"] = isLoop; value = frameMap; }else if (type == PropertyType::ANIMATION) { // value = readInt(true); value = valueProtobuf.intvalue(); }else if (type == PropertyType::TEXT) { // value = readInt(true); value = Value(readCachedString(valueProtobuf.intvalue())); } else if (type == PropertyType::BAKE_ANIMATION) { RedreamInfo::BakeAnimation bakeAnimation = valueProtobuf.bakeanimation(); value = Value(ValueVector({ Value(bakeAnimation.animationname()), Value(bakeAnimation.elapsedtime()), Value(bakeAnimation.loop()) })); } else { CCASSERT(false, "unexpected Property"); } if (!value.isNull()) keyframe->setValue(value); return keyframe; } bool REDReader::readCallbackKeyframesForSeq(REDSequence* seq, RedreamInfo::Sequences& sequences) { // int numKeyframes = readInt(false); // if(!numKeyframes) return true; int numKeyframes = sequences.callbackkeyframe_size(); if(numKeyframes == 0) return true; REDSequenceProperty* channel = new (std::nothrow) REDSequenceProperty(); channel->autorelease(); for(int i = 0; i < numKeyframes; ++i) { RedreamInfo::CallbackKeyframe callbackKeyframe = sequences.callbackkeyframe(i); // float time = readFloat(); // std::string callbackName = readCachedString(); // int callbackType = readInt(false); float time = callbackKeyframe.time(); std::string callbackName = readCachedString(callbackKeyframe.name()); int callbackType = callbackKeyframe.type(); ValueVector valueVector; valueVector.push_back(Value(callbackName)); valueVector.push_back(Value(callbackType)); REDKeyframe* keyframe = new (std::nothrow) REDKeyframe(); keyframe->autorelease(); keyframe->setTime(time); keyframe->setValue(Value(valueVector)); channel->getKeyframes().pushBack(keyframe); } seq->setCallbackChannel(channel); return true; } bool REDReader::readSoundKeyframesForSeq(REDSequence* seq, RedreamInfo::Sequences& sequences) { // int numKeyframes = readInt(false); // if(!numKeyframes) return true; int numKeyframes = sequences.soundkeyframe_size(); if(numKeyframes == 0) return true; REDSequenceProperty* channel = new (std::nothrow) REDSequenceProperty(); channel->autorelease(); for(int i = 0; i < numKeyframes; ++i) { RedreamInfo::SoundKeyframe soundKeyframe = sequences.soundkeyframe(i); // float time = readFloat(); // std::string soundFile = readCachedString(); // float pitch = readFloat(); // float pan = readFloat(); // float gain = readFloat(); float time = soundKeyframe.time(); std::string soundFile = readCachedString(soundKeyframe.soundfile()); float pitch = soundKeyframe.pitch(); float pan = soundKeyframe.pan(); float gain = soundKeyframe.gain(); ValueVector vec; vec.push_back(Value(soundFile)); vec.push_back(Value(pitch)); vec.push_back(Value(pan)); vec.push_back(Value(gain)); REDKeyframe* keyframe = new (std::nothrow) REDKeyframe(); keyframe->setTime(time); keyframe->setValue(Value(vec)); channel->getKeyframes().pushBack(keyframe); keyframe->release(); } seq->setSoundChannel(channel); return true; } bool REDReader::readWiseKeyframesForSeq(REDSequence *seq, RedreamInfo::Sequences &sequences) { int numKeyframes = sequences.wisekeyframe_size(); if (numKeyframes == 0) { return true; } REDSequenceProperty* channel = new (std::nothrow) REDSequenceProperty(); channel->autorelease(); for(int i = 0; i < numKeyframes; ++i) { RedreamInfo::WiseKeyframe wiseKeyframe = sequences.wisekeyframe(i); float time = wiseKeyframe.time(); std::string bnkFileName = wiseKeyframe.bnk_file_name(); std::string eventName = wiseKeyframe.event_name(); bool forcePostEvent = wiseKeyframe.force_post_event(); ValueVector params; for (const RedreamInfo::WiseKeyframeParam& rParam : wiseKeyframe.params()) { std::string paramKey = rParam.key(); float paramValue = rParam.value(); ValueVector paramVec = ValueVector({ Value(paramKey), Value(paramValue) }); params.push_back(Value(paramVec)); } ValueVector valueVec({ Value(bnkFileName), Value(eventName), Value(forcePostEvent), Value(params) }); REDKeyframe* keyframe = new (std::nothrow) REDKeyframe(); keyframe->autorelease(); keyframe->setTime(time); keyframe->setValue(Value(valueVec)); channel->getKeyframes().pushBack(keyframe); } seq->setWiseChannel(channel); return true; } Node * REDReader::readNodeGraph() { return this->readNodeGraph(nullptr, _redFileProtobuf->root()); } bool REDReader::readSequences() { auto& sequences = _animationManager->getSequences(); // int numSeqs = readInt(false); int numSeqs = _redFileProtobuf->sequences_size(); for (int i = 0; i < numSeqs; i++) { REDSequence *seq = new (std::nothrow) REDSequence(); seq->autorelease(); RedreamInfo::Sequences sequencesProtobuf = _redFileProtobuf->sequences(i); // seq->setDuration(readFloat()); // seq->setName(readCachedString().c_str()); // seq->setSequenceId(readInt(false)); // seq->setChainedSequenceId(readInt(true)); seq->setDuration(sequencesProtobuf.duration()); seq->setName(readCachedString(sequencesProtobuf.name()).c_str()); seq->setSequenceId(sequencesProtobuf.sequenceid()); seq->setChainedSequenceId(sequencesProtobuf.chainedsequenceid()); if(!readCallbackKeyframesForSeq(seq, sequencesProtobuf)) return false; if(!readSoundKeyframesForSeq(seq, sequencesProtobuf)) return false; if(!readWiseKeyframesForSeq(seq, sequencesProtobuf)) return false; sequences.pushBack(seq); } // _animationManager->setAutoPlaySequenceId(readInt(true)); _animationManager->setAutoPlaySequenceId(_redFileProtobuf->autoplaysequenceid()); return true; } std::string REDReader::lastPathComponent(const char* pPath) { std::string path(pPath); size_t slashPos = path.find_last_of("/"); if(slashPos != std::string::npos) { return path.substr(slashPos + 1, path.length() - slashPos); } return path; } std::string REDReader::deletePathExtension(const char* pPath) { std::string path(pPath); size_t dotPos = path.find_last_of("."); if(dotPos != std::string::npos) { return path.substr(0, dotPos); } return path; } std::string REDReader::toLowerCase(const char* pString) { std::string copy(pString); std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower); return copy; } bool REDReader::endsWith(const char* pString, const char* pEnding) { std::string string(pString); std::string ending(pEnding); if(string.length() >= ending.length()) { return (string.compare(string.length() - ending.length(), ending.length(), ending) == 0); } else { return false; } } bool REDReader::isJSControlled() { return false; } void REDReader::addOwnerCallbackName(const std::string& name) { _ownerCallbackNames.push_back(name); } void REDReader::addOwnerCallbackNode(Node *node) { _ownerCallbackNodes.pushBack(node); } void REDReader::addOwnerCallbackControlEvents(Control::EventType type) { _ownerOwnerCallbackControlEvents.push_back(Value((int)type)); } void REDReader::addDocumentCallbackName(const std::string& name) { _animationManager->addDocumentCallbackName(name); } void REDReader::addDocumentCallbackNode(Node *node) { _animationManager->addDocumentCallbackNode(node); } void REDReader::addDocumentCallbackControlEvents(Control::EventType eventType) { _animationManager->addDocumentCallbackControlEvents(eventType); } ValueVector REDReader::getOwnerCallbackNames() { ValueVector ret; ret.reserve(_ownerCallbackNames.size()); std::vector::iterator it = _ownerCallbackNames.begin(); for (; it != _ownerCallbackNames.end(); ++it) { ret.push_back(Value(*it)); } return ret; } Vector& REDReader::getOwnerCallbackNodes() { return _ownerCallbackNodes; } ValueVector& REDReader::getOwnerCallbackControlEvents() { return _ownerOwnerCallbackControlEvents; } ValueVector REDReader::getOwnerOutletNames() { ValueVector ret; ret.reserve(_ownerOutletNames.size()); std::vector::iterator it = _ownerOutletNames.begin(); for (; it != _ownerOutletNames.end(); ++it) { ret.push_back(Value(*it)); } return ret; } Vector& REDReader::getOwnerOutletNodes() { return _ownerOutletNodes; } Vector& REDReader::getNodesWithAnimationManagers() { return _nodesWithAnimationManagers; } Vector& REDReader::getAnimationManagersForNodes() { return _animationManagersForNodes; } void REDReader::addOwnerOutletName(std::string name) { _ownerOutletNames.push_back(name); } void REDReader::addOwnerOutletNode(Node *node) { if (nullptr == node) return; _ownerOutletNodes.pushBack(node); } /************************************************************************ Static functions ************************************************************************/ static float __ccbResolutionScale = 1.0f; float REDReader::getResolutionScale() { return __ccbResolutionScale; } void REDReader::setResolutionScale(float scale) { __ccbResolutionScale = scale; } /// ---- add by songqingyu ///之前好几个地方都写一遍此逻辑去获取图片,现在统一放在一个方法里面 ///根据file和sheet去获取SpriteFrame如果没有去找单图,单图没有,用空图替换,不会崩溃 SpriteFrame* REDReader::getSpriteFrameByName(std::string spriteFile,std::string spriteSheet,bool useDefaultEmpty){ //注意 此函数的SpriteFrame创建使用方法=>SpriteFrame::create(spriteFile, bounds); //因为这样才能记住spritefile的名字.方便之后的重置. SpriteFrame* spriteFrame = nullptr; SpriteFrameCache* frameCache = SpriteFrameCache::getInstance(); TextureCache* textCache = Director::getInstance()->getTextureCache(); spriteFrame = frameCache->getSpriteFrameByName(spriteFile,_plistSt); if (CocosConfig::getIgnoreCCBPath()) { if (!spriteFrame) { spriteFile = _REDRootPath + spriteFile; Texture2D * texture = textCache->addImage(spriteFile); if(texture != NULL) { Rect bounds = Rect(0, 0, texture->getContentSize().width, texture->getContentSize().height); spriteFrame = SpriteFrame::createWithTexture(texture, bounds); if (spriteFrame) { spriteFrame->setTextureFilename(spriteFile); } } } }else{ if (spriteSheet.empty()) { if (!spriteFrame) { spriteFile = _REDRootPath + spriteFile; Texture2D * texture = textCache->addImage(spriteFile); if(texture != NULL) { Rect bounds = Rect(0, 0, texture->getContentSize().width, texture->getContentSize().height); spriteFrame = SpriteFrame::createWithTexture(texture, bounds); if (spriteFrame) { spriteFrame->setTextureFilename(spriteFile); } } } } else { if (!spriteFrame) { spriteSheet = _REDRootPath + spriteSheet; // Load the sprite sheet only if it is not loaded if (_loadedSpriteSheets.find(spriteSheet) == _loadedSpriteSheets.end()) { frameCache->addSpriteFramesWithFile(spriteSheet); _loadedSpriteSheets.insert(spriteSheet); CCLOG("sqttest 没有图 %s",spriteSheet.c_str()); } spriteFrame = frameCache->getSpriteFrameByName(spriteFile,{spriteSheet}); } } } //add by djd 防止崩溃,用默认空白图 if (!spriteFrame && useDefaultEmpty) { spriteFile = CocosConfig::getDefaultEmptyPic(); Texture2D * texture = textCache->addImage(spriteFile); if(texture != NULL) { Rect bounds = Rect(0, 0, texture->getContentSize().width, texture->getContentSize().height); spriteFrame = SpriteFrame::createWithTexture(texture, bounds); if (spriteFrame) { spriteFrame->setTextureFilename(spriteFile); } } } return spriteFrame; } bool REDReader::readFrameNamesFromFile(const char *pREDFileName){ if (nullptr == pREDFileName || strlen(pREDFileName) == 0) { return false; } std::string strREDFileName(pREDFileName); size_t pos = strREDFileName.rfind("."); if (pos == string::npos) {//要求必须有后缀名 return false; } std::string strSuffix(".batchredream"); std::string endSuffix = strREDFileName.substr(pos); if (endSuffix == strSuffix) { _isBatchNode = true; } std::string strPath = FileUtils::getInstance()->fullPathForFilename(strREDFileName); // auto dataPtr = std::make_shared(FileUtils::getInstance()->getDataFromFile(strPath)); _data = this->getBytesFromREDFileByName(strPath); _currentByte = 0; _currentBit = 0; _owner = nullptr; _redFileProtobuf = new RedreamInfo::RedFile(); bool isSuccess = _redFileProtobuf->ParseFromArray(_data->getBytes(), (int)_data->getSize());//获取到所有的字符串,然后创建内容 if(!isSuccess) { CC_SAFE_DELETE(_redFileProtobuf); return false; } if ( !readHeader()) { CC_SAFE_DELETE(_redFileProtobuf); return false; } if (! readSequences()) { CC_SAFE_DELETE(_redFileProtobuf); return false; } readFrameNames(); CC_SAFE_DELETE(_redFileProtobuf); return true; } void REDReader::readFrameNames(){ RedreamInfo::BatchRed bt = _redFileProtobuf->batchred(); const RedreamInfo::BatchRed_TextureList& tl = bt.textures(); //读取plist对应的图 for (auto it : bt.frames()) { vector frames; frames.reserve(it.second.texturename_size()); for (auto el : it.second.texturename()) { frames.push_back(el); } _batchPlistFrameNames[it.first] = frames; } //读取单图资源列表 for (auto el : tl.texturename()) { vector frames; frames.push_back(el); _batchPlistFrameNames[el] = frames; } } };