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 28 /** 29 * Minimum priority level for user scheduling. 30 * @constant 31 * @type Number 32 */ 33 cc.PRIORITY_NON_SYSTEM = cc.PRIORITY_SYSTEM + 1; 34 35 //data structures 36 /** 37 * A list double-linked list used for "updates with priority" 38 * @Class 39 * @name cc.ListEntry 40 * @param {cc.ListEntry} prev 41 * @param {cc.ListEntry} next 42 * @param {function} callback 43 * @param {cc.Class} target not retained (retained by hashUpdateEntry) 44 * @param {Number} priority 45 * @param {Boolean} paused 46 * @param {Boolean} markedForDeletion selector will no longer be called and entry will be removed at end of the next tick 47 */ 48 cc.ListEntry = function (prev, next, callback, target, priority, paused, markedForDeletion) { 49 this.prev = prev; 50 this.next = next; 51 this.callback = callback; 52 this.target = target; 53 this.priority = priority; 54 this.paused = paused; 55 this.markedForDeletion = markedForDeletion; 56 }; 57 58 /** 59 * A update entry list 60 * @Class 61 * @name cc.HashUpdateEntry 62 * @param {Array} list Which list does it belong to ? 63 * @param {cc.ListEntry} entry entry in the list 64 * @param {cc.Class} target hash key (retained) 65 * @param {function} callback 66 * @param {Array} hh 67 */ 68 cc.HashUpdateEntry = function (list, entry, target, callback, hh) { 69 this.list = list; 70 this.entry = entry; 71 this.target = target; 72 this.callback = callback; 73 this.hh = hh; 74 }; 75 76 // 77 /** 78 * Hash Element used for "selectors with interval" 79 * @Class 80 * @param {Array} timers 81 * @param {cc.Class} target hash key (retained) 82 * @param {Number} timerIndex 83 * @param {cc.Timer} currentTimer 84 * @param {Boolean} currentTimerSalvaged 85 * @param {Boolean} paused 86 * @param {Array} hh 87 */ 88 cc.HashTimerEntry = cc.hashSelectorEntry = function (timers, target, timerIndex, currentTimer, currentTimerSalvaged, paused, hh) { 89 var _t = this; 90 _t.timers = timers; 91 _t.target = target; 92 _t.timerIndex = timerIndex; 93 _t.currentTimer = currentTimer; 94 _t.currentTimerSalvaged = currentTimerSalvaged; 95 _t.paused = paused; 96 _t.hh = hh; 97 }; 98 99 /** 100 * Light weight timer 101 * @class 102 * @extends cc.Class 103 */ 104 cc.Timer = cc.Class.extend(/** @lends cc.Timer# */{ 105 _scheduler: null, 106 _elapsed:0.0, 107 _runForever:false, 108 _useDelay:false, 109 _timesExecuted:0, 110 _repeat:0, //0 = once, 1 is 2 x executed 111 _delay:0, 112 _interval:0.0, 113 114 /** 115 * @return {Number} returns interval of timer 116 */ 117 getInterval : function(){return this._interval;}, 118 /** 119 * @param {Number} interval set interval in seconds 120 */ 121 setInterval : function(interval){this._interval = interval;}, 122 123 setupTimerWithInterval: function(seconds, repeat, delay){ 124 this._elapsed = -1; 125 this._interval = seconds; 126 this._delay = delay; 127 this._useDelay = (this._delay > 0); 128 this._repeat = repeat; 129 this._runForever = (this._repeat === cc.REPEAT_FOREVER); 130 }, 131 132 trigger: function(){ 133 return 0; 134 }, 135 136 cancel: function(){ 137 return 0; 138 }, 139 140 /** 141 * cc.Timer's Constructor 142 * Constructor of cc.Timer 143 */ 144 ctor:function () { 145 this._scheduler = null; 146 this._elapsed = -1; 147 this._runForever = false; 148 this._useDelay = false; 149 this._timesExecuted = 0; 150 this._repeat = 0; 151 this._delay = 0; 152 this._interval = 0; 153 }, 154 155 /** 156 * triggers the timer 157 * @param {Number} dt delta time 158 */ 159 update:function (dt) { 160 if (this._elapsed === -1) { 161 this._elapsed = 0; 162 this._timesExecuted = 0; 163 } else { 164 this._elapsed += dt; 165 if (this._runForever && !this._useDelay) {//standard timer usage 166 if (this._elapsed >= this._interval) { 167 this.trigger(); 168 this._elapsed = 0; 169 } 170 } else {//advanced usage 171 if (this._useDelay) { 172 if (this._elapsed >= this._delay) { 173 this.trigger(); 174 175 this._elapsed -= this._delay; 176 this._timesExecuted += 1; 177 this._useDelay = false; 178 } 179 } else { 180 if (this._elapsed >= this._interval) { 181 this.trigger(); 182 183 this._elapsed = 0; 184 this._timesExecuted += 1; 185 } 186 } 187 188 if (!this._runForever && this._timesExecuted > this._repeat) 189 this.cancel(); 190 } 191 } 192 } 193 }); 194 195 cc.TimerTargetSelector = cc.Timer.extend({ 196 _target: null, 197 _selector: null, 198 199 ctor: function(){ 200 this._target = null; 201 this._selector = null; 202 }, 203 204 initWithSelector: function(scheduler, selector, target, seconds, repeat, delay){ 205 this._scheduler = scheduler; 206 this._target = target; 207 this._selector = selector; 208 this.setupTimerWithInterval(seconds, repeat, delay); 209 return true; 210 }, 211 212 getSelector: function(){ 213 return this._selector; 214 }, 215 216 trigger: function(){ 217 //override 218 if (this._target && this._selector){ 219 this._target.call(this._selector, this._elapsed); 220 } 221 }, 222 223 cancel: function(){ 224 //override 225 this._scheduler.unschedule(this._selector, this._target); 226 } 227 228 }); 229 230 cc.TimerTargetCallback = cc.Timer.extend({ 231 232 _target: null, 233 _callback: null, 234 _key: null, 235 236 ctor: function(){ 237 this._target = null; 238 this._callback = null; 239 }, 240 241 initWithCallback: function(scheduler, callback, target, key, seconds, repeat, delay){ 242 this._scheduler = scheduler; 243 this._target = target; 244 this._callback = callback; 245 this._key = key; 246 this.setupTimerWithInterval(seconds, repeat, delay); 247 return true; 248 }, 249 250 getCallback: function(){ 251 return this._callback; 252 }, 253 254 getKey: function(){ 255 return this._key; 256 }, 257 258 trigger: function(){ 259 //override 260 if(this._callback) 261 this._callback.call(this._target, this._elapsed); 262 }, 263 264 cancel: function(){ 265 //override 266 this._scheduler.unschedule(this._callback, this._target); 267 } 268 269 }); 270 271 /** 272 * <p> 273 * Scheduler is responsible of triggering the scheduled callbacks.<br/> 274 * You should not use NSTimer. Instead use this class.<br/> 275 * <br/> 276 * There are 2 different types of callbacks (selectors):<br/> 277 * - update callback: the 'update' callback will be called every frame. You can customize the priority.<br/> 278 * - custom callback: A custom callback will be called every frame, or with a custom interval of time<br/> 279 * <br/> 280 * The 'custom selectors' should be avoided when possible. It is faster, and consumes less memory to use the 'update callback'. * 281 * </p> 282 * @class 283 * @extends cc.Class 284 * 285 * @example 286 * //register a schedule to scheduler 287 * cc.director.getScheduler().schedule(callback, this, interval, !this._isRunning); 288 */ 289 cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{ 290 _timeScale:1.0, 291 292 //_updates : null, //_updates[0] list of priority < 0, _updates[1] list of priority == 0, _updates[2] list of priority > 0, 293 _updatesNegList: null, 294 _updates0List: null, 295 _updatesPosList: null, 296 297 _hashForTimers:null, //Used for "selectors with interval" 298 _arrayForTimers:null, //Speed up indexing 299 _hashForUpdates:null, // hash used to fetch quickly the list entries for pause,delete,etc 300 //_arrayForUpdates:null, //Speed up indexing 301 302 _currentTarget:null, 303 _currentTargetSalvaged:false, 304 _updateHashLocked:false, //If true unschedule will not remove anything from a hash. Elements will only be marked for deletion. 305 306 307 ctor:function () { 308 this._timeScale = 1.0; 309 this._updatesNegList = []; 310 this._updates0List = []; 311 this._updatesPosList = []; 312 313 this._hashForUpdates = {}; 314 this._hashForTimers = {}; 315 this._currentTarget = null; 316 this._currentTargetSalvaged = false; 317 this._updateHashLocked = false; 318 319 this._arrayForTimers = []; 320 //this._arrayForUpdates = []; 321 322 }, 323 324 //-----------------------private method---------------------- 325 326 _schedulePerFrame: function(callback, target, priority, paused){ 327 var hashElement = this._hashForUpdates[target.__instanceId]; 328 if (hashElement && hashElement.entry){ 329 // check if priority has changed 330 if (hashElement.entry.priority !== priority){ 331 if (this._updateHashLocked){ 332 cc.log("warning: you CANNOT change update priority in scheduled function"); 333 hashElement.entry.markedForDeletion = false; 334 hashElement.entry.paused = paused; 335 return; 336 }else{ 337 // will be added again outside if (hashElement). 338 this.unscheduleUpdate(target); 339 } 340 }else{ 341 hashElement.entry.markedForDeletion = false; 342 hashElement.entry.paused = paused; 343 return; 344 } 345 } 346 347 // most of the updates are going to be 0, that's way there 348 // is an special list for updates with priority 0 349 if (priority === 0){ 350 this._appendIn(this._updates0List, callback, target, paused); 351 }else if (priority < 0){ 352 this._priorityIn(this._updatesNegList, callback, target, priority, paused); 353 }else{ 354 // priority > 0 355 this._priorityIn(this._updatesPosList, callback, target, priority, paused); 356 } 357 }, 358 359 _removeHashElement:function (element) { 360 delete this._hashForTimers[element.target.__instanceId]; 361 cc.arrayRemoveObject(this._arrayForTimers, element); 362 element.Timer = null; 363 element.target = null; 364 element = null; 365 }, 366 367 _removeUpdateFromHash:function (entry) { 368 var self = this, element = self._hashForUpdates[entry.target.__instanceId]; 369 if (element) { 370 //list entry 371 cc.arrayRemoveObject(element.list, element.entry); 372 373 delete self._hashForUpdates[element.target.__instanceId]; 374 //cc.arrayRemoveObject(self._hashForUpdates, element); 375 element.entry = null; 376 377 //hash entry 378 element.target = null; 379 } 380 }, 381 382 _priorityIn:function (ppList, callback, target, priority, paused) { 383 var self = this, 384 listElement = new cc.ListEntry(null, null, callback, target, priority, paused, false); 385 386 // empey list ? 387 if (!ppList) { 388 ppList = []; 389 ppList.push(listElement); 390 } else { 391 var index2Insert = ppList.length - 1; 392 for(var i = 0; i <= index2Insert; i++){ 393 if (priority < ppList[i].priority) { 394 index2Insert = i; 395 break; 396 } 397 } 398 ppList.splice(i, 0, listElement); 399 } 400 401 //update hash entry for quick access 402 self._hashForUpdates[target.__instanceId] = new cc.HashUpdateEntry(ppList, listElement, target, null); 403 404 return ppList; 405 }, 406 407 _appendIn:function (ppList, callback, target, paused) { 408 var self = this, listElement = new cc.ListEntry(null, null, callback, target, 0, paused, false); 409 ppList.push(listElement); 410 411 //update hash entry for quicker access 412 self._hashForUpdates[target.__instanceId] = new cc.HashUpdateEntry(ppList, listElement, target, null, null); 413 }, 414 415 //-----------------------public method------------------------- 416 /** 417 * <p> 418 * Modifies the time of all scheduled callbacks.<br/> 419 * You can use this property to create a 'slow motion' or 'fast forward' effect.<br/> 420 * Default is 1.0. To create a 'slow motion' effect, use values below 1.0.<br/> 421 * To create a 'fast forward' effect, use values higher than 1.0.<br/> 422 * @warning It will affect EVERY scheduled selector / action. 423 * </p> 424 * @param {Number} timeScale 425 */ 426 setTimeScale:function (timeScale) { 427 this._timeScale = timeScale; 428 }, 429 430 /** 431 * Returns time scale of scheduler 432 * @return {Number} 433 */ 434 getTimeScale:function () { 435 return this._timeScale; 436 }, 437 438 /** 439 * 'update' the scheduler. (You should NEVER call this method, unless you know what you are doing.) 440 * @param {Number} dt delta time 441 */ 442 update:function (dt) { 443 this._updateHashLocked = true; 444 if(this._timeScale !== 1) 445 dt *= this._timeScale; 446 447 var i, list, len, entry; 448 449 for(i=0,list=this._updatesNegList, len = list.length; i<len; i++){ 450 entry = list[i]; 451 if(!entry.paused && !entry.markedForDeletion) 452 entry.callback(dt); 453 } 454 455 for(i=0, list=this._updates0List, len=list.length; i<len; i++){ 456 entry = list[i]; 457 if (!entry.paused && !entry.markedForDeletion) 458 entry.callback(dt); 459 } 460 461 for(i=0, list=this._updatesPosList, len=list.length; i<len; i++){ 462 entry = list[i]; 463 if (!entry.paused && !entry.markedForDeletion) 464 entry.callback(dt); 465 } 466 467 // Iterate over all the custom selectors 468 var elt, arr = this._arrayForTimers; 469 for(i=0; i<arr.length; i++){ 470 elt = arr[i]; 471 this._currentTarget = elt; 472 this._currentTargetSalvaged = false; 473 474 if (!elt.paused){ 475 // The 'timers' array may change while inside this loop 476 for (elt.timerIndex = 0; elt.timerIndex < elt.timers.length; ++(elt.timerIndex)){ 477 elt.currentTimer = elt.timers[elt.timerIndex]; 478 elt.currentTimerSalvaged = false; 479 480 elt.currentTimer.update(dt); 481 elt.currentTimer = null; 482 } 483 } 484 485 // elt, at this moment, is still valid 486 // so it is safe to ask this here (issue #490) 487 //elt = elt.hh.next; 488 489 // only delete currentTarget if no actions were scheduled during the cycle (issue #481) 490 if (this._currentTargetSalvaged && this._currentTarget.timers.length === 0) 491 this._removeHashElement(this._currentTarget); 492 } 493 494 // delete all updates that are marked for deletion 495 // updates with priority < 0 496 for(i=0,list=this._updatesNegList; i<list.length; ){ 497 entry = list[i]; 498 if(entry.markedForDeletion) 499 this._removeUpdateFromHash(entry); 500 else 501 i++; 502 } 503 504 for(i=0, list=this._updates0List; i<list.length; ){ 505 entry = list[i]; 506 if (entry.markedForDeletion) 507 this._removeUpdateFromHash(entry); 508 else 509 i++; 510 } 511 512 for(i=0, list=this._updatesPosList; i<list.length; ){ 513 entry = list[i]; 514 if (entry.markedForDeletion) 515 this._removeUpdateFromHash(entry); 516 else 517 i++; 518 } 519 520 this._updateHashLocked = false; 521 this._currentTarget = null; 522 }, 523 524 /** 525 * <p> 526 * The scheduled method will be called every 'interval' seconds.</br> 527 * If paused is YES, then it won't be called until it is resumed.<br/> 528 * If 'interval' is 0, it will be called every frame, but if so, it recommended to use 'scheduleUpdateForTarget:' instead.<br/> 529 * If the callback function is already scheduled, then only the interval parameter will be updated without re-scheduling it again.<br/> 530 * repeat let the action be repeated repeat + 1 times, use cc.REPEAT_FOREVER to let the action run continuously<br/> 531 * delay is the amount of time the action will wait before it'll start<br/> 532 * </p> 533 * @deprecated since v3.4 please use .schedule 534 * @param {cc.Class} target 535 * @param {function} callback_fn 536 * @param {Number} interval 537 * @param {Number} repeat 538 * @param {Number} delay 539 * @param {Boolean} paused 540 * @example 541 * //register a schedule to scheduler 542 * cc.director.getScheduler().scheduleCallbackForTarget(this, function, interval, repeat, delay, !this._isRunning ); 543 */ 544 scheduleCallbackForTarget: function(target, callback_fn, interval, repeat, delay, paused){ 545 //cc.log("scheduleCallbackForTarget is deprecated. Please use schedule."); 546 this.schedule(callback_fn, target, interval, repeat, delay, paused, target.__instanceId + ""); 547 }, 548 549 schedule: function(callback, target, interval, repeat, delay, paused, key){ 550 var isSelector = false; 551 if(typeof callback !== "function"){ 552 var selector = callback; 553 isSelector = true; 554 } 555 556 if(isSelector === false){ 557 //callback, target, interval, repeat, delay, paused, key 558 //callback, target, interval, paused, key 559 if(arguments.length === 4 || arguments.length === 5){ 560 key = delay; 561 paused = repeat; 562 delay = 0; 563 repeat = cc.REPEAT_FOREVER; 564 } 565 }else{ 566 //selector, target, interval, repeat, delay, paused 567 //selector, target, interval, paused 568 if(arguments.length === 4){ 569 paused = repeat; 570 repeat = cc.REPEAT_FOREVER; 571 delay = 0; 572 } 573 } 574 if (key === undefined) { 575 key = target.__instanceId + ""; 576 } 577 578 cc.assert(target, cc._LogInfos.Scheduler_scheduleCallbackForTarget_3); 579 580 var element = this._hashForTimers[target.__instanceId]; 581 582 if(!element){ 583 // Is this the 1st element ? Then set the pause level to all the callback_fns of this target 584 element = new cc.HashTimerEntry(null, target, 0, null, null, paused, null); 585 this._arrayForTimers.push(element); 586 this._hashForTimers[target.__instanceId] = element; 587 }else{ 588 cc.assert(element.paused === paused, ""); 589 } 590 591 var timer, i; 592 if (element.timers == null) { 593 element.timers = []; 594 } else if(isSelector === false) { 595 for (i = 0; i < element.timers.length; i++) { 596 timer = element.timers[i]; 597 if (callback === timer._callback) { 598 cc.log(cc._LogInfos.Scheduler_scheduleCallbackForTarget, timer.getInterval().toFixed(4), interval.toFixed(4)); 599 timer._interval = interval; 600 return; 601 } 602 } 603 }else{ 604 for (i = 0; i < element.timers.length; ++i){ 605 timer =element.timers[i]; 606 if (timer && selector === timer.getSelector()){ 607 cc.log("CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f", timer.getInterval(), interval); 608 timer.setInterval(interval); 609 return; 610 } 611 } 612 //ccArrayEnsureExtraCapacity(element->timers, 1); 613 } 614 615 if(isSelector === false){ 616 timer = new cc.TimerTargetCallback(); 617 timer.initWithCallback(this, callback, target, key, interval, repeat, delay); 618 element.timers.push(timer); 619 }else{ 620 timer = new cc.TimerTargetSelector(); 621 timer.initWithSelector(this, selector, target, interval, repeat, delay); 622 element.timers.push(timer); 623 } 624 }, 625 626 scheduleUpdate: function(target, priority, paused){ 627 this._schedulePerFrame(function(dt){ 628 target.update(dt); 629 }, target, priority, paused); 630 }, 631 632 _getUnscheduleMark: function(key, timer){ 633 //key, callback, selector 634 switch (typeof key){ 635 case "number": 636 case "string": 637 return key === timer.getKey(); 638 case "function": 639 return key === timer._callback; 640 default: 641 return key === timer.getSelector(); 642 } 643 }, 644 unschedule: function(key, target){ 645 //key, target 646 //selector, target 647 //callback, target - This is in order to increase compatibility 648 649 // explicity handle nil arguments when removing an object 650 if (!target || !key) 651 return; 652 653 var self = this, element = self._hashForTimers[target.__instanceId]; 654 if (element) { 655 var timers = element.timers; 656 for(var i = 0, li = timers.length; i < li; i++){ 657 var timer = timers[i]; 658 if (this._getUnscheduleMark(key, timer)) { 659 if ((timer === element.currentTimer) && (!element.currentTimerSalvaged)) { 660 element.currentTimerSalvaged = true; 661 } 662 timers.splice(i, 1); 663 //update timerIndex in case we are in tick;, looping over the actions 664 if (element.timerIndex >= i) { 665 element.timerIndex--; 666 } 667 668 if (timers.length === 0) { 669 if (self._currentTarget === element) { 670 self._currentTargetSalvaged = true; 671 } else { 672 self._removeHashElement(element); 673 } 674 } 675 return; 676 } 677 } 678 } 679 }, 680 681 unscheduleUpdate: function(target){ 682 if (target == null) 683 return; 684 685 var element = this._hashForUpdates[target.__instanceId]; 686 687 if (element){ 688 if (this._updateHashLocked){ 689 element.entry.markedForDeletion = true; 690 }else{ 691 this._removeUpdateFromHash(element.entry); 692 } 693 } 694 }, 695 696 unscheduleAllForTarget: function(target){ 697 // explicit nullptr handling 698 if (target == null){ 699 return; 700 } 701 702 // Custom Selectors 703 var element = this._hashForTimers[target.__instanceId]; 704 705 if (element){ 706 if (element.timers.indexOf(element.currentTimer) > -1 707 && (! element.currentTimerSalvaged)){ 708 element.currentTimerSalvaged = true; 709 } 710 // ccArrayRemoveAllObjects(element.timers); 711 element.timers.length = 0; 712 713 if (this._currentTarget === element){ 714 this._currentTargetSalvaged = true; 715 }else{ 716 this._removeHashElement(element); 717 } 718 } 719 720 // update selector 721 this.unscheduleUpdate(target); 722 }, 723 724 unscheduleAll: function(){ 725 this.unscheduleAllWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM); 726 }, 727 728 unscheduleAllWithMinPriority: function(minPriority){ 729 // Custom Selectors 730 var i, element, arr = this._arrayForTimers; 731 for(i=arr.length-1; i>=0; i--){ 732 element = arr[i]; 733 this.unscheduleAllForTarget(element.target); 734 } 735 736 // Updates selectors 737 var entry; 738 var temp_length = 0; 739 if(minPriority < 0){ 740 for(i=0; i<this._updatesNegList.length; ){ 741 temp_length = this._updatesNegList.length; 742 entry = this._updatesNegList[i]; 743 if(entry && entry.priority >= minPriority) 744 this.unscheduleUpdate(entry.target); 745 if (temp_length == this._updatesNegList.length) 746 i++; 747 } 748 } 749 750 if(minPriority <= 0){ 751 for(i=0; i<this._updates0List.length; ){ 752 temp_length = this._updates0List.length; 753 entry = this._updates0List[i]; 754 if (entry) 755 this.unscheduleUpdate(entry.target); 756 if (temp_length == this._updates0List.length) 757 i++; 758 } 759 } 760 761 for(i=0; i<this._updatesPosList.length; ){ 762 temp_length = this._updatesPosList.length; 763 entry = this._updatesPosList[i]; 764 if(entry && entry.priority >= minPriority) 765 this.unscheduleUpdate(entry.target); 766 if (temp_length == this._updatesPosList.length) 767 i++; 768 } 769 }, 770 771 isScheduled: function(key, target){ 772 //key, target 773 //selector, target 774 cc.assert(key, "Argument key must not be empty"); 775 cc.assert(target, "Argument target must be non-nullptr"); 776 777 var element = this._hashForUpdates[target.__instanceId]; 778 779 if (!element){ 780 return false; 781 } 782 783 if (element.timers == null){ 784 return false; 785 }else{ 786 var timers = element.timers; 787 for (var i = 0; i < timers.length; ++i){ 788 var timer = timers[i]; 789 790 if (key === timer.getKey()){ 791 return true; 792 } 793 } 794 return false; 795 } 796 }, 797 798 /** 799 * <p> 800 * Pause all selectors from all targets.<br/> 801 * You should NEVER call this method, unless you know what you are doing. 802 * </p> 803 */ 804 pauseAllTargets:function () { 805 return this.pauseAllTargetsWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM); 806 }, 807 808 /** 809 * Pause all selectors from all targets with a minimum priority. <br/> 810 * You should only call this with kCCPriorityNonSystemMin or higher. 811 * @param {Number} minPriority 812 */ 813 pauseAllTargetsWithMinPriority:function (minPriority) { 814 var idsWithSelectors = []; 815 816 var self = this, element, locArrayForTimers = self._arrayForTimers; 817 var i, li; 818 // Custom Selectors 819 for(i = 0, li = locArrayForTimers.length; i < li; i++){ 820 element = locArrayForTimers[i]; 821 if (element) { 822 element.paused = true; 823 idsWithSelectors.push(element.target); 824 } 825 } 826 827 var entry; 828 if(minPriority < 0){ 829 for(i=0; i<this._updatesNegList.length; i++){ 830 entry = this._updatesNegList[i]; 831 if (entry) { 832 if(entry.priority >= minPriority){ 833 entry.paused = true; 834 idsWithSelectors.push(entry.target); 835 } 836 } 837 } 838 } 839 840 if(minPriority <= 0){ 841 for(i=0; i<this._updates0List.length; i++){ 842 entry = this._updates0List[i]; 843 if (entry) { 844 entry.paused = true; 845 idsWithSelectors.push(entry.target); 846 } 847 } 848 } 849 850 for(i=0; i<this._updatesPosList.length; i++){ 851 entry = this._updatesPosList[i]; 852 if (entry) { 853 if(entry.priority >= minPriority){ 854 entry.paused = true; 855 idsWithSelectors.push(entry.target); 856 } 857 } 858 } 859 860 return idsWithSelectors; 861 }, 862 863 /** 864 * Resume selectors on a set of targets.<br/> 865 * This can be useful for undoing a call to pauseAllCallbacks. 866 * @param {Array} targetsToResume 867 */ 868 resumeTargets:function (targetsToResume) { 869 if (!targetsToResume) 870 return; 871 872 for (var i = 0; i < targetsToResume.length; i++) { 873 this.resumeTarget(targetsToResume[i]); 874 } 875 }, 876 877 /** 878 * <p> 879 * Pauses the target.<br/> 880 * All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.<br/> 881 * If the target is not present, nothing happens. 882 * </p> 883 * @param {cc.Class} target 884 */ 885 pauseTarget:function (target) { 886 887 cc.assert(target, cc._LogInfos.Scheduler_pauseTarget); 888 889 //customer selectors 890 var self = this, element = self._hashForTimers[target.__instanceId]; 891 if (element) { 892 element.paused = true; 893 } 894 895 //update callback 896 var elementUpdate = self._hashForUpdates[target.__instanceId]; 897 if (elementUpdate) { 898 elementUpdate.entry.paused = true; 899 } 900 }, 901 902 /** 903 * Resumes the target.<br/> 904 * The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again.<br/> 905 * If the target is not present, nothing happens. 906 * @param {cc.Class} target 907 */ 908 resumeTarget:function (target) { 909 910 cc.assert(target, cc._LogInfos.Scheduler_resumeTarget); 911 912 // custom selectors 913 var self = this, element = self._hashForTimers[target.__instanceId]; 914 915 if (element) { 916 element.paused = false; 917 } 918 919 //update callback 920 var elementUpdate = self._hashForUpdates[target.__instanceId]; 921 922 if (elementUpdate) { 923 elementUpdate.entry.paused = false; 924 } 925 }, 926 927 /** 928 * Returns whether or not the target is paused 929 * @param {cc.Class} target 930 * @return {Boolean} 931 */ 932 isTargetPaused:function (target) { 933 934 cc.assert(target, cc._LogInfos.Scheduler_isTargetPaused); 935 936 // Custom selectors 937 var element = this._hashForTimers[target.__instanceId]; 938 if (element) { 939 return element.paused; 940 } 941 var elementUpdate = this._hashForUpdates[target.__instanceId]; 942 if (elementUpdate) { 943 return elementUpdate.entry.paused; 944 } 945 return false; 946 }, 947 948 /** 949 * <p> 950 * Schedules the 'update' callback_fn for a given target with a given priority.<br/> 951 * The 'update' callback_fn will be called every frame.<br/> 952 * The lower the priority, the earlier it is called. 953 * </p> 954 * @deprecated since v3.4 please use .scheduleUpdate 955 * @param {cc.Class} target 956 * @param {Number} priority 957 * @param {Boolean} paused 958 * @example 959 * //register this object to scheduler 960 * cc.director.getScheduler().scheduleUpdateForTarget(this, priority, !this._isRunning ); 961 */ 962 scheduleUpdateForTarget: function(target, priority, paused){ 963 //cc.log("scheduleUpdateForTarget is deprecated. Please use scheduleUpdate."); 964 this.scheduleUpdate(target, priority, paused); 965 }, 966 967 /** 968 * <p> 969 * Unschedule a callback function for a given target.<br/> 970 * If you want to unschedule the "update", use unscheudleUpdateForTarget. 971 * </p> 972 * @deprecated since v3.4 please use .unschedule 973 * @param {cc.Class} target 974 * @param {function} callback callback[Function] or key[String] 975 * @example 976 * //unschedule a callback of target 977 * cc.director.getScheduler().unscheduleCallbackForTarget(function, this); 978 */ 979 unscheduleCallbackForTarget:function (target, callback) { 980 //cc.log("unscheduleCallbackForTarget is deprecated. Please use unschedule."); 981 this.unschedule(callback, target); 982 }, 983 984 /** 985 * Unschedules the update callback function for a given target 986 * @param {cc.Class} target 987 * @deprecated since v3.4 please use .unschedule 988 * @example 989 * //unschedules the "update" method. 990 * cc.director.getScheduler().unscheduleUpdateForTarget(this); 991 */ 992 unscheduleUpdateForTarget:function (target) { 993 //cc.log("unscheduleUpdateForTarget is deprecated. Please use unschedule."); 994 this.unscheduleUpdate(target); 995 }, 996 997 /** 998 * Unschedules all function callbacks for a given target. This also includes the "update" callback function. 999 * @deprecated since v3.4 please use .unscheduleAll 1000 * @param {cc.Class} target 1001 */ 1002 unscheduleAllCallbacksForTarget: function(target){ 1003 //cc.log("unscheduleAllCallbacksForTarget is deprecated. Please use unscheduleAll."); 1004 this.unschedule(target.__instanceId + "", target); 1005 }, 1006 1007 /** 1008 * <p> 1009 * Unschedules all function callbacks from all targets. <br/> 1010 * You should NEVER call this method, unless you know what you are doing. 1011 * </p> 1012 * @deprecated since v3.4 please use .unscheduleAllWithMinPriority 1013 */ 1014 unscheduleAllCallbacks: function(){ 1015 //cc.log("unscheduleAllCallbacks is deprecated. Please use unscheduleAll."); 1016 this.unscheduleAllWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM); 1017 }, 1018 1019 /** 1020 * <p> 1021 * Unschedules all function callbacks from all targets with a minimum priority.<br/> 1022 * You should only call this with kCCPriorityNonSystemMin or higher. 1023 * </p> 1024 * @deprecated since v3.4 please use .unscheduleAllWithMinPriority 1025 * @param {Number} minPriority 1026 */ 1027 unscheduleAllCallbacksWithMinPriority:function (minPriority) { 1028 //cc.log("unscheduleAllCallbacksWithMinPriority is deprecated. Please use unscheduleAllWithMinPriority."); 1029 this.unscheduleAllWithMinPriority(minPriority); 1030 } 1031 }); 1032 /** 1033 * Priority level reserved for system services. 1034 * @constant 1035 * @type Number 1036 */ 1037 cc.Scheduler.PRIORITY_SYSTEM = (-2147483647 - 1); 1038