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