CCNode.js 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401
  1. /****************************************************************************
  2. Copyright (c) 2010-2012 cocos2d-x.org
  3. Copyright (c) 2008-2010 Ricardo Quesada
  4. Copyright (c) 2011 Zynga Inc.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. /**
  23. * Default Node tag
  24. * @constant
  25. * @type Number
  26. */
  27. cc.NODE_TAG_INVALID = -1;
  28. /**
  29. * Node on enter
  30. * @constant
  31. */
  32. cc.NODE_ON_ENTER = null;
  33. /**
  34. * Node on exit
  35. * @constant
  36. */
  37. cc.NODE_ON_EXIT = null;
  38. /**
  39. * XXX: Yes, nodes might have a sort problem once every 15 days if the game runs at 60 FPS and each frame sprites are reordered.
  40. * @type Number
  41. */
  42. cc.s_globalOrderOfArrival = 1;
  43. /** <p>cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.<br/>
  44. The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu.<br/></p>
  45. <p>The main features of a cc.Node are: <br/>
  46. - They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc) <br/>
  47. - They can schedule periodic callback (schedule, unschedule, etc) <br/>
  48. - They can execute actions (runAction, stopAction, etc) <br/></p>
  49. <p>Some cc.Node nodes provide extra functionality for them or their children.</p>
  50. <p>Subclassing a cc.Node usually means (one/all) of: <br/>
  51. - overriding init to initialize resources and schedule callbacks <br/>
  52. - create callbacks to handle the advancement of time <br/>
  53. - overriding draw to render the node <br/></p>
  54. <p>Features of cc.Node: <br/>
  55. - position <br/>
  56. - scale (x, y) <br/>
  57. - rotation (in degrees, clockwise) <br/>
  58. - anchor point<br/>
  59. - size <br/>
  60. - visible<br/>
  61. - z-order <br/>
  62. - openGL z position <br/></P>
  63. <p> Default values: <br/>
  64. - rotation: 0 <br/>
  65. - position: (x=0,y=0) <br/>
  66. - scale: (x=1,y=1) <br/>
  67. - contentSize: (x=0,y=0)<br/>
  68. - anchorPoint: (x=0,y=0)<br/></p>
  69. <p> Limitations:<br/>
  70. - A cc.Node is a "void" object. It doesn't have a texture <br/></P>
  71. <p>Order in transformations with grid disabled <br/>
  72. -# The node will be translated (position) <br/>
  73. -# The node will be rotated (rotation)<br/>
  74. -# The node will be scaled (scale) <br/>
  75. <p>Order in transformations with grid enabled<br/>
  76. -# The node will be translated (position)<br/>
  77. -# The node will be rotated (rotation) <br/>
  78. -# The node will be scaled (scale) <br/>
  79. -# The grid will capture the screen <br/>
  80. -# The node will be moved according to the camera values (camera) <br/>
  81. -# The grid will render the captured screen <br/></P>
  82. * @class
  83. * @extends cc.Class
  84. * @example
  85. * // example
  86. * cc.Sprite = cc.Node.extend({});
  87. * cc.Sprite.initWithImage = function(){
  88. * };
  89. */
  90. cc.Node = cc.Class.extend(/** @lends cc.Node# */{
  91. _zOrder:0,
  92. _vertexZ:0.0,
  93. _rotationX:0,
  94. _rotationY:0.0,
  95. _scaleX:1.0,
  96. _scaleY:1.0,
  97. _position:null,
  98. _skewX:0.0,
  99. _skewY:0.0,
  100. // children (lazy allocs),
  101. _children:null,
  102. // lazy alloc,
  103. _visible:true,
  104. _anchorPoint:null,
  105. _anchorPointInPoints:null,
  106. _contentSize:null,
  107. _running:false,
  108. _parent:null,
  109. // "whole screen" objects. like Scenes and Layers, should set _ignoreAnchorPointForPosition to true
  110. _ignoreAnchorPointForPosition:false,
  111. _tag:cc.NODE_TAG_INVALID,
  112. // userData is always inited as nil
  113. _userData:null,
  114. _userObject:null,
  115. _transformDirty:true,
  116. _inverseDirty:true,
  117. _cacheDirty:true,
  118. _transformGLDirty:null,
  119. _transform:null,
  120. _inverse:null,
  121. //since 2.0 api
  122. _reorderChildDirty:false,
  123. _shaderProgram:null,
  124. _orderOfArrival:0,
  125. _actionManager:null,
  126. _scheduler:null,
  127. _initializedNode:false,
  128. _additionalTransformDirty:false,
  129. _additionalTransform:null,
  130. _componentContainer:null,
  131. _isTransitionFinished:false,
  132. _rotationRadiansX:0,
  133. _rotationRadiansY:0,
  134. _initNode:function () {
  135. this._anchorPoint = cc.p(0, 0);
  136. this._anchorPointInPoints = cc.p(0, 0);
  137. this._contentSize = cc.size(0, 0);
  138. this._position = cc.p(0, 0);
  139. this._children = [];
  140. this._transform = {a:1, b:0, c:0, d:1, tx:0, ty:0};
  141. var director = cc.Director.getInstance();
  142. this._actionManager = director.getActionManager();
  143. this._scheduler = director.getScheduler();
  144. this._initializedNode = true;
  145. this._additionalTransform = cc.AffineTransformMakeIdentity();
  146. if(cc.ComponentContainer){
  147. this._componentContainer = new cc.ComponentContainer(this);
  148. }
  149. },
  150. /**
  151. * Initializes the instance of cc.Node
  152. * @returns {boolean} Whether the initialization was successful.
  153. */
  154. init:function () {
  155. if (this._initializedNode === false)
  156. this._initNode();
  157. return true;
  158. },
  159. /**
  160. * @param {Array} array
  161. * @param {cc.Node.StateCallbackType} callbackType
  162. * @private
  163. */
  164. _arrayMakeObjectsPerformSelector:function (array, callbackType) {
  165. if (!array || array.length === 0)
  166. return;
  167. var i, len = array.length,node;
  168. var nodeCallbackType = cc.Node.StateCallbackType;
  169. switch (callbackType) {
  170. case nodeCallbackType.onEnter:
  171. for (i = 0; i < len; i++) {
  172. node = array[i];
  173. if (node)
  174. node.onEnter();
  175. }
  176. break;
  177. case nodeCallbackType.onExit:
  178. for (i = 0; i < len; i++) {
  179. node = array[i];
  180. if (node)
  181. node.onExit();
  182. }
  183. break;
  184. case nodeCallbackType.onEnterTransitionDidFinish:
  185. for (i = 0; i < len; i++) {
  186. node = array[i];
  187. if (node)
  188. node.onEnterTransitionDidFinish();
  189. }
  190. break;
  191. case nodeCallbackType.cleanup:
  192. for (i = 0; i < len; i++) {
  193. node = array[i];
  194. if (node)
  195. node.cleanup();
  196. }
  197. break;
  198. case nodeCallbackType.updateTransform:
  199. for (i = 0; i < len; i++) {
  200. node = array[i];
  201. if (node)
  202. node.updateTransform();
  203. }
  204. break;
  205. case nodeCallbackType.onExitTransitionDidStart:
  206. for (i = 0; i < len; i++) {
  207. node = array[i];
  208. if (node)
  209. node.onExitTransitionDidStart();
  210. }
  211. break;
  212. case nodeCallbackType.sortAllChildren:
  213. for (i = 0; i < len; i++) {
  214. node = array[i];
  215. if (node)
  216. node.sortAllChildren();
  217. }
  218. break;
  219. default :
  220. throw "Unknown callback function";
  221. break;
  222. }
  223. },
  224. /**
  225. * set the dirty node
  226. */
  227. setNodeDirty:null,
  228. _setNodeDirtyForCanvas:function () {
  229. this._setNodeDirtyForCache();
  230. if(this._transformDirty === false)
  231. this._transformDirty = this._inverseDirty = true;
  232. },
  233. _setNodeDirtyForWebGL:function () {
  234. if(this._transformDirty === false)
  235. this._transformDirty = this._inverseDirty = true;
  236. },
  237. /**
  238. * <p>get the skew degrees in X </br>
  239. * The X skew angle of the node in degrees. <br/>
  240. * This angle describes the shear distortion in the X direction.<br/>
  241. * Thus, it is the angle between the Y axis and the left edge of the shape </br>
  242. * The default skewX angle is 0. Positive values distort the node in a CW direction.</br>
  243. * </p>
  244. * @return {Number} The X skew angle of the node in degrees.
  245. */
  246. getSkewX:function () {
  247. return this._skewX;
  248. },
  249. /**
  250. * <p>
  251. * Changes the X skew angle of the node in degrees. <br/>
  252. * <br/>
  253. * This angle describes the shear distortion in the X direction. <br/>
  254. * Thus, it is the angle between the Y axis and the left edge of the shape <br/>
  255. * The default skewX angle is 0. Positive values distort the node in a CW direction.
  256. * </p>
  257. * @param {Number} newSkewX The X skew angle of the node in degrees.
  258. */
  259. setSkewX:function (newSkewX) {
  260. this._skewX = newSkewX;
  261. this.setNodeDirty();
  262. },
  263. /**
  264. * <p>get the skew degrees in Y <br/>
  265. * The Y skew angle of the node in degrees. <br/>
  266. * This angle describes the shear distortion in the Y direction. <br/>
  267. * Thus, it is the angle between the X axis and the bottom edge of the shape <br/>
  268. * The default skewY angle is 0. Positive values distort the node in a CCW direction. <br/>
  269. * </p>
  270. * @return {Number} The Y skew angle of the node in degrees.
  271. */
  272. getSkewY:function () {
  273. return this._skewY;
  274. },
  275. /**
  276. * <p>
  277. * Changes the Y skew angle of the node in degrees.
  278. *
  279. * This angle describes the shear distortion in the Y direction.
  280. * Thus, it is the angle between the X axis and the bottom edge of the shape
  281. * The default skewY angle is 0. Positive values distort the node in a CCW direction.
  282. * </p>
  283. * @param {Number} newSkewY The Y skew angle of the node in degrees.
  284. */
  285. setSkewY:function (newSkewY) {
  286. this._skewY = newSkewY;
  287. this.setNodeDirty();
  288. },
  289. /**
  290. * zOrder getter
  291. * @return {Number}
  292. */
  293. getZOrder:function () {
  294. return this._zOrder;
  295. },
  296. /**
  297. * <p>
  298. * Sets the z order which stands for the drawing order <br/>
  299. * <br/>
  300. * This is an internal method. Don't call it outside the framework. <br/>
  301. * The difference between setZOrder(int) and _setOrder(int) is: <br/>
  302. * - _setZOrder(int) is a pure setter for m_nZOrder member variable <br/>
  303. * - setZOrder(int) firstly changes m_nZOrder, then recorder this node in its parent's children array.
  304. * </p>
  305. * @param {Number} z
  306. * @private
  307. */
  308. _setZOrder:function (z) {
  309. this._zOrder = z;
  310. },
  311. /**
  312. * <p>
  313. * Sets the Z order which stands for the drawing order, and reorder this node in its parent's children array. <br/>
  314. * <br/>
  315. * The Z order of node is relative to its "brothers": children of the same parent. <br/>
  316. * It's nothing to do with OpenGL's z vertex. This one only affects the draw order of nodes in cocos2d. <br/>
  317. * The larger number it is, the later this node will be drawn in each message loop. <br/>
  318. * Please refer to setVertexZ(float) for the difference.
  319. * </p>
  320. * @param {Number} z Z order of this node.
  321. */
  322. setZOrder:function (z) {
  323. // ZOrder is set on parent's reorderChild.
  324. if (this._parent)
  325. this._parent.reorderChild(this, z);
  326. else
  327. this._setZOrder(z);
  328. },
  329. /**
  330. * Gets WebGL Z vertex of this node.
  331. * @return {Number} WebGL Z vertex of this node
  332. */
  333. getVertexZ:function () {
  334. return this._vertexZ;
  335. },
  336. /**
  337. * <p>
  338. * Sets the real WebGL Z vertex. <br/>
  339. * <br/>
  340. * Differences between openGL Z vertex and cocos2d Z order: <br/>
  341. * - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children <br/>
  342. * - OpenGL Z might require to set 2D projection <br/>
  343. * - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0 <br/>
  344. * <br/>
  345. * @warning Use it at your own risk since it might break the cocos2d parent-children z order
  346. * </p>
  347. * @param {Number} Var
  348. */
  349. setVertexZ:function (Var) {
  350. this._vertexZ = Var;
  351. },
  352. /**
  353. * The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW.
  354. * @return {Number} The rotation of the node in degrees.
  355. */
  356. getRotation:function () {
  357. if(this._rotationX !== this._rotationY)
  358. cc.log("cc.Node.rotation(): RotationX != RotationY. Don't know which one to return");
  359. return this._rotationX;
  360. },
  361. /**
  362. * <p>
  363. * Sets the rotation (angle) of the node in degrees. <br/>
  364. * <br/>
  365. * 0 is the default rotation angle. <br/>
  366. * Positive values rotate node clockwise, and negative values for anti-clockwise.
  367. * </p>
  368. * @param {Number} newRotation The rotation of the node in degrees.
  369. */
  370. setRotation:function (newRotation) {
  371. this._rotationX = this._rotationY = newRotation;
  372. this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180);
  373. this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180);
  374. this.setNodeDirty();
  375. },
  376. /**
  377. * The rotation (angle) of the node in degrees. 0 is the default rotation angle. <br/>
  378. * Positive values rotate node CW. It only modifies the X rotation performing a horizontal rotational skew .
  379. * (support only in WebGl rendering mode)
  380. * @return {Number} The X rotation in degrees.
  381. */
  382. getRotationX:function () {
  383. return this._rotationX;
  384. },
  385. /**
  386. * <p>
  387. * Sets the X rotation (angle) of the node in degrees which performs a horizontal rotational skew. <br/>
  388. * <br/>
  389. * 0 is the default rotation angle. <br/>
  390. * Positive values rotate node clockwise, and negative values for anti-clockwise.
  391. * </p>
  392. * @param {Number} rotationX The X rotation in degrees which performs a horizontal rotational skew.
  393. */
  394. setRotationX:function (rotationX) {
  395. this._rotationX = rotationX;
  396. this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180);
  397. this.setNodeDirty();
  398. },
  399. /**
  400. * The rotation (angle) of the node in degrees. 0 is the default rotation angle. <br/>
  401. * Positive values rotate node CW. It only modifies the Y rotation performing a vertical rotational skew .
  402. * @return {Number} The Y rotation in degrees.
  403. */
  404. getRotationY:function () {
  405. return this._rotationY;
  406. },
  407. /**
  408. * <p>
  409. * Sets the Y rotation (angle) of the node in degrees which performs a vertical rotational skew. <br/>
  410. * <br/>
  411. * 0 is the default rotation angle. <br/>
  412. * Positive values rotate node clockwise, and negative values for anti-clockwise.
  413. * </p>
  414. * @param rotationY The Y rotation in degrees.
  415. */
  416. setRotationY:function (rotationY) {
  417. this._rotationY = rotationY;
  418. this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180);
  419. this.setNodeDirty();
  420. },
  421. /** Get the scale factor of the node.
  422. * @warning: Assert when _scaleX != _scaleY.
  423. * @return {Number}
  424. */
  425. getScale:function () {
  426. if(this._scaleX !== this._scaleY)
  427. cc.log("cc.Node.getScale(): ScaleX != ScaleY. Don't know which one to return");
  428. return this._scaleX;
  429. },
  430. /**
  431. * The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time.
  432. * @param {Number} scale or scaleX value
  433. * @param {Number} [scaleY=]
  434. */
  435. setScale:function (scale, scaleY) {
  436. this._scaleX = scale;
  437. this._scaleY = (scaleY || scaleY === 0) ? scaleY : scale;
  438. this.setNodeDirty();
  439. },
  440. /**
  441. * Returns the scale factor on X axis of this node
  442. * @return {Number} The scale factor on X axis.
  443. */
  444. getScaleX:function () {
  445. return this._scaleX;
  446. },
  447. /**
  448. * <p>
  449. * Changes the scale factor on X axis of this node <br/>
  450. * The deafult value is 1.0 if you haven't changed it before
  451. * </p>
  452. * @param {Number} newScaleX The scale factor on X axis.
  453. */
  454. setScaleX:function (newScaleX) {
  455. this._scaleX = newScaleX;
  456. this.setNodeDirty();
  457. },
  458. /**
  459. * Returns the scale factor on Y axis of this node
  460. * @return {Number} The scale factor on Y axis.
  461. */
  462. getScaleY:function () {
  463. return this._scaleY;
  464. },
  465. /**
  466. * <p>
  467. * Changes the scale factor on Y axis of this node <br/>
  468. * The Default value is 1.0 if you haven't changed it before.
  469. * </p>
  470. * @param {Number} newScaleY The scale factor on Y axis.
  471. */
  472. setScaleY:function (newScaleY) {
  473. this._scaleY = newScaleY;
  474. this.setNodeDirty();
  475. },
  476. /**
  477. * <p>
  478. * Changes the position (x,y) of the node in OpenGL coordinates
  479. * Usually we use ccp(x,y) to compose CCPoint object.
  480. * The original point (0,0) is at the left-bottom corner of screen.
  481. * and Passing two numbers (x,y) is much efficient than passing CCPoint object.
  482. * </p>
  483. * @param {cc.Point|Number} newPosOrxValue The position (x,y) of the node in coordinates or X coordinate for position
  484. * @param {Number} [yValue] Y coordinate for position
  485. * @example
  486. * var size = cc.Director.getInstance().getWinSize();
  487. * node.setPosition(size.width/2, size.height/2);
  488. */
  489. setPosition:function (newPosOrxValue, yValue) {
  490. var locPosition = this._position;
  491. if (yValue === undefined) {
  492. locPosition.x = newPosOrxValue.x;
  493. locPosition.y = newPosOrxValue.y;
  494. } else {
  495. locPosition.x = newPosOrxValue;
  496. locPosition.y = yValue;
  497. }
  498. this.setNodeDirty();
  499. },
  500. /**
  501. * <p>Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner. </p>
  502. * @const
  503. * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates
  504. */
  505. getPosition:function () {
  506. return cc.p(this._position);
  507. },
  508. /**
  509. * @return {Number}
  510. */
  511. getPositionX:function () {
  512. return this._position.x;
  513. },
  514. /**
  515. * @param {Number} x
  516. */
  517. setPositionX:function (x) {
  518. this._position.x = x;
  519. this.setNodeDirty();
  520. },
  521. /**
  522. * @return {Number}
  523. */
  524. getPositionY:function () {
  525. return this._position.y;
  526. },
  527. /**
  528. * @param {Number} y
  529. */
  530. setPositionY:function (y) {
  531. this._position.y = y;
  532. this.setNodeDirty();
  533. },
  534. /**
  535. * Get the amount of children.
  536. * @return {Number} The amount of children.
  537. */
  538. getChildrenCount:function () {
  539. return this._children.length;
  540. },
  541. /**
  542. * Return an array of children <br/>
  543. * Composing a "tree" structure is a very important feature of CCNode
  544. * @return {Array} An array of children
  545. * @example
  546. * //This sample code traverses all children nodes, and set their position to (0,0)
  547. * var allChildren = parent.getChildren();
  548. * for(var i = 0; i< allChildren.length; i++) {
  549. * allChildren[i].setPosition(0,0);
  550. * }
  551. */
  552. getChildren:function () {
  553. return this._children;
  554. },
  555. /**
  556. * Determines if the node is visible
  557. * @see setVisible(bool)
  558. * @return {Boolean} true if the node is visible, false if the node is hidden.
  559. */
  560. isVisible:function () {
  561. return this._visible;
  562. },
  563. /**
  564. * Sets whether the node is visible <br/>
  565. * The default value is true, a node is default to visible
  566. * @param {Boolean} Var true if the node is visible, false if the node is hidden.
  567. */
  568. setVisible:function (Var) {
  569. this._visible = Var;
  570. this.setNodeDirty();
  571. },
  572. /**
  573. * <p>anchorPoint is the point around which all transformations and positioning manipulations take place.<br/>
  574. * It's like a pin in the node where it is "attached" to its parent. <br/>
  575. * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. <br/>
  576. * But you can use values higher than (1,1) and lower than (0,0) too. <br/>
  577. * The default anchorPoint is (0.5,0.5), so it starts in the center of the node. <br/></p>
  578. * @const
  579. * @return {cc.Point} The anchor point of node.
  580. */
  581. getAnchorPoint:function () {
  582. return cc.p(this._anchorPoint);
  583. },
  584. /**
  585. * <p>
  586. * Sets the anchor point in percent. <br/>
  587. * <br/>
  588. * anchorPoint is the point around which all transformations and positioning manipulations take place. <br/>
  589. * It's like a pin in the node where it is "attached" to its parent. <br/>
  590. * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. <br/>
  591. * But you can use values higher than (1,1) and lower than (0,0) too. <br/>
  592. * The default anchorPoint is (0.5,0.5), so it starts in the center of the node.
  593. * </p>
  594. * @param {cc.Point|Number} point The anchor point of node or The anchor point.x of node.
  595. * @param {Number} [y] The anchor point.y of node.
  596. */
  597. setAnchorPoint:function (point, y) {
  598. var locAnchorPoint = this._anchorPoint;
  599. if (y === undefined) {
  600. if ((point.x === locAnchorPoint.x) && (point.y === locAnchorPoint.y))
  601. return;
  602. locAnchorPoint.x = point.x;
  603. locAnchorPoint.y = point.y;
  604. } else {
  605. if ((point === locAnchorPoint.x) && (y === locAnchorPoint.y))
  606. return;
  607. locAnchorPoint.x = point;
  608. locAnchorPoint.y = y;
  609. }
  610. var locAPP = this._anchorPointInPoints, locSize = this._contentSize;
  611. locAPP.x = locSize.width * locAnchorPoint.x;
  612. locAPP.y = locSize.height * locAnchorPoint.y;
  613. this.setNodeDirty();
  614. },
  615. /**
  616. * The anchorPoint in absolute pixels. <br/>
  617. * you can only read it. If you wish to modify it, use anchorPoint instead
  618. * @see getAnchorPoint()
  619. * @const
  620. * @return {cc.Point} The anchor point in absolute pixels.
  621. */
  622. getAnchorPointInPoints:function () {
  623. return cc.p(this._anchorPointInPoints);
  624. },
  625. /**
  626. * <p>The untransformed size of the node. <br/>
  627. * The contentSize remains the same no matter the node is scaled or rotated.<br/>
  628. * All nodes has a size. Layer and Scene has the same size of the screen. <br/></p>
  629. * @const
  630. * @return {cc.Size} The untransformed size of the node.
  631. */
  632. getContentSize:function () {
  633. return cc.size(this._contentSize);
  634. },
  635. /**
  636. * <p>
  637. * Sets the untransformed size of the node. <br/>
  638. * <br/>
  639. * The contentSize remains the same no matter the node is scaled or rotated. <br/>
  640. * All nodes has a size. Layer and Scene has the same size of the screen.
  641. * </p>
  642. * @param {cc.Size|Number} size The untransformed size of the node or The untransformed size's width of the node.
  643. * @param {Number} [height] The untransformed size's height of the node.
  644. */
  645. setContentSize:function (size, height) {
  646. var locContentSize = this._contentSize;
  647. if (height === undefined) {
  648. if ((size.width === locContentSize.width) && (size.height === locContentSize.height))
  649. return;
  650. locContentSize.width = size.width;
  651. locContentSize.height = size.height;
  652. } else {
  653. if ((size === locContentSize.width) && (height === locContentSize.height))
  654. return;
  655. locContentSize.width = size;
  656. locContentSize.height = height;
  657. }
  658. var locAPP = this._anchorPointInPoints, locAnchorPoint = this._anchorPoint;
  659. locAPP.x = locContentSize.width * locAnchorPoint.x;
  660. locAPP.y = locContentSize.height * locAnchorPoint.y;
  661. this.setNodeDirty();
  662. },
  663. /**
  664. * <p>
  665. * Returns whether or not the node accepts event callbacks. <br/>
  666. * Running means the node accept event callbacks like onEnter(), onExit(), update()
  667. * </p>
  668. * @return {Boolean} Whether or not the node is running.
  669. */
  670. isRunning:function () {
  671. return this._running;
  672. },
  673. /**
  674. * Returns a pointer to the parent node
  675. * @return {cc.Node} A pointer to the parent node
  676. */
  677. getParent:function () {
  678. return this._parent;
  679. },
  680. /**
  681. * Sets the parent node
  682. * @param {cc.Node} Var A pointer to the parent node
  683. */
  684. setParent:function (Var) {
  685. this._parent = Var;
  686. },
  687. /**
  688. * Gets whether the anchor point will be (0,0) when you position this node.
  689. * @see ignoreAnchorPointForPosition(bool)
  690. * @return {Boolean} true if the anchor point will be (0,0) when you position this node.
  691. */
  692. isIgnoreAnchorPointForPosition:function () {
  693. return this._ignoreAnchorPointForPosition;
  694. },
  695. /**
  696. * <p>
  697. * Sets whether the anchor point will be (0,0) when you position this node. <br/>
  698. * <br/>
  699. * This is an internal method, only used by CCLayer and CCScene. Don't call it outside framework. <br/>
  700. * The default value is false, while in CCLayer and CCScene are true
  701. * </p>
  702. * @param {Boolean} newValue true if anchor point will be (0,0) when you position this node
  703. */
  704. ignoreAnchorPointForPosition:function (newValue) {
  705. if (newValue != this._ignoreAnchorPointForPosition) {
  706. this._ignoreAnchorPointForPosition = newValue;
  707. this.setNodeDirty();
  708. }
  709. },
  710. /**
  711. * Returns a tag that is used to identify the node easily.
  712. *
  713. * @return {Number} An integer that identifies the node.
  714. * @example
  715. * //You can set tags to node then identify them easily.
  716. * // set tags
  717. * node1.setTag(TAG_PLAYER);
  718. * node2.setTag(TAG_MONSTER);
  719. * node3.setTag(TAG_BOSS);
  720. * parent.addChild(node1);
  721. * parent.addChild(node2);
  722. * parent.addChild(node3);
  723. * // identify by tags
  724. * var allChildren = parent.getChildren();
  725. * for(var i = 0; i < allChildren.length; i++){
  726. * switch(node.getTag()) {
  727. * case TAG_PLAYER:
  728. * break;
  729. * case TAG_MONSTER:
  730. * break;
  731. * case TAG_BOSS:
  732. * break;
  733. * }
  734. * }
  735. */
  736. getTag:function () {
  737. return this._tag;
  738. },
  739. /**
  740. * Changes the tag that is used to identify the node easily. <br/>
  741. * Please refer to getTag for the sample code.
  742. * @param {Number} Var A integer that identifies the node.
  743. */
  744. setTag:function (Var) {
  745. this._tag = Var;
  746. },
  747. /**
  748. * <p>
  749. * Returns a custom user data pointer <br/>
  750. * You can set everything in UserData pointer, a data block, a structure or an object.
  751. * </p>
  752. * @return {object} A custom user data pointer
  753. */
  754. getUserData:function () {
  755. return this._userData;
  756. },
  757. /**
  758. * <p>
  759. * Sets a custom user data pointer <br/>
  760. * You can set everything in UserData pointer, a data block, a structure or an object, etc.
  761. * </p>
  762. * @warning Don't forget to release the memory manually,especially before you change this data pointer, and before this node is autoreleased.
  763. * @param {object} Var A custom user data
  764. */
  765. setUserData:function (Var) {
  766. this._userData = Var;
  767. },
  768. /**
  769. * Returns a user assigned CCObject. <br/>
  770. * Similar to userData, but instead of holding a void* it holds an id
  771. * @return {object} A user assigned CCObject
  772. */
  773. getUserObject:function () {
  774. return this._userObject;
  775. },
  776. /**
  777. * <p>
  778. * Returns a user assigned CCObject <br/>
  779. * Similar to UserData, but instead of holding a void* it holds an object. <br/>
  780. * The UserObject will be retained once in this method, and the previous UserObject (if existed) will be release. <br/>
  781. * The UserObject will be released in CCNode's destruction.
  782. * </p>
  783. * @param {object} newValue A user assigned CCObject
  784. */
  785. setUserObject:function (newValue) {
  786. if (this._userObject != newValue) {
  787. this._userObject = newValue;
  788. }
  789. },
  790. /**
  791. * Returns the arrival order, indicates which children is added previously.
  792. * @return {Number} The arrival order.
  793. */
  794. getOrderOfArrival:function () {
  795. return this._orderOfArrival;
  796. },
  797. /**
  798. * <p>
  799. * Sets the arrival order when this node has a same ZOrder with other children. <br/>
  800. * <br/>
  801. * A node which called addChild subsequently will take a larger arrival order, <br/>
  802. * If two children have the same Z order, the child with larger arrival order will be drawn later.
  803. * </p>
  804. * @warning This method is used internally for zOrder sorting, don't change this manually
  805. * @param {Number} Var The arrival order.
  806. */
  807. setOrderOfArrival:function (Var) {
  808. this._orderOfArrival = Var;
  809. },
  810. /**
  811. * <p>Gets the CCActionManager object that is used by all actions.<br/>
  812. * (IMPORTANT: If you set a new cc.ActionManager, then previously created actions are going to be removed.)</p>
  813. * @see setActionManager()
  814. * @return {cc.ActionManager} A CCActionManager object.
  815. */
  816. getActionManager:function () {
  817. if (!this._actionManager) {
  818. this._actionManager = cc.Director.getInstance().getActionManager();
  819. }
  820. return this._actionManager;
  821. },
  822. /**
  823. * <p>Sets the cc.ActionManager object that is used by all actions. </p>
  824. * @warning If you set a new CCActionManager, then previously created actions will be removed.
  825. * @param {cc.ActionManager} actionManager A CCActionManager object that is used by all actions.
  826. */
  827. setActionManager:function (actionManager) {
  828. if (this._actionManager != actionManager) {
  829. this.stopAllActions();
  830. this._actionManager = actionManager;
  831. }
  832. },
  833. /**
  834. * <p>
  835. * cc.Scheduler used to schedule all "updates" and timers.<br/>
  836. * IMPORTANT: If you set a new cc.Scheduler, then previously created timers/update are going to be removed.
  837. * </p>
  838. * @return {cc.Scheduler} A CCScheduler object.
  839. */
  840. getScheduler:function () {
  841. if (!this._scheduler) {
  842. this._scheduler = cc.Director.getInstance().getScheduler();
  843. }
  844. return this._scheduler;
  845. },
  846. /**
  847. * <p>
  848. * Sets a CCScheduler object that is used to schedule all "updates" and timers. <br/>
  849. * </p>
  850. * @warning If you set a new CCScheduler, then previously created timers/update are going to be removed.
  851. * @param scheduler A cc.Scheduler object that is used to schedule all "update" and timers.
  852. */
  853. setScheduler:function (scheduler) {
  854. if (this._scheduler != scheduler) {
  855. this.unscheduleAllCallbacks();
  856. this._scheduler = scheduler;
  857. }
  858. },
  859. /**
  860. * Returns a "local" axis aligned bounding box of the node. <br/>
  861. * The returned box is relative only to its parent.
  862. * @note This method returns a temporary variable, so it can't returns const CCRect&
  863. * @const
  864. * @return {cc.Rect}
  865. */
  866. getBoundingBox:function () {
  867. var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
  868. return cc._RectApplyAffineTransformIn(rect, this.nodeToParentTransform());
  869. },
  870. /**
  871. * Stops all running actions and schedulers
  872. */
  873. cleanup:function () {
  874. // actions
  875. this.stopAllActions();
  876. this.unscheduleAllCallbacks();
  877. // timers
  878. this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.cleanup);
  879. },
  880. /**
  881. * Gets the description string. It makes debugging easier.
  882. * @return {String}
  883. */
  884. description:function () {
  885. return "<cc.Node | Tag =" + this._tag + ">";
  886. },
  887. // composition: GET
  888. /**
  889. * Gets a child from the container given its tag
  890. * @param {Number} aTag An identifier to find the child node.
  891. * @return {cc.Node} a CCNode object whose tag equals to the input parameter
  892. */
  893. getChildByTag:function (aTag) {
  894. var __children = this._children;
  895. if (__children != null) {
  896. for (var i = 0; i < __children.length; i++) {
  897. var node = __children[i];
  898. if (node && node._tag == aTag)
  899. return node;
  900. }
  901. }
  902. //throw "not found";
  903. return null;
  904. },
  905. // composition: ADD
  906. /** <p>"add" logic MUST only be on this method <br/> </p>
  907. *
  908. * <p>If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.</p>
  909. *
  910. * @param {cc.Node} child A child node
  911. * @param {Number} [zOrder=] Z order for drawing priority. Please refer to setZOrder(int)
  912. * @param {Number} [tag=] A integer to identify the node easily. Please refer to setTag(int)
  913. */
  914. addChild:function (child, zOrder, tag) {
  915. if(!child)
  916. throw "cc.Node.addChild(): child must be non-null";
  917. if (child === this) {
  918. cc.log('cc.Node.addChild(): An Node can\'t be added as a child of itself.');
  919. return;
  920. }
  921. if (child._parent !== null) {
  922. cc.log("cc.Node.addChild(): child already added. It can't be added again");
  923. return;
  924. }
  925. var tmpzOrder = (zOrder != null) ? zOrder : child._zOrder;
  926. child._tag = (tag != null) ? tag : child._tag;
  927. this._insertChild(child, tmpzOrder);
  928. child._parent = this;
  929. if (this._running) {
  930. child.onEnter();
  931. // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter
  932. if(this._isTransitionFinished)
  933. child.onEnterTransitionDidFinish();
  934. }
  935. },
  936. // composition: REMOVE
  937. /**
  938. * Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks. <br/>
  939. * If the cleanup parameter is not passed, it will force a cleanup. <br/>
  940. * If the node orphan, then nothing happens.
  941. * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise.
  942. * @see removeFromParentAndCleanup(bool)
  943. */
  944. removeFromParent:function (cleanup) {
  945. if (this._parent) {
  946. if (cleanup == null)
  947. cleanup = true;
  948. this._parent.removeChild(this, cleanup);
  949. }
  950. },
  951. /**
  952. * Removes this node itself from its parent node. <br/>
  953. * If the node orphan, then nothing happens.
  954. * @deprecated
  955. * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise.
  956. */
  957. removeFromParentAndCleanup:function (cleanup) {
  958. cc.log("removeFromParentAndCleanup is deprecated. Use removeFromParent instead");
  959. this.removeFromParent(cleanup);
  960. },
  961. /** <p>Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. </p>
  962. * If the cleanup parameter is not passed, it will force a cleanup. <br/>
  963. *<p> "remove" logic MUST only be on this method <br/>
  964. * If a class wants to extend the 'removeChild' behavior it only needs <br/>
  965. * to override this method </p>
  966. *
  967. * @param {cc.Node} child The child node which will be removed.
  968. * @param {Boolean|null} [cleanup=null] true if all running actions and callbacks on the child node will be cleanup, false otherwise.
  969. */
  970. removeChild:function (child, cleanup) {
  971. // explicit nil handling
  972. if (this._children.length === 0)
  973. return;
  974. if (cleanup == null)
  975. cleanup = true;
  976. if (this._children.indexOf(child) > -1)
  977. this._detachChild(child, cleanup);
  978. this.setNodeDirty();
  979. },
  980. /**
  981. * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter.
  982. * If the cleanup parameter is not passed, it will force a cleanup. <br/>
  983. * @param {Number} tag An integer number that identifies a child node
  984. * @param {Boolean} cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise.
  985. * @see removeChildByTag(int, bool)
  986. */
  987. removeChildByTag:function (tag, cleanup) {
  988. if(tag === cc.NODE_TAG_INVALID)
  989. cc.log("cc.Node.removeChildByTag(): argument tag is an invalid tag");
  990. var child = this.getChildByTag(tag);
  991. if (child == null)
  992. cc.log("cocos2d: removeChildByTag(tag = " + tag + "): child not found!");
  993. else
  994. this.removeChild(child, cleanup);
  995. },
  996. /**
  997. * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
  998. * @deprecated
  999. * @param {Boolean | null } cleanup
  1000. */
  1001. removeAllChildrenWithCleanup:function (cleanup) {
  1002. cc.log("removeAllChildrenWithCleanup is deprecated. Use removeAllChildren instead");
  1003. this.removeAllChildren(cleanup);
  1004. },
  1005. /**
  1006. * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. <br/>
  1007. * If the cleanup parameter is not passed, it will force a cleanup. <br/>
  1008. * @param {Boolean | null } cleanup true if all running actions on all children nodes should be cleanup, false otherwise.
  1009. */
  1010. removeAllChildren:function (cleanup) {
  1011. // not using detachChild improves speed here
  1012. var __children = this._children;
  1013. if (__children != null) {
  1014. if (cleanup == null)
  1015. cleanup = true;
  1016. for (var i = 0; i < __children.length; i++) {
  1017. var node = __children[i];
  1018. if (node) {
  1019. // IMPORTANT:
  1020. // -1st do onExit
  1021. // -2nd cleanup
  1022. if (this._running) {
  1023. node.onExitTransitionDidStart();
  1024. node.onExit();
  1025. }
  1026. if (cleanup)
  1027. node.cleanup();
  1028. // set parent nil at the end
  1029. node.setParent(null);
  1030. }
  1031. }
  1032. this._children.length = 0;
  1033. }
  1034. },
  1035. /**
  1036. * @param {cc.Node} child
  1037. * @param {Boolean} doCleanup
  1038. * @private
  1039. */
  1040. _detachChild:function (child, doCleanup) {
  1041. // IMPORTANT:
  1042. // -1st do onExit
  1043. // -2nd cleanup
  1044. if (this._running) {
  1045. child.onExitTransitionDidStart();
  1046. child.onExit();
  1047. }
  1048. // If you don't do cleanup, the child's actions will not get removed and the
  1049. // its scheduledSelectors_ dict will not get released!
  1050. if (doCleanup)
  1051. child.cleanup();
  1052. // set parent nil at the end
  1053. child.setParent(null);
  1054. cc.ArrayRemoveObject(this._children, child);
  1055. },
  1056. /** helper used by reorderChild & add
  1057. * @param {cc.Node} child
  1058. * @param {Number} z
  1059. * @private
  1060. */
  1061. _insertChild:function (child, z) {
  1062. this._reorderChildDirty = true;
  1063. this._children.push(child);
  1064. child._setZOrder(z);
  1065. },
  1066. /** Reorders a child according to a new z value. <br/>
  1067. * The child MUST be already added.
  1068. * @param {cc.Node} child An already added child node. It MUST be already added.
  1069. * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int)
  1070. */
  1071. reorderChild:function (child, zOrder) {
  1072. if(!child)
  1073. throw "cc.Node.reorderChild(): child must be non-null";
  1074. this._reorderChildDirty = true;
  1075. child.setOrderOfArrival(cc.s_globalOrderOfArrival++);
  1076. child._setZOrder(zOrder);
  1077. this.setNodeDirty();
  1078. },
  1079. /**
  1080. * <p>
  1081. * Sorts the children array once before drawing, instead of every time when a child is added or reordered. <br/>
  1082. * This approach can improves the performance massively.
  1083. * </p>
  1084. * @note Don't call this manually unless a child added needs to be removed in the same frame
  1085. */
  1086. sortAllChildren:function () {
  1087. if (this._reorderChildDirty) {
  1088. var _children = this._children;
  1089. var i, j, length = _children.length,tempChild;
  1090. // insertion sort
  1091. for (i = 0; i < length; i++) {
  1092. var tempItem = _children[i];
  1093. j = i - 1;
  1094. tempChild = _children[j];
  1095. //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
  1096. while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder ||
  1097. ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) {
  1098. _children[j + 1] = tempChild;
  1099. j = j - 1;
  1100. tempChild = _children[j];
  1101. }
  1102. _children[j + 1] = tempItem;
  1103. }
  1104. //don't need to check children recursively, that's done in visit of each child
  1105. this._reorderChildDirty = false;
  1106. }
  1107. },
  1108. // draw
  1109. /** <p>Override this method to draw your own node. <br/>
  1110. * The following GL states will be enabled by default: <br/>
  1111. - glEnableClientState(GL_VERTEX_ARRAY); <br/>
  1112. - glEnableClientState(GL_COLOR_ARRAY); <br/>
  1113. - glEnableClientState(GL_TEXTURE_COORD_ARRAY); <br/>
  1114. - glEnable(GL_TEXTURE_2D); </p>
  1115. <p>AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE</p>
  1116. <p>But if you enable any other GL state, you should disable it after drawing your node. </p>
  1117. * @param {CanvasContext} ctx
  1118. */
  1119. draw:function (ctx) {
  1120. // override me
  1121. // Only use- this function to draw your staff.
  1122. // DON'T draw your stuff outside this method
  1123. },
  1124. /** performs OpenGL view-matrix transformation of it's ancestors.<br/>
  1125. * Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO) <br/>
  1126. * it's necessary to transform the ancestors again.
  1127. */
  1128. transformAncestors:function () {
  1129. if (this._parent != null) {
  1130. this._parent.transformAncestors();
  1131. this._parent.transform();
  1132. }
  1133. },
  1134. //scene managment
  1135. /**
  1136. * <p>
  1137. * Event callback that is invoked every time when CCNode enters the 'stage'. <br/>
  1138. * If the CCNode enters the 'stage' with a transition, this event is called when the transition starts. <br/>
  1139. * During onEnter you can't access a "sister/brother" node. <br/>
  1140. * If you override onEnter, you shall call its parent's one, e.g., CCNode::onEnter().
  1141. * </p>
  1142. */
  1143. onEnter:function () {
  1144. this._isTransitionFinished = false;
  1145. this._running = true;//should be running before resumeSchedule
  1146. this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnter);
  1147. this.resumeSchedulerAndActions();
  1148. },
  1149. /**
  1150. * <p>
  1151. * Event callback that is invoked when the CCNode enters in the 'stage'. <br/>
  1152. * If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes. <br/>
  1153. * If you override onEnterTransitionDidFinish, you shall call its parent's one, e.g. CCNode::onEnterTransitionDidFinish()
  1154. * </p>
  1155. */
  1156. onEnterTransitionDidFinish:function () {
  1157. this._isTransitionFinished = true;
  1158. this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnterTransitionDidFinish);
  1159. },
  1160. /**
  1161. * <p>callback that is called every time the cc.Node leaves the 'stage'. <br/>
  1162. * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts. </p>
  1163. */
  1164. onExitTransitionDidStart:function () {
  1165. this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExitTransitionDidStart);
  1166. },
  1167. /**
  1168. * <p>
  1169. * callback that is called every time the cc.Node leaves the 'stage'. <br/>
  1170. * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes. <br/>
  1171. * During onExit you can't access a sibling node. <br/>
  1172. * If you override onExit, you shall call its parent's one, e.g., CCNode::onExit().
  1173. * </p>
  1174. */
  1175. onExit:function () {
  1176. this._running = false;
  1177. this.pauseSchedulerAndActions();
  1178. this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExit);
  1179. if(this._componentContainer){
  1180. this._componentContainer.removeAll();
  1181. }
  1182. },
  1183. // actions
  1184. /**
  1185. * Executes an action, and returns the action that is executed.<br/>
  1186. * The node becomes the action's target. Refer to CCAction::getTarget()
  1187. * @warning Starting from v0.8 actions don't retain their target anymore.
  1188. * @param {cc.Action} action
  1189. * @return {cc.Action} An Action pointer
  1190. */
  1191. runAction:function (action) {
  1192. if(!action)
  1193. throw "cc.Node.runAction(): action must be non-null";
  1194. this.getActionManager().addAction(action, this, !this._running);
  1195. return action;
  1196. },
  1197. /**
  1198. * Stops and removes all actions from the running action list .
  1199. */
  1200. stopAllActions:function () {
  1201. this.getActionManager().removeAllActionsFromTarget(this);
  1202. },
  1203. /**
  1204. * Stops and removes an action from the running action list.
  1205. * @param {cc.Action} action An action object to be removed.
  1206. */
  1207. stopAction:function (action) {
  1208. this.getActionManager().removeAction(action);
  1209. },
  1210. /**
  1211. * Removes an action from the running action list by its tag.
  1212. * @param {Number} tag A tag that indicates the action to be removed.
  1213. */
  1214. stopActionByTag:function (tag) {
  1215. if(tag === cc.ACTION_TAG_INVALID){
  1216. cc.log("cc.Node.stopActionBy(): argument tag an invalid tag");
  1217. return;
  1218. }
  1219. this.getActionManager().removeActionByTag(tag, this);
  1220. },
  1221. /**
  1222. * Gets an action from the running action list by its tag.
  1223. * @see setTag(int), getTag().
  1224. * @param {Number} tag
  1225. * @return {cc.Action} The action object with the given tag.
  1226. */
  1227. getActionByTag:function (tag) {
  1228. if(tag === cc.ACTION_TAG_INVALID){
  1229. cc.log("cc.Node.getActionByTag(): argument tag is an invalid tag");
  1230. return null;
  1231. }
  1232. return this.getActionManager().getActionByTag(tag, this);
  1233. },
  1234. /** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).<br/>
  1235. * Composable actions are counted as 1 action. Example:<br/>
  1236. * If you are running 1 Sequence of 7 actions, it will return 1. <br/>
  1237. * If you are running 7 Sequences of 2 actions, it will return 7.
  1238. * @return {Number} The number of actions that are running plus the ones that are schedule to run
  1239. */
  1240. getNumberOfRunningActions:function () {
  1241. return this.getActionManager().numberOfRunningActionsInTarget(this);
  1242. },
  1243. // cc.Node - Callbacks
  1244. // timers
  1245. /**
  1246. * schedules the "update" method. <br/>
  1247. * It will use the order number 0. This method will be called every frame. <br/>
  1248. * Scheduled methods with a lower order value will be called before the ones that have a higher order value.<br/>
  1249. * Only one "update" method could be scheduled per node.
  1250. */
  1251. scheduleUpdate:function () {
  1252. this.scheduleUpdateWithPriority(0);
  1253. },
  1254. /**
  1255. * <p>
  1256. * schedules the "update" callback function with a custom priority.
  1257. * This callback function will be called every frame.<br/>
  1258. * Scheduled callback functions with a lower priority will be called before the ones that have a higher value.<br/>
  1259. * Only one "update" callback function could be scheduled per node (You can't have 2 'update' callback functions).<br/>
  1260. * </p>
  1261. * @param {Number} priority
  1262. */
  1263. scheduleUpdateWithPriority:function (priority) {
  1264. this.getScheduler().scheduleUpdateForTarget(this, priority, !this._running);
  1265. },
  1266. /**
  1267. * unschedules the "update" method.
  1268. * @see scheduleUpdate();
  1269. */
  1270. unscheduleUpdate:function () {
  1271. this.getScheduler().unscheduleUpdateForTarget(this);
  1272. },
  1273. /**
  1274. * Schedules a custom selector. <br/>
  1275. * If the selector is already scheduled, then the interval parameter will be updated without scheduling it again.
  1276. *
  1277. * @param {function} callback_fn A function wrapped as a selector
  1278. * @param {Number} interval Tick interval in seconds. 0 means tick every frame. If interval = 0, it's recommended to use scheduleUpdate() instead.
  1279. * @param {Number} repeat The selector will be executed (repeat + 1) times, you can use kCCRepeatForever for tick infinitely.
  1280. * @param {Number} delay The amount of time that the first tick will wait before execution.
  1281. */
  1282. schedule:function (callback_fn, interval, repeat, delay) {
  1283. interval = interval || 0;
  1284. if(!callback_fn)
  1285. throw "cc.Node.schedule(): callback function must be non-null";
  1286. if(interval < 0)
  1287. throw "cc.Node.schedule(): interval must be positive";
  1288. repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
  1289. delay = delay || 0;
  1290. this.getScheduler().scheduleCallbackForTarget(this, callback_fn, interval, repeat, delay, !this._running);
  1291. },
  1292. /**
  1293. * Schedules a callback function that runs only once, with a delay of 0 or larger
  1294. * @see schedule(SEL_SCHEDULE, float, unsigned int, float)
  1295. * @param {function} callback_fn A function wrapped as a selector
  1296. * @param {Number} delay The amount of time that the first tick will wait before execution.
  1297. */
  1298. scheduleOnce:function (callback_fn, delay) {
  1299. this.schedule(callback_fn, 0.0, 0, delay);
  1300. },
  1301. /**
  1302. * unschedules a custom callback function.
  1303. * @see schedule(SEL_SCHEDULE, float, unsigned int, float)
  1304. * @param {function} callback_fn A function wrapped as a selector
  1305. */
  1306. unschedule:function (callback_fn) {
  1307. // explicit nil handling
  1308. if (!callback_fn)
  1309. return;
  1310. this.getScheduler().unscheduleCallbackForTarget(this, callback_fn);
  1311. },
  1312. /**
  1313. * unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.<br/>
  1314. * Actions are not affected by this method.
  1315. */
  1316. unscheduleAllCallbacks:function () {
  1317. this.getScheduler().unscheduleAllCallbacksForTarget(this);
  1318. },
  1319. /**
  1320. * Resumes all scheduled selectors and actions.<br/>
  1321. * This method is called internally by onEnter
  1322. */
  1323. resumeSchedulerAndActions:function () {
  1324. this.getScheduler().resumeTarget(this);
  1325. this.getActionManager().resumeTarget(this);
  1326. },
  1327. /**
  1328. * Pauses all scheduled selectors and actions.<br/>
  1329. * This method is called internally by onExit
  1330. */
  1331. pauseSchedulerAndActions:function () {
  1332. this.getScheduler().pauseTarget(this);
  1333. this.getActionManager().pauseTarget(this);
  1334. },
  1335. /**
  1336. *<p> Sets the additional transform.<br/>
  1337. * The additional transform will be concatenated at the end of nodeToParentTransform.<br/>
  1338. * It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't).<br/>
  1339. * </p>
  1340. * @example
  1341. * // create a batchNode
  1342. * var batch= cc.SpriteBatchNode.create("Icon-114.png");
  1343. * this.addChild(batch);
  1344. *
  1345. * // create two sprites, spriteA will be added to batchNode, they are using different textures.
  1346. * var spriteA = cc.Sprite.createWithTexture(batch->getTexture());
  1347. * var spriteB = cc.Sprite.create("Icon-72.png");
  1348. *
  1349. * batch.addChild(spriteA);
  1350. *
  1351. * // We can't make spriteB as spriteA's child since they use different textures. So just add it to layer.
  1352. * // But we want to simulate `parent-child` relationship for these two node.
  1353. * this.addChild(spriteB);
  1354. *
  1355. * //position
  1356. * spriteA.setPosition(ccp(200, 200));
  1357. *
  1358. * // Gets the spriteA's transform.
  1359. * var t = spriteA.nodeToParentTransform();
  1360. *
  1361. * // Sets the additional transform to spriteB, spriteB's position will based on its pseudo parent i.e. spriteA.
  1362. * spriteB.setAdditionalTransform(t);
  1363. *
  1364. * //scale
  1365. * spriteA.setScale(2);
  1366. *
  1367. * // Gets the spriteA's transform.
  1368. * t = spriteA.nodeToParentTransform();
  1369. *
  1370. * // Sets the additional transform to spriteB, spriteB's scale will based on its pseudo parent i.e. spriteA.
  1371. * spriteB.setAdditionalTransform(t);
  1372. *
  1373. * //rotation
  1374. * spriteA.setRotation(20);
  1375. *
  1376. * // Gets the spriteA's transform.
  1377. * t = spriteA.nodeToParentTransform();
  1378. *
  1379. * // Sets the additional transform to spriteB, spriteB's rotation will based on its pseudo parent i.e. spriteA.
  1380. * spriteB.setAdditionalTransform(t);
  1381. */
  1382. setAdditionalTransform:function (additionalTransform) {
  1383. this._additionalTransform = additionalTransform;
  1384. this._transformDirty = true;
  1385. this._additionalTransformDirty = true;
  1386. },
  1387. /**
  1388. * Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.<br/>
  1389. * The matrix is in Pixels.
  1390. * @return {cc.AffineTransform}
  1391. */
  1392. parentToNodeTransform:function () {
  1393. if (this._inverseDirty) {
  1394. this._inverse = cc.AffineTransformInvert(this.nodeToParentTransform());
  1395. this._inverseDirty = false;
  1396. }
  1397. return this._inverse;
  1398. },
  1399. /**
  1400. * Returns the world affine transform matrix. The matrix is in Pixels.
  1401. * @return {cc.AffineTransform}
  1402. */
  1403. nodeToWorldTransform:function () {
  1404. var t = this.nodeToParentTransform();
  1405. for (var p = this._parent; p != null; p = p.getParent())
  1406. t = cc.AffineTransformConcat(t, p.nodeToParentTransform());
  1407. return t;
  1408. },
  1409. /**
  1410. * Returns the inverse world affine transform matrix. The matrix is in Pixels.
  1411. * @return {cc.AffineTransform}
  1412. */
  1413. worldToNodeTransform:function () {
  1414. return cc.AffineTransformInvert(this.nodeToWorldTransform());
  1415. },
  1416. /**
  1417. * Converts a Point to node (local) space coordinates. The result is in Points.
  1418. * @param {cc.Point} worldPoint
  1419. * @return {cc.Point}
  1420. */
  1421. convertToNodeSpace:function (worldPoint) {
  1422. return cc.PointApplyAffineTransform(worldPoint, this.worldToNodeTransform());
  1423. },
  1424. /**
  1425. * Converts a Point to world space coordinates. The result is in Points.
  1426. * @param {cc.Point} nodePoint
  1427. * @return {cc.Point}
  1428. */
  1429. convertToWorldSpace:function (nodePoint) {
  1430. return cc.PointApplyAffineTransform(nodePoint, this.nodeToWorldTransform());
  1431. },
  1432. /**
  1433. * Converts a Point to node (local) space coordinates. The result is in Points.<br/>
  1434. * treating the returned/received node point as anchor relative.
  1435. * @param {cc.Point} worldPoint
  1436. * @return {cc.Point}
  1437. */
  1438. convertToNodeSpaceAR:function (worldPoint) {
  1439. return cc.pSub(this.convertToNodeSpace(worldPoint), this._anchorPointInPoints);
  1440. },
  1441. /**
  1442. * Converts a local Point to world space coordinates.The result is in Points.<br/>
  1443. * treating the returned/received node point as anchor relative.
  1444. * @param {cc.Point} nodePoint
  1445. * @return {cc.Point}
  1446. */
  1447. convertToWorldSpaceAR:function (nodePoint) {
  1448. var pt = cc.pAdd(nodePoint, this._anchorPointInPoints);
  1449. return this.convertToWorldSpace(pt);
  1450. },
  1451. _convertToWindowSpace:function (nodePoint) {
  1452. var worldPoint = this.convertToWorldSpace(nodePoint);
  1453. return cc.Director.getInstance().convertToUI(worldPoint);
  1454. },
  1455. /** convenience methods which take a cc.Touch instead of cc.Point
  1456. * @param {cc.Touch} touch
  1457. * @return {cc.Point}
  1458. */
  1459. convertTouchToNodeSpace:function (touch) {
  1460. var point = touch.getLocation();
  1461. //TODO This point needn't convert to GL in HTML5
  1462. //point = cc.Director.getInstance().convertToGL(point);
  1463. return this.convertToNodeSpace(point);
  1464. },
  1465. /**
  1466. * converts a cc.Touch (world coordinates) into a local coordiante. This method is AR (Anchor Relative).
  1467. * @param {cc.Touch}touch
  1468. * @return {cc.Point}
  1469. */
  1470. convertTouchToNodeSpaceAR:function (touch) {
  1471. var point = touch.getLocation();
  1472. point = cc.Director.getInstance().convertToGL(point);
  1473. return this.convertToNodeSpaceAR(point);
  1474. },
  1475. /**
  1476. * Update will be called automatically every frame if "scheduleUpdate" is called, and the node is "live" <br/>
  1477. * (override me)
  1478. * @param {Number} dt deltaTime
  1479. */
  1480. update:function (dt) {
  1481. if(this._componentContainer && !this._componentContainer.isEmpty())
  1482. this._componentContainer.visit(dt);
  1483. },
  1484. /**
  1485. * <p>
  1486. * Calls children's updateTransform() method recursively. <br/>
  1487. * <br/>
  1488. * This method is moved from CCSprite, so it's no longer specific to CCSprite. <br/>
  1489. * As the result, you apply CCSpriteBatchNode's optimization on your customed CCNode. <br/>
  1490. * e.g., batchNode->addChild(myCustomNode), while you can only addChild(sprite) before.
  1491. * </p>
  1492. */
  1493. updateTransform:function () {
  1494. // Recursively iterate over children
  1495. this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform);
  1496. },
  1497. /**
  1498. * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
  1499. * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
  1500. * This is a hack, and should be removed once JSB fixes the retain/release bug
  1501. */
  1502. retain:function () {
  1503. },
  1504. release:function () {
  1505. },
  1506. /**
  1507. * gets a component by its name
  1508. * @param {String} name
  1509. * @return {cc.Component} gets a component by its name
  1510. */
  1511. getComponent:function(name){
  1512. return this._componentContainer.getComponent(name);
  1513. },
  1514. /**
  1515. * adds a component
  1516. * @param {cc.Component} component
  1517. */
  1518. addComponent:function(component){
  1519. this._componentContainer.add(component);
  1520. },
  1521. /**
  1522. * removes a component by its name or a component
  1523. * @param {String|cc.Component} name
  1524. */
  1525. removeComponent:function(name){
  1526. return this._componentContainer.remove(name);
  1527. },
  1528. /**
  1529. * removes all components
  1530. */
  1531. removeAllComponents:function(){
  1532. this._componentContainer.removeAll();
  1533. },
  1534. _transform4x4:null,
  1535. _stackMatrix:null,
  1536. _glServerState:null,
  1537. _camera:null,
  1538. _grid:null,
  1539. /**
  1540. * Constructor
  1541. */
  1542. ctor: null,
  1543. _ctorForCanvas: function () {
  1544. this._initNode();
  1545. //Canvas
  1546. },
  1547. _ctorForWebGL: function () {
  1548. this._initNode();
  1549. //WebGL
  1550. var mat4 = new cc.kmMat4();
  1551. mat4.mat[2] = mat4.mat[3] = mat4.mat[6] = mat4.mat[7] = mat4.mat[8] = mat4.mat[9] = mat4.mat[11] = mat4.mat[14] = 0.0;
  1552. mat4.mat[10] = mat4.mat[15] = 1.0;
  1553. this._transform4x4 = mat4;
  1554. this._glServerState = 0;
  1555. this._stackMatrix = new cc.kmMat4();
  1556. },
  1557. /**
  1558. * recursive method that visit its children and draw them
  1559. * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx
  1560. */
  1561. visit:null,
  1562. _visitForCanvas:function (ctx) {
  1563. // quick return if not visible
  1564. if (!this._visible)
  1565. return;
  1566. //visit for canvas
  1567. var context = ctx || cc.renderContext, i;
  1568. var children = this._children,child;
  1569. context.save();
  1570. this.transform(context);
  1571. var len = children.length;
  1572. if (len > 0) {
  1573. this.sortAllChildren();
  1574. // draw children zOrder < 0
  1575. for (i = 0; i < len; i++) {
  1576. child = children[i];
  1577. if (child._zOrder < 0)
  1578. child.visit(context);
  1579. else
  1580. break;
  1581. }
  1582. this.draw(context);
  1583. for (; i < len; i++) {
  1584. children[i].visit(context);
  1585. }
  1586. } else
  1587. this.draw(context);
  1588. this._orderOfArrival = 0;
  1589. context.restore();
  1590. },
  1591. _visitForWebGL: function(){
  1592. // quick return if not visible
  1593. if (!this._visible)
  1594. return;
  1595. var context = cc.renderContext, i, currentStack = cc.current_stack;
  1596. //cc.kmGLPushMatrixWitMat4(this._stackMatrix);
  1597. //optimize performance for javascript
  1598. currentStack.stack.push(currentStack.top);
  1599. cc.kmMat4Assign(this._stackMatrix, currentStack.top);
  1600. currentStack.top = this._stackMatrix;
  1601. var locGrid = this._grid;
  1602. if (locGrid && locGrid._active)
  1603. locGrid.beforeDraw();
  1604. this.transform();
  1605. var locChildren = this._children;
  1606. if (locChildren && locChildren.length > 0) {
  1607. var childLen = locChildren.length;
  1608. this.sortAllChildren();
  1609. // draw children zOrder < 0
  1610. for (i = 0; i < childLen; i++) {
  1611. if (locChildren[i] && locChildren[i]._zOrder < 0)
  1612. locChildren[i].visit();
  1613. else
  1614. break;
  1615. }
  1616. this.draw(context);
  1617. // draw children zOrder >= 0
  1618. for (; i < childLen; i++) {
  1619. if (locChildren[i]) {
  1620. locChildren[i].visit();
  1621. }
  1622. }
  1623. } else
  1624. this.draw(context);
  1625. this._orderOfArrival = 0;
  1626. if (locGrid && locGrid._active)
  1627. locGrid.afterDraw(this);
  1628. //cc.kmGLPopMatrix();
  1629. //optimize performance for javascript
  1630. currentStack.top = currentStack.stack.pop();
  1631. },
  1632. /**
  1633. * Performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes.
  1634. */
  1635. transform:null,
  1636. _transformForCanvas: function (ctx) {
  1637. // transform for canvas
  1638. var context = ctx || cc.renderContext, eglViewer = cc.EGLView.getInstance();
  1639. var t = this.nodeToParentTransform();
  1640. context.transform(t.a, t.c, t.b, t.d, t.tx * eglViewer.getScaleX(), -t.ty * eglViewer.getScaleY());
  1641. },
  1642. _transformForWebGL: function () {
  1643. //optimize performance for javascript
  1644. var t4x4 = this._transform4x4, topMat4 = cc.current_stack.top;
  1645. // Convert 3x3 into 4x4 matrix
  1646. //cc.CGAffineToGL(this.nodeToParentTransform(), this._transform4x4.mat);
  1647. var trans = this.nodeToParentTransform();
  1648. var t4x4Mat = t4x4.mat;
  1649. t4x4Mat[0] = trans.a;
  1650. t4x4Mat[4] = trans.c;
  1651. t4x4Mat[12] = trans.tx;
  1652. t4x4Mat[1] = trans.b;
  1653. t4x4Mat[5] = trans.d;
  1654. t4x4Mat[13] = trans.ty;
  1655. // Update Z vertex manually
  1656. //this._transform4x4.mat[14] = this._vertexZ;
  1657. t4x4Mat[14] = this._vertexZ;
  1658. //optimize performance for Javascript
  1659. cc.kmMat4Multiply(topMat4, topMat4, t4x4); // = cc.kmGLMultMatrix(this._transform4x4);
  1660. // XXX: Expensive calls. Camera should be integrated into the cached affine matrix
  1661. if (this._camera != null && !(this._grid != null && this._grid.isActive())) {
  1662. var apx = this._anchorPointInPoints.x, apy = this._anchorPointInPoints.y;
  1663. var translate = (apx !== 0.0 || apy !== 0.0);
  1664. if (translate){
  1665. cc.kmGLTranslatef(cc.RENDER_IN_SUBPIXEL(apx), cc.RENDER_IN_SUBPIXEL(apy), 0);
  1666. this._camera.locate();
  1667. cc.kmGLTranslatef(cc.RENDER_IN_SUBPIXEL(-apx), cc.RENDER_IN_SUBPIXEL(-apy), 0);
  1668. } else {
  1669. this._camera.locate();
  1670. }
  1671. }
  1672. },
  1673. /** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.<br/>
  1674. * The matrix is in Pixels.
  1675. * @return {cc.AffineTransform}
  1676. */
  1677. nodeToParentTransform: null,
  1678. _nodeToParentTransformForCanvas:function () {
  1679. if (this._transformDirty) {
  1680. var t = this._transform;// quick reference
  1681. // base position
  1682. t.tx = this._position.x;
  1683. t.ty = this._position.y;
  1684. // rotation Cos and Sin
  1685. var Cos = 1, Sin = 0;
  1686. if (this._rotationX) {
  1687. Cos = Math.cos(this._rotationRadiansX);
  1688. Sin = Math.sin(this._rotationRadiansX);
  1689. }
  1690. // base abcd
  1691. t.a = t.d = Cos;
  1692. t.b = -Sin;
  1693. t.c = Sin;
  1694. var lScaleX = this._scaleX, lScaleY = this._scaleY;
  1695. var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y;
  1696. // Firefox on Vista and XP crashes
  1697. // GPU thread in case of scale(0.0, 0.0)
  1698. var sx = (lScaleX < 0.000001 && lScaleX > -0.000001)? 0.000001 : lScaleX,
  1699. sy = (lScaleY < 0.000001 && lScaleY > -0.000001)? 0.000001 : lScaleY;
  1700. // skew
  1701. if (this._skewX || this._skewY) {
  1702. // offset the anchorpoint
  1703. var skx = Math.tan(-this._skewX * Math.PI / 180);
  1704. var sky = Math.tan(-this._skewY * Math.PI / 180);
  1705. var xx = appY * skx * sx;
  1706. var yy = appX * sky * sy;
  1707. t.a = Cos + -Sin * sky;
  1708. t.b = Cos * skx + -Sin;
  1709. t.c = Sin + Cos * sky;
  1710. t.d = Sin * skx + Cos;
  1711. t.tx += Cos * xx + -Sin * yy;
  1712. t.ty += Sin * xx + Cos * yy;
  1713. }
  1714. // scale
  1715. if (lScaleX !== 1 || lScaleY !== 1) {
  1716. t.a *= sx;
  1717. t.c *= sx;
  1718. t.b *= sy;
  1719. t.d *= sy;
  1720. }
  1721. // adjust anchorPoint
  1722. t.tx += Cos * -appX * sx + -Sin * appY * sy;
  1723. t.ty -= Sin * -appX * sx + Cos * appY * sy;
  1724. // if ignore anchorPoint
  1725. if (this._ignoreAnchorPointForPosition) {
  1726. t.tx += appX;
  1727. t.ty += appY;
  1728. }
  1729. if (this._additionalTransformDirty) {
  1730. this._transform = cc.AffineTransformConcat(t, this._additionalTransform);
  1731. this._additionalTransformDirty = false;
  1732. }
  1733. this._transformDirty = false;
  1734. }
  1735. return this._transform;
  1736. },
  1737. _nodeToParentTransformForWebGL:function () {
  1738. if (this._transformDirty) {
  1739. // Translate values
  1740. var x = this._position.x;
  1741. var y = this._position.y;
  1742. var apx = this._anchorPointInPoints.x, napx = -apx;
  1743. var apy = this._anchorPointInPoints.y, napy = -apy;
  1744. var scx = this._scaleX, scy = this._scaleY;
  1745. if (this._ignoreAnchorPointForPosition) {
  1746. x += apx;
  1747. y += apy;
  1748. }
  1749. // Rotation values
  1750. // Change rotation code to handle X and Y
  1751. // If we skew with the exact same value for both x and y then we're simply just rotating
  1752. var cx = 1, sx = 0, cy = 1, sy = 0;
  1753. if (this._rotationX !== 0 || this._rotationY !== 0) {
  1754. cx = Math.cos(-this._rotationRadiansX);
  1755. sx = Math.sin(-this._rotationRadiansX);
  1756. cy = Math.cos(-this._rotationRadiansY);
  1757. sy = Math.sin(-this._rotationRadiansY);
  1758. }
  1759. var needsSkewMatrix = ( this._skewX || this._skewY );
  1760. // optimization:
  1761. // inline anchor point calculation if skew is not needed
  1762. // Adjusted transform calculation for rotational skew
  1763. if (!needsSkewMatrix && (apx !== 0 || apy !== 0)) {
  1764. x += cy * napx * scx + -sx * napy * scy;
  1765. y += sy * napx * scx + cx * napy * scy;
  1766. }
  1767. // Build Transform Matrix
  1768. // Adjusted transform calculation for rotational skew
  1769. var t = this._transform;
  1770. t.a = cy * scx;
  1771. t.b = sy * scx;
  1772. t.c = -sx * scy;
  1773. t.d = cx * scy;
  1774. t.tx = x;
  1775. t.ty = y;
  1776. // XXX: Try to inline skew
  1777. // If skew is needed, apply skew and then anchor point
  1778. if (needsSkewMatrix) {
  1779. t = cc.AffineTransformConcat({a: 1.0, b: Math.tan(cc.DEGREES_TO_RADIANS(this._skewY)),
  1780. c: Math.tan(cc.DEGREES_TO_RADIANS(this._skewX)), d: 1.0, tx: 0.0, ty: 0.0}, t);
  1781. // adjust anchor point
  1782. if (apx !== 0 || apy !== 0)
  1783. t = cc.AffineTransformTranslate(t, napx, napy);
  1784. }
  1785. if (this._additionalTransformDirty) {
  1786. t = cc.AffineTransformConcat(t, this._additionalTransform);
  1787. this._additionalTransformDirty = false;
  1788. }
  1789. this._transform = t;
  1790. this._transformDirty = false;
  1791. }
  1792. return this._transform;
  1793. },
  1794. _setNodeDirtyForCache:function () {
  1795. this._cacheDirty = true;
  1796. if (this._parent) {
  1797. this._parent._setNodeDirtyForCache();
  1798. }
  1799. },
  1800. /**
  1801. * Returns a camera object that lets you move the node using a gluLookAt
  1802. * @return {cc.Camera} A CCCamera object that lets you move the node using a gluLookAt
  1803. * @example
  1804. * var camera = node.getCamera();
  1805. * camera.setEye(0, 0, 415/2);
  1806. * camera.setCenter(0, 0, 0);
  1807. */
  1808. getCamera:function () {
  1809. if (!this._camera) {
  1810. this._camera = new cc.Camera();
  1811. }
  1812. return this._camera;
  1813. },
  1814. /**
  1815. * Returns a grid object that is used when applying effects
  1816. * @return {cc.GridBase} A CCGrid object that is used when applying effects
  1817. */
  1818. getGrid:function () {
  1819. return this._grid;
  1820. },
  1821. /**
  1822. * Changes a grid object that is used when applying effects
  1823. * @param {cc.GridBase} grid A CCGrid object that is used when applying effects
  1824. */
  1825. setGrid:function (grid) {
  1826. this._grid = grid;
  1827. },
  1828. /**
  1829. * Return the shader program currently used for this node
  1830. * @return {cc.GLProgram} The shader program currelty used for this node
  1831. */
  1832. getShaderProgram:function () {
  1833. return this._shaderProgram;
  1834. },
  1835. /**
  1836. * <p>
  1837. * Sets the shader program for this node
  1838. *
  1839. * Since v2.0, each rendering node must set its shader program.
  1840. * It should be set in initialize phase.
  1841. * </p>
  1842. * @param {cc.GLProgram} newShaderProgram The shader program which fetchs from CCShaderCache.
  1843. * @example
  1844. * node.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
  1845. */
  1846. setShaderProgram:function (newShaderProgram) {
  1847. this._shaderProgram = newShaderProgram;
  1848. },
  1849. /**
  1850. * Returns the state of OpenGL server side.
  1851. * @return {Number} The state of OpenGL server side.
  1852. */
  1853. getGLServerState:function () {
  1854. return this._glServerState;
  1855. },
  1856. /**
  1857. * Sets the state of OpenGL server side.
  1858. * @param {Number} state The state of OpenGL server side.
  1859. */
  1860. setGLServerState:function (state) {
  1861. this._glServerState = state;
  1862. },
  1863. /** returns a "world" axis aligned bounding box of the node. <br/>
  1864. * @return {cc.Rect}
  1865. */
  1866. getBoundingBoxToWorld:function () {
  1867. var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
  1868. var trans = this.nodeToWorldTransform();
  1869. rect = cc.RectApplyAffineTransform(rect, this.nodeToWorldTransform());
  1870. //rect = cc.rect(0 | rect.x - 4, 0 | rect.y - 4, 0 | rect.width + 8, 0 | rect.height + 8);
  1871. //query child's BoundingBox
  1872. if (!this._children)
  1873. return rect;
  1874. var locChildren = this._children;
  1875. for (var i = 0; i < locChildren.length; i++) {
  1876. var child = locChildren[i];
  1877. if (child && child._visible) {
  1878. var childRect = child._getBoundingBoxToCurrentNode(trans);
  1879. if (childRect)
  1880. rect = cc.rectUnion(rect, childRect);
  1881. }
  1882. }
  1883. return rect;
  1884. },
  1885. _getBoundingBoxToCurrentNode: function (parentTransform) {
  1886. var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
  1887. var trans = (parentTransform == null) ? this.nodeToParentTransform() : cc.AffineTransformConcat(this.nodeToParentTransform(), parentTransform);
  1888. rect = cc.RectApplyAffineTransform(rect, trans);
  1889. //query child's BoundingBox
  1890. if (!this._children)
  1891. return rect;
  1892. var locChildren = this._children;
  1893. for (var i = 0; i < locChildren.length; i++) {
  1894. var child = locChildren[i];
  1895. if (child && child._visible) {
  1896. var childRect = child._getBoundingBoxToCurrentNode(trans);
  1897. if (childRect)
  1898. rect = cc.rectUnion(rect, childRect);
  1899. }
  1900. }
  1901. return rect;
  1902. }
  1903. });
  1904. if(cc.Browser.supportWebGL){
  1905. //WebGL
  1906. cc.Node.prototype.ctor = cc.Node.prototype._ctorForWebGL;
  1907. cc.Node.prototype.setNodeDirty = cc.Node.prototype._setNodeDirtyForWebGL;
  1908. cc.Node.prototype.visit = cc.Node.prototype._visitForWebGL;
  1909. cc.Node.prototype.transform = cc.Node.prototype._transformForWebGL;
  1910. cc.Node.prototype.nodeToParentTransform = cc.Node.prototype._nodeToParentTransformForWebGL;
  1911. }else{
  1912. //Canvas
  1913. cc.Node.prototype.ctor = cc.Node.prototype._ctorForCanvas;
  1914. cc.Node.prototype.setNodeDirty = cc.Node.prototype._setNodeDirtyForCanvas;
  1915. cc.Node.prototype.visit = cc.Node.prototype._visitForCanvas;
  1916. cc.Node.prototype.transform = cc.Node.prototype._transformForCanvas;
  1917. cc.Node.prototype.nodeToParentTransform = cc.Node.prototype._nodeToParentTransformForCanvas;
  1918. }
  1919. /**
  1920. * allocates and initializes a node.
  1921. * @constructs
  1922. * @return {cc.Node}
  1923. * @example
  1924. * // example
  1925. * var node = cc.Node.create();
  1926. */
  1927. cc.Node.create = function () {
  1928. return new cc.Node();
  1929. };
  1930. /**
  1931. * cc.Node's state callback type
  1932. * @constant
  1933. * @type Number
  1934. */
  1935. cc.Node.StateCallbackType = {onEnter:1, onExit:2, cleanup:3, onEnterTransitionDidFinish:4, updateTransform:5, onExitTransitionDidStart:6, sortAllChildren:7};
  1936. /**
  1937. * <p>
  1938. * cc.NodeRGBA is a subclass of cc.Node that implements the CCRGBAProtocol protocol. <br/>
  1939. * <br/>
  1940. * All features from CCNode are valid, plus the following new features: <br/>
  1941. * - opacity <br/>
  1942. * - RGB colors <br/>
  1943. * <br/>
  1944. * Opacity/Color propagates into children that conform to the CCRGBAProtocol if cascadeOpacity/cascadeColor is enabled. <br/>
  1945. * </p>
  1946. *
  1947. * @class
  1948. * @extends cc.Node
  1949. */
  1950. cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{
  1951. RGBAProtocol:true,
  1952. _displayedOpacity:255,
  1953. _realOpacity:255,
  1954. _displayedColor:null,
  1955. _realColor:null,
  1956. _cascadeColorEnabled:false,
  1957. _cascadeOpacityEnabled:false,
  1958. ctor:function(){
  1959. cc.Node.prototype.ctor.call(this);
  1960. this._displayedOpacity = 255;
  1961. this._realOpacity = 255;
  1962. this._displayedColor = cc.white();
  1963. this._realColor = cc.white();
  1964. this._cascadeColorEnabled = false;
  1965. this._cascadeOpacityEnabled = false;
  1966. },
  1967. /**
  1968. * Get the opacity of Node
  1969. * @returns {number} opacity
  1970. */
  1971. getOpacity:function(){
  1972. return this._realOpacity;
  1973. },
  1974. /**
  1975. * Get the displayed opacity of Node
  1976. * @returns {number} displayed opacity
  1977. */
  1978. getDisplayedOpacity:function(){
  1979. return this._displayedOpacity;
  1980. },
  1981. /**
  1982. * Set the opacity of Node
  1983. * @param {Number} opacity
  1984. */
  1985. setOpacity:function(opacity){
  1986. this._displayedOpacity = this._realOpacity = opacity;
  1987. var parentOpacity = 255, locParent = this._parent;
  1988. if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled())
  1989. parentOpacity = locParent.getDisplayedOpacity();
  1990. this.updateDisplayedOpacity(parentOpacity);
  1991. },
  1992. /**
  1993. * Update displayed opacity
  1994. * @param {Number} parentOpacity
  1995. */
  1996. updateDisplayedOpacity: function (parentOpacity) {
  1997. this._displayedOpacity = this._realOpacity * parentOpacity / 255.0;
  1998. if (this._cascadeOpacityEnabled) {
  1999. var selChildren = this._children;
  2000. for (var i = 0; i < selChildren.length; i++) {
  2001. var item = selChildren[i];
  2002. if (item && item.RGBAProtocol)
  2003. item.updateDisplayedOpacity(this._displayedOpacity);
  2004. }
  2005. }
  2006. },
  2007. /**
  2008. * whether or not it will set cascade opacity.
  2009. * @returns {boolean}
  2010. */
  2011. isCascadeOpacityEnabled:function(){
  2012. return this._cascadeOpacityEnabled;
  2013. },
  2014. /**
  2015. * Enable or disable cascade opacity
  2016. * @param {boolean} cascadeOpacityEnabled
  2017. */
  2018. setCascadeOpacityEnabled:function(cascadeOpacityEnabled){
  2019. if(this._cascadeOpacityEnabled === cascadeOpacityEnabled)
  2020. return;
  2021. this._cascadeOpacityEnabled = cascadeOpacityEnabled;
  2022. if(cascadeOpacityEnabled)
  2023. this._enableCascadeOpacity();
  2024. else
  2025. this._disableCascadeOpacity();
  2026. },
  2027. _enableCascadeOpacity:function(){
  2028. var parentOpacity = 255, locParent = this._parent;
  2029. if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled())
  2030. parentOpacity = locParent.getDisplayedOpacity();
  2031. this.updateDisplayedOpacity(parentOpacity);
  2032. },
  2033. _disableCascadeOpacity:function(){
  2034. this._displayedOpacity = this._realOpacity;
  2035. var selChildren = this._children;
  2036. for(var i = 0; i< selChildren.length;i++){
  2037. var item = selChildren[i];
  2038. if(item && item.RGBAProtocol)
  2039. item.updateDisplayedOpacity(255);
  2040. }
  2041. },
  2042. /**
  2043. * Get the color of Node
  2044. * @returns {cc.Color3B}
  2045. */
  2046. getColor:function(){
  2047. var locRealColor = this._realColor;
  2048. return new cc.Color3B(locRealColor.r, locRealColor.g, locRealColor.b);
  2049. },
  2050. /**
  2051. * Get the displayed color of Node
  2052. * @returns {cc.Color3B}
  2053. */
  2054. getDisplayedColor:function(){
  2055. return this._displayedColor;
  2056. },
  2057. /**
  2058. * Set the color of Node
  2059. * @param {cc.Color3B} color
  2060. */
  2061. setColor:function(color){
  2062. var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
  2063. locDisplayedColor.r = locRealColor.r = color.r;
  2064. locDisplayedColor.g = locRealColor.g = color.g;
  2065. locDisplayedColor.b = locRealColor.b = color.b;
  2066. var parentColor, locParent = this._parent;
  2067. if (locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled())
  2068. parentColor = locParent.getDisplayedColor();
  2069. else
  2070. parentColor = cc.white();
  2071. this.updateDisplayedColor(parentColor);
  2072. },
  2073. /**
  2074. * update the displayed color of Node
  2075. * @param {cc.Color3B} parentColor
  2076. */
  2077. updateDisplayedColor: function (parentColor) {
  2078. var locDispColor = this._displayedColor, locRealColor = this._realColor;
  2079. locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
  2080. locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
  2081. locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
  2082. if (this._cascadeColorEnabled) {
  2083. var selChildren = this._children;
  2084. for (var i = 0; i < selChildren.length; i++) {
  2085. var item = selChildren[i];
  2086. if (item && item.RGBAProtocol)
  2087. item.updateDisplayedColor(locDispColor);
  2088. }
  2089. }
  2090. },
  2091. /**
  2092. * whether or not it will set cascade color.
  2093. * @returns {boolean}
  2094. */
  2095. isCascadeColorEnabled:function(){
  2096. return this._cascadeColorEnabled;
  2097. },
  2098. /**
  2099. * Enable or disable cascade color
  2100. * @param {boolean} cascadeColorEnabled
  2101. */
  2102. setCascadeColorEnabled:function(cascadeColorEnabled){
  2103. if(this._cascadeColorEnabled === cascadeColorEnabled)
  2104. return;
  2105. this._cascadeColorEnabled = cascadeColorEnabled;
  2106. if(this._cascadeColorEnabled)
  2107. this._enableCascadeColor();
  2108. else
  2109. this._disableCascadeColor();
  2110. },
  2111. _enableCascadeColor: function(){
  2112. var parentColor , locParent = this._parent;
  2113. if (locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled())
  2114. parentColor = locParent.getDisplayedColor();
  2115. else
  2116. parentColor = cc.white();
  2117. this.updateDisplayedColor(parentColor);
  2118. },
  2119. _disableCascadeColor: function(){
  2120. var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
  2121. locDisplayedColor.r = locRealColor.r;
  2122. locDisplayedColor.g = locRealColor.g;
  2123. locDisplayedColor.b = locRealColor.b;
  2124. var selChildren = this._children, whiteColor = cc.white();
  2125. for(var i = 0; i< selChildren.length;i++){
  2126. var item = selChildren[i];
  2127. if(item && item.RGBAProtocol)
  2128. item.updateDisplayedColor(whiteColor);
  2129. }
  2130. },
  2131. /**
  2132. * add a child to node
  2133. * @overried
  2134. * @param {cc.Node} child A child node
  2135. * @param {Number} [zOrder=] Z order for drawing priority. Please refer to setZOrder(int)
  2136. * @param {Number} [tag=] A integer to identify the node easily. Please refer to setTag(int)
  2137. */
  2138. addChild:function(child, zOrder, tag){
  2139. cc.Node.prototype.addChild.call(this, child, zOrder, tag);
  2140. if(this._cascadeColorEnabled)
  2141. this._enableCascadeColor();
  2142. if(this._cascadeOpacityEnabled)
  2143. this._enableCascadeOpacity();
  2144. },
  2145. setOpacityModifyRGB:function(opacityValue){},
  2146. isOpacityModifyRGB:function(){
  2147. return false;
  2148. }
  2149. });
  2150. cc.NodeRGBA.create = function () {
  2151. var res = new cc.NodeRGBA();
  2152. res.init();
  2153. return res;
  2154. };