1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 cc.g_NumberOfDraws = 0; 28 29 cc.GLToClipTransform = function (transformOut) { 30 //var projection = new cc.math.Matrix4(); 31 //cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, projection); 32 cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, transformOut); 33 34 var modelview = new cc.math.Matrix4(); 35 cc.kmGLGetMatrix(cc.KM_GL_MODELVIEW, modelview); 36 37 transformOut.multiply(modelview); 38 }; 39 //---------------------------------------------------------------------------------------------------------------------- 40 41 /** 42 * <p> 43 * ATTENTION: USE cc.director INSTEAD OF cc.Director.<br/> 44 * cc.director is a singleton object which manage your game's logic flow.<br/> 45 * Since the cc.director is a singleton, you don't need to call any constructor or create functions,<br/> 46 * the standard way to use it is by calling:<br/> 47 * - cc.director.methodName(); <br/> 48 * 49 * It creates and handle the main Window and manages how and when to execute the Scenes.<br/> 50 * <br/> 51 * The cc.director is also responsible for:<br/> 52 * - initializing the OpenGL context<br/> 53 * - setting the OpenGL pixel format (default on is RGB565)<br/> 54 * - setting the OpenGL pixel format (default on is RGB565)<br/> 55 * - setting the OpenGL buffer depth (default one is 0-bit)<br/> 56 - setting the color for clear screen (default one is BLACK)<br/> 57 * - setting the projection (default one is 3D)<br/> 58 * - setting the orientation (default one is Portrait)<br/> 59 * <br/> 60 * <br/> 61 * The cc.director also sets the default OpenGL context:<br/> 62 * - GL_TEXTURE_2D is enabled<br/> 63 * - GL_VERTEX_ARRAY is enabled<br/> 64 * - GL_COLOR_ARRAY is enabled<br/> 65 * - GL_TEXTURE_COORD_ARRAY is enabled<br/> 66 * </p> 67 * <p> 68 * cc.director also synchronizes timers with the refresh rate of the display.<br/> 69 * Features and Limitations:<br/> 70 * - Scheduled timers & drawing are synchronizes with the refresh rate of the display<br/> 71 * - Only supports animation intervals of 1/60 1/30 & 1/15<br/> 72 * </p> 73 * @class 74 * @name cc.Director 75 */ 76 cc.Director = cc.Class.extend(/** @lends cc.Director# */{ 77 //Variables 78 _landscape: false, 79 _nextDeltaTimeZero: false, 80 _paused: false, 81 _purgeDirectorInNextLoop: false, 82 _sendCleanupToScene: false, 83 _animationInterval: 0.0, 84 _oldAnimationInterval: 0.0, 85 _projection: 0, 86 _accumDt: 0.0, 87 _contentScaleFactor: 1.0, 88 89 _displayStats: false, 90 _deltaTime: 0.0, 91 _frameRate: 0.0, 92 93 _FPSLabel: null, 94 _SPFLabel: null, 95 _drawsLabel: null, 96 97 _winSizeInPoints: null, 98 99 _lastUpdate: null, 100 _nextScene: null, 101 _notificationNode: null, 102 _openGLView: null, 103 _scenesStack: null, 104 _projectionDelegate: null, 105 _runningScene: null, 106 107 _frames: 0, 108 _totalFrames: 0, 109 _secondsPerFrame: 0, 110 111 _dirtyRegion: null, 112 113 _scheduler: null, 114 _actionManager: null, 115 _eventProjectionChanged: null, 116 _eventAfterDraw: null, 117 _eventAfterVisit: null, 118 _eventAfterUpdate: null, 119 120 ctor: function () { 121 var self = this; 122 self._lastUpdate = Date.now(); 123 cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function () { 124 self._lastUpdate = Date.now(); 125 }); 126 }, 127 128 init: function () { 129 // scenes 130 this._oldAnimationInterval = this._animationInterval = 1.0 / cc.defaultFPS; 131 this._scenesStack = []; 132 // Set default projection (3D) 133 this._projection = cc.Director.PROJECTION_DEFAULT; 134 // projection delegate if "Custom" projection is used 135 this._projectionDelegate = null; 136 137 //FPS 138 this._accumDt = 0; 139 this._frameRate = 0; 140 this._displayStats = false;//can remove 141 this._totalFrames = this._frames = 0; 142 this._lastUpdate = Date.now(); 143 144 //Paused? 145 this._paused = false; 146 147 //purge? 148 this._purgeDirectorInNextLoop = false; 149 150 this._winSizeInPoints = cc.size(0, 0); 151 152 this._openGLView = null; 153 this._contentScaleFactor = 1.0; 154 155 //scheduler 156 this._scheduler = new cc.Scheduler(); 157 //action manager 158 if(cc.ActionManager){ 159 this._actionManager = new cc.ActionManager(); 160 this._scheduler.scheduleUpdate(this._actionManager, cc.Scheduler.PRIORITY_SYSTEM, false); 161 }else{ 162 this._actionManager = null; 163 } 164 165 this._eventAfterDraw = new cc.EventCustom(cc.Director.EVENT_AFTER_DRAW); 166 this._eventAfterDraw.setUserData(this); 167 this._eventAfterVisit = new cc.EventCustom(cc.Director.EVENT_AFTER_VISIT); 168 this._eventAfterVisit.setUserData(this); 169 this._eventAfterUpdate = new cc.EventCustom(cc.Director.EVENT_AFTER_UPDATE); 170 this._eventAfterUpdate.setUserData(this); 171 this._eventProjectionChanged = new cc.EventCustom(cc.Director.EVENT_PROJECTION_CHANGED); 172 this._eventProjectionChanged.setUserData(this); 173 174 return true; 175 }, 176 177 /** 178 * calculates delta time since last time it was called 179 */ 180 calculateDeltaTime: function () { 181 var now = Date.now(); 182 183 // new delta time. 184 if (this._nextDeltaTimeZero) { 185 this._deltaTime = 0; 186 this._nextDeltaTimeZero = false; 187 } else { 188 this._deltaTime = (now - this._lastUpdate) / 1000; 189 } 190 191 if ((cc.game.config[cc.game.CONFIG_KEY.debugMode] > 0) && (this._deltaTime > 0.2)) 192 this._deltaTime = 1 / 60.0; 193 194 this._lastUpdate = now; 195 }, 196 197 /** 198 * Converts a view coordinate to an WebGL coordinate<br/> 199 * Useful to convert (multi) touches coordinates to the current layout (portrait or landscape)<br/> 200 * Implementation can be found in CCDirectorWebGL 201 * @function 202 * @param {cc.Point} uiPoint 203 * @return {cc.Point} 204 */ 205 convertToGL: null, 206 207 /** 208 * Converts an WebGL coordinate to a view coordinate<br/> 209 * Useful to convert node points to window points for calls such as glScissor<br/> 210 * Implementation can be found in CCDirectorWebGL 211 * @function 212 * @param {cc.Point} glPoint 213 * @return {cc.Point} 214 */ 215 convertToUI: null, 216 217 /** 218 * Draw the scene. This method is called every frame. Don't call it manually. 219 */ 220 drawScene: function () { 221 var renderer = cc.renderer; 222 // calculate "global" dt 223 this.calculateDeltaTime(); 224 225 //tick before glClear: issue #533 226 if (!this._paused) { 227 this._scheduler.update(this._deltaTime); 228 cc.eventManager.dispatchEvent(this._eventAfterUpdate); 229 } 230 231 renderer.clear(); 232 233 /* to avoid flickr, nextScene MUST be here: after tick and before draw. 234 XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */ 235 if (this._nextScene) { 236 this.setNextScene(); 237 } 238 239 if (this._beforeVisitScene) 240 this._beforeVisitScene(); 241 242 // draw the scene 243 if (this._runningScene) { 244 if (renderer.childrenOrderDirty === true) { 245 cc.renderer.clearRenderCommands(); 246 this._runningScene._renderCmd._curLevel = 0; //level start from 0; 247 this._runningScene.visit(); 248 renderer.resetFlag(); 249 } else if (renderer.transformDirty() === true) 250 renderer.transform(); 251 252 cc.eventManager.dispatchEvent(this._eventAfterVisit); 253 } 254 255 // draw the notifications node 256 if (this._notificationNode) 257 this._notificationNode.visit(); 258 259 if (this._displayStats) 260 this._showStats(); 261 262 if (this._afterVisitScene) 263 this._afterVisitScene(); 264 265 renderer.rendering(cc._renderContext); 266 cc.eventManager.dispatchEvent(this._eventAfterDraw); 267 this._totalFrames++; 268 269 if (this._displayStats) 270 this._calculateMPF(); 271 }, 272 273 _beforeVisitScene: null, 274 _afterVisitScene: null, 275 276 /** 277 * End the life of director in the next frame 278 */ 279 end: function () { 280 this._purgeDirectorInNextLoop = true; 281 }, 282 283 /** 284 * Returns the size in pixels of the surface. It could be different than the screen size.<br/> 285 * High-res devices might have a higher surface size than the screen size. 286 * @return {Number} 287 */ 288 getContentScaleFactor: function () { 289 return this._contentScaleFactor; 290 }, 291 292 /** 293 * This object will be visited after the main scene is visited.<br/> 294 * This object MUST implement the "visit" selector.<br/> 295 * Useful to hook a notification object 296 * @return {cc.Node} 297 */ 298 getNotificationNode: function () { 299 return this._notificationNode; 300 }, 301 302 /** 303 * Returns the size of the WebGL view in points.<br/> 304 * It takes into account any possible rotation (device orientation) of the window 305 * @return {cc.Size} 306 */ 307 getWinSize: function () { 308 return cc.size(this._winSizeInPoints); 309 }, 310 311 /** 312 * Returns the size of the OpenGL view in pixels.<br/> 313 * It takes into account any possible rotation (device orientation) of the window.<br/> 314 * On Mac winSize and winSizeInPixels return the same value. 315 * @return {cc.Size} 316 */ 317 getWinSizeInPixels: function () { 318 return cc.size(this._winSizeInPoints.width * this._contentScaleFactor, this._winSizeInPoints.height * this._contentScaleFactor); 319 }, 320 321 /** 322 * getVisibleSize/getVisibleOrigin move to CCDirectorWebGL/CCDirectorCanvas 323 * getZEye move to CCDirectorWebGL 324 */ 325 326 /** 327 * Returns the visible size of the running scene 328 * @function 329 * @return {cc.Size} 330 */ 331 getVisibleSize: null, 332 333 /** 334 * Returns the visible origin of the running scene 335 * @function 336 * @return {cc.Point} 337 */ 338 getVisibleOrigin: null, 339 340 /** 341 * Returns the z eye, only available in WebGL mode 342 * @function 343 * @return {Number} 344 */ 345 getZEye: null, 346 347 /** 348 * Pause the director's ticker 349 */ 350 pause: function () { 351 if (this._paused) 352 return; 353 354 this._oldAnimationInterval = this._animationInterval; 355 // when paused, don't consume CPU 356 this.setAnimationInterval(1 / 4.0); 357 this._paused = true; 358 }, 359 360 /** 361 * Pops out a scene from the queue.<br/> 362 * This scene will replace the running one.<br/> 363 * The running scene will be deleted. If there are no more scenes in the stack the execution is terminated.<br/> 364 * ONLY call it if there is a running scene. 365 */ 366 popScene: function () { 367 368 cc.assert(this._runningScene, cc._LogInfos.Director_popScene); 369 370 this._scenesStack.pop(); 371 var c = this._scenesStack.length; 372 373 if (c === 0) 374 this.end(); 375 else { 376 this._sendCleanupToScene = true; 377 this._nextScene = this._scenesStack[c - 1]; 378 } 379 }, 380 381 /** 382 * Removes cached all cocos2d cached data. It will purge the cc.textureCache, cc.spriteFrameCache, cc.animationCache 383 */ 384 purgeCachedData: function () { 385 cc.animationCache._clear(); 386 cc.spriteFrameCache._clear(); 387 cc.textureCache._clear(); 388 }, 389 390 /** 391 * Purge the cc.director itself, including unschedule all schedule, remove all event listeners, clean up and exit the running scene, stops all animations, clear cached data. 392 */ 393 purgeDirector: function () { 394 //cleanup scheduler 395 this.getScheduler().unscheduleAll(); 396 397 // Disable event dispatching 398 if (cc.eventManager) 399 cc.eventManager.setEnabled(false); 400 401 // don't release the event handlers 402 // They are needed in case the director is run again 403 404 if (this._runningScene) { 405 this._runningScene.onExitTransitionDidStart(); 406 this._runningScene.onExit(); 407 this._runningScene.cleanup(); 408 } 409 410 this._runningScene = null; 411 this._nextScene = null; 412 413 // remove all objects, but don't release it. 414 // runScene might be executed after 'end'. 415 this._scenesStack.length = 0; 416 417 this.stopAnimation(); 418 419 // Clear all caches 420 this.purgeCachedData(); 421 422 cc.checkGLErrorDebug(); 423 }, 424 425 /** 426 * Suspends the execution of the running scene, pushing it on the stack of suspended scenes.<br/> 427 * The new scene will be executed.<br/> 428 * Try to avoid big stacks of pushed scenes to reduce memory allocation.<br/> 429 * ONLY call it if there is a running scene. 430 * @param {cc.Scene} scene 431 */ 432 pushScene: function (scene) { 433 434 cc.assert(scene, cc._LogInfos.Director_pushScene); 435 436 this._sendCleanupToScene = false; 437 438 this._scenesStack.push(scene); 439 this._nextScene = scene; 440 }, 441 442 /** 443 * Run a scene. Replaces the running scene with a new one or enter the first scene. 444 * @param {cc.Scene} scene 445 */ 446 runScene: function (scene) { 447 448 cc.assert(scene, cc._LogInfos.Director_pushScene); 449 450 if (!this._runningScene) { 451 //start scene 452 this.pushScene(scene); 453 this.startAnimation(); 454 } else { 455 //replace scene 456 var i = this._scenesStack.length; 457 if (i === 0) { 458 this._sendCleanupToScene = true; 459 this._scenesStack[i] = scene; 460 this._nextScene = scene; 461 } else { 462 this._sendCleanupToScene = true; 463 this._scenesStack[i - 1] = scene; 464 this._nextScene = scene; 465 } 466 } 467 }, 468 469 /** 470 * Resume director after pause, if the current scene is not paused, nothing will happen. 471 */ 472 resume: function () { 473 if (!this._paused) { 474 return; 475 } 476 477 this.setAnimationInterval(this._oldAnimationInterval); 478 this._lastUpdate = Date.now(); 479 if (!this._lastUpdate) { 480 cc.log(cc._LogInfos.Director_resume); 481 } 482 483 this._paused = false; 484 this._deltaTime = 0; 485 }, 486 487 /** 488 * The size in pixels of the surface. It could be different than the screen size.<br/> 489 * High-res devices might have a higher surface size than the screen size. 490 * @param {Number} scaleFactor 491 */ 492 setContentScaleFactor: function (scaleFactor) { 493 if (scaleFactor !== this._contentScaleFactor) { 494 this._contentScaleFactor = scaleFactor; 495 this._createStatsLabel(); 496 } 497 }, 498 499 /** 500 * Enables or disables WebGL depth test.<br/> 501 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js 502 * @function 503 * @param {Boolean} on 504 */ 505 setDepthTest: null, 506 507 /** 508 * set color for clear screen.<br/> 509 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js 510 * @function 511 * @param {cc.color} clearColor 512 */ 513 setClearColor: null, 514 /** 515 * Sets the default values based on the CCConfiguration info 516 */ 517 setDefaultValues: function () { 518 519 }, 520 521 /** 522 * Sets whether next delta time equals to zero 523 * @param {Boolean} nextDeltaTimeZero 524 */ 525 setNextDeltaTimeZero: function (nextDeltaTimeZero) { 526 this._nextDeltaTimeZero = nextDeltaTimeZero; 527 }, 528 529 /** 530 * Starts the registered next scene 531 */ 532 setNextScene: function () { 533 var runningIsTransition = false, newIsTransition = false; 534 if (cc.TransitionScene) { 535 runningIsTransition = this._runningScene ? this._runningScene instanceof cc.TransitionScene : false; 536 newIsTransition = this._nextScene ? this._nextScene instanceof cc.TransitionScene : false; 537 } 538 539 // If it is not a transition, call onExit/cleanup 540 if (!newIsTransition) { 541 var locRunningScene = this._runningScene; 542 if (locRunningScene) { 543 locRunningScene.onExitTransitionDidStart(); 544 locRunningScene.onExit(); 545 } 546 547 // issue #709. the root node (scene) should receive the cleanup message too 548 // otherwise it might be leaked. 549 if (this._sendCleanupToScene && locRunningScene) 550 locRunningScene.cleanup(); 551 } 552 553 this._runningScene = this._nextScene; 554 cc.renderer.childrenOrderDirty = true; 555 556 this._nextScene = null; 557 if ((!runningIsTransition) && (this._runningScene !== null)) { 558 this._runningScene.onEnter(); 559 this._runningScene.onEnterTransitionDidFinish(); 560 } 561 }, 562 563 /** 564 * Sets Notification Node 565 * @param {cc.Node} node 566 */ 567 setNotificationNode: function (node) { 568 this._notificationNode = node; 569 if(!node) 570 cc.renderer.childrenOrderDirty = true; 571 }, 572 573 /** 574 * Returns the cc.director delegate. 575 * @return {cc.DirectorDelegate} 576 */ 577 getDelegate: function () { 578 return this._projectionDelegate; 579 }, 580 581 /** 582 * Sets the cc.director delegate. It shall implement the CCDirectorDelegate protocol 583 * @return {cc.DirectorDelegate} 584 */ 585 setDelegate: function (delegate) { 586 this._projectionDelegate = delegate; 587 }, 588 589 /** 590 * Sets the view, where everything is rendered, do not call this function.<br/> 591 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js. 592 * @function 593 * @param {cc.view} openGLView 594 */ 595 setOpenGLView: null, 596 597 /** 598 * Sets an OpenGL projection.<br/> 599 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js. 600 * @function 601 * @param {Number} projection 602 */ 603 setProjection: null, 604 605 /** 606 * Update the view port.<br/> 607 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js. 608 * @function 609 */ 610 setViewport: null, 611 612 /** 613 * Get the CCEGLView, where everything is rendered.<br/> 614 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js. 615 * @function 616 * @return {cc.view} 617 */ 618 getOpenGLView: null, 619 620 /** 621 * Sets an OpenGL projection.<br/> 622 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js. 623 * @function 624 * @return {Number} 625 */ 626 getProjection: null, 627 628 /** 629 * Enables/disables OpenGL alpha blending.<br/> 630 * Implementation can be found in CCDirectorCanvas.js/CCDirectorWebGL.js. 631 * @function 632 * @param {Boolean} on 633 */ 634 setAlphaBlending: null, 635 636 _showStats: function () { 637 this._frames++; 638 this._accumDt += this._deltaTime; 639 if (this._FPSLabel && this._SPFLabel && this._drawsLabel) { 640 if (this._accumDt > cc.DIRECTOR_FPS_INTERVAL) { 641 this._SPFLabel.string = this._secondsPerFrame.toFixed(3); 642 643 this._frameRate = this._frames / this._accumDt; 644 this._frames = 0; 645 this._accumDt = 0; 646 647 this._FPSLabel.string = this._frameRate.toFixed(1); 648 this._drawsLabel.string = (0 | cc.g_NumberOfDraws).toString(); 649 } 650 this._FPSLabel.visit(); 651 this._SPFLabel.visit(); 652 this._drawsLabel.visit(); 653 } else 654 this._createStatsLabel(); 655 cc.g_NumberOfDraws = 0; 656 }, 657 658 /** 659 * Returns whether or not the replaced scene will receive the cleanup message.<br> 660 * If the new scene is pushed, then the old scene won't receive the "cleanup" message.<br/> 661 * If the new scene replaces the old one, the it will receive the "cleanup" message. 662 * @return {Boolean} 663 */ 664 isSendCleanupToScene: function () { 665 return this._sendCleanupToScene; 666 }, 667 668 /** 669 * Returns current running Scene. Director can only run one Scene at the time 670 * @return {cc.Scene} 671 */ 672 getRunningScene: function () { 673 return this._runningScene; 674 }, 675 676 /** 677 * Returns the FPS value 678 * @return {Number} 679 */ 680 getAnimationInterval: function () { 681 return this._animationInterval; 682 }, 683 684 /** 685 * Returns whether or not to display the FPS informations 686 * @return {Boolean} 687 */ 688 isDisplayStats: function () { 689 return this._displayStats; 690 }, 691 692 /** 693 * Sets whether display the FPS on the bottom-left corner 694 * @param {Boolean} displayStats 695 */ 696 setDisplayStats: function (displayStats) { 697 this._displayStats = displayStats; 698 }, 699 700 /** 701 * Returns seconds per frame 702 * @return {Number} 703 */ 704 getSecondsPerFrame: function () { 705 return this._secondsPerFrame; 706 }, 707 708 /** 709 * Returns whether next delta time equals to zero 710 * @return {Boolean} 711 */ 712 isNextDeltaTimeZero: function () { 713 return this._nextDeltaTimeZero; 714 }, 715 716 /** 717 * Returns whether or not the Director is paused 718 * @return {Boolean} 719 */ 720 isPaused: function () { 721 return this._paused; 722 }, 723 724 /** 725 * Returns how many frames were called since the director started 726 * @return {Number} 727 */ 728 getTotalFrames: function () { 729 return this._totalFrames; 730 }, 731 732 /** 733 * Pops out all scenes from the queue until the root scene in the queue. <br/> 734 * This scene will replace the running one. <br/> 735 * Internally it will call "popToSceneStackLevel(1)" 736 */ 737 popToRootScene: function () { 738 this.popToSceneStackLevel(1); 739 }, 740 741 /** 742 * Pops out all scenes from the queue until it reaches "level". <br/> 743 * If level is 0, it will end the director. <br/> 744 * If level is 1, it will pop all scenes until it reaches to root scene. <br/> 745 * If level is <= than the current stack level, it won't do anything. 746 * @param {Number} level 747 */ 748 popToSceneStackLevel: function (level) { 749 cc.assert(this._runningScene, cc._LogInfos.Director_popToSceneStackLevel_2); 750 751 var locScenesStack = this._scenesStack; 752 var c = locScenesStack.length; 753 754 if (c === 0) { 755 this.end(); 756 return; 757 } 758 // current level or lower -> nothing 759 if (level > c) 760 return; 761 762 // pop stack until reaching desired level 763 while (c > level) { 764 var current = locScenesStack.pop(); 765 if (current.running) { 766 current.onExitTransitionDidStart(); 767 current.onExit(); 768 } 769 current.cleanup(); 770 c--; 771 } 772 this._nextScene = locScenesStack[locScenesStack.length - 1]; 773 this._sendCleanupToScene = false; 774 }, 775 776 /** 777 * Returns the cc.Scheduler associated with this director 778 * @return {cc.Scheduler} 779 */ 780 getScheduler: function () { 781 return this._scheduler; 782 }, 783 784 /** 785 * Sets the cc.Scheduler associated with this director 786 * @param {cc.Scheduler} scheduler 787 */ 788 setScheduler: function (scheduler) { 789 if (this._scheduler !== scheduler) { 790 this._scheduler = scheduler; 791 } 792 }, 793 794 /** 795 * Returns the cc.ActionManager associated with this director 796 * @return {cc.ActionManager} 797 */ 798 getActionManager: function () { 799 return this._actionManager; 800 }, 801 /** 802 * Sets the cc.ActionManager associated with this director 803 * @param {cc.ActionManager} actionManager 804 */ 805 setActionManager: function (actionManager) { 806 if (this._actionManager !== actionManager) { 807 this._actionManager = actionManager; 808 } 809 }, 810 811 /** 812 * Returns the delta time since last frame 813 * @return {Number} 814 */ 815 getDeltaTime: function () { 816 return this._deltaTime; 817 }, 818 819 _createStatsLabel: null, 820 821 _calculateMPF: function () { 822 var now = Date.now(); 823 this._secondsPerFrame = (now - this._lastUpdate) / 1000; 824 } 825 }); 826 827 /** 828 * The event projection changed of cc.Director 829 * @constant 830 * @type {string} 831 * @example 832 * cc.eventManager.addCustomListener(cc.Director.EVENT_PROJECTION_CHANGED, function(event) { 833 * cc.log("Projection changed."); 834 * }); 835 */ 836 cc.Director.EVENT_PROJECTION_CHANGED = "director_projection_changed"; 837 838 /** 839 * The event after draw of cc.Director 840 * @constant 841 * @type {string} 842 * @example 843 * cc.eventManager.addCustomListener(cc.Director.EVENT_AFTER_DRAW, function(event) { 844 * cc.log("after draw event."); 845 * }); 846 */ 847 cc.Director.EVENT_AFTER_DRAW = "director_after_draw"; 848 849 /** 850 * The event after visit of cc.Director 851 * @constant 852 * @type {string} 853 * @example 854 * cc.eventManager.addCustomListener(cc.Director.EVENT_AFTER_VISIT, function(event) { 855 * cc.log("after visit event."); 856 * }); 857 */ 858 cc.Director.EVENT_AFTER_VISIT = "director_after_visit"; 859 860 /** 861 * The event after update of cc.Director 862 * @constant 863 * @type {string} 864 * @example 865 * cc.eventManager.addCustomListener(cc.Director.EVENT_AFTER_UPDATE, function(event) { 866 * cc.log("after update event."); 867 * }); 868 */ 869 cc.Director.EVENT_AFTER_UPDATE = "director_after_update"; 870 871 /*************************************************** 872 * implementation of DisplayLinkDirector 873 **************************************************/ 874 cc.DisplayLinkDirector = cc.Director.extend(/** @lends cc.Director# */{ 875 invalid: false, 876 877 /** 878 * Starts Animation 879 */ 880 startAnimation: function () { 881 this._nextDeltaTimeZero = true; 882 this.invalid = false; 883 }, 884 885 /** 886 * Run main loop of director 887 */ 888 mainLoop: function () { 889 if (this._purgeDirectorInNextLoop) { 890 this._purgeDirectorInNextLoop = false; 891 this.purgeDirector(); 892 } 893 else if (!this.invalid) { 894 this.drawScene(); 895 } 896 }, 897 898 /** 899 * Stops animation 900 */ 901 stopAnimation: function () { 902 this.invalid = true; 903 }, 904 905 /** 906 * Sets animation interval 907 * @param {Number} value the animation interval desired 908 */ 909 setAnimationInterval: function (value) { 910 this._animationInterval = value; 911 if (!this.invalid) { 912 this.stopAnimation(); 913 this.startAnimation(); 914 } 915 } 916 }); 917 918 cc.Director.sharedDirector = null; 919 cc.Director.firstUseDirector = true; 920 921 cc.Director._getInstance = function () { 922 if (cc.Director.firstUseDirector) { 923 cc.Director.firstUseDirector = false; 924 cc.Director.sharedDirector = new cc.DisplayLinkDirector(); 925 cc.Director.sharedDirector.init(); 926 } 927 return cc.Director.sharedDirector; 928 }; 929 930 /** 931 * Default fps is 60 932 * @type {Number} 933 */ 934 cc.defaultFPS = 60; 935 936 //Possible OpenGL projections used by director 937 /** 938 * Constant for 2D projection (orthogonal projection) 939 * @constant 940 * @type {Number} 941 */ 942 cc.Director.PROJECTION_2D = 0; 943 944 /** 945 * Constant for 3D projection with a fovy=60, znear=0.5f and zfar=1500. 946 * @constant 947 * @type {Number} 948 */ 949 cc.Director.PROJECTION_3D = 1; 950 951 /** 952 * Constant for custom projection, if cc.Director's projection set to it, it calls "updateProjection" on the projection delegate. 953 * @constant 954 * @type {Number} 955 */ 956 cc.Director.PROJECTION_CUSTOM = 3; 957 958 /** 959 * Constant for default projection of cc.Director, default projection is 3D projection 960 * @constant 961 * @type {Number} 962 */ 963 cc.Director.PROJECTION_DEFAULT = cc.Director.PROJECTION_3D;