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 === 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 575 cc.assert(target, cc._LogInfos.Scheduler_scheduleCallbackForTarget_3); 576 if(isSelector === false) 577 cc.assert(key, "key should not be empty!"); 578 579 var element = this._hashForTimers[target.__instanceId]; 580 581 if(!element){ 582 // Is this the 1st element ? Then set the pause level to all the callback_fns of this target 583 element = new cc.HashTimerEntry(null, target, 0, null, null, paused, null); 584 this._arrayForTimers.push(element); 585 this._hashForTimers[target.__instanceId] = element; 586 }else{ 587 cc.assert(element.paused === paused, ""); 588 } 589 590 var timer, i; 591 if (element.timers == null) { 592 element.timers = []; 593 } else if(isSelector === false) { 594 for (i = 0; i < element.timers.length; i++) { 595 timer = element.timers[i]; 596 if (callback === timer._callback) { 597 cc.log(cc._LogInfos.Scheduler_scheduleCallbackForTarget, timer.getInterval().toFixed(4), interval.toFixed(4)); 598 timer._interval = interval; 599 return; 600 } 601 } 602 }else{ 603 for (i = 0; i < element.timers.length; ++i){ 604 timer =element.timers[i]; 605 if (timer && selector === timer.getSelector()){ 606 cc.log("CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f", timer.getInterval(), interval); 607 timer.setInterval(interval); 608 return; 609 } 610 } 611 //ccArrayEnsureExtraCapacity(element->timers, 1); 612 } 613 614 if(isSelector === false){ 615 timer = new cc.TimerTargetCallback(); 616 timer.initWithCallback(this, callback, target, key, interval, repeat, delay); 617 element.timers.push(timer); 618 }else{ 619 timer = new cc.TimerTargetSelector(); 620 timer.initWithSelector(this, selector, target, interval, repeat, delay); 621 element.timers.push(timer); 622 } 623 }, 624 625 scheduleUpdate: function(target, priority, paused){ 626 this._schedulePerFrame(function(dt){ 627 target.update(dt); 628 }, target, priority, paused); 629 }, 630 631 _getUnscheduleMark: function(key, timer){ 632 //key, callback, selector 633 switch (typeof key){ 634 case "number": 635 case "string": 636 return key === timer.getKey(); 637 case "function": 638 return key === timer._callback; 639 default: 640 return key === timer.getSelector(); 641 } 642 }, 643 unschedule: function(key, target){ 644 //key, target 645 //selector, target 646 //callback, target - This is in order to increase compatibility 647 648 // explicity handle nil arguments when removing an object 649 if (!target || !key) 650 return; 651 652 var self = this, element = self._hashForTimers[target.__instanceId]; 653 if (element) { 654 var timers = element.timers; 655 for(var i = 0, li = timers.length; i < li; i++){ 656 var timer = timers[i]; 657 if (this._getUnscheduleMark(key, timer)) { 658 if ((timer === element.currentTimer) && (!element.currentTimerSalvaged)) { 659 element.currentTimerSalvaged = true; 660 } 661 timers.splice(i, 1); 662 //update timerIndex in case we are in tick;, looping over the actions 663 if (element.timerIndex >= i) { 664 element.timerIndex--; 665 } 666 667 if (timers.length === 0) { 668 if (self._currentTarget === element) { 669 self._currentTargetSalvaged = true; 670 } else { 671 self._removeHashElement(element); 672 } 673 } 674 return; 675 } 676 } 677 } 678 }, 679 680 unscheduleUpdate: function(target){ 681 if (target == null) 682 return; 683 684 var element = this._hashForUpdates[target.__instanceId]; 685 686 if (element){ 687 if (this._updateHashLocked){ 688 element.entry.markedForDeletion = true; 689 }else{ 690 this._removeUpdateFromHash(element.entry); 691 } 692 } 693 }, 694 695 unscheduleAllForTarget: function(target){ 696 // explicit nullptr handling 697 if (target == null){ 698 return; 699 } 700 701 // Custom Selectors 702 var element = this._hashForTimers[target.__instanceId]; 703 704 if (element){ 705 if (element.timers.indexOf(element.currentTimer) > -1 706 && (! element.currentTimerSalvaged)){ 707 element.currentTimerSalvaged = true; 708 } 709 // ccArrayRemoveAllObjects(element.timers); 710 element.timers.length = 0; 711 712 if (this._currentTarget === element){ 713 this._currentTargetSalvaged = true; 714 }else{ 715 this._removeHashElement(element); 716 } 717 } 718 719 // update selector 720 this.unscheduleUpdate(target); 721 }, 722 723 unscheduleAll: function(){ 724 this.unscheduleAllWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM); 725 }, 726 727 unscheduleAllWithMinPriority: function(minPriority){ 728 // Custom Selectors 729 var i, element, arr = this._arrayForTimers; 730 for(i=arr.length-1; i>=0; i--){ 731 element = arr[i]; 732 this.unscheduleAllForTarget(element.target); 733 } 734 735 // Updates selectors 736 var entry; 737 var temp_length = 0; 738 if(minPriority < 0){ 739 for(i=0; i<this._updatesNegList.length; ){ 740 temp_length = this._updatesNegList.length; 741 entry = this._updatesNegList[i]; 742 if(entry && entry.priority >= minPriority) 743 this.unscheduleUpdate(entry.target); 744 if (temp_length == this._updatesNegList.length) 745 i++; 746 } 747 } 748 749 if(minPriority <= 0){ 750 for(i=0; i<this._updates0List.length; ){ 751 temp_length = this._updates0List.length; 752 entry = this._updates0List[i]; 753 if (entry) 754 this.unscheduleUpdate(entry.target); 755 if (temp_length == this._updates0List.length) 756 i++; 757 } 758 } 759 760 for(i=0; i<this._updatesPosList.length; ){ 761 temp_length = this._updatesPosList.length; 762 entry = this._updatesPosList[i]; 763 if(entry && entry.priority >= minPriority) 764 this.unscheduleUpdate(entry.target); 765 if (temp_length == this._updatesPosList.length) 766 i++; 767 } 768 }, 769 770 isScheduled: function(key, target){ 771 //key, target 772 //selector, target 773 cc.assert(key, "Argument key must not be empty"); 774 cc.assert(target, "Argument target must be non-nullptr"); 775 776 var element = this._hashForUpdates[target.__instanceId]; 777 778 if (!element){ 779 return false; 780 } 781 782 if (element.timers == null){ 783 return false; 784 }else{ 785 var timers = element.timers; 786 for (var i = 0; i < timers.length; ++i){ 787 var timer = timers[i]; 788 789 if (key === timer.getKey()){ 790 return true; 791 } 792 } 793 return false; 794 } 795 }, 796 797 /** 798 * <p> 799 * Pause all selectors from all targets.<br/> 800 * You should NEVER call this method, unless you know what you are doing. 801 * </p> 802 */ 803 pauseAllTargets:function () { 804 return this.pauseAllTargetsWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM); 805 }, 806 807 /** 808 * Pause all selectors from all targets with a minimum priority. <br/> 809 * You should only call this with kCCPriorityNonSystemMin or higher. 810 * @param {Number} minPriority 811 */ 812 pauseAllTargetsWithMinPriority:function (minPriority) { 813 var idsWithSelectors = []; 814 815 var self = this, element, locArrayForTimers = self._arrayForTimers; 816 var i, li; 817 // Custom Selectors 818 for(i = 0, li = locArrayForTimers.length; i < li; i++){ 819 element = locArrayForTimers[i]; 820 if (element) { 821 element.paused = true; 822 idsWithSelectors.push(element.target); 823 } 824 } 825 826 var entry; 827 if(minPriority < 0){ 828 for(i=0; i<this._updatesNegList.length; i++){ 829 entry = this._updatesNegList[i]; 830 if (entry) { 831 if(entry.priority >= minPriority){ 832 entry.paused = true; 833 idsWithSelectors.push(entry.target); 834 } 835 } 836 } 837 } 838 839 if(minPriority <= 0){ 840 for(i=0; i<this._updates0List.length; i++){ 841 entry = this._updates0List[i]; 842 if (entry) { 843 entry.paused = true; 844 idsWithSelectors.push(entry.target); 845 } 846 } 847 } 848 849 for(i=0; i<this._updatesPosList.length; i++){ 850 entry = this._updatesPosList[i]; 851 if (entry) { 852 if(entry.priority >= minPriority){ 853 entry.paused = true; 854 idsWithSelectors.push(entry.target); 855 } 856 } 857 } 858 859 return idsWithSelectors; 860 }, 861 862 /** 863 * Resume selectors on a set of targets.<br/> 864 * This can be useful for undoing a call to pauseAllCallbacks. 865 * @param {Array} targetsToResume 866 */ 867 resumeTargets:function (targetsToResume) { 868 if (!targetsToResume) 869 return; 870 871 for (var i = 0; i < targetsToResume.length; i++) { 872 this.resumeTarget(targetsToResume[i]); 873 } 874 }, 875 876 /** 877 * <p> 878 * Pauses the target.<br/> 879 * All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.<br/> 880 * If the target is not present, nothing happens. 881 * </p> 882 * @param {cc.Class} target 883 */ 884 pauseTarget:function (target) { 885 886 cc.assert(target, cc._LogInfos.Scheduler_pauseTarget); 887 888 //customer selectors 889 var self = this, element = self._hashForTimers[target.__instanceId]; 890 if (element) { 891 element.paused = true; 892 } 893 894 //update callback 895 var elementUpdate = self._hashForUpdates[target.__instanceId]; 896 if (elementUpdate) { 897 elementUpdate.entry.paused = true; 898 } 899 }, 900 901 /** 902 * Resumes the target.<br/> 903 * The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again.<br/> 904 * If the target is not present, nothing happens. 905 * @param {cc.Class} target 906 */ 907 resumeTarget:function (target) { 908 909 cc.assert(target, cc._LogInfos.Scheduler_resumeTarget); 910 911 // custom selectors 912 var self = this, element = self._hashForTimers[target.__instanceId]; 913 914 if (element) { 915 element.paused = false; 916 } 917 918 //update callback 919 var elementUpdate = self._hashForUpdates[target.__instanceId]; 920 921 if (elementUpdate) { 922 elementUpdate.entry.paused = false; 923 } 924 }, 925 926 /** 927 * Returns whether or not the target is paused 928 * @param {cc.Class} target 929 * @return {Boolean} 930 */ 931 isTargetPaused:function (target) { 932 933 cc.assert(target, cc._LogInfos.Scheduler_isTargetPaused); 934 935 // Custom selectors 936 var element = this._hashForTimers[target.__instanceId]; 937 if (element) { 938 return element.paused; 939 } 940 var elementUpdate = this._hashForUpdates[target.__instanceId]; 941 if (elementUpdate) { 942 return elementUpdate.entry.paused; 943 } 944 return false; 945 }, 946 947 /** 948 * <p> 949 * Schedules the 'update' callback_fn for a given target with a given priority.<br/> 950 * The 'update' callback_fn will be called every frame.<br/> 951 * The lower the priority, the earlier it is called. 952 * </p> 953 * @deprecated since v3.4 please use .scheduleUpdate 954 * @param {cc.Class} target 955 * @param {Number} priority 956 * @param {Boolean} paused 957 * @example 958 * //register this object to scheduler 959 * cc.director.getScheduler().scheduleUpdateForTarget(this, priority, !this._isRunning ); 960 */ 961 scheduleUpdateForTarget: function(target, priority, paused){ 962 //cc.log("scheduleUpdateForTarget is deprecated. Please use scheduleUpdate."); 963 this.scheduleUpdate(target, priority, paused); 964 }, 965 966 /** 967 * <p> 968 * Unschedule a callback function for a given target.<br/> 969 * If you want to unschedule the "update", use unscheudleUpdateForTarget. 970 * </p> 971 * @deprecated since v3.4 please use .unschedule 972 * @param {cc.Class} target 973 * @param {function} callback callback[Function] or key[String] 974 * @example 975 * //unschedule a callback of target 976 * cc.director.getScheduler().unscheduleCallbackForTarget(function, this); 977 */ 978 unscheduleCallbackForTarget:function (target, callback) { 979 //cc.log("unscheduleCallbackForTarget is deprecated. Please use unschedule."); 980 this.unschedule(callback, target); 981 }, 982 983 /** 984 * Unschedules the update callback function for a given target 985 * @param {cc.Class} target 986 * @deprecated since v3.4 please use .unschedule 987 * @example 988 * //unschedules the "update" method. 989 * cc.director.getScheduler().unscheduleUpdateForTarget(this); 990 */ 991 unscheduleUpdateForTarget:function (target) { 992 //cc.log("unscheduleUpdateForTarget is deprecated. Please use unschedule."); 993 this.unscheduleUpdate(target); 994 }, 995 996 /** 997 * Unschedules all function callbacks for a given target. This also includes the "update" callback function. 998 * @deprecated since v3.4 please use .unscheduleAll 999 * @param {cc.Class} target 1000 */ 1001 unscheduleAllCallbacksForTarget: function(target){ 1002 //cc.log("unscheduleAllCallbacksForTarget is deprecated. Please use unscheduleAll."); 1003 this.unschedule(target.__instanceId + "", target); 1004 }, 1005 1006 /** 1007 * <p> 1008 * Unschedules all function callbacks from all targets. <br/> 1009 * You should NEVER call this method, unless you know what you are doing. 1010 * </p> 1011 * @deprecated since v3.4 please use .unscheduleAllWithMinPriority 1012 */ 1013 unscheduleAllCallbacks: function(){ 1014 //cc.log("unscheduleAllCallbacks is deprecated. Please use unscheduleAll."); 1015 this.unscheduleAllWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM); 1016 }, 1017 1018 /** 1019 * <p> 1020 * Unschedules all function callbacks from all targets with a minimum priority.<br/> 1021 * You should only call this with kCCPriorityNonSystemMin or higher. 1022 * </p> 1023 * @deprecated since v3.4 please use .unscheduleAllWithMinPriority 1024 * @param {Number} minPriority 1025 */ 1026 unscheduleAllCallbacksWithMinPriority:function (minPriority) { 1027 //cc.log("unscheduleAllCallbacksWithMinPriority is deprecated. Please use unscheduleAllWithMinPriority."); 1028 this.unscheduleAllWithMinPriority(minPriority); 1029 } 1030 }); 1031 /** 1032 * Priority level reserved for system services. 1033 * @constant 1034 * @type Number 1035 */ 1036 cc.Scheduler.PRIORITY_SYSTEM = (-2147483647 - 1); 1037