CCBReader.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. #include <ctype.h>
  2. #include <algorithm>
  3. #include "base/CCDirector.h"
  4. #include "platform/CCFileUtils.h"
  5. #include "2d/CCScene.h"
  6. #include "2d/CCSpriteFrameCache.h"
  7. #include "renderer/CCTextureCache.h"
  8. #include "editor-support/cocosbuilder/CCBReader.h"
  9. #include "editor-support/cocosbuilder/CCNodeLoader.h"
  10. #include "editor-support/cocosbuilder/CCNodeLoaderLibrary.h"
  11. #include "editor-support/cocosbuilder/CCNodeLoaderListener.h"
  12. #include "editor-support/cocosbuilder/CCBMemberVariableAssigner.h"
  13. #include "editor-support/cocosbuilder/CCBSelectorResolver.h"
  14. #include "editor-support/cocosbuilder/CCBAnimationManager.h"
  15. #include "editor-support/cocosbuilder/CCBSequenceProperty.h"
  16. #include "editor-support/cocosbuilder/CCBKeyframe.h"
  17. #include <sstream>
  18. using namespace cocos2d;
  19. using namespace cocos2d::extension;
  20. namespace cocosbuilder {
  21. /*************************************************************************
  22. Implementation of CCBFile
  23. *************************************************************************/
  24. CCBFile::CCBFile():_CCBFileNode(nullptr) {}
  25. CCBFile* CCBFile::create()
  26. {
  27. CCBFile *ret = new (std::nothrow) CCBFile();
  28. if (ret)
  29. {
  30. ret->autorelease();
  31. }
  32. return ret;
  33. }
  34. Node* CCBFile::getCCBFileNode()
  35. {
  36. return _CCBFileNode;
  37. }
  38. void CCBFile::setCCBFileNode(Node *pNode)
  39. {
  40. CC_SAFE_RELEASE(_CCBFileNode);
  41. _CCBFileNode = pNode;
  42. CC_SAFE_RETAIN(_CCBFileNode);
  43. }
  44. /*************************************************************************
  45. Implementation of CCBReader
  46. *************************************************************************/
  47. CCBReader::CCBReader(NodeLoaderLibrary * pNodeLoaderLibrary, CCBMemberVariableAssigner * pCCBMemberVariableAssigner, CCBSelectorResolver * pCCBSelectorResolver, NodeLoaderListener * pNodeLoaderListener)
  48. : _data(nullptr)
  49. , _bytes(nullptr)
  50. , _currentByte(-1)
  51. , _currentBit(-1)
  52. , _owner(nullptr)
  53. , _animationManager(nullptr)
  54. , _animatedProps(nullptr)
  55. {
  56. this->_nodeLoaderLibrary = pNodeLoaderLibrary;
  57. this->_nodeLoaderLibrary->retain();
  58. this->_CCBMemberVariableAssigner = pCCBMemberVariableAssigner;
  59. this->_CCBSelectorResolver = pCCBSelectorResolver;
  60. this->_nodeLoaderListener = pNodeLoaderListener;
  61. init();
  62. }
  63. CCBReader::CCBReader(CCBReader * ccbReader)
  64. : _data(nullptr)
  65. , _bytes(nullptr)
  66. , _currentByte(-1)
  67. , _currentBit(-1)
  68. , _owner(nullptr)
  69. , _animationManager(nullptr)
  70. , _animatedProps(nullptr)
  71. {
  72. this->_loadedSpriteSheets = ccbReader->_loadedSpriteSheets;
  73. this->_nodeLoaderLibrary = ccbReader->_nodeLoaderLibrary;
  74. this->_nodeLoaderLibrary->retain();
  75. this->_CCBMemberVariableAssigner = ccbReader->_CCBMemberVariableAssigner;
  76. this->_CCBSelectorResolver = ccbReader->_CCBSelectorResolver;
  77. this->_nodeLoaderListener = ccbReader->_nodeLoaderListener;
  78. this->_CCBRootPath = ccbReader->getCCBRootPath();
  79. init();
  80. }
  81. CCBReader::CCBReader()
  82. : _data(nullptr)
  83. , _bytes(nullptr)
  84. , _currentByte(-1)
  85. , _currentBit(-1)
  86. , _owner(nullptr)
  87. , _animationManager(nullptr)
  88. , _nodeLoaderLibrary(nullptr)
  89. , _nodeLoaderListener(nullptr)
  90. , _CCBMemberVariableAssigner(nullptr)
  91. , _CCBSelectorResolver(nullptr)
  92. {
  93. init();
  94. }
  95. CCBReader::~CCBReader()
  96. {
  97. CC_SAFE_RELEASE_NULL(_owner);
  98. this->_nodeLoaderLibrary->release();
  99. _ownerOutletNames.clear();
  100. _ownerCallbackNames.clear();
  101. // Clear string cache.
  102. this->_stringCache.clear();
  103. setAnimationManager(nullptr);
  104. }
  105. void CCBReader::setCCBRootPath(const char* ccbRootPath)
  106. {
  107. CCASSERT(ccbRootPath != nullptr, "ccbRootPath can't be nullptr!");
  108. _CCBRootPath = ccbRootPath;
  109. }
  110. const std::string& CCBReader::getCCBRootPath() const
  111. {
  112. return _CCBRootPath;
  113. }
  114. bool CCBReader::init()
  115. {
  116. // Setup action manager
  117. CCBAnimationManager *pActionManager = new (std::nothrow) CCBAnimationManager();
  118. setAnimationManager(pActionManager);
  119. pActionManager->release();
  120. // Setup resolution scale and container size
  121. _animationManager->setRootContainerSize(Director::getInstance()->getWinSize());
  122. return true;
  123. }
  124. CCBAnimationManager* CCBReader::getAnimationManager()
  125. {
  126. return _animationManager;
  127. }
  128. void CCBReader::setAnimationManager(CCBAnimationManager *pAnimationManager)
  129. {
  130. CC_SAFE_RELEASE(_animationManager);
  131. _animationManager = pAnimationManager;
  132. CC_SAFE_RETAIN(_animationManager);
  133. }
  134. CCBReader::CCBAnimationManagerMapPtr CCBReader::getAnimationManagers()
  135. {
  136. return _animationManagers;
  137. }
  138. void CCBReader::setAnimationManagers(CCBAnimationManagerMapPtr x)
  139. {
  140. _animationManagers = x;
  141. }
  142. CCBMemberVariableAssigner * CCBReader::getCCBMemberVariableAssigner() {
  143. return this->_CCBMemberVariableAssigner;
  144. }
  145. CCBSelectorResolver * CCBReader::getCCBSelectorResolver() {
  146. return this->_CCBSelectorResolver;
  147. }
  148. std::set<std::string>* CCBReader::getAnimatedProperties()
  149. {
  150. return _animatedProps;
  151. }
  152. std::set<std::string>& CCBReader::getLoadedSpriteSheet()
  153. {
  154. return _loadedSpriteSheets;
  155. }
  156. Ref* CCBReader::getOwner()
  157. {
  158. return _owner;
  159. }
  160. Node* CCBReader::readNodeGraphFromFile(const char *pCCBFileName)
  161. {
  162. return this->readNodeGraphFromFile(pCCBFileName, nullptr);
  163. }
  164. Node* CCBReader::readNodeGraphFromFile(const char* pCCBFileName, Ref* pOwner)
  165. {
  166. return this->readNodeGraphFromFile(pCCBFileName, pOwner, Director::getInstance()->getWinSize());
  167. }
  168. Node* CCBReader::readNodeGraphFromFile(const char *pCCBFileName, Ref *pOwner, const Size &parentSize)
  169. {
  170. if (nullptr == pCCBFileName || strlen(pCCBFileName) == 0)
  171. {
  172. return nullptr;
  173. }
  174. std::string strCCBFileName(pCCBFileName);
  175. std::string strSuffix(".ccbi");
  176. // Add ccbi suffix
  177. if (!CCBReader::endsWith(strCCBFileName.c_str(), strSuffix.c_str()))
  178. {
  179. strCCBFileName += strSuffix;
  180. }
  181. std::string strPath = FileUtils::getInstance()->fullPathForFilename(strCCBFileName);
  182. auto dataPtr = std::make_shared<Data>(FileUtils::getInstance()->getDataFromFile(strPath));
  183. Node *ret = this->readNodeGraphFromData(dataPtr, pOwner, parentSize);
  184. return ret;
  185. }
  186. Node* CCBReader::readNodeGraphFromData(std::shared_ptr<cocos2d::Data> data, Ref *pOwner, const Size &parentSize)
  187. {
  188. _data = data;
  189. _bytes =_data->getBytes();
  190. _currentByte = 0;
  191. _currentBit = 0;
  192. _owner = pOwner;
  193. CC_SAFE_RETAIN(_owner);
  194. _animationManager->setRootContainerSize(parentSize);
  195. _animationManager->_owner = _owner;
  196. Node *pNodeGraph = readFileWithCleanUp(true, std::make_shared<CCBAnimationManagerMap>());
  197. if (pNodeGraph && _animationManager->getAutoPlaySequenceId() != -1)
  198. {
  199. // Auto play animations
  200. _animationManager->runAnimationsForSequenceIdTweenDuration(_animationManager->getAutoPlaySequenceId(), 0);
  201. }
  202. // Assign actionManagers to userObject
  203. for (auto iter = _animationManagers->begin(); iter != _animationManagers->end(); ++iter)
  204. {
  205. Node* pNode = iter->first;
  206. CCBAnimationManager* manager = iter->second;
  207. pNode->setUserObject(manager);
  208. if (_jsControlled)
  209. {
  210. _nodesWithAnimationManagers.pushBack(pNode);
  211. _animationManagersForNodes.pushBack(manager);
  212. }
  213. }
  214. return pNodeGraph;
  215. }
  216. Scene* CCBReader::createSceneWithNodeGraphFromFile(const char *pCCBFileName)
  217. {
  218. return createSceneWithNodeGraphFromFile(pCCBFileName, nullptr);
  219. }
  220. Scene* CCBReader::createSceneWithNodeGraphFromFile(const char *pCCBFileName, Ref *pOwner)
  221. {
  222. return createSceneWithNodeGraphFromFile(pCCBFileName, pOwner, Director::getInstance()->getWinSize());
  223. }
  224. Scene* CCBReader::createSceneWithNodeGraphFromFile(const char *pCCBFileName, Ref *pOwner, const Size &parentSize)
  225. {
  226. Node *pNode = readNodeGraphFromFile(pCCBFileName, pOwner, parentSize);
  227. Scene *pScene = Scene::create();
  228. pScene->addChild(pNode);
  229. return pScene;
  230. }
  231. void CCBReader::cleanUpNodeGraph(Node *node)
  232. {
  233. node->setUserObject(nullptr);
  234. auto& children = node->getChildren();
  235. for(const auto &obj : children) {
  236. cleanUpNodeGraph(obj);
  237. }
  238. }
  239. Node* CCBReader::readFileWithCleanUp(bool bCleanUp, CCBAnimationManagerMapPtr am)
  240. {
  241. if (! readHeader())
  242. {
  243. return nullptr;
  244. }
  245. if (! readStringCache())
  246. {
  247. return nullptr;
  248. }
  249. if (! readSequences())
  250. {
  251. return nullptr;
  252. }
  253. setAnimationManagers(am);
  254. Node *pNode = readNodeGraph(nullptr);
  255. _animationManagers->insert(pNode, _animationManager);
  256. if (bCleanUp)
  257. {
  258. cleanUpNodeGraph(pNode);
  259. }
  260. return pNode;
  261. }
  262. bool CCBReader::readStringCache() {
  263. int numStrings = this->readInt(false);
  264. for(int i = 0; i < numStrings; i++) {
  265. this->_stringCache.push_back(this->readUTF8());
  266. }
  267. return true;
  268. }
  269. bool CCBReader::readHeader()
  270. {
  271. /* If no bytes loaded, don't crash about it. */
  272. if(this->_bytes == nullptr) {
  273. return false;
  274. }
  275. /* Read magic bytes */
  276. int magicBytes = *((int*)(this->_bytes + this->_currentByte));
  277. this->_currentByte += 4;
  278. if(CC_SWAP_INT32_BIG_TO_HOST(magicBytes) != (*reinterpret_cast<const int*>("ccbi"))) {
  279. return false;
  280. }
  281. /* Read version. */
  282. int version = this->readInt(false);
  283. if(version != CCB_VERSION) {
  284. log("WARNING! Incompatible ccbi file version (file: %d reader: %d)", version, CCB_VERSION);
  285. return false;
  286. }
  287. // Read JS check
  288. _jsControlled = this->readBool();
  289. _animationManager->_jsControlled = _jsControlled;
  290. return true;
  291. }
  292. unsigned char CCBReader::readByte()
  293. {
  294. unsigned char byte = this->_bytes[this->_currentByte];
  295. this->_currentByte++;
  296. return byte;
  297. }
  298. bool CCBReader::readBool()
  299. {
  300. return 0 == this->readByte() ? false : true;
  301. }
  302. std::string CCBReader::readUTF8()
  303. {
  304. std::string ret;
  305. int b0 = this->readByte();
  306. int b1 = this->readByte();
  307. int numBytes = b0 << 8 | b1;
  308. char* pStr = (char*)malloc(numBytes+1);
  309. memcpy(pStr, _bytes+_currentByte, numBytes);
  310. pStr[numBytes] = '\0';
  311. ret = pStr;
  312. free(pStr);
  313. _currentByte += numBytes;
  314. return ret;
  315. }
  316. bool CCBReader::getBit() {
  317. bool bit;
  318. unsigned char byte = *(this->_bytes + this->_currentByte);
  319. if(byte & (1 << this->_currentBit)) {
  320. bit = true;
  321. } else {
  322. bit = false;
  323. }
  324. this->_currentBit++;
  325. if(this->_currentBit >= 8) {
  326. this->_currentBit = 0;
  327. this->_currentByte++;
  328. }
  329. return bit;
  330. }
  331. void CCBReader::alignBits() {
  332. if(this->_currentBit) {
  333. this->_currentBit = 0;
  334. this->_currentByte++;
  335. }
  336. }
  337. int CCBReader::readInt(bool pSigned) {
  338. // Read encoded int
  339. int numBits = 0;
  340. while(!this->getBit()) {
  341. numBits++;
  342. }
  343. long long current = 0;
  344. for(int a = numBits - 1; a >= 0; a--) {
  345. if(this->getBit()) {
  346. current |= 1LL << a;
  347. }
  348. }
  349. current |= 1LL << numBits;
  350. int num;
  351. if(pSigned) {
  352. int s = current % 2;
  353. if(s) {
  354. num = static_cast<int>(current / 2);
  355. } else {
  356. num = static_cast<int>(-current / 2);
  357. }
  358. } else {
  359. num = static_cast<int>(current - 1);
  360. }
  361. this->alignBits();
  362. return num;
  363. }
  364. float CCBReader::readFloat()
  365. {
  366. FloatType type = static_cast<FloatType>(this->readByte());
  367. switch (type)
  368. {
  369. case FloatType::_0:
  370. return 0;
  371. case FloatType::_1:
  372. return 1;
  373. case FloatType::MINUS1:
  374. return -1;
  375. case FloatType::_05:
  376. return 0.5f;
  377. case FloatType::INTEGER:
  378. return (float)this->readInt(true);
  379. default:
  380. {
  381. /* using a memcpy since the compiler isn't
  382. * doing the float ptr math correctly on device.
  383. * TODO: still applies in C++ ? */
  384. unsigned char* pF = (this->_bytes + this->_currentByte);
  385. float f = 0;
  386. // N.B - in order to avoid an unaligned memory access crash on 'memcpy()' the the (void*) casts of the source and
  387. // destination pointers are EXTREMELY important for the ARM compiler.
  388. //
  389. // Without a (void*) cast, the ARM compiler makes the assumption that the float* pointer is naturally aligned
  390. // according to it's type size (aligned along 4 byte boundaries) and thus tries to call a more optimized
  391. // version of memcpy() which makes this alignment assumption also. When reading back from a file of course our pointers
  392. // may not be aligned, hence we need to avoid the compiler making this assumption. The (void*) cast serves this purpose,
  393. // and causes the ARM compiler to choose the slower, more generalized (unaligned) version of memcpy()
  394. //
  395. // For more about this compiler behavior, see:
  396. // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3934.html
  397. memcpy((void*) &f, (const void*) pF, sizeof(float));
  398. this->_currentByte += sizeof(float);
  399. return f;
  400. }
  401. }
  402. }
  403. std::string CCBReader::readCachedString()
  404. {
  405. int n = this->readInt(false);
  406. return this->_stringCache[n];
  407. }
  408. Node * CCBReader::readNodeGraph(Node * pParent)
  409. {
  410. /* Read class name. */
  411. std::string className = this->readCachedString();
  412. std::string _jsControlledName;
  413. if(_jsControlled) {
  414. _jsControlledName = this->readCachedString();
  415. }
  416. // Read assignment type and name
  417. TargetType memberVarAssignmentType = static_cast<TargetType>(this->readInt(false));
  418. std::string memberVarAssignmentName;
  419. if(memberVarAssignmentType != TargetType::NONE)
  420. {
  421. memberVarAssignmentName = this->readCachedString();
  422. }
  423. NodeLoader *ccNodeLoader = this->_nodeLoaderLibrary->getNodeLoader(className.c_str());
  424. if (! ccNodeLoader)
  425. {
  426. log("no corresponding node loader for %s", className.c_str());
  427. return nullptr;
  428. }
  429. Node *node = ccNodeLoader->loadNode(pParent, this);
  430. // Set root node
  431. if (! _animationManager->getRootNode())
  432. {
  433. _animationManager->setRootNode(node);
  434. }
  435. // Assign controller
  436. if(_jsControlled && node == _animationManager->getRootNode())
  437. {
  438. _animationManager->setDocumentControllerName(_jsControlledName);
  439. }
  440. // Read animated properties
  441. std::unordered_map<int, Map<std::string, CCBSequenceProperty*>> seqs;
  442. _animatedProps = new std::set<std::string>();
  443. int numSequence = readInt(false);
  444. for (int i = 0; i < numSequence; ++i)
  445. {
  446. int seqId = readInt(false);
  447. Map<std::string, CCBSequenceProperty*> seqNodeProps;
  448. int numProps = readInt(false);
  449. for (int j = 0; j < numProps; ++j)
  450. {
  451. CCBSequenceProperty *seqProp = new (std::nothrow) CCBSequenceProperty();
  452. seqProp->autorelease();
  453. seqProp->setName(readCachedString().c_str());
  454. seqProp->setType(readInt(false));
  455. _animatedProps->insert(seqProp->getName());
  456. int numKeyframes = readInt(false);
  457. for (int k = 0; k < numKeyframes; ++k)
  458. {
  459. CCBKeyframe *keyframe = readKeyframe(static_cast<PropertyType>(seqProp->getType()));
  460. seqProp->getKeyframes().pushBack(keyframe);
  461. }
  462. seqNodeProps.insert(seqProp->getName(), seqProp);
  463. }
  464. seqs[seqId] = seqNodeProps;
  465. }
  466. if (!seqs.empty())
  467. {
  468. _animationManager->addNode(node, seqs);
  469. }
  470. // Read properties
  471. ccNodeLoader->parseProperties(node, pParent, this);
  472. bool isCCBFileNode = (nullptr == dynamic_cast<CCBFile*>(node)) ? false : true;
  473. // Handle sub ccb files (remove middle node)
  474. if (isCCBFileNode)
  475. {
  476. CCBFile *ccbFileNode = (CCBFile*)node;
  477. Node *embeddedNode = ccbFileNode->getCCBFileNode();
  478. embeddedNode->setPosition(ccbFileNode->getPosition());
  479. embeddedNode->setRotation(ccbFileNode->getRotation());
  480. embeddedNode->setScaleX(ccbFileNode->getScaleX());
  481. embeddedNode->setScaleY(ccbFileNode->getScaleY());
  482. embeddedNode->setTag(ccbFileNode->getTag());
  483. embeddedNode->setVisible(true);
  484. //embeddedNode->setIgnoreAnchorPointForPosition(ccbFileNode->isIgnoreAnchorPointForPosition());
  485. _animationManager->moveAnimationsFromNode(ccbFileNode, embeddedNode);
  486. ccbFileNode->setCCBFileNode(nullptr);
  487. node = embeddedNode;
  488. }
  489. if (memberVarAssignmentType != TargetType::NONE)
  490. {
  491. if(!_jsControlled)
  492. {
  493. Ref* target = nullptr;
  494. if(memberVarAssignmentType == TargetType::DOCUMENT_ROOT)
  495. {
  496. target = _animationManager->getRootNode();
  497. }
  498. else if(memberVarAssignmentType == TargetType::OWNER)
  499. {
  500. target = this->_owner;
  501. }
  502. if(target != nullptr)
  503. {
  504. CCBMemberVariableAssigner * targetAsCCBMemberVariableAssigner = dynamic_cast<CCBMemberVariableAssigner *>(target);
  505. bool assigned = false;
  506. if (memberVarAssignmentType != TargetType::NONE)
  507. {
  508. if(targetAsCCBMemberVariableAssigner != nullptr)
  509. {
  510. assigned = targetAsCCBMemberVariableAssigner->onAssignCCBMemberVariable(target, memberVarAssignmentName.c_str(), node);
  511. }
  512. if(!assigned && this->_CCBMemberVariableAssigner != nullptr)
  513. {
  514. assigned = this->_CCBMemberVariableAssigner->onAssignCCBMemberVariable(target, memberVarAssignmentName.c_str(), node);
  515. }
  516. }
  517. }
  518. }
  519. else
  520. {
  521. if(memberVarAssignmentType == TargetType::DOCUMENT_ROOT)
  522. {
  523. _animationManager->addDocumentOutletName(memberVarAssignmentName);
  524. _animationManager->addDocumentOutletNode(node);
  525. }
  526. else
  527. {
  528. _ownerOutletNames.push_back(memberVarAssignmentName);
  529. _ownerOutletNodes.pushBack(node);
  530. }
  531. }
  532. }
  533. // Assign custom properties.
  534. if (!ccNodeLoader->getCustomProperties().empty())
  535. {
  536. bool customAssigned = false;
  537. if(!_jsControlled)
  538. {
  539. Ref* target = node;
  540. if(target != nullptr)
  541. {
  542. CCBMemberVariableAssigner * targetAsCCBMemberVariableAssigner = dynamic_cast<CCBMemberVariableAssigner *>(target);
  543. if(targetAsCCBMemberVariableAssigner != nullptr)
  544. {
  545. auto& customPropeties = ccNodeLoader->getCustomProperties();
  546. for (auto iter = customPropeties.begin(); iter != customPropeties.end(); ++iter)
  547. {
  548. customAssigned = targetAsCCBMemberVariableAssigner->onAssignCCBCustomProperty(target, iter->first.c_str(), iter->second);
  549. if(!customAssigned && this->_CCBMemberVariableAssigner != nullptr)
  550. {
  551. customAssigned = this->_CCBMemberVariableAssigner->onAssignCCBCustomProperty(target, iter->first.c_str(), iter->second);
  552. }
  553. }
  554. }
  555. }
  556. }
  557. }
  558. delete _animatedProps;
  559. _animatedProps = nullptr;
  560. /* Read and add children. */
  561. int numChildren = this->readInt(false);
  562. for(int i = 0; i < numChildren; i++)
  563. {
  564. Node * child = this->readNodeGraph(node);
  565. node->addChild(child);
  566. }
  567. // FIX ISSUE #1860: "onNodeLoaded will be called twice if ccb was added as a CCBFile".
  568. // If it's a sub-ccb node, skip notification to NodeLoaderListener since it will be
  569. // notified at LINE #734: Node * child = this->readNodeGraph(node);
  570. if (!isCCBFileNode)
  571. {
  572. // Call onNodeLoaded
  573. NodeLoaderListener * nodeAsNodeLoaderListener = dynamic_cast<NodeLoaderListener *>(node);
  574. if(nodeAsNodeLoaderListener != nullptr)
  575. {
  576. nodeAsNodeLoaderListener->onNodeLoaded(node, ccNodeLoader);
  577. }
  578. else if(this->_nodeLoaderListener != nullptr)
  579. {
  580. this->_nodeLoaderListener->onNodeLoaded(node, ccNodeLoader);
  581. }
  582. }
  583. return node;
  584. }
  585. CCBKeyframe* CCBReader::readKeyframe(PropertyType type)
  586. {
  587. CCBKeyframe *keyframe = new (std::nothrow) CCBKeyframe();
  588. keyframe->autorelease();
  589. keyframe->setTime(readFloat());
  590. CCBKeyframe::EasingType easingType = static_cast<CCBKeyframe::EasingType>(readInt(false));
  591. float easingOpt = 0;
  592. Value value;
  593. if (easingType == CCBKeyframe::EasingType::CUBIC_IN
  594. || easingType == CCBKeyframe::EasingType::CUBIC_OUT
  595. || easingType == CCBKeyframe::EasingType::CUBIC_INOUT
  596. || easingType == CCBKeyframe::EasingType::ELASTIC_IN
  597. || easingType == CCBKeyframe::EasingType::ELASTIC_OUT
  598. || easingType == CCBKeyframe::EasingType::ELASTIC_INOUT)
  599. {
  600. easingOpt = readFloat();
  601. }
  602. keyframe->setEasingType(easingType);
  603. keyframe->setEasingOpt(easingOpt);
  604. if (type == PropertyType::CHECK)
  605. {
  606. value = readBool();
  607. }
  608. else if (type == PropertyType::BYTE)
  609. {
  610. value = readByte();
  611. }
  612. else if (type == PropertyType::COLOR3)
  613. {
  614. unsigned char r = readByte();
  615. unsigned char g = readByte();
  616. unsigned char b = readByte();
  617. ValueMap colorMap;
  618. colorMap["r"] = r;
  619. colorMap["g"] = g;
  620. colorMap["b"] = b;
  621. value = colorMap;
  622. }
  623. else if (type == PropertyType::DEGREES)
  624. {
  625. value = readFloat();
  626. }
  627. else if (type == PropertyType::SCALE_LOCK || type == PropertyType::POSITION
  628. || type == PropertyType::FLOAT_XY)
  629. {
  630. float a = readFloat();
  631. float b = readFloat();
  632. ValueVector ab;
  633. ab.push_back(Value(a));
  634. ab.push_back(Value(b));
  635. value = ab;
  636. }
  637. else if (type == PropertyType::SPRITEFRAME)
  638. {
  639. std::string spriteSheet = readCachedString();
  640. std::string spriteFile = readCachedString();
  641. SpriteFrame* spriteFrame;
  642. if (spriteSheet.empty())
  643. {
  644. spriteFile = _CCBRootPath + spriteFile;
  645. Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(spriteFile);
  646. Rect bounds = Rect(0, 0, texture->getContentSize().width, texture->getContentSize().height);
  647. spriteFrame = SpriteFrame::createWithTexture(texture, bounds);
  648. }
  649. else
  650. {
  651. spriteSheet = _CCBRootPath + spriteSheet;
  652. SpriteFrameCache* frameCache = SpriteFrameCache::getInstance();
  653. // Load the sprite sheet only if it is not loaded
  654. if (_loadedSpriteSheets.find(spriteSheet) == _loadedSpriteSheets.end())
  655. {
  656. frameCache->addSpriteFramesWithFile(spriteSheet);
  657. _loadedSpriteSheets.insert(spriteSheet);
  658. }
  659. spriteFrame = frameCache->getSpriteFrameByName(spriteFile);
  660. }
  661. keyframe->setObject(spriteFrame);
  662. }
  663. if (!value.isNull())
  664. keyframe->setValue(value);
  665. return keyframe;
  666. }
  667. bool CCBReader::readCallbackKeyframesForSeq(CCBSequence* seq)
  668. {
  669. int numKeyframes = readInt(false);
  670. if(!numKeyframes) return true;
  671. CCBSequenceProperty* channel = new (std::nothrow) CCBSequenceProperty();
  672. channel->autorelease();
  673. for(int i = 0; i < numKeyframes; ++i) {
  674. float time = readFloat();
  675. std::string callbackName = readCachedString();
  676. int callbackType = readInt(false);
  677. ValueVector valueVector;
  678. valueVector.push_back(Value(callbackName));
  679. valueVector.push_back(Value(callbackType));
  680. CCBKeyframe* keyframe = new (std::nothrow) CCBKeyframe();
  681. keyframe->autorelease();
  682. keyframe->setTime(time);
  683. keyframe->setValue(Value(valueVector));
  684. if(_jsControlled) {
  685. std::stringstream callbackIdentifier;
  686. callbackIdentifier << callbackType;
  687. callbackIdentifier << ":" + callbackName;
  688. _animationManager->getKeyframeCallbacks().push_back(Value(callbackIdentifier.str()));
  689. }
  690. channel->getKeyframes().pushBack(keyframe);
  691. }
  692. seq->setCallbackChannel(channel);
  693. return true;
  694. }
  695. bool CCBReader::readSoundKeyframesForSeq(CCBSequence* seq) {
  696. int numKeyframes = readInt(false);
  697. if(!numKeyframes) return true;
  698. CCBSequenceProperty* channel = new (std::nothrow) CCBSequenceProperty();
  699. channel->autorelease();
  700. for(int i = 0; i < numKeyframes; ++i) {
  701. float time = readFloat();
  702. std::string soundFile = readCachedString();
  703. float pitch = readFloat();
  704. float pan = readFloat();
  705. float gain = readFloat();
  706. ValueVector vec;
  707. vec.push_back(Value(soundFile));
  708. vec.push_back(Value(pitch));
  709. vec.push_back(Value(pan));
  710. vec.push_back(Value(gain));
  711. CCBKeyframe* keyframe = new (std::nothrow) CCBKeyframe();
  712. keyframe->setTime(time);
  713. keyframe->setValue(Value(vec));
  714. channel->getKeyframes().pushBack(keyframe);
  715. keyframe->release();
  716. }
  717. seq->setSoundChannel(channel);
  718. return true;
  719. }
  720. Node * CCBReader::readNodeGraph() {
  721. return this->readNodeGraph(nullptr);
  722. }
  723. bool CCBReader::readSequences()
  724. {
  725. auto& sequences = _animationManager->getSequences();
  726. int numSeqs = readInt(false);
  727. for (int i = 0; i < numSeqs; i++)
  728. {
  729. CCBSequence *seq = new (std::nothrow) CCBSequence();
  730. seq->autorelease();
  731. seq->setDuration(readFloat());
  732. seq->setName(readCachedString().c_str());
  733. seq->setSequenceId(readInt(false));
  734. seq->setChainedSequenceId(readInt(true));
  735. if(!readCallbackKeyframesForSeq(seq)) return false;
  736. if(!readSoundKeyframesForSeq(seq)) return false;
  737. sequences.pushBack(seq);
  738. }
  739. _animationManager->setAutoPlaySequenceId(readInt(true));
  740. return true;
  741. }
  742. std::string CCBReader::lastPathComponent(const char* pPath) {
  743. std::string path(pPath);
  744. size_t slashPos = path.find_last_of("/");
  745. if(slashPos != std::string::npos) {
  746. return path.substr(slashPos + 1, path.length() - slashPos);
  747. }
  748. return path;
  749. }
  750. std::string CCBReader::deletePathExtension(const char* pPath) {
  751. std::string path(pPath);
  752. size_t dotPos = path.find_last_of(".");
  753. if(dotPos != std::string::npos) {
  754. return path.substr(0, dotPos);
  755. }
  756. return path;
  757. }
  758. std::string CCBReader::toLowerCase(const char* pString) {
  759. std::string copy(pString);
  760. std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower);
  761. return copy;
  762. }
  763. bool CCBReader::endsWith(const char* pString, const char* pEnding) {
  764. std::string string(pString);
  765. std::string ending(pEnding);
  766. if(string.length() >= ending.length()) {
  767. return (string.compare(string.length() - ending.length(), ending.length(), ending) == 0);
  768. } else {
  769. return false;
  770. }
  771. }
  772. bool CCBReader::isJSControlled()
  773. {
  774. return _jsControlled;
  775. }
  776. void CCBReader::addOwnerCallbackName(const std::string& name)
  777. {
  778. _ownerCallbackNames.push_back(name);
  779. }
  780. void CCBReader::addOwnerCallbackNode(Node *node)
  781. {
  782. _ownerCallbackNodes.pushBack(node);
  783. }
  784. void CCBReader::addOwnerCallbackControlEvents(Control::EventType type)
  785. {
  786. _ownerOwnerCallbackControlEvents.push_back(Value((int)type));
  787. }
  788. void CCBReader::addDocumentCallbackName(const std::string& name)
  789. {
  790. _animationManager->addDocumentCallbackName(name);
  791. }
  792. void CCBReader::addDocumentCallbackNode(Node *node)
  793. {
  794. _animationManager->addDocumentCallbackNode(node);
  795. }
  796. void CCBReader::addDocumentCallbackControlEvents(Control::EventType eventType)
  797. {
  798. _animationManager->addDocumentCallbackControlEvents(eventType);
  799. }
  800. ValueVector CCBReader::getOwnerCallbackNames()
  801. {
  802. ValueVector ret;
  803. ret.reserve(_ownerCallbackNames.size());
  804. std::vector<std::string>::iterator it = _ownerCallbackNames.begin();
  805. for (; it != _ownerCallbackNames.end(); ++it)
  806. {
  807. ret.push_back(Value(*it));
  808. }
  809. return ret;
  810. }
  811. Vector<Node*>& CCBReader::getOwnerCallbackNodes()
  812. {
  813. return _ownerCallbackNodes;
  814. }
  815. ValueVector& CCBReader::getOwnerCallbackControlEvents()
  816. {
  817. return _ownerOwnerCallbackControlEvents;
  818. }
  819. ValueVector CCBReader::getOwnerOutletNames()
  820. {
  821. ValueVector ret;
  822. ret.reserve(_ownerOutletNames.size());
  823. std::vector<std::string>::iterator it = _ownerOutletNames.begin();
  824. for (; it != _ownerOutletNames.end(); ++it)
  825. {
  826. ret.push_back(Value(*it));
  827. }
  828. return ret;
  829. }
  830. Vector<Node*>& CCBReader::getOwnerOutletNodes()
  831. {
  832. return _ownerOutletNodes;
  833. }
  834. Vector<Node*>& CCBReader::getNodesWithAnimationManagers()
  835. {
  836. return _nodesWithAnimationManagers;
  837. }
  838. Vector<CCBAnimationManager*>& CCBReader::getAnimationManagersForNodes()
  839. {
  840. return _animationManagersForNodes;
  841. }
  842. void CCBReader::addOwnerOutletName(std::string name)
  843. {
  844. _ownerOutletNames.push_back(name);
  845. }
  846. void CCBReader::addOwnerOutletNode(Node *node)
  847. {
  848. if (nullptr == node)
  849. return;
  850. _ownerOutletNodes.pushBack(node);
  851. }
  852. /************************************************************************
  853. Static functions
  854. ************************************************************************/
  855. static float __ccbResolutionScale = 1.0f;
  856. float CCBReader::getResolutionScale()
  857. {
  858. return __ccbResolutionScale;
  859. }
  860. void CCBReader::setResolutionScale(float scale)
  861. {
  862. __ccbResolutionScale = scale;
  863. }
  864. };