123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101 |
- /****************************************************************************
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
-
- http://www.cocos2d-x.org
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- #include <ctype.h>
- #include <algorithm>
- #include "base/CCDirector.h"
- #include "platform/CCFileUtils.h"
- #include "2d/CCScene.h"
- #include "2d/CCSpriteFrameCache.h"
- #include "renderer/CCTextureCache.h"
- #include "editor-support/cocosbuilder/CCBReader.h"
- #include "editor-support/cocosbuilder/CCNodeLoader.h"
- #include "editor-support/cocosbuilder/CCNodeLoaderLibrary.h"
- #include "editor-support/cocosbuilder/CCNodeLoaderListener.h"
- #include "editor-support/cocosbuilder/CCBMemberVariableAssigner.h"
- #include "editor-support/cocosbuilder/CCBSelectorResolver.h"
- #include "editor-support/cocosbuilder/CCBAnimationManager.h"
- #include "editor-support/cocosbuilder/CCBSequenceProperty.h"
- #include "editor-support/cocosbuilder/CCBKeyframe.h"
- #include <sstream>
- using namespace cocos2d;
- using namespace cocos2d::extension;
- namespace cocosbuilder {
- /*************************************************************************
- Implementation of CCBFile
- *************************************************************************/
- CCBFile::CCBFile():_CCBFileNode(nullptr) {}
- CCBFile* CCBFile::create()
- {
- CCBFile *ret = new (std::nothrow) CCBFile();
-
- if (ret)
- {
- ret->autorelease();
- }
-
- return ret;
- }
- Node* CCBFile::getCCBFileNode()
- {
- return _CCBFileNode;
- }
- void CCBFile::setCCBFileNode(Node *pNode)
- {
- CC_SAFE_RELEASE(_CCBFileNode);
- _CCBFileNode = pNode;
- CC_SAFE_RETAIN(_CCBFileNode);
- }
- /*************************************************************************
- Implementation of CCBReader
- *************************************************************************/
- CCBReader::CCBReader(NodeLoaderLibrary * pNodeLoaderLibrary, CCBMemberVariableAssigner * pCCBMemberVariableAssigner, CCBSelectorResolver * pCCBSelectorResolver, NodeLoaderListener * pNodeLoaderListener)
- : _data(nullptr)
- , _bytes(nullptr)
- , _currentByte(-1)
- , _currentBit(-1)
- , _owner(nullptr)
- , _animationManager(nullptr)
- , _animatedProps(nullptr)
- {
- this->_nodeLoaderLibrary = pNodeLoaderLibrary;
- this->_nodeLoaderLibrary->retain();
- this->_CCBMemberVariableAssigner = pCCBMemberVariableAssigner;
- this->_CCBSelectorResolver = pCCBSelectorResolver;
- this->_nodeLoaderListener = pNodeLoaderListener;
- init();
- }
- CCBReader::CCBReader(CCBReader * ccbReader)
- : _data(nullptr)
- , _bytes(nullptr)
- , _currentByte(-1)
- , _currentBit(-1)
- , _owner(nullptr)
- , _animationManager(nullptr)
- , _animatedProps(nullptr)
- {
- this->_loadedSpriteSheets = ccbReader->_loadedSpriteSheets;
- this->_nodeLoaderLibrary = ccbReader->_nodeLoaderLibrary;
- this->_nodeLoaderLibrary->retain();
- this->_CCBMemberVariableAssigner = ccbReader->_CCBMemberVariableAssigner;
- this->_CCBSelectorResolver = ccbReader->_CCBSelectorResolver;
- this->_nodeLoaderListener = ccbReader->_nodeLoaderListener;
-
- this->_CCBRootPath = ccbReader->getCCBRootPath();
-
- init();
- }
- CCBReader::CCBReader()
- : _data(nullptr)
- , _bytes(nullptr)
- , _currentByte(-1)
- , _currentBit(-1)
- , _owner(nullptr)
- , _animationManager(nullptr)
- , _nodeLoaderLibrary(nullptr)
- , _nodeLoaderListener(nullptr)
- , _CCBMemberVariableAssigner(nullptr)
- , _CCBSelectorResolver(nullptr)
- {
- init();
- }
- CCBReader::~CCBReader()
- {
- CC_SAFE_RELEASE_NULL(_owner);
- this->_nodeLoaderLibrary->release();
- _ownerOutletNames.clear();
- _ownerCallbackNames.clear();
-
- // Clear string cache.
- this->_stringCache.clear();
- setAnimationManager(nullptr);
- }
- void CCBReader::setCCBRootPath(const char* ccbRootPath)
- {
- CCASSERT(ccbRootPath != nullptr, "ccbRootPath can't be nullptr!");
- _CCBRootPath = ccbRootPath;
- }
- const std::string& CCBReader::getCCBRootPath() const
- {
- return _CCBRootPath;
- }
- bool CCBReader::init()
- {
- // Setup action manager
- CCBAnimationManager *pActionManager = new (std::nothrow) CCBAnimationManager();
- setAnimationManager(pActionManager);
- pActionManager->release();
-
- // Setup resolution scale and container size
- _animationManager->setRootContainerSize(Director::getInstance()->getWinSize());
-
- return true;
- }
- CCBAnimationManager* CCBReader::getAnimationManager()
- {
- return _animationManager;
- }
- void CCBReader::setAnimationManager(CCBAnimationManager *pAnimationManager)
- {
- CC_SAFE_RELEASE(_animationManager);
- _animationManager = pAnimationManager;
- CC_SAFE_RETAIN(_animationManager);
- }
- CCBReader::CCBAnimationManagerMapPtr CCBReader::getAnimationManagers()
- {
- return _animationManagers;
- }
- void CCBReader::setAnimationManagers(CCBAnimationManagerMapPtr x)
- {
- _animationManagers = x;
- }
- CCBMemberVariableAssigner * CCBReader::getCCBMemberVariableAssigner() {
- return this->_CCBMemberVariableAssigner;
- }
- CCBSelectorResolver * CCBReader::getCCBSelectorResolver() {
- return this->_CCBSelectorResolver;
- }
- std::set<std::string>* CCBReader::getAnimatedProperties()
- {
- return _animatedProps;
- }
- std::set<std::string>& CCBReader::getLoadedSpriteSheet()
- {
- return _loadedSpriteSheets;
- }
- Ref* CCBReader::getOwner()
- {
- return _owner;
- }
- 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);
- std::string strSuffix(".ccbi");
- // Add ccbi suffix
- if (!CCBReader::endsWith(strCCBFileName.c_str(), strSuffix.c_str()))
- {
- strCCBFileName += strSuffix;
- }
- std::string strPath = FileUtils::getInstance()->fullPathForFilename(strCCBFileName);
- auto dataPtr = std::make_shared<Data>(FileUtils::getInstance()->getDataFromFile(strPath));
-
- Node *ret = this->readNodeGraphFromData(dataPtr, pOwner, parentSize);
-
- return ret;
- }
- Node* CCBReader::readNodeGraphFromData(std::shared_ptr<cocos2d::Data> data, Ref *pOwner, const Size &parentSize)
- {
- _data = data;
- _bytes =_data->getBytes();
- _currentByte = 0;
- _currentBit = 0;
- _owner = pOwner;
- 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;
- }
- Scene* CCBReader::createSceneWithNodeGraphFromFile(const char *pCCBFileName)
- {
- return createSceneWithNodeGraphFromFile(pCCBFileName, nullptr);
- }
- Scene* CCBReader::createSceneWithNodeGraphFromFile(const char *pCCBFileName, Ref *pOwner)
- {
- return createSceneWithNodeGraphFromFile(pCCBFileName, pOwner, Director::getInstance()->getWinSize());
- }
- Scene* CCBReader::createSceneWithNodeGraphFromFile(const char *pCCBFileName, Ref *pOwner, const Size &parentSize)
- {
- Node *pNode = readNodeGraphFromFile(pCCBFileName, pOwner, parentSize);
- Scene *pScene = Scene::create();
- pScene->addChild(pNode);
-
- return pScene;
- }
- void CCBReader::cleanUpNodeGraph(Node *node)
- {
- node->setUserObject(nullptr);
-
- auto& children = node->getChildren();
- for(const auto &obj : children) {
- cleanUpNodeGraph(obj);
- }
- }
- 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::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;
- }
- unsigned char CCBReader::readByte()
- {
- unsigned char byte = this->_bytes[this->_currentByte];
- this->_currentByte++;
- return byte;
- }
- bool CCBReader::readBool()
- {
- return 0 == this->readByte() ? false : true;
- }
- std::string CCBReader::readUTF8()
- {
- std::string ret;
- int b0 = this->readByte();
- int b1 = this->readByte();
- int numBytes = b0 << 8 | b1;
- char* pStr = (char*)malloc(numBytes+1);
- memcpy(pStr, _bytes+_currentByte, numBytes);
- pStr[numBytes] = '\0';
- ret = pStr;
- free(pStr);
- _currentByte += numBytes;
- return ret;
- }
- bool CCBReader::getBit() {
- bool bit;
- unsigned char byte = *(this->_bytes + this->_currentByte);
- if(byte & (1 << this->_currentBit)) {
- bit = true;
- } else {
- bit = false;
- }
- this->_currentBit++;
- if(this->_currentBit >= 8) {
- this->_currentBit = 0;
- this->_currentByte++;
- }
- return bit;
- }
- void CCBReader::alignBits() {
- if(this->_currentBit) {
- this->_currentBit = 0;
- this->_currentByte++;
- }
- }
- int CCBReader::readInt(bool pSigned) {
- // Read encoded int
- int numBits = 0;
- while(!this->getBit()) {
- numBits++;
- }
-
- long long current = 0;
- for(int a = numBits - 1; a >= 0; a--) {
- if(this->getBit()) {
- current |= 1LL << a;
- }
- }
- current |= 1LL << numBits;
-
- int num;
- if(pSigned) {
- int s = current % 2;
- if(s) {
- num = static_cast<int>(current / 2);
- } else {
- num = static_cast<int>(-current / 2);
- }
- } else {
- num = static_cast<int>(current - 1);
- }
-
- this->alignBits();
-
- return num;
- }
- float CCBReader::readFloat()
- {
- FloatType type = static_cast<FloatType>(this->readByte());
-
- switch (type)
- {
- case FloatType::_0:
- return 0;
- case FloatType::_1:
- return 1;
- case FloatType::MINUS1:
- return -1;
- case FloatType::_05:
- return 0.5f;
- case FloatType::INTEGER:
- return (float)this->readInt(true);
- default:
- {
- /* using a memcpy since the compiler isn't
- * doing the float ptr math correctly on device.
- * TODO: still applies in C++ ? */
- unsigned char* pF = (this->_bytes + this->_currentByte);
- float f = 0;
-
- // N.B - in order to avoid an unaligned memory access crash on 'memcpy()' the the (void*) casts of the source and
- // destination pointers are EXTREMELY important for the ARM compiler.
- //
- // Without a (void*) cast, the ARM compiler makes the assumption that the float* pointer is naturally aligned
- // according to it's type size (aligned along 4 byte boundaries) and thus tries to call a more optimized
- // version of memcpy() which makes this alignment assumption also. When reading back from a file of course our pointers
- // may not be aligned, hence we need to avoid the compiler making this assumption. The (void*) cast serves this purpose,
- // and causes the ARM compiler to choose the slower, more generalized (unaligned) version of memcpy()
- //
- // For more about this compiler behavior, see:
- // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3934.html
- memcpy((void*) &f, (const void*) pF, sizeof(float));
-
- this->_currentByte += sizeof(float);
- return f;
- }
- }
- }
- std::string CCBReader::readCachedString()
- {
- int n = this->readInt(false);
- return this->_stringCache[n];
- }
- Node * CCBReader::readNodeGraph(Node * pParent)
- {
- /* Read class name. */
- std::string className = this->readCachedString();
- std::string _jsControlledName;
-
- if(_jsControlled) {
- _jsControlledName = this->readCachedString();
- }
-
- // Read assignment type and name
- TargetType memberVarAssignmentType = static_cast<TargetType>(this->readInt(false));
- std::string memberVarAssignmentName;
- if(memberVarAssignmentType != TargetType::NONE)
- {
- memberVarAssignmentName = this->readCachedString();
- }
-
- NodeLoader *ccNodeLoader = this->_nodeLoaderLibrary->getNodeLoader(className.c_str());
-
- if (! ccNodeLoader)
- {
- log("no corresponding node loader for %s", className.c_str());
- return nullptr;
- }
- Node *node = ccNodeLoader->loadNode(pParent, this);
- // Set root node
- if (! _animationManager->getRootNode())
- {
- _animationManager->setRootNode(node);
- }
-
- // Assign controller
- if(_jsControlled && node == _animationManager->getRootNode())
- {
- _animationManager->setDocumentControllerName(_jsControlledName);
- }
- // Read animated properties
- std::unordered_map<int, Map<std::string, CCBSequenceProperty*>> seqs;
- _animatedProps = new std::set<std::string>();
-
- int numSequence = readInt(false);
- for (int i = 0; i < numSequence; ++i)
- {
- int seqId = readInt(false);
- Map<std::string, CCBSequenceProperty*> seqNodeProps;
-
- int numProps = readInt(false);
-
- for (int j = 0; j < numProps; ++j)
- {
- CCBSequenceProperty *seqProp = new (std::nothrow) CCBSequenceProperty();
- seqProp->autorelease();
-
- seqProp->setName(readCachedString().c_str());
- seqProp->setType(readInt(false));
- _animatedProps->insert(seqProp->getName());
-
- int numKeyframes = readInt(false);
-
- for (int k = 0; k < numKeyframes; ++k)
- {
- CCBKeyframe *keyframe = readKeyframe(static_cast<PropertyType>(seqProp->getType()));
-
- seqProp->getKeyframes().pushBack(keyframe);
- }
-
- seqNodeProps.insert(seqProp->getName(), seqProp);
- }
-
- seqs[seqId] = seqNodeProps;
- }
-
- if (!seqs.empty())
- {
- _animationManager->addNode(node, seqs);
- }
-
- // Read properties
- ccNodeLoader->parseProperties(node, pParent, this);
-
- bool isCCBFileNode = (nullptr == dynamic_cast<CCBFile*>(node)) ? false : true;
- // Handle sub ccb files (remove middle node)
- if (isCCBFileNode)
- {
- CCBFile *ccbFileNode = (CCBFile*)node;
-
- Node *embeddedNode = ccbFileNode->getCCBFileNode();
- embeddedNode->setPosition(ccbFileNode->getPosition());
- embeddedNode->setRotation(ccbFileNode->getRotation());
- embeddedNode->setScaleX(ccbFileNode->getScaleX());
- embeddedNode->setScaleY(ccbFileNode->getScaleY());
- embeddedNode->setTag(ccbFileNode->getTag());
- embeddedNode->setVisible(true);
- //embeddedNode->setIgnoreAnchorPointForPosition(ccbFileNode->isIgnoreAnchorPointForPosition());
-
- _animationManager->moveAnimationsFromNode(ccbFileNode, embeddedNode);
- ccbFileNode->setCCBFileNode(nullptr);
-
- node = embeddedNode;
- }
- if (memberVarAssignmentType != TargetType::NONE)
- {
- if(!_jsControlled)
- {
- Ref* target = nullptr;
- if(memberVarAssignmentType == TargetType::DOCUMENT_ROOT)
- {
- target = _animationManager->getRootNode();
- }
- else if(memberVarAssignmentType == TargetType::OWNER)
- {
- target = this->_owner;
- }
-
- if(target != nullptr)
- {
- CCBMemberVariableAssigner * targetAsCCBMemberVariableAssigner = dynamic_cast<CCBMemberVariableAssigner *>(target);
-
- bool assigned = false;
- if (memberVarAssignmentType != TargetType::NONE)
- {
- if(targetAsCCBMemberVariableAssigner != nullptr)
- {
- assigned = targetAsCCBMemberVariableAssigner->onAssignCCBMemberVariable(target, memberVarAssignmentName.c_str(), node);
- }
-
- if(!assigned && this->_CCBMemberVariableAssigner != nullptr)
- {
- assigned = this->_CCBMemberVariableAssigner->onAssignCCBMemberVariable(target, memberVarAssignmentName.c_str(), node);
- }
- }
- }
- }
- else
- {
- if(memberVarAssignmentType == TargetType::DOCUMENT_ROOT)
- {
- _animationManager->addDocumentOutletName(memberVarAssignmentName);
- _animationManager->addDocumentOutletNode(node);
- }
- else
- {
- _ownerOutletNames.push_back(memberVarAssignmentName);
- _ownerOutletNodes.pushBack(node);
- }
- }
- }
-
- // Assign custom properties.
- if (!ccNodeLoader->getCustomProperties().empty())
- {
- bool customAssigned = false;
-
- if(!_jsControlled)
- {
- Ref* target = node;
- if(target != nullptr)
- {
- CCBMemberVariableAssigner * targetAsCCBMemberVariableAssigner = dynamic_cast<CCBMemberVariableAssigner *>(target);
- if(targetAsCCBMemberVariableAssigner != nullptr)
- {
- auto& customPropeties = ccNodeLoader->getCustomProperties();
-
- for (auto iter = customPropeties.begin(); iter != customPropeties.end(); ++iter)
- {
- customAssigned = targetAsCCBMemberVariableAssigner->onAssignCCBCustomProperty(target, iter->first.c_str(), iter->second);
- if(!customAssigned && this->_CCBMemberVariableAssigner != nullptr)
- {
- customAssigned = this->_CCBMemberVariableAssigner->onAssignCCBCustomProperty(target, iter->first.c_str(), iter->second);
- }
- }
- }
- }
- }
- }
-
- delete _animatedProps;
- _animatedProps = nullptr;
- /* Read and add children. */
- int numChildren = this->readInt(false);
- for(int i = 0; i < numChildren; i++)
- {
- Node * child = this->readNodeGraph(node);
- node->addChild(child);
- }
- // FIX ISSUE #1860: "onNodeLoaded will be called twice if ccb was added as a CCBFile".
- // 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 (!isCCBFileNode)
- {
- // Call onNodeLoaded
- NodeLoaderListener * nodeAsNodeLoaderListener = dynamic_cast<NodeLoaderListener *>(node);
- if(nodeAsNodeLoaderListener != nullptr)
- {
- nodeAsNodeLoaderListener->onNodeLoaded(node, ccNodeLoader);
- }
- else if(this->_nodeLoaderListener != nullptr)
- {
- this->_nodeLoaderListener->onNodeLoaded(node, ccNodeLoader);
- }
- }
- return node;
- }
- CCBKeyframe* CCBReader::readKeyframe(PropertyType type)
- {
- CCBKeyframe *keyframe = new (std::nothrow) CCBKeyframe();
- keyframe->autorelease();
-
- keyframe->setTime(readFloat());
-
- CCBKeyframe::EasingType easingType = static_cast<CCBKeyframe::EasingType>(readInt(false));
- float easingOpt = 0;
- Value value;
-
- if (easingType == CCBKeyframe::EasingType::CUBIC_IN
- || easingType == CCBKeyframe::EasingType::CUBIC_OUT
- || easingType == CCBKeyframe::EasingType::CUBIC_INOUT
- || easingType == CCBKeyframe::EasingType::ELASTIC_IN
- || easingType == CCBKeyframe::EasingType::ELASTIC_OUT
- || easingType == CCBKeyframe::EasingType::ELASTIC_INOUT)
- {
- easingOpt = readFloat();
- }
- keyframe->setEasingType(easingType);
- keyframe->setEasingOpt(easingOpt);
-
- if (type == PropertyType::CHECK)
- {
- value = readBool();
- }
- else if (type == PropertyType::BYTE)
- {
- value = readByte();
- }
- else if (type == PropertyType::COLOR3)
- {
- unsigned char r = readByte();
- unsigned char g = readByte();
- unsigned char b = readByte();
-
- ValueMap colorMap;
- colorMap["r"] = r;
- colorMap["g"] = g;
- colorMap["b"] = b;
-
- value = colorMap;
- }
- else if (type == PropertyType::DEGREES)
- {
- value = readFloat();
- }
- else if (type == PropertyType::SCALE_LOCK || type == PropertyType::POSITION
- || type == PropertyType::FLOAT_XY)
- {
- float a = readFloat();
- float b = readFloat();
-
- 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();
-
- SpriteFrame* spriteFrame;
- if (spriteSheet.empty())
- {
- spriteFile = _CCBRootPath + spriteFile;
- Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(spriteFile);
- Rect bounds = Rect(0, 0, texture->getContentSize().width, texture->getContentSize().height);
-
- spriteFrame = SpriteFrame::createWithTexture(texture, bounds);
- }
- else
- {
- spriteSheet = _CCBRootPath + spriteSheet;
- SpriteFrameCache* frameCache = SpriteFrameCache::getInstance();
-
- // Load the sprite sheet only if it is not loaded
- if (_loadedSpriteSheets.find(spriteSheet) == _loadedSpriteSheets.end())
- {
- frameCache->addSpriteFramesWithFile(spriteSheet);
- _loadedSpriteSheets.insert(spriteSheet);
- }
-
- spriteFrame = frameCache->getSpriteFrameByName(spriteFile);
- }
-
- keyframe->setObject(spriteFrame);
- }
-
- if (!value.isNull())
- keyframe->setValue(value);
-
- return keyframe;
- }
- bool CCBReader::readCallbackKeyframesForSeq(CCBSequence* seq)
- {
- int numKeyframes = readInt(false);
- if(!numKeyframes) return true;
-
- CCBSequenceProperty* channel = new (std::nothrow) CCBSequenceProperty();
- channel->autorelease();
- for(int i = 0; i < numKeyframes; ++i) {
-
- float time = readFloat();
- std::string callbackName = readCachedString();
-
- int callbackType = readInt(false);
-
- ValueVector valueVector;
- valueVector.push_back(Value(callbackName));
- valueVector.push_back(Value(callbackType));
-
- CCBKeyframe* keyframe = new (std::nothrow) CCBKeyframe();
- keyframe->autorelease();
-
- keyframe->setTime(time);
- keyframe->setValue(Value(valueVector));
-
- if(_jsControlled) {
- std::stringstream callbackIdentifier;
- callbackIdentifier << callbackType;
- callbackIdentifier << ":" + callbackName;
- _animationManager->getKeyframeCallbacks().push_back(Value(callbackIdentifier.str()));
- }
-
- channel->getKeyframes().pushBack(keyframe);
- }
-
- seq->setCallbackChannel(channel);
-
- return true;
- }
- bool CCBReader::readSoundKeyframesForSeq(CCBSequence* seq) {
- int numKeyframes = readInt(false);
- if(!numKeyframes) return true;
-
- CCBSequenceProperty* channel = new (std::nothrow) CCBSequenceProperty();
- channel->autorelease();
- for(int i = 0; i < numKeyframes; ++i) {
-
- float time = readFloat();
- std::string soundFile = readCachedString();
- float pitch = readFloat();
- float pan = readFloat();
- float gain = readFloat();
-
- ValueVector vec;
- vec.push_back(Value(soundFile));
- vec.push_back(Value(pitch));
- vec.push_back(Value(pan));
- vec.push_back(Value(gain));
-
- CCBKeyframe* keyframe = new (std::nothrow) CCBKeyframe();
- keyframe->setTime(time);
- keyframe->setValue(Value(vec));
- channel->getKeyframes().pushBack(keyframe);
- keyframe->release();
- }
-
- seq->setSoundChannel(channel);
-
- return true;
- }
- Node * CCBReader::readNodeGraph() {
- return this->readNodeGraph(nullptr);
- }
- 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;
- }
- std::string CCBReader::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 CCBReader::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 CCBReader::toLowerCase(const char* pString) {
- std::string copy(pString);
- std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower);
- return copy;
- }
- bool CCBReader::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 CCBReader::isJSControlled()
- {
- return _jsControlled;
- }
- void CCBReader::addOwnerCallbackName(const std::string& name)
- {
- _ownerCallbackNames.push_back(name);
- }
- void CCBReader::addOwnerCallbackNode(Node *node)
- {
- _ownerCallbackNodes.pushBack(node);
- }
- void CCBReader::addOwnerCallbackControlEvents(Control::EventType type)
- {
- _ownerOwnerCallbackControlEvents.push_back(Value((int)type));
- }
- void CCBReader::addDocumentCallbackName(const std::string& name)
- {
- _animationManager->addDocumentCallbackName(name);
- }
- void CCBReader::addDocumentCallbackNode(Node *node)
- {
- _animationManager->addDocumentCallbackNode(node);
- }
- void CCBReader::addDocumentCallbackControlEvents(Control::EventType eventType)
- {
- _animationManager->addDocumentCallbackControlEvents(eventType);
- }
- ValueVector CCBReader::getOwnerCallbackNames()
- {
- ValueVector ret;
- ret.reserve(_ownerCallbackNames.size());
-
- std::vector<std::string>::iterator it = _ownerCallbackNames.begin();
- for (; it != _ownerCallbackNames.end(); ++it)
- {
- ret.push_back(Value(*it));
- }
-
- return ret;
- }
- Vector<Node*>& CCBReader::getOwnerCallbackNodes()
- {
- return _ownerCallbackNodes;
- }
- ValueVector& CCBReader::getOwnerCallbackControlEvents()
- {
- return _ownerOwnerCallbackControlEvents;
- }
- ValueVector CCBReader::getOwnerOutletNames()
- {
- ValueVector ret;
- ret.reserve(_ownerOutletNames.size());
- std::vector<std::string>::iterator it = _ownerOutletNames.begin();
- for (; it != _ownerOutletNames.end(); ++it)
- {
- ret.push_back(Value(*it));
- }
- return ret;
- }
- Vector<Node*>& CCBReader::getOwnerOutletNodes()
- {
- return _ownerOutletNodes;
- }
- Vector<Node*>& CCBReader::getNodesWithAnimationManagers()
- {
- return _nodesWithAnimationManagers;
- }
- Vector<CCBAnimationManager*>& CCBReader::getAnimationManagersForNodes()
- {
- return _animationManagersForNodes;
- }
- void CCBReader::addOwnerOutletName(std::string name)
- {
- _ownerOutletNames.push_back(name);
- }
- void CCBReader::addOwnerOutletNode(Node *node)
- {
- if (nullptr == node)
- return;
-
- _ownerOutletNodes.pushBack(node);
- }
- /************************************************************************
- Static functions
- ************************************************************************/
- static float __ccbResolutionScale = 1.0f;
- float CCBReader::getResolutionScale()
- {
- return __ccbResolutionScale;
- }
- void CCBReader::setResolutionScale(float scale)
- {
- __ccbResolutionScale = scale;
- }
- };
|