PageRenderTime 44ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/cocos2d/cocos/2d/CCNode.cpp

https://gitlab.com/gasabr/flappy-test
C++ | 2033 lines | 1526 code | 358 blank | 149 comment | 252 complexity | 39e226542e5877aa1bb689754f1441d6 MD5 | raw file
  1. /****************************************************************************
  2. Copyright (c) 2008-2010 Ricardo Quesada
  3. Copyright (c) 2009 Valentin Milea
  4. Copyright (c) 2010-2012 cocos2d-x.org
  5. Copyright (c) 2011 Zynga Inc.
  6. Copyright (c) 2013-2014 Chukong Technologies Inc.
  7. http://www.cocos2d-x.org
  8. Permission is hereby granted, free of charge, to any person obtaining a copy
  9. of this software and associated documentation files (the "Software"), to deal
  10. in the Software without restriction, including without limitation the rights
  11. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. copies of the Software, and to permit persons to whom the Software is
  13. furnished to do so, subject to the following conditions:
  14. The above copyright notice and this permission notice shall be included in
  15. all copies or substantial portions of the Software.
  16. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. THE SOFTWARE.
  23. ****************************************************************************/
  24. #include "2d/CCNode.h"
  25. #include <algorithm>
  26. #include <string>
  27. #include <regex>
  28. #include "base/CCDirector.h"
  29. #include "base/CCScheduler.h"
  30. #include "base/CCEventDispatcher.h"
  31. #include "2d/CCCamera.h"
  32. #include "2d/CCActionManager.h"
  33. #include "2d/CCScene.h"
  34. #include "2d/CCComponent.h"
  35. #include "renderer/CCGLProgram.h"
  36. #include "renderer/CCGLProgramState.h"
  37. #include "renderer/CCMaterial.h"
  38. #include "math/TransformUtils.h"
  39. #include "deprecated/CCString.h"
  40. #if CC_NODE_RENDER_SUBPIXEL
  41. #define RENDER_IN_SUBPIXEL
  42. #else
  43. #define RENDER_IN_SUBPIXEL(__ARGS__) (ceil(__ARGS__))
  44. #endif
  45. NS_CC_BEGIN
  46. bool nodeComparisonLess(Node* n1, Node* n2)
  47. {
  48. return( n1->getLocalZOrder() < n2->getLocalZOrder() ||
  49. ( n1->getLocalZOrder() == n2->getLocalZOrder() && n1->getOrderOfArrival() < n2->getOrderOfArrival() )
  50. );
  51. }
  52. // FIXME:: Yes, nodes might have a sort problem once every 15 days if the game runs at 60 FPS and each frame sprites are reordered.
  53. int Node::s_globalOrderOfArrival = 1;
  54. // MARK: Constructor, Destructor, Init
  55. Node::Node()
  56. : _rotationX(0.0f)
  57. , _rotationY(0.0f)
  58. , _rotationZ_X(0.0f)
  59. , _rotationZ_Y(0.0f)
  60. , _scaleX(1.0f)
  61. , _scaleY(1.0f)
  62. , _scaleZ(1.0f)
  63. , _positionZ(0.0f)
  64. , _usingNormalizedPosition(false)
  65. , _normalizedPositionDirty(false)
  66. , _skewX(0.0f)
  67. , _skewY(0.0f)
  68. , _contentSize(Size::ZERO)
  69. , _contentSizeDirty(true)
  70. , _transformDirty(true)
  71. , _inverseDirty(true)
  72. , _useAdditionalTransform(false)
  73. , _transformUpdated(true)
  74. // children (lazy allocs)
  75. // lazy alloc
  76. , _localZOrder(0)
  77. , _globalZOrder(0)
  78. , _parent(nullptr)
  79. // "whole screen" objects. like Scenes and Layers, should set _ignoreAnchorPointForPosition to true
  80. , _tag(Node::INVALID_TAG)
  81. , _name("")
  82. , _hashOfName(0)
  83. // userData is always inited as nil
  84. , _userData(nullptr)
  85. , _userObject(nullptr)
  86. , _glProgramState(nullptr)
  87. , _orderOfArrival(0)
  88. , _running(false)
  89. , _visible(true)
  90. , _ignoreAnchorPointForPosition(false)
  91. , _reorderChildDirty(false)
  92. , _isTransitionFinished(false)
  93. #if CC_ENABLE_SCRIPT_BINDING
  94. , _updateScriptHandler(0)
  95. #endif
  96. , _componentContainer(nullptr)
  97. , _displayedOpacity(255)
  98. , _realOpacity(255)
  99. , _displayedColor(Color3B::WHITE)
  100. , _realColor(Color3B::WHITE)
  101. , _cascadeColorEnabled(false)
  102. , _cascadeOpacityEnabled(false)
  103. , _cameraMask(1)
  104. #if CC_USE_PHYSICS
  105. , _physicsBody(nullptr)
  106. #endif
  107. {
  108. // set default scheduler and actionManager
  109. _director = Director::getInstance();
  110. _actionManager = _director->getActionManager();
  111. _actionManager->retain();
  112. _scheduler = _director->getScheduler();
  113. _scheduler->retain();
  114. _eventDispatcher = _director->getEventDispatcher();
  115. _eventDispatcher->retain();
  116. #if CC_ENABLE_SCRIPT_BINDING
  117. ScriptEngineProtocol* engine = ScriptEngineManager::getInstance()->getScriptEngine();
  118. _scriptType = engine != nullptr ? engine->getScriptType() : kScriptTypeNone;
  119. #endif
  120. _transform = _inverse = _additionalTransform = Mat4::IDENTITY;
  121. }
  122. Node * Node::create()
  123. {
  124. Node * ret = new (std::nothrow) Node();
  125. if (ret && ret->init())
  126. {
  127. ret->autorelease();
  128. }
  129. else
  130. {
  131. CC_SAFE_DELETE(ret);
  132. }
  133. return ret;
  134. }
  135. Node::~Node()
  136. {
  137. CCLOGINFO( "deallocing Node: %p - tag: %i", this, _tag );
  138. #if CC_ENABLE_SCRIPT_BINDING
  139. if (_updateScriptHandler)
  140. {
  141. ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptHandler(_updateScriptHandler);
  142. }
  143. #endif
  144. // User object has to be released before others, since userObject may have a weak reference of this node
  145. // It may invoke `node->stopAllAction();` while `_actionManager` is null if the next line is after `CC_SAFE_RELEASE_NULL(_actionManager)`.
  146. CC_SAFE_RELEASE_NULL(_userObject);
  147. // attributes
  148. CC_SAFE_RELEASE_NULL(_glProgramState);
  149. for (auto& child : _children)
  150. {
  151. child->_parent = nullptr;
  152. }
  153. removeAllComponents();
  154. CC_SAFE_DELETE(_componentContainer);
  155. stopAllActions();
  156. unscheduleAllCallbacks();
  157. CC_SAFE_RELEASE_NULL(_actionManager);
  158. CC_SAFE_RELEASE_NULL(_scheduler);
  159. _eventDispatcher->removeEventListenersForTarget(this);
  160. #if CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS && COCOS2D_DEBUG > 0
  161. _eventDispatcher->debugCheckNodeHasNoEventListenersOnDestruction(this);
  162. #endif
  163. CCASSERT(!_running, "Node still marked as running on node destruction! Was base class onExit() called in derived class onExit() implementations?");
  164. CC_SAFE_RELEASE(_eventDispatcher);
  165. }
  166. bool Node::init()
  167. {
  168. return true;
  169. }
  170. void Node::cleanup()
  171. {
  172. #if CC_ENABLE_SCRIPT_BINDING
  173. if (_scriptType == kScriptTypeJavascript)
  174. {
  175. if (ScriptEngineManager::sendNodeEventToJS(this, kNodeOnCleanup))
  176. return;
  177. }
  178. else if (_scriptType == kScriptTypeLua)
  179. {
  180. ScriptEngineManager::sendNodeEventToLua(this, kNodeOnCleanup);
  181. }
  182. #endif // #if CC_ENABLE_SCRIPT_BINDING
  183. // actions
  184. this->stopAllActions();
  185. // timers
  186. this->unscheduleAllCallbacks();
  187. for( const auto &child: _children)
  188. child->cleanup();
  189. }
  190. std::string Node::getDescription() const
  191. {
  192. return StringUtils::format("<Node | Tag = %d", _tag);
  193. }
  194. // MARK: getters / setters
  195. float Node::getSkewX() const
  196. {
  197. return _skewX;
  198. }
  199. void Node::setSkewX(float skewX)
  200. {
  201. if (_skewX == skewX)
  202. return;
  203. _skewX = skewX;
  204. _transformUpdated = _transformDirty = _inverseDirty = true;
  205. }
  206. float Node::getSkewY() const
  207. {
  208. return _skewY;
  209. }
  210. void Node::setSkewY(float skewY)
  211. {
  212. if (_skewY == skewY)
  213. return;
  214. _skewY = skewY;
  215. _transformUpdated = _transformDirty = _inverseDirty = true;
  216. }
  217. void Node::setLocalZOrder(int z)
  218. {
  219. if (_localZOrder == z)
  220. return;
  221. _localZOrder = z;
  222. if (_parent)
  223. {
  224. _parent->reorderChild(this, z);
  225. }
  226. _eventDispatcher->setDirtyForNode(this);
  227. }
  228. /// zOrder setter : private method
  229. /// used internally to alter the zOrder variable. DON'T call this method manually
  230. void Node::_setLocalZOrder(int z)
  231. {
  232. _localZOrder = z;
  233. }
  234. void Node::setGlobalZOrder(float globalZOrder)
  235. {
  236. if (_globalZOrder != globalZOrder)
  237. {
  238. _globalZOrder = globalZOrder;
  239. _eventDispatcher->setDirtyForNode(this);
  240. }
  241. }
  242. /// rotation getter
  243. float Node::getRotation() const
  244. {
  245. CCASSERT(_rotationZ_X == _rotationZ_Y, "CCNode#rotation. RotationX != RotationY. Don't know which one to return");
  246. return _rotationZ_X;
  247. }
  248. /// rotation setter
  249. void Node::setRotation(float rotation)
  250. {
  251. if (_rotationZ_X == rotation)
  252. return;
  253. _rotationZ_X = _rotationZ_Y = rotation;
  254. _transformUpdated = _transformDirty = _inverseDirty = true;
  255. updateRotationQuat();
  256. }
  257. float Node::getRotationSkewX() const
  258. {
  259. return _rotationZ_X;
  260. }
  261. void Node::setRotation3D(const Vec3& rotation)
  262. {
  263. if (_rotationX == rotation.x &&
  264. _rotationY == rotation.y &&
  265. _rotationZ_X == rotation.z)
  266. return;
  267. _transformUpdated = _transformDirty = _inverseDirty = true;
  268. _rotationX = rotation.x;
  269. _rotationY = rotation.y;
  270. // rotation Z is decomposed in 2 to simulate Skew for Flash animations
  271. _rotationZ_Y = _rotationZ_X = rotation.z;
  272. updateRotationQuat();
  273. }
  274. Vec3 Node::getRotation3D() const
  275. {
  276. // rotation Z is decomposed in 2 to simulate Skew for Flash animations
  277. CCASSERT(_rotationZ_X == _rotationZ_Y, "_rotationZ_X != _rotationZ_Y");
  278. return Vec3(_rotationX,_rotationY,_rotationZ_X);
  279. }
  280. void Node::updateRotationQuat()
  281. {
  282. // convert Euler angle to quaternion
  283. // when _rotationZ_X == _rotationZ_Y, _rotationQuat = RotationZ_X * RotationY * RotationX
  284. // when _rotationZ_X != _rotationZ_Y, _rotationQuat = RotationY * RotationX
  285. float halfRadx = CC_DEGREES_TO_RADIANS(_rotationX / 2.f), halfRady = CC_DEGREES_TO_RADIANS(_rotationY / 2.f), halfRadz = _rotationZ_X == _rotationZ_Y ? -CC_DEGREES_TO_RADIANS(_rotationZ_X / 2.f) : 0;
  286. float coshalfRadx = cosf(halfRadx), sinhalfRadx = sinf(halfRadx), coshalfRady = cosf(halfRady), sinhalfRady = sinf(halfRady), coshalfRadz = cosf(halfRadz), sinhalfRadz = sinf(halfRadz);
  287. _rotationQuat.x = sinhalfRadx * coshalfRady * coshalfRadz - coshalfRadx * sinhalfRady * sinhalfRadz;
  288. _rotationQuat.y = coshalfRadx * sinhalfRady * coshalfRadz + sinhalfRadx * coshalfRady * sinhalfRadz;
  289. _rotationQuat.z = coshalfRadx * coshalfRady * sinhalfRadz - sinhalfRadx * sinhalfRady * coshalfRadz;
  290. _rotationQuat.w = coshalfRadx * coshalfRady * coshalfRadz + sinhalfRadx * sinhalfRady * sinhalfRadz;
  291. }
  292. void Node::updateRotation3D()
  293. {
  294. //convert quaternion to Euler angle
  295. float x = _rotationQuat.x, y = _rotationQuat.y, z = _rotationQuat.z, w = _rotationQuat.w;
  296. _rotationX = atan2f(2.f * (w * x + y * z), 1.f - 2.f * (x * x + y * y));
  297. float sy = 2.f * (w * y - z * x);
  298. sy = clampf(sy, -1, 1);
  299. _rotationY = asinf(sy);
  300. _rotationZ_X = atan2f(2.f * (w * z + x * y), 1.f - 2.f * (y * y + z * z));
  301. _rotationX = CC_RADIANS_TO_DEGREES(_rotationX);
  302. _rotationY = CC_RADIANS_TO_DEGREES(_rotationY);
  303. _rotationZ_X = _rotationZ_Y = -CC_RADIANS_TO_DEGREES(_rotationZ_X);
  304. }
  305. void Node::setRotationQuat(const Quaternion& quat)
  306. {
  307. _rotationQuat = quat;
  308. updateRotation3D();
  309. _transformUpdated = _transformDirty = _inverseDirty = true;
  310. }
  311. Quaternion Node::getRotationQuat() const
  312. {
  313. return _rotationQuat;
  314. }
  315. void Node::setRotationSkewX(float rotationX)
  316. {
  317. if (_rotationZ_X == rotationX)
  318. return;
  319. _rotationZ_X = rotationX;
  320. _transformUpdated = _transformDirty = _inverseDirty = true;
  321. updateRotationQuat();
  322. }
  323. float Node::getRotationSkewY() const
  324. {
  325. return _rotationZ_Y;
  326. }
  327. void Node::setRotationSkewY(float rotationY)
  328. {
  329. if (_rotationZ_Y == rotationY)
  330. return;
  331. _rotationZ_Y = rotationY;
  332. _transformUpdated = _transformDirty = _inverseDirty = true;
  333. updateRotationQuat();
  334. }
  335. /// scale getter
  336. float Node::getScale(void) const
  337. {
  338. CCASSERT( _scaleX == _scaleY, "CCNode#scale. ScaleX != ScaleY. Don't know which one to return");
  339. return _scaleX;
  340. }
  341. /// scale setter
  342. void Node::setScale(float scale)
  343. {
  344. if (_scaleX == scale && _scaleY == scale && _scaleZ == scale)
  345. return;
  346. _scaleX = _scaleY = _scaleZ = scale;
  347. _transformUpdated = _transformDirty = _inverseDirty = true;
  348. }
  349. /// scaleX getter
  350. float Node::getScaleX() const
  351. {
  352. return _scaleX;
  353. }
  354. /// scale setter
  355. void Node::setScale(float scaleX,float scaleY)
  356. {
  357. if (_scaleX == scaleX && _scaleY == scaleY)
  358. return;
  359. _scaleX = scaleX;
  360. _scaleY = scaleY;
  361. _transformUpdated = _transformDirty = _inverseDirty = true;
  362. }
  363. /// scaleX setter
  364. void Node::setScaleX(float scaleX)
  365. {
  366. if (_scaleX == scaleX)
  367. return;
  368. _scaleX = scaleX;
  369. _transformUpdated = _transformDirty = _inverseDirty = true;
  370. }
  371. /// scaleY getter
  372. float Node::getScaleY() const
  373. {
  374. return _scaleY;
  375. }
  376. /// scaleY setter
  377. void Node::setScaleZ(float scaleZ)
  378. {
  379. if (_scaleZ == scaleZ)
  380. return;
  381. _scaleZ = scaleZ;
  382. _transformUpdated = _transformDirty = _inverseDirty = true;
  383. }
  384. /// scaleY getter
  385. float Node::getScaleZ() const
  386. {
  387. return _scaleZ;
  388. }
  389. /// scaleY setter
  390. void Node::setScaleY(float scaleY)
  391. {
  392. if (_scaleY == scaleY)
  393. return;
  394. _scaleY = scaleY;
  395. _transformUpdated = _transformDirty = _inverseDirty = true;
  396. }
  397. /// position getter
  398. const Vec2& Node::getPosition() const
  399. {
  400. return _position;
  401. }
  402. /// position setter
  403. void Node::setPosition(const Vec2& position)
  404. {
  405. setPosition(position.x, position.y);
  406. }
  407. void Node::getPosition(float* x, float* y) const
  408. {
  409. *x = _position.x;
  410. *y = _position.y;
  411. }
  412. void Node::setPosition(float x, float y)
  413. {
  414. if (_position.x == x && _position.y == y)
  415. return;
  416. _position.x = x;
  417. _position.y = y;
  418. _transformUpdated = _transformDirty = _inverseDirty = true;
  419. _usingNormalizedPosition = false;
  420. }
  421. void Node::setPosition3D(const Vec3& position)
  422. {
  423. setPositionZ(position.z);
  424. setPosition(position.x, position.y);
  425. }
  426. Vec3 Node::getPosition3D() const
  427. {
  428. return Vec3(_position.x, _position.y, _positionZ);
  429. }
  430. float Node::getPositionX() const
  431. {
  432. return _position.x;
  433. }
  434. void Node::setPositionX(float x)
  435. {
  436. setPosition(x, _position.y);
  437. }
  438. float Node::getPositionY() const
  439. {
  440. return _position.y;
  441. }
  442. void Node::setPositionY(float y)
  443. {
  444. setPosition(_position.x, y);
  445. }
  446. float Node::getPositionZ() const
  447. {
  448. return _positionZ;
  449. }
  450. void Node::setPositionZ(float positionZ)
  451. {
  452. if (_positionZ == positionZ)
  453. return;
  454. _transformUpdated = _transformDirty = _inverseDirty = true;
  455. _positionZ = positionZ;
  456. }
  457. /// position getter
  458. const Vec2& Node::getNormalizedPosition() const
  459. {
  460. return _normalizedPosition;
  461. }
  462. /// position setter
  463. void Node::setNormalizedPosition(const Vec2& position)
  464. {
  465. if (_normalizedPosition.equals(position))
  466. return;
  467. _normalizedPosition = position;
  468. _usingNormalizedPosition = true;
  469. _normalizedPositionDirty = true;
  470. _transformUpdated = _transformDirty = _inverseDirty = true;
  471. }
  472. ssize_t Node::getChildrenCount() const
  473. {
  474. return _children.size();
  475. }
  476. /// isVisible getter
  477. bool Node::isVisible() const
  478. {
  479. return _visible;
  480. }
  481. /// isVisible setter
  482. void Node::setVisible(bool visible)
  483. {
  484. if(visible != _visible)
  485. {
  486. _visible = visible;
  487. if(_visible)
  488. _transformUpdated = _transformDirty = _inverseDirty = true;
  489. }
  490. }
  491. const Vec2& Node::getAnchorPointInPoints() const
  492. {
  493. return _anchorPointInPoints;
  494. }
  495. /// anchorPoint getter
  496. const Vec2& Node::getAnchorPoint() const
  497. {
  498. return _anchorPoint;
  499. }
  500. void Node::setAnchorPoint(const Vec2& point)
  501. {
  502. if (! point.equals(_anchorPoint))
  503. {
  504. _anchorPoint = point;
  505. _anchorPointInPoints.set(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y);
  506. _transformUpdated = _transformDirty = _inverseDirty = true;
  507. }
  508. }
  509. /// contentSize getter
  510. const Size& Node::getContentSize() const
  511. {
  512. return _contentSize;
  513. }
  514. void Node::setContentSize(const Size & size)
  515. {
  516. if (! size.equals(_contentSize))
  517. {
  518. _contentSize = size;
  519. _anchorPointInPoints.set(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y);
  520. _transformUpdated = _transformDirty = _inverseDirty = _contentSizeDirty = true;
  521. }
  522. }
  523. // isRunning getter
  524. bool Node::isRunning() const
  525. {
  526. return _running;
  527. }
  528. /// parent setter
  529. void Node::setParent(Node * parent)
  530. {
  531. _parent = parent;
  532. _transformUpdated = _transformDirty = _inverseDirty = true;
  533. }
  534. /// isRelativeAnchorPoint getter
  535. bool Node::isIgnoreAnchorPointForPosition() const
  536. {
  537. return _ignoreAnchorPointForPosition;
  538. }
  539. /// isRelativeAnchorPoint setter
  540. void Node::ignoreAnchorPointForPosition(bool newValue)
  541. {
  542. if (newValue != _ignoreAnchorPointForPosition)
  543. {
  544. _ignoreAnchorPointForPosition = newValue;
  545. _transformUpdated = _transformDirty = _inverseDirty = true;
  546. }
  547. }
  548. /// tag getter
  549. int Node::getTag() const
  550. {
  551. return _tag;
  552. }
  553. /// tag setter
  554. void Node::setTag(int tag)
  555. {
  556. _tag = tag ;
  557. }
  558. const std::string& Node::getName() const
  559. {
  560. return _name;
  561. }
  562. void Node::setName(const std::string& name)
  563. {
  564. _name = name;
  565. std::hash<std::string> h;
  566. _hashOfName = h(name);
  567. }
  568. /// userData setter
  569. void Node::setUserData(void *userData)
  570. {
  571. _userData = userData;
  572. }
  573. int Node::getOrderOfArrival() const
  574. {
  575. return _orderOfArrival;
  576. }
  577. void Node::setOrderOfArrival(int orderOfArrival)
  578. {
  579. CCASSERT(orderOfArrival >=0, "Invalid orderOfArrival");
  580. _orderOfArrival = orderOfArrival;
  581. }
  582. void Node::setUserObject(Ref* userObject)
  583. {
  584. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  585. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  586. if (sEngine)
  587. {
  588. if (userObject)
  589. sEngine->retainScriptObject(this, userObject);
  590. if (_userObject)
  591. sEngine->releaseScriptObject(this, _userObject);
  592. }
  593. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  594. CC_SAFE_RETAIN(userObject);
  595. CC_SAFE_RELEASE(_userObject);
  596. _userObject = userObject;
  597. }
  598. GLProgramState* Node::getGLProgramState() const
  599. {
  600. return _glProgramState;
  601. }
  602. void Node::setGLProgramState(cocos2d::GLProgramState* glProgramState)
  603. {
  604. if (glProgramState != _glProgramState)
  605. {
  606. CC_SAFE_RELEASE(_glProgramState);
  607. _glProgramState = glProgramState;
  608. CC_SAFE_RETAIN(_glProgramState);
  609. if (_glProgramState)
  610. _glProgramState->setNodeBinding(this);
  611. }
  612. }
  613. void Node::setGLProgram(GLProgram* glProgram)
  614. {
  615. if (_glProgramState == nullptr || (_glProgramState && _glProgramState->getGLProgram() != glProgram))
  616. {
  617. CC_SAFE_RELEASE(_glProgramState);
  618. _glProgramState = GLProgramState::getOrCreateWithGLProgram(glProgram);
  619. _glProgramState->retain();
  620. _glProgramState->setNodeBinding(this);
  621. }
  622. }
  623. GLProgram * Node::getGLProgram() const
  624. {
  625. return _glProgramState ? _glProgramState->getGLProgram() : nullptr;
  626. }
  627. Scene* Node::getScene() const
  628. {
  629. if (!_parent)
  630. return nullptr;
  631. auto sceneNode = _parent;
  632. while (sceneNode->_parent)
  633. {
  634. sceneNode = sceneNode->_parent;
  635. }
  636. return dynamic_cast<Scene*>(sceneNode);
  637. }
  638. Rect Node::getBoundingBox() const
  639. {
  640. Rect rect(0, 0, _contentSize.width, _contentSize.height);
  641. return RectApplyAffineTransform(rect, getNodeToParentAffineTransform());
  642. }
  643. // MARK: Children logic
  644. // lazy allocs
  645. void Node::childrenAlloc()
  646. {
  647. _children.reserve(4);
  648. }
  649. Node* Node::getChildByTag(int tag) const
  650. {
  651. CCASSERT(tag != Node::INVALID_TAG, "Invalid tag");
  652. for (const auto child : _children)
  653. {
  654. if(child && child->_tag == tag)
  655. return child;
  656. }
  657. return nullptr;
  658. }
  659. Node* Node::getChildByName(const std::string& name) const
  660. {
  661. CCASSERT(!name.empty(), "Invalid name");
  662. std::hash<std::string> h;
  663. size_t hash = h(name);
  664. for (const auto& child : _children)
  665. {
  666. // Different strings may have the same hash code, but can use it to compare first for speed
  667. if(child->_hashOfName == hash && child->_name.compare(name) == 0)
  668. return child;
  669. }
  670. return nullptr;
  671. }
  672. void Node::enumerateChildren(const std::string &name, std::function<bool (Node *)> callback) const
  673. {
  674. CCASSERT(!name.empty(), "Invalid name");
  675. CCASSERT(callback != nullptr, "Invalid callback function");
  676. size_t length = name.length();
  677. size_t subStrStartPos = 0; // sub string start index
  678. size_t subStrlength = length; // sub string length
  679. // Starts with '//'?
  680. bool searchRecursively = false;
  681. if (length > 2 && name[0] == '/' && name[1] == '/')
  682. {
  683. searchRecursively = true;
  684. subStrStartPos = 2;
  685. subStrlength -= 2;
  686. }
  687. // End with '/..'?
  688. bool searchFromParent = false;
  689. if (length > 3 &&
  690. name[length-3] == '/' &&
  691. name[length-2] == '.' &&
  692. name[length-1] == '.')
  693. {
  694. searchFromParent = true;
  695. subStrlength -= 3;
  696. }
  697. // Remove '//', '/..' if exist
  698. std::string newName = name.substr(subStrStartPos, subStrlength);
  699. if (searchFromParent)
  700. {
  701. newName.insert(0, "[[:alnum:]]+/");
  702. }
  703. if (searchRecursively)
  704. {
  705. // name is '//xxx'
  706. doEnumerateRecursive(this, newName, callback);
  707. }
  708. else
  709. {
  710. // name is xxx
  711. doEnumerate(newName, callback);
  712. }
  713. }
  714. bool Node::doEnumerateRecursive(const Node* node, const std::string &name, std::function<bool (Node *)> callback) const
  715. {
  716. bool ret =false;
  717. if (node->doEnumerate(name, callback))
  718. {
  719. // search itself
  720. ret = true;
  721. }
  722. else
  723. {
  724. // search its children
  725. for (const auto& child : node->getChildren())
  726. {
  727. if (doEnumerateRecursive(child, name, callback))
  728. {
  729. ret = true;
  730. break;
  731. }
  732. }
  733. }
  734. return ret;
  735. }
  736. bool Node::doEnumerate(std::string name, std::function<bool (Node *)> callback) const
  737. {
  738. // name may be xxx/yyy, should find its parent
  739. size_t pos = name.find('/');
  740. std::string searchName = name;
  741. bool needRecursive = false;
  742. if (pos != name.npos)
  743. {
  744. searchName = name.substr(0, pos);
  745. name.erase(0, pos+1);
  746. needRecursive = true;
  747. }
  748. bool ret = false;
  749. for (const auto& child : getChildren())
  750. {
  751. if (std::regex_match(child->_name, std::regex(searchName)))
  752. {
  753. if (!needRecursive)
  754. {
  755. // terminate enumeration if callback return true
  756. if (callback(child))
  757. {
  758. ret = true;
  759. break;
  760. }
  761. }
  762. else
  763. {
  764. ret = child->doEnumerate(name, callback);
  765. if (ret)
  766. break;
  767. }
  768. }
  769. }
  770. return ret;
  771. }
  772. /* "add" logic MUST only be on this method
  773. * If a class want's to extend the 'addChild' behavior it only needs
  774. * to override this method
  775. */
  776. void Node::addChild(Node *child, int localZOrder, int tag)
  777. {
  778. CCASSERT( child != nullptr, "Argument must be non-nil");
  779. CCASSERT( child->_parent == nullptr, "child already added. It can't be added again");
  780. addChildHelper(child, localZOrder, tag, "", true);
  781. }
  782. void Node::addChild(Node* child, int localZOrder, const std::string &name)
  783. {
  784. CCASSERT(child != nullptr, "Argument must be non-nil");
  785. CCASSERT(child->_parent == nullptr, "child already added. It can't be added again");
  786. addChildHelper(child, localZOrder, INVALID_TAG, name, false);
  787. }
  788. void Node::addChildHelper(Node* child, int localZOrder, int tag, const std::string &name, bool setTag)
  789. {
  790. if (_children.empty())
  791. {
  792. this->childrenAlloc();
  793. }
  794. this->insertChild(child, localZOrder);
  795. if (setTag)
  796. child->setTag(tag);
  797. else
  798. child->setName(name);
  799. child->setParent(this);
  800. child->setOrderOfArrival(s_globalOrderOfArrival++);
  801. if( _running )
  802. {
  803. child->onEnter();
  804. // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter
  805. if (_isTransitionFinished)
  806. {
  807. child->onEnterTransitionDidFinish();
  808. }
  809. }
  810. if (_cascadeColorEnabled)
  811. {
  812. updateCascadeColor();
  813. }
  814. if (_cascadeOpacityEnabled)
  815. {
  816. updateCascadeOpacity();
  817. }
  818. }
  819. void Node::addChild(Node *child, int zOrder)
  820. {
  821. CCASSERT( child != nullptr, "Argument must be non-nil");
  822. this->addChild(child, zOrder, child->_name);
  823. }
  824. void Node::addChild(Node *child)
  825. {
  826. CCASSERT( child != nullptr, "Argument must be non-nil");
  827. this->addChild(child, child->_localZOrder, child->_name);
  828. }
  829. void Node::removeFromParent()
  830. {
  831. this->removeFromParentAndCleanup(true);
  832. }
  833. void Node::removeFromParentAndCleanup(bool cleanup)
  834. {
  835. if (_parent != nullptr)
  836. {
  837. _parent->removeChild(this,cleanup);
  838. }
  839. }
  840. /* "remove" logic MUST only be on this method
  841. * If a class want's to extend the 'removeChild' behavior it only needs
  842. * to override this method
  843. */
  844. void Node::removeChild(Node* child, bool cleanup /* = true */)
  845. {
  846. // explicit nil handling
  847. if (_children.empty())
  848. {
  849. return;
  850. }
  851. ssize_t index = _children.getIndex(child);
  852. if( index != CC_INVALID_INDEX )
  853. this->detachChild( child, index, cleanup );
  854. }
  855. void Node::removeChildByTag(int tag, bool cleanup/* = true */)
  856. {
  857. CCASSERT( tag != Node::INVALID_TAG, "Invalid tag");
  858. Node *child = this->getChildByTag(tag);
  859. if (child == nullptr)
  860. {
  861. CCLOG("cocos2d: removeChildByTag(tag = %d): child not found!", tag);
  862. }
  863. else
  864. {
  865. this->removeChild(child, cleanup);
  866. }
  867. }
  868. void Node::removeChildByName(const std::string &name, bool cleanup)
  869. {
  870. CCASSERT(!name.empty(), "Invalid name");
  871. Node *child = this->getChildByName(name);
  872. if (child == nullptr)
  873. {
  874. CCLOG("cocos2d: removeChildByName(name = %s): child not found!", name.c_str());
  875. }
  876. else
  877. {
  878. this->removeChild(child, cleanup);
  879. }
  880. }
  881. void Node::removeAllChildren()
  882. {
  883. this->removeAllChildrenWithCleanup(true);
  884. }
  885. void Node::removeAllChildrenWithCleanup(bool cleanup)
  886. {
  887. // not using detachChild improves speed here
  888. for (const auto& child : _children)
  889. {
  890. // IMPORTANT:
  891. // -1st do onExit
  892. // -2nd cleanup
  893. if(_running)
  894. {
  895. child->onExitTransitionDidStart();
  896. child->onExit();
  897. }
  898. if (cleanup)
  899. {
  900. child->cleanup();
  901. }
  902. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  903. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  904. if (sEngine)
  905. {
  906. sEngine->releaseScriptObject(this, child);
  907. }
  908. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  909. // set parent nil at the end
  910. child->setParent(nullptr);
  911. }
  912. _children.clear();
  913. }
  914. void Node::detachChild(Node *child, ssize_t childIndex, bool doCleanup)
  915. {
  916. // IMPORTANT:
  917. // -1st do onExit
  918. // -2nd cleanup
  919. if (_running)
  920. {
  921. child->onExitTransitionDidStart();
  922. child->onExit();
  923. }
  924. // If you don't do cleanup, the child's actions will not get removed and the
  925. // its scheduledSelectors_ dict will not get released!
  926. if (doCleanup)
  927. {
  928. child->cleanup();
  929. }
  930. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  931. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  932. if (sEngine)
  933. {
  934. sEngine->releaseScriptObject(this, child);
  935. }
  936. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  937. // set parent nil at the end
  938. child->setParent(nullptr);
  939. _children.erase(childIndex);
  940. }
  941. // helper used by reorderChild & add
  942. void Node::insertChild(Node* child, int z)
  943. {
  944. #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  945. auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
  946. if (sEngine)
  947. {
  948. sEngine->retainScriptObject(this, child);
  949. }
  950. #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
  951. _transformUpdated = true;
  952. _reorderChildDirty = true;
  953. _children.pushBack(child);
  954. child->_localZOrder = z;
  955. }
  956. void Node::reorderChild(Node *child, int zOrder)
  957. {
  958. CCASSERT( child != nullptr, "Child must be non-nil");
  959. _reorderChildDirty = true;
  960. child->setOrderOfArrival(s_globalOrderOfArrival++);
  961. child->_localZOrder = zOrder;
  962. }
  963. void Node::sortAllChildren()
  964. {
  965. if (_reorderChildDirty)
  966. {
  967. std::sort(std::begin(_children), std::end(_children), nodeComparisonLess);
  968. _reorderChildDirty = false;
  969. }
  970. }
  971. // MARK: draw / visit
  972. void Node::draw()
  973. {
  974. auto renderer = _director->getRenderer();
  975. draw(renderer, _modelViewTransform, true);
  976. }
  977. void Node::draw(Renderer* renderer, const Mat4 &transform, uint32_t flags)
  978. {
  979. }
  980. void Node::visit()
  981. {
  982. auto renderer = _director->getRenderer();
  983. auto& parentTransform = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  984. visit(renderer, parentTransform, true);
  985. }
  986. uint32_t Node::processParentFlags(const Mat4& parentTransform, uint32_t parentFlags)
  987. {
  988. if(_usingNormalizedPosition)
  989. {
  990. CCASSERT(_parent, "setNormalizedPosition() doesn't work with orphan nodes");
  991. if ((parentFlags & FLAGS_CONTENT_SIZE_DIRTY) || _normalizedPositionDirty)
  992. {
  993. auto& s = _parent->getContentSize();
  994. _position.x = _normalizedPosition.x * s.width;
  995. _position.y = _normalizedPosition.y * s.height;
  996. _transformUpdated = _transformDirty = _inverseDirty = true;
  997. _normalizedPositionDirty = false;
  998. }
  999. }
  1000. //remove this two line given that isVisitableByVisitingCamera should not affect the calculation of transform given that we are visiting scene
  1001. //without involving view and projection matrix.
  1002. // if (!isVisitableByVisitingCamera())
  1003. // return parentFlags;
  1004. uint32_t flags = parentFlags;
  1005. flags |= (_transformUpdated ? FLAGS_TRANSFORM_DIRTY : 0);
  1006. flags |= (_contentSizeDirty ? FLAGS_CONTENT_SIZE_DIRTY : 0);
  1007. if(flags & FLAGS_DIRTY_MASK)
  1008. _modelViewTransform = this->transform(parentTransform);
  1009. _transformUpdated = false;
  1010. _contentSizeDirty = false;
  1011. return flags;
  1012. }
  1013. bool Node::isVisitableByVisitingCamera() const
  1014. {
  1015. auto camera = Camera::getVisitingCamera();
  1016. bool visibleByCamera = camera ? ((unsigned short)camera->getCameraFlag() & _cameraMask) != 0 : true;
  1017. return visibleByCamera;
  1018. }
  1019. void Node::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags)
  1020. {
  1021. // quick return if not visible. children won't be drawn.
  1022. if (!_visible)
  1023. {
  1024. return;
  1025. }
  1026. uint32_t flags = processParentFlags(parentTransform, parentFlags);
  1027. // IMPORTANT:
  1028. // To ease the migration to v3.0, we still support the Mat4 stack,
  1029. // but it is deprecated and your code should not rely on it
  1030. _director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  1031. _director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
  1032. bool visibleByCamera = isVisitableByVisitingCamera();
  1033. int i = 0;
  1034. if(!_children.empty())
  1035. {
  1036. sortAllChildren();
  1037. // draw children zOrder < 0
  1038. for( ; i < _children.size(); i++ )
  1039. {
  1040. auto node = _children.at(i);
  1041. if (node && node->_localZOrder < 0)
  1042. node->visit(renderer, _modelViewTransform, flags);
  1043. else
  1044. break;
  1045. }
  1046. // self draw
  1047. if (visibleByCamera)
  1048. this->draw(renderer, _modelViewTransform, flags);
  1049. for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
  1050. (*it)->visit(renderer, _modelViewTransform, flags);
  1051. }
  1052. else if (visibleByCamera)
  1053. {
  1054. this->draw(renderer, _modelViewTransform, flags);
  1055. }
  1056. _director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  1057. // FIX ME: Why need to set _orderOfArrival to 0??
  1058. // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920
  1059. // reset for next frame
  1060. // _orderOfArrival = 0;
  1061. }
  1062. Mat4 Node::transform(const Mat4& parentTransform)
  1063. {
  1064. return parentTransform * this->getNodeToParentTransform();
  1065. }
  1066. // MARK: events
  1067. void Node::onEnter()
  1068. {
  1069. #if CC_ENABLE_SCRIPT_BINDING
  1070. if (_scriptType == kScriptTypeJavascript)
  1071. {
  1072. if (ScriptEngineManager::sendNodeEventToJS(this, kNodeOnEnter))
  1073. return;
  1074. }
  1075. #endif
  1076. if (_onEnterCallback)
  1077. _onEnterCallback();
  1078. if (_componentContainer && !_componentContainer->isEmpty())
  1079. {
  1080. _componentContainer->onEnter();
  1081. }
  1082. _isTransitionFinished = false;
  1083. for( const auto &child: _children)
  1084. child->onEnter();
  1085. this->resume();
  1086. _running = true;
  1087. #if CC_ENABLE_SCRIPT_BINDING
  1088. if (_scriptType == kScriptTypeLua)
  1089. {
  1090. ScriptEngineManager::sendNodeEventToLua(this, kNodeOnEnter);
  1091. }
  1092. #endif
  1093. }
  1094. void Node::onEnterTransitionDidFinish()
  1095. {
  1096. #if CC_ENABLE_SCRIPT_BINDING
  1097. if (_scriptType == kScriptTypeJavascript)
  1098. {
  1099. if (ScriptEngineManager::sendNodeEventToJS(this, kNodeOnEnterTransitionDidFinish))
  1100. return;
  1101. }
  1102. #endif
  1103. if (_onEnterTransitionDidFinishCallback)
  1104. _onEnterTransitionDidFinishCallback();
  1105. _isTransitionFinished = true;
  1106. for( const auto &child: _children)
  1107. child->onEnterTransitionDidFinish();
  1108. #if CC_ENABLE_SCRIPT_BINDING
  1109. if (_scriptType == kScriptTypeLua)
  1110. {
  1111. ScriptEngineManager::sendNodeEventToLua(this, kNodeOnEnterTransitionDidFinish);
  1112. }
  1113. #endif
  1114. }
  1115. void Node::onExitTransitionDidStart()
  1116. {
  1117. #if CC_ENABLE_SCRIPT_BINDING
  1118. if (_scriptType == kScriptTypeJavascript)
  1119. {
  1120. if (ScriptEngineManager::sendNodeEventToJS(this, kNodeOnExitTransitionDidStart))
  1121. return;
  1122. }
  1123. #endif
  1124. if (_onExitTransitionDidStartCallback)
  1125. _onExitTransitionDidStartCallback();
  1126. for( const auto &child: _children)
  1127. child->onExitTransitionDidStart();
  1128. #if CC_ENABLE_SCRIPT_BINDING
  1129. if (_scriptType == kScriptTypeLua)
  1130. {
  1131. ScriptEngineManager::sendNodeEventToLua(this, kNodeOnExitTransitionDidStart);
  1132. }
  1133. #endif
  1134. }
  1135. void Node::onExit()
  1136. {
  1137. #if CC_ENABLE_SCRIPT_BINDING
  1138. if (_scriptType == kScriptTypeJavascript)
  1139. {
  1140. if (ScriptEngineManager::sendNodeEventToJS(this, kNodeOnExit))
  1141. return;
  1142. }
  1143. #endif
  1144. if (_onExitCallback)
  1145. _onExitCallback();
  1146. if (_componentContainer && !_componentContainer->isEmpty())
  1147. {
  1148. _componentContainer->onExit();
  1149. }
  1150. this->pause();
  1151. _running = false;
  1152. for( const auto &child: _children)
  1153. child->onExit();
  1154. #if CC_ENABLE_SCRIPT_BINDING
  1155. if (_scriptType == kScriptTypeLua)
  1156. {
  1157. ScriptEngineManager::sendNodeEventToLua(this, kNodeOnExit);
  1158. }
  1159. #endif
  1160. }
  1161. void Node::setEventDispatcher(EventDispatcher* dispatcher)
  1162. {
  1163. if (dispatcher != _eventDispatcher)
  1164. {
  1165. _eventDispatcher->removeEventListenersForTarget(this);
  1166. CC_SAFE_RETAIN(dispatcher);
  1167. CC_SAFE_RELEASE(_eventDispatcher);
  1168. _eventDispatcher = dispatcher;
  1169. }
  1170. }
  1171. void Node::setActionManager(ActionManager* actionManager)
  1172. {
  1173. if( actionManager != _actionManager )
  1174. {
  1175. this->stopAllActions();
  1176. CC_SAFE_RETAIN(actionManager);
  1177. CC_SAFE_RELEASE(_actionManager);
  1178. _actionManager = actionManager;
  1179. }
  1180. }
  1181. // MARK: actions
  1182. Action * Node::runAction(Action* action)
  1183. {
  1184. CCASSERT( action != nullptr, "Argument must be non-nil");
  1185. _actionManager->addAction(action, this, !_running);
  1186. return action;
  1187. }
  1188. void Node::stopAllActions()
  1189. {
  1190. _actionManager->removeAllActionsFromTarget(this);
  1191. }
  1192. void Node::stopAction(Action* action)
  1193. {
  1194. _actionManager->removeAction(action);
  1195. }
  1196. void Node::stopActionByTag(int tag)
  1197. {
  1198. CCASSERT( tag != Action::INVALID_TAG, "Invalid tag");
  1199. _actionManager->removeActionByTag(tag, this);
  1200. }
  1201. void Node::stopAllActionsByTag(int tag)
  1202. {
  1203. CCASSERT( tag != Action::INVALID_TAG, "Invalid tag");
  1204. _actionManager->removeAllActionsByTag(tag, this);
  1205. }
  1206. void Node::stopActionsByFlags(unsigned int flags)
  1207. {
  1208. if (flags > 0)
  1209. {
  1210. _actionManager->removeActionsByFlags(flags, this);
  1211. }
  1212. }
  1213. Action * Node::getActionByTag(int tag)
  1214. {
  1215. CCASSERT( tag != Action::INVALID_TAG, "Invalid tag");
  1216. return _actionManager->getActionByTag(tag, this);
  1217. }
  1218. ssize_t Node::getNumberOfRunningActions() const
  1219. {
  1220. return _actionManager->getNumberOfRunningActionsInTarget(this);
  1221. }
  1222. // MARK: Callbacks
  1223. void Node::setScheduler(Scheduler* scheduler)
  1224. {
  1225. if( scheduler != _scheduler )
  1226. {
  1227. this->unscheduleAllCallbacks();
  1228. CC_SAFE_RETAIN(scheduler);
  1229. CC_SAFE_RELEASE(_scheduler);
  1230. _scheduler = scheduler;
  1231. }
  1232. }
  1233. bool Node::isScheduled(SEL_SCHEDULE selector)
  1234. {
  1235. return _scheduler->isScheduled(selector, this);
  1236. }
  1237. bool Node::isScheduled(const std::string &key)
  1238. {
  1239. return _scheduler->isScheduled(key, this);
  1240. }
  1241. void Node::scheduleUpdate()
  1242. {
  1243. scheduleUpdateWithPriority(0);
  1244. }
  1245. void Node::scheduleUpdateWithPriority(int priority)
  1246. {
  1247. _scheduler->scheduleUpdate(this, priority, !_running);
  1248. }
  1249. void Node::scheduleUpdateWithPriorityLua(int nHandler, int priority)
  1250. {
  1251. unscheduleUpdate();
  1252. #if CC_ENABLE_SCRIPT_BINDING
  1253. _updateScriptHandler = nHandler;
  1254. #endif
  1255. _scheduler->scheduleUpdate(this, priority, !_running);
  1256. }
  1257. void Node::unscheduleUpdate()
  1258. {
  1259. _scheduler->unscheduleUpdate(this);
  1260. #if CC_ENABLE_SCRIPT_BINDING
  1261. if (_updateScriptHandler)
  1262. {
  1263. ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptHandler(_updateScriptHandler);
  1264. _updateScriptHandler = 0;
  1265. }
  1266. #endif
  1267. }
  1268. void Node::schedule(SEL_SCHEDULE selector)
  1269. {
  1270. this->schedule(selector, 0.0f, CC_REPEAT_FOREVER, 0.0f);
  1271. }
  1272. void Node::schedule(SEL_SCHEDULE selector, float interval)
  1273. {
  1274. this->schedule(selector, interval, CC_REPEAT_FOREVER, 0.0f);
  1275. }
  1276. void Node::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay)
  1277. {
  1278. CCASSERT( selector, "Argument must be non-nil");
  1279. CCASSERT( interval >=0, "Argument must be positive");
  1280. _scheduler->schedule(selector, this, interval , repeat, delay, !_running);
  1281. }
  1282. void Node::schedule(const std::function<void(float)> &callback, const std::string &key)
  1283. {
  1284. _scheduler->schedule(callback, this, 0, !_running, key);
  1285. }
  1286. void Node::schedule(const std::function<void(float)> &callback, float interval, const std::string &key)
  1287. {
  1288. _scheduler->schedule(callback, this, interval, !_running, key);
  1289. }
  1290. void Node::schedule(const std::function<void(float)>& callback, float interval, unsigned int repeat, float delay, const std::string &key)
  1291. {
  1292. _scheduler->schedule(callback, this, interval, repeat, delay, !_running, key);
  1293. }
  1294. void Node::scheduleOnce(SEL_SCHEDULE selector, float delay)
  1295. {
  1296. this->schedule(selector, 0.0f, 0, delay);
  1297. }
  1298. void Node::scheduleOnce(const std::function<void(float)> &callback, float delay, const std::string &key)
  1299. {
  1300. _scheduler->schedule(callback, this, 0, 0, delay, !_running, key);
  1301. }
  1302. void Node::unschedule(SEL_SCHEDULE selector)
  1303. {
  1304. // explicit null handling
  1305. if (selector == nullptr)
  1306. return;
  1307. _scheduler->unschedule(selector, this);
  1308. }
  1309. void Node::unschedule(const std::string &key)
  1310. {
  1311. _scheduler->unschedule(key, this);
  1312. }
  1313. void Node::unscheduleAllCallbacks()
  1314. {
  1315. _scheduler->unscheduleAllForTarget(this);
  1316. }
  1317. void Node::resume()
  1318. {
  1319. _scheduler->resumeTarget(this);
  1320. _actionManager->resumeTarget(this);
  1321. _eventDispatcher->resumeEventListenersForTarget(this);
  1322. }
  1323. void Node::pause()
  1324. {
  1325. _scheduler->pauseTarget(this);
  1326. _actionManager->pauseTarget(this);
  1327. _eventDispatcher->pauseEventListenersForTarget(this);
  1328. }
  1329. void Node::resumeSchedulerAndActions()
  1330. {
  1331. resume();
  1332. }
  1333. void Node::pauseSchedulerAndActions()
  1334. {
  1335. pause();
  1336. }
  1337. // override me
  1338. void Node::update(float fDelta)
  1339. {
  1340. #if CC_ENABLE_SCRIPT_BINDING
  1341. if (0 != _updateScriptHandler)
  1342. {
  1343. //only lua use
  1344. SchedulerScriptData data(_updateScriptHandler,fDelta);
  1345. ScriptEvent event(kScheduleEvent,&data);
  1346. ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
  1347. }
  1348. #endif
  1349. if (_componentContainer && !_componentContainer->isEmpty())
  1350. {
  1351. _componentContainer->visit(fDelta);
  1352. }
  1353. }
  1354. // MARK: coordinates
  1355. AffineTransform Node::getNodeToParentAffineTransform() const
  1356. {
  1357. AffineTransform ret;
  1358. GLToCGAffine(getNodeToParentTransform().m, &ret);
  1359. return ret;
  1360. }
  1361. Mat4 Node::getNodeToParentTransform(Node* ancestor) const
  1362. {
  1363. Mat4 t(this->getNodeToParentTransform());
  1364. for (Node *p = _parent; p != nullptr && p != ancestor ; p = p->getParent())
  1365. {
  1366. t = p->getNodeToParentTransform() * t;
  1367. }
  1368. return t;
  1369. }
  1370. AffineTransform Node::getNodeToParentAffineTransform(Node* ancestor) const
  1371. {
  1372. AffineTransform t(this->getNodeToParentAffineTransform());
  1373. for (Node *p = _parent; p != nullptr && p != ancestor; p = p->getParent())
  1374. t = AffineTransformConcat(t, p->getNodeToParentAffineTransform());
  1375. return t;
  1376. }
  1377. const Mat4& Node::getNodeToParentTransform() const
  1378. {
  1379. if (_transformDirty)
  1380. {
  1381. // Translate values
  1382. float x = _position.x;
  1383. float y = _position.y;
  1384. float z = _positionZ;
  1385. if (_ignoreAnchorPointForPosition)
  1386. {
  1387. x += _anchorPointInPoints.x;
  1388. y += _anchorPointInPoints.y;
  1389. }
  1390. bool needsSkewMatrix = ( _skewX || _skewY );
  1391. Vec2 anchorPoint(_anchorPointInPoints.x * _scaleX, _anchorPointInPoints.y * _scaleY);
  1392. // calculate real position
  1393. if (! needsSkewMatrix && !_anchorPointInPoints.isZero())
  1394. {
  1395. x += -anchorPoint.x;
  1396. y += -anchorPoint.y;
  1397. }
  1398. // Build Transform Matrix = translation * rotation * scale
  1399. Mat4 translation;
  1400. //move to anchor point first, then rotate
  1401. Mat4::createTranslation(x + anchorPoint.x, y + anchorPoint.y, z, &translation);
  1402. Mat4::createRotation(_rotationQuat, &_transform);
  1403. if (_rotationZ_X != _rotationZ_Y)
  1404. {
  1405. // Rotation values
  1406. // Change rotation code to handle X and Y
  1407. // If we skew with the exact same value for both x and y then we're simply just rotating
  1408. float radiansX = -CC_DEGREES_TO_RADIANS(_rotationZ_X);
  1409. float radiansY = -CC_DEGREES_TO_RADIANS(_rotationZ_Y);
  1410. float cx = cosf(radiansX);
  1411. float sx = sinf(radiansX);
  1412. float cy = cosf(radiansY);
  1413. float sy = sinf(radiansY);
  1414. float m0 = _transform.m[0], m1 = _transform.m[1], m4 = _transform.m[4], m5 = _transform.m[5], m8 = _transform.m[8], m9 = _transform.m[9];
  1415. _transform.m[0] = cy * m0 - sx * m1, _transform.m[4] = cy * m4 - sx * m5, _transform.m[8] = cy * m8 - sx * m9;
  1416. _transform.m[1] = sy * m0 + cx * m1, _transform.m[5] = sy * m4 + cx * m5, _transform.m[9] = sy * m8 + cx * m9;
  1417. }
  1418. _transform = translation * _transform;
  1419. //move by (-anchorPoint.x, -anchorPoint.y, 0) after rotation
  1420. _transform.translate(-anchorPoint.x, -anchorPoint.y, 0);
  1421. if (_scaleX != 1.f)
  1422. {
  1423. _transform.m[0] *= _scaleX, _transform.m[1] *= _scaleX, _transform.m[2] *= _scaleX;
  1424. }
  1425. if (_scaleY != 1.f)
  1426. {
  1427. _transform.m[4] *= _scaleY, _transform.m[5] *= _scaleY, _transform.m[6] *= _scaleY;
  1428. }
  1429. if (_scaleZ != 1.f)
  1430. {
  1431. _transform.m[8] *= _scaleZ, _transform.m[9] *= _scaleZ, _transform.m[10] *= _scaleZ;
  1432. }
  1433. // FIXME:: Try to inline skew
  1434. // If skew is needed, apply skew and then anchor point
  1435. if (needsSkewMatrix)
  1436. {
  1437. float skewMatArray[16] =
  1438. {
  1439. 1, (float)tanf(CC_DEGREES_TO_RADIANS(_skewY)), 0, 0,
  1440. (float)tanf(CC_DEGREES_TO_RADIANS(_skewX)), 1, 0, 0,
  1441. 0, 0, 1, 0,
  1442. 0, 0, 0, 1
  1443. };
  1444. Mat4 skewMatrix(skewMatArray);
  1445. _transform = _transform * skewMatrix;
  1446. // adjust anchor point
  1447. if (!_anchorPointInPoints.isZero())
  1448. {
  1449. // FIXME:: Argh, Mat4 needs a "translate" method.
  1450. // FIXME:: Although this is faster than multiplying a vec4 * mat4
  1451. _transform.m[12] += _transform.m[0] * -_anchorPointInPoints.x + _transform.m[4] * -_anchorPointInPoints.y;
  1452. _transform.m[13] += _transform.m[1] * -_anchorPointInPoints.x + _transform.m[5] * -_anchorPointInPoints.y;
  1453. }
  1454. }
  1455. if (_useAdditionalTransform)
  1456. {
  1457. _transform = _transform * _additionalTransform;
  1458. }
  1459. _transformDirty = false;
  1460. }
  1461. return _transform;
  1462. }
  1463. void Node::setNodeToParentTransform(const Mat4& transform)
  1464. {
  1465. _transform = transform;
  1466. _transformDirty = false;
  1467. _transformUpdated = true;
  1468. }
  1469. void Node::setAdditionalTransform(const AffineTransform& additionalTransform)
  1470. {
  1471. Mat4 tmp;
  1472. CGAffineToGL(additionalTransform, tmp.m);
  1473. setAdditionalTransform(&tmp);
  1474. }
  1475. void Node::setAdditionalTransform(Mat4* additionalTransform)
  1476. {
  1477. if (additionalTransform == nullptr)
  1478. {
  1479. _useAdditionalTransform = false;
  1480. }
  1481. else
  1482. {
  1483. _additionalTransform = *additionalTransform;
  1484. _useAdditionalTransform = true;
  1485. }
  1486. _transformUpdated = _transformDirty = _inverseDirty = true;
  1487. }
  1488. AffineTransform Node::getParentToNodeAffineTransform() const
  1489. {
  1490. AffineTransform ret;
  1491. GLToCGAffine(getParentToNodeTransform().m,&ret);
  1492. return ret;
  1493. }
  1494. const Mat4& Node::getParentToNodeTransform() const
  1495. {
  1496. if ( _inverseDirty )
  1497. {
  1498. _inverse = getNodeToParentTransform().getInversed();
  1499. _inverseDirty = false;
  1500. }
  1501. return _inverse;
  1502. }
  1503. AffineTransform Node::getNodeToWorldAffineTransform() const
  1504. {
  1505. return this->getNodeToParentAffineTransform(nullptr);
  1506. }
  1507. Mat4 Node::getNodeToWorldTransform() const
  1508. {
  1509. return this->getNodeToParentTransform(nullptr);
  1510. }
  1511. AffineTransform Node::getWorldToNodeAffineTransform() const
  1512. {
  1513. return AffineTransformInvert(this->getNodeToWorldAffineTransform());
  1514. }
  1515. Mat4 Node::getWorldToNodeTransform() const
  1516. {
  1517. return getNodeToWorldTransform().getInversed();
  1518. }
  1519. Vec2 Node::convertToNodeSpace(const Vec2& worldPoint) const
  1520. {
  1521. Mat4 tmp = getWorldToNodeTransform();
  1522. Vec3 vec3(worldPoint.x, worldPoint.y, 0);
  1523. Vec3 ret;
  1524. tmp.transformPoint(vec3,&ret);
  1525. return Vec2(ret.x, ret.y);
  1526. }
  1527. Vec2 Node::convertToWorldSpace(const Vec2& nodePoint) const
  1528. {
  1529. Mat4 tmp = getNodeToWorldTransform();
  1530. Vec3 vec3(nodePoint.x, nodePoint.y, 0);
  1531. Vec3 ret;
  1532. tmp.transformPoint(vec3,&ret);
  1533. return Vec2(ret.x, ret.y);
  1534. }
  1535. Vec2 Node::convertToNodeSpaceAR(const Vec2& worldPoint) const
  1536. {
  1537. Vec2 nodePoint(convertToNodeSpace(worldPoint));
  1538. return nodePoint - _anchorPointInPoints;
  1539. }
  1540. Vec2 Node::convertToWorldSpaceAR(const Vec2& nodePoint) const
  1541. {
  1542. return convertToWorldSpace(nodePoint + _anchorPointInPoints);
  1543. }
  1544. Vec2 Node::convertToWindowSpace(const Vec2& nodePoint) const
  1545. {
  1546. Vec2 worldPoint(this->convertToWorldSpace(nodePoint));
  1547. return _director->convertToUI(worldPoint);
  1548. }
  1549. // convenience methods which take a Touch instead of Vec2
  1550. Vec2 Node::convertTouchToNodeSpace(Touch *touch) const
  1551. {
  1552. return this->convertToNodeSpace(touch->getLocation());
  1553. }
  1554. Vec2 Node::convertTouchToNodeSpaceAR(Touch *touch) const
  1555. {
  1556. Vec2 point = touch->getLocation();
  1557. return this->convertToNodeSpaceAR(point);
  1558. }
  1559. void Node::updateTransform()
  1560. {
  1561. // Recursively iterate over children
  1562. for( const auto &child: _children)
  1563. child->updateTransform();
  1564. }
  1565. // MARK: components
  1566. Component* Node::getComponent(const std::string& name)
  1567. {
  1568. if (_componentContainer)
  1569. return _componentContainer->get(name);
  1570. return nullptr;
  1571. }
  1572. bool Node::addComponent(Component *component)
  1573. {
  1574. // lazy alloc
  1575. if (!_componentContainer)
  1576. _componentContainer = new (std::nothrow) ComponentContainer(this);
  1577. // should enable schedule update, then all components can receive this call back
  1578. scheduleUpdate();
  1579. return _componentContainer->add(component);
  1580. }
  1581. bool Node::removeComponent(const std::string& name)
  1582. {
  1583. if (_componentContainer)
  1584. return _componentContainer->remove(name);
  1585. return false;
  1586. }
  1587. bool Node::removeComponent(Component *component)
  1588. {
  1589. if (_componentContainer)
  1590. {
  1591. return _componentContainer->remove(component);
  1592. }
  1593. return false;
  1594. }
  1595. void Node::removeAllComponents()
  1596. {
  1597. if (_componentContainer)
  1598. _componentContainer->removeAll();
  1599. }
  1600. // MARK: Opacity and Color
  1601. GLubyte Node::getOpacity(void) const
  1602. {
  1603. return _realOpacity;
  1604. }
  1605. GLubyte Node::getDisplayedOpacity() const
  1606. {
  1607. return _displayedOpacity;
  1608. }
  1609. void Node::setOpacity(GLubyte opacity)
  1610. {
  1611. _displayedOpacity = _realOpacity = opacity;
  1612. updateCascadeOpacity();
  1613. }
  1614. void Node::updateDisplayedOpacity(GLubyte parentOpacity)
  1615. {
  1616. _displayedOpacity = _realOpacity * parentOpacity/255.0;
  1617. updateColor();
  1618. if (_cascadeOpacityEnabled)
  1619. {
  1620. for(const auto& child : _children)
  1621. {
  1622. child->updateDisplayedOpacity(_displayedOpacity);
  1623. }
  1624. }
  1625. }
  1626. bool Node::isCascadeOpacityEnabled(void) const
  1627. {
  1628. return _cascadeOpacityEnabled;
  1629. }
  1630. void Node::setCascadeOpacityEnabled(bool cascadeOpacityEnabled)
  1631. {
  1632. if (_cascadeOpacityEnabled == cascadeOpacityEnabled)
  1633. {
  1634. return;
  1635. }
  1636. _cascadeOpacityEnabled = cascadeOpacityEnabled;
  1637. if (cascadeOpacityEnabled)
  1638. {
  1639. updateCascadeOpacity();
  1640. }
  1641. else
  1642. {
  1643. disableCascadeOpacity();
  1644. }
  1645. }
  1646. void Node::updateCascadeOpacity()
  1647. {
  1648. GLubyte parentOpacity = 255;
  1649. if (_parent != nullptr && _parent->isCascadeOpacityEnabled())
  1650. {
  1651. parentOpacity = _parent->getDisplayedOpacity();
  1652. }
  1653. updateDisplayedOpacity(parentOpacity);
  1654. }
  1655. void Node::disableCascadeOpacity()
  1656. {
  1657. _displayedOpacity = _realOpacity;
  1658. for(const auto& child : _children)
  1659. {
  1660. child->updateDisplayedOpacity(255);
  1661. }
  1662. }
  1663. const Color3B& Node::getColor(void) const
  1664. {
  1665. return _realColor;
  1666. }
  1667. const Color3B& Node::getDisplayedColor() const
  1668. {
  1669. return _displayedColor;
  1670. }
  1671. void Node::setColor