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 {cc.Class} target not retained (retained by hashUpdateEntry)
 43  * @param {Number} priority
 44  * @param {Boolean} paused
 45  * @param {Boolean} markedForDeletion selector will no longer be called and entry will be removed at end of the next tick
 46  */
 47 cc.ListEntry = function (prev, next, target, priority, paused, markedForDeletion) {
 48     this.prev = prev;
 49     this.next = next;
 50     this.target = target;
 51     this.priority = priority;
 52     this.paused = paused;
 53     this.markedForDeletion = markedForDeletion;
 54 };
 55 
 56 /**
 57  * A update entry list
 58  * @Class
 59  * @name cc.HashUpdateEntry
 60  * @param {cc.ListEntry} list Which list does it belong to ?
 61  * @param {cc.ListEntry} entry entry in the list
 62  * @param {cc.Class} target hash key (retained)
 63  * @param {Array} hh
 64  */
 65 cc.HashUpdateEntry = function (list, entry, target, hh) {
 66     this.list = list;
 67     this.entry = entry;
 68     this.target = target;
 69     this.hh = hh;
 70 };
 71 
 72 //
 73 /**
 74  * Hash Element used for "selectors with interval"
 75  * @Class
 76  * @param {Array} timers
 77  * @param {cc.Class} target  hash key (retained)
 78  * @param {Number} timerIndex
 79  * @param {cc.Timer} currentTimer
 80  * @param {Boolean} currentTimerSalvaged
 81  * @param {Boolean} paused
 82  * @param {Array} hh
 83  */
 84 cc.HashTimerEntry = function (timers, target, timerIndex, currentTimer, currentTimerSalvaged, paused, hh) {
 85     var _t = this;
 86     _t.timers = timers;
 87     _t.target = target;
 88     _t.timerIndex = timerIndex;
 89     _t.currentTimer = currentTimer;
 90     _t.currentTimerSalvaged = currentTimerSalvaged;
 91     _t.paused = paused;
 92     _t.hh = hh;
 93 };
 94 
 95 /**
 96  * Light weight timer
 97  * @class
 98  * @extends cc.Class
 99  */
100 cc.Timer = cc.Class.extend(/** @lends cc.Timer# */{
101     _interval:0.0,
102     _callback:null,//is called _callback before
103 
104     _target:null,//target of _callback
105     _elapsed:0.0,
106 
107     _runForever:false,
108     _useDelay:false,
109     _timesExecuted:0,
110     _repeat:0, //0 = once, 1 is 2 x executed
111     _delay:0,
112 
113     /**
114      * @return {Number} returns interval of timer
115      */
116     getInterval : function(){return this._interval;},
117     /**
118      * @param {Number} interval set interval in seconds
119      */
120     setInterval : function(interval){this._interval = interval;},
121 
122     /**
123      * @return {String|function} returns callback
124      */
125     getCallback : function(){return this._callback},
126 
127 
128     /**
129      * cc.Timer's Constructor
130      * Constructor of cc.Timer
131      * @param {cc.Class} target target
132      * @param {String|function} callback Selector
133      * @param {Number} [interval=0] second
134      * @param {Number} [repeat=cc.REPEAT_FOREVER] repeat times
135      * @param {Number} [delay=0] delay
136      */
137     ctor:function (target, callback, interval, repeat, delay) {
138         var self = this;
139         self._target = target;
140         self._callback = callback;
141         self._elapsed = -1;
142         self._interval = interval || 0;
143         self._delay = delay || 0;
144         self._useDelay = self._delay > 0;
145         self._repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
146         self._runForever = (self._repeat == cc.REPEAT_FOREVER);
147     },
148 
149     _doCallback:function(){
150         var self = this;
151         if (typeof(self._callback) == "string")
152             self._target[self._callback](self._elapsed);
153         else // if (typeof(this._callback) == "function") {
154             self._callback.call(self._target, self._elapsed);
155     },
156 
157     /**
158      * triggers the timer
159      * @param {Number} dt delta time
160      */
161     update:function (dt) {
162         var self = this;
163         if (self._elapsed == -1) {
164             self._elapsed = 0;
165             self._timesExecuted = 0;
166         } else {
167             var locTarget = self._target, locCallback = self._callback;
168             self._elapsed += dt;//standard timer usage
169             if (self._runForever && !self._useDelay) {
170                 if (self._elapsed >= self._interval) {
171                     if (locTarget && locCallback)
172                         self._doCallback();
173                     self._elapsed = 0;
174                 }
175             } else {
176                 //advanced usage
177                 if (self._useDelay) {
178                     if (self._elapsed >= self._delay) {
179                         if (locTarget && locCallback)
180                             self._doCallback();
181 
182                         self._elapsed = self._elapsed - self._delay;
183                         self._timesExecuted += 1;
184                         self._useDelay = false;
185                     }
186                 } else {
187                     if (self._elapsed >= self._interval) {
188                         if (locTarget && locCallback)
189                             self._doCallback();
190 
191                         self._elapsed = 0;
192                         self._timesExecuted += 1;
193                     }
194                 }
195 
196                 if (self._timesExecuted > self._repeat)
197                     cc.director.getScheduler().unscheduleCallbackForTarget(locTarget, locCallback);
198             }
199         }
200     }
201 });
202 
203 /**
204  * <p>
205  *    Scheduler is responsible of triggering the scheduled callbacks.<br/>
206  *    You should not use NSTimer. Instead use this class.<br/>
207  *    <br/>
208  *    There are 2 different types of callbacks (selectors):<br/>
209  *       - update callback: the 'update' callback will be called every frame. You can customize the priority.<br/>
210  *       - custom callback: A custom callback will be called every frame, or with a custom interval of time<br/>
211  *       <br/>
212  *    The 'custom selectors' should be avoided when possible. It is faster, and consumes less memory to use the 'update callback'. *
213  * </p>
214  * @class
215  * @extends cc.Class
216  *
217  * @example
218  * //register a schedule to scheduler
219  * cc.director.getScheduler().scheduleSelector(callback, this, interval, !this._isRunning);
220  */
221 cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{
222     _timeScale:1.0,
223 
224     _updates : null, //_updates[0] list of priority < 0, _updates[1] list of priority == 0, _updates[2] list of priority > 0,
225 
226     _hashForUpdates:null, // hash used to fetch quickly the list entries for pause,delete,etc
227     _arrayForUpdates:null,
228 
229     _hashForTimers:null, //Used for "selectors with interval"
230     _arrayForTimes:null,
231 
232     _currentTarget:null,
233     _currentTargetSalvaged:false,
234     _updateHashLocked:false, //If true unschedule will not remove anything from a hash. Elements will only be marked for deletion.
235 
236     ctor:function () {
237         var self = this;
238         self._timeScale = 1.0;
239         self._updates = [[], [], []];
240 
241         self._hashForUpdates = {};
242         self._arrayForUpdates = [];
243 
244         self._hashForTimers = {};
245         self._arrayForTimers = [];
246 
247         self._currentTarget = null;
248         self._currentTargetSalvaged = false;
249         self._updateHashLocked = false;
250     },
251 
252     //-----------------------private method----------------------
253     _removeHashElement:function (element) {
254         delete this._hashForTimers[element.target.__instanceId];
255         cc.arrayRemoveObject(this._arrayForTimers, element);
256         element.Timer = null;
257         element.target = null;
258         element = null;
259     },
260 
261     _removeUpdateFromHash:function (entry) {
262         var self = this, element = self._hashForUpdates[entry.target.__instanceId];
263         if (element) {
264             //list entry
265             cc.arrayRemoveObject(element.list, element.entry);
266 
267             delete self._hashForUpdates[element.target.__instanceId];
268             cc.arrayRemoveObject(self._arrayForUpdates, element);
269             element.entry = null;
270 
271             //hash entry
272             element.target = null;
273         }
274     },
275 
276     _priorityIn:function (ppList, target, priority, paused) {
277         var self = this, listElement = new cc.ListEntry(null, null, target, priority, paused, false);
278 
279         // empey list ?
280         if (!ppList) {
281             ppList = [];
282             ppList.push(listElement);
283         } else {
284             var index2Insert = ppList.length - 1;
285             for(var i = 0; i <= index2Insert; i++){
286                 if (priority < ppList[i].priority) {
287                     index2Insert = i;
288                     break;
289                 }
290             }
291             ppList.splice(i, 0, listElement);
292         }
293 
294         //update hash entry for quick access
295         var hashElement = new cc.HashUpdateEntry(ppList, listElement, target, null);
296         self._arrayForUpdates.push(hashElement);
297         self._hashForUpdates[target.__instanceId] = hashElement;
298 
299         return ppList;
300     },
301 
302     _appendIn:function (ppList, target, paused) {
303         var self = this, listElement = new cc.ListEntry(null, null, target, 0, paused, false);
304         ppList.push(listElement);
305 
306         //update hash entry for quicker access
307         var hashElement = new cc.HashUpdateEntry(ppList, listElement, target, null);
308         self._arrayForUpdates.push(hashElement);
309         self._hashForUpdates[target.__instanceId] = hashElement;
310     },
311 
312     //-----------------------public method-------------------------
313     /**
314      * <p>
315      *    Modifies the time of all scheduled callbacks.<br/>
316      *    You can use this property to create a 'slow motion' or 'fast forward' effect.<br/>
317      *    Default is 1.0. To create a 'slow motion' effect, use values below 1.0.<br/>
318      *    To create a 'fast forward' effect, use values higher than 1.0.<br/>
319      *    @warning It will affect EVERY scheduled selector / action.
320      * </p>
321      * @param {Number} timeScale
322      */
323     setTimeScale:function (timeScale) {
324         this._timeScale = timeScale;
325     },
326 
327     /**
328      * Returns time scale of scheduler
329      * @return {Number}
330      */
331     getTimeScale:function () {
332         return this._timeScale;
333     },
334 
335     /**
336      * 'update' the scheduler. (You should NEVER call this method, unless you know what you are doing.)
337      * @param {Number} dt delta time
338      */
339     update:function (dt) {
340         var self = this;
341         var locUpdates = self._updates, locArrayForTimers = self._arrayForTimers;
342         var tmpEntry, elt, i, li;
343         self._updateHashLocked = true;
344 
345         if (this._timeScale != 1.0) {
346             dt *= this._timeScale;
347         }
348 
349         for(i = 0, li = locUpdates.length; i < li && i >= 0; i++){
350             var update = self._updates[i];
351             for(var j = 0, lj = update.length; j < lj; j++){
352                 tmpEntry = update[j];
353                 if ((!tmpEntry.paused) && (!tmpEntry.markedForDeletion)) tmpEntry.target.update(dt);
354             }
355         }
356 
357         //Interate all over the custom callbacks
358         for(i = 0, li = locArrayForTimers.length; i < li; i++){
359             elt = locArrayForTimers[i];
360             if(!elt) break;
361             self._currentTarget = elt;
362             self._currentTargetSalvaged = false;
363 
364             if (!elt.paused) {
365                 // The 'timers' array may change while inside this loop
366                 for (elt.timerIndex = 0; elt.timerIndex < elt.timers.length; elt.timerIndex++) {
367                     elt.currentTimer = elt.timers[elt.timerIndex];
368                     elt.currentTimerSalvaged = false;
369 
370                     elt.currentTimer.update(dt);
371                     elt.currentTimer = null;
372                 }
373             }
374 
375             if ((self._currentTargetSalvaged) && (elt.timers.length == 0)){
376                 self._removeHashElement(elt);
377                 i--;
378             }
379         }
380 
381         for(i = 0, li = locUpdates.length; i < li; i++){
382             var update = self._updates[i];
383             for(var j = 0, lj = update.length; j < lj; ){
384                 tmpEntry = update[j];
385                 if(!tmpEntry) break;
386                 if (tmpEntry.markedForDeletion) self._removeUpdateFromHash(tmpEntry);
387                 else j++;
388             }
389         }
390 
391         self._updateHashLocked = false;
392         self._currentTarget = null;
393     },
394 
395     /**
396      * <p>
397      *   The scheduled method will be called every 'interval' seconds.</br>
398      *   If paused is YES, then it won't be called until it is resumed.<br/>
399      *   If 'interval' is 0, it will be called every frame, but if so, it recommended to use 'scheduleUpdateForTarget:' instead.<br/>
400      *   If the callback function is already scheduled, then only the interval parameter will be updated without re-scheduling it again.<br/>
401      *   repeat let the action be repeated repeat + 1 times, use cc.REPEAT_FOREVER to let the action run continuously<br/>
402      *   delay is the amount of time the action will wait before it'll start<br/>
403      * </p>
404      * @param {cc.Class} target
405      * @param {function} callback_fn
406      * @param {Number} interval
407      * @param {Number} repeat
408      * @param {Number} delay
409      * @param {Boolean} paused
410      * @example
411      * //register a schedule to scheduler
412      * cc.director.getScheduler().scheduleCallbackForTarget(this, function, interval, repeat, delay, !this._isRunning );
413      */
414     scheduleCallbackForTarget:function (target, callback_fn, interval, repeat, delay, paused) {
415 
416         cc.assert(callback_fn, cc._LogInfos.Scheduler_scheduleCallbackForTarget_2);
417 
418         cc.assert(target, cc._LogInfos.Scheduler_scheduleCallbackForTarget_3);
419 
420         // default arguments
421         interval = interval || 0;
422         repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat;
423         delay = delay || 0;
424         paused = paused || false;
425 
426         var self = this, timer;
427         var element = self._hashForTimers[target.__instanceId];
428 
429         if (!element) {
430             // Is this the 1st element ? Then set the pause level to all the callback_fns of this target
431             element = new cc.HashTimerEntry(null, target, 0, null, null, paused, null);
432             self._arrayForTimers.push(element);
433             self._hashForTimers[target.__instanceId] = element;
434         }
435 
436         if (element.timers == null) {
437             element.timers = [];
438         } else {
439             for (var i = 0; i < element.timers.length; i++) {
440                 timer = element.timers[i];
441                 if (callback_fn == timer._callback) {
442                     cc.log(cc._LogInfos.Scheduler_scheduleCallbackForTarget, timer.getInterval().toFixed(4), interval.toFixed(4));
443                     timer._interval = interval;
444                     return;
445                 }
446             }
447         }
448 
449         timer = new cc.Timer(target, callback_fn, interval, repeat, delay);
450         element.timers.push(timer);
451     },
452 
453     /**
454      * <p>
455      *    Schedules the 'update' callback_fn for a given target with a given priority.<br/>
456      *    The 'update' callback_fn will be called every frame.<br/>
457      *    The lower the priority, the earlier it is called.
458      * </p>
459      * @param {cc.Class} target
460      * @param {Number} priority
461      * @param {Boolean} paused
462      * @example
463      * //register this object to scheduler
464      * cc.director.getScheduler().scheduleUpdateForTarget(this, priority, !this._isRunning );
465      */
466     scheduleUpdateForTarget:function (target, priority, paused) {
467         if(target === null)
468             return;
469         var self = this, locUpdates = self._updates;
470         var hashElement = self._hashForUpdates[target.__instanceId];
471 
472         if (hashElement) {
473             // TODO: check if priority has changed!
474             hashElement.entry.markedForDeletion = false;
475             return;
476         }
477 
478         // most of the updates are going to be 0, that's way there
479         // is an special list for updates with priority 0
480         if (priority == 0) {
481             self._appendIn(locUpdates[1], target, paused);
482         } else if (priority < 0) {
483             locUpdates[0] = self._priorityIn(locUpdates[0], target, priority, paused);
484         } else {
485             // priority > 0
486             locUpdates[2] = self._priorityIn(locUpdates[2], target, priority, paused);
487         }
488     },
489 
490     /**
491      * <p>
492      *   Unschedule a callback function for a given target.<br/>
493      *   If you want to unschedule the "update", use unscheudleUpdateForTarget.
494      * </p>
495      * @param {cc.Class} target
496      * @param {function} callback_fn
497      * @example
498      * //unschedule a callback of target
499      * cc.director.getScheduler().unscheduleCallbackForTarget(function, this);
500      */
501     unscheduleCallbackForTarget:function (target, callback_fn) {
502         // explicity handle nil arguments when removing an object
503         if ((target == null) || (callback_fn == null)) {
504             return;
505         }
506 
507         var self = this, element = self._hashForTimers[target.__instanceId];
508         if (element) {
509             var timers = element.timers;
510             for(var i = 0, li = timers.length; i < li; i++){
511                 var timer = timers[i];
512                 if (callback_fn == timer._callback) {
513                     if ((timer == element.currentTimer) && (!element.currentTimerSalvaged)) {
514                         element.currentTimerSalvaged = true;
515                     }
516                     timers.splice(i, 1)
517                     //update timerIndex in case we are in tick;, looping over the actions
518                     if (element.timerIndex >= i) {
519                         element.timerIndex--;
520                     }
521 
522                     if (timers.length == 0) {
523                         if (self._currentTarget == element) {
524                             self._currentTargetSalvaged = true;
525                         } else {
526                             self._removeHashElement(element);
527                         }
528                     }
529                     return;
530                 }
531             }
532         }
533     },
534 
535     /**
536      * Unschedules the update callback function for a given target
537      * @param {cc.Class} target
538      * @example
539      * //unschedules the "update" method.
540      * cc.director.getScheduler().unscheduleUpdateForTarget(this);
541      */
542     unscheduleUpdateForTarget:function (target) {
543         if (target == null) {
544             return;
545         }
546 
547         var self = this, element = self._hashForUpdates[target.__instanceId];
548         if (element != null) {
549             if (self._updateHashLocked) {
550                 element.entry.markedForDeletion = true;
551             } else {
552                 self._removeUpdateFromHash(element.entry);
553             }
554         }
555     },
556 
557     /**
558      * Unschedules all function callbacks for a given target. This also includes the "update" callback function.
559      * @param {cc.Class} target
560      */
561     unscheduleAllCallbacksForTarget:function (target) {
562         //explicit NULL handling
563         if (target == null) {
564             return;
565         }
566 
567         var self = this, element = self._hashForTimers[target.__instanceId];
568         if (element) {
569             var timers = element.timers;
570             if ((!element.currentTimerSalvaged) && (timers.indexOf(element.currentTimer) >= 0)) {
571                 element.currentTimerSalvaged = true;
572             }
573             timers.length = 0;
574 
575             if (self._currentTarget == element) {
576                 self._currentTargetSalvaged = true;
577             } else {
578                 self._removeHashElement(element);
579             }
580         }
581         // update callback
582         self.unscheduleUpdateForTarget(target);
583     },
584 
585     /**
586      *  <p>
587      *      Unschedules all function callbacks from all targets. <br/>
588      *      You should NEVER call this method, unless you know what you are doing.
589      *  </p>
590      */
591     unscheduleAllCallbacks:function () {
592         this.unscheduleAllCallbacksWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
593     },
594 
595     /**
596      * <p>
597      *    Unschedules all function callbacks from all targets with a minimum priority.<br/>
598      *    You should only call this with kCCPriorityNonSystemMin or higher.
599      * </p>
600      * @param {Number} minPriority
601      */
602     unscheduleAllCallbacksWithMinPriority:function (minPriority) {
603         // Custom Selectors
604         var self = this, locArrayForTimers = self._arrayForTimers, locUpdates = self._updates;
605         for(var i = 0, li = locArrayForTimers.length; i < li; i++){
606             // element may be removed in unscheduleAllCallbacksForTarget
607             self.unscheduleAllCallbacksForTarget(locArrayForTimers[i].target);
608         }
609         for(var i = 2; i >= 0; i--){
610             if((i == 1 && minPriority > 0) || (i == 0 && minPriority >= 0)) continue;
611             var updates = locUpdates[i];
612             for(var j = 0, lj = updates.length; j < lj; j++){
613                 self.unscheduleUpdateForTarget(updates[j].target);
614             }
615         }
616     },
617 
618     /**
619      * <p>
620      *  Pause all selectors from all targets.<br/>
621      *  You should NEVER call this method, unless you know what you are doing.
622      * </p>
623      */
624     pauseAllTargets:function () {
625         return this.pauseAllTargetsWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
626     },
627 
628     /**
629      * Pause all selectors from all targets with a minimum priority. <br/>
630      * You should only call this with kCCPriorityNonSystemMin or higher.
631      * @param {Number} minPriority
632      */
633     pauseAllTargetsWithMinPriority:function (minPriority) {
634         var idsWithSelectors = [];
635 
636         var self = this, element, locArrayForTimers = self._arrayForTimers, locUpdates = self._updates;
637         // Custom Selectors
638         for(var i = 0, li = locArrayForTimers.length; i < li; i++){
639             element = locArrayForTimers[i];
640             if (element) {
641                 element.paused = true;
642                 idsWithSelectors.push(element.target);
643             }
644         }
645         for(var i = 0, li = locUpdates.length; i < li; i++){
646             var updates = locUpdates[i];
647             for(var j = 0, lj = updates.length; j < lj; j++){
648                 element = updates[j];
649                 if (element) {
650                     element.paused = true;
651                     idsWithSelectors.push(element.target);
652                 }
653             }
654         }
655         return idsWithSelectors;
656     },
657 
658     /**
659      * Resume selectors on a set of targets.<br/>
660      * This can be useful for undoing a call to pauseAllCallbacks.
661      * @param {Array} targetsToResume
662      */
663     resumeTargets:function (targetsToResume) {
664         if (!targetsToResume)
665             return;
666 
667         for (var i = 0; i < targetsToResume.length; i++) {
668             this.resumeTarget(targetsToResume[i]);
669         }
670     },
671 
672     /**
673      * <p>
674      *    Pauses the target.<br/>
675      *    All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.<br/>
676      *    If the target is not present, nothing happens.
677      * </p>
678      * @param {cc.Class} target
679      */
680     pauseTarget:function (target) {
681 
682         cc.assert(target, cc._LogInfos.Scheduler_pauseTarget);
683 
684         //customer selectors
685         var self = this, element = self._hashForTimers[target.__instanceId];
686         if (element) {
687             element.paused = true;
688         }
689 
690         //update callback
691         var elementUpdate = self._hashForUpdates[target.__instanceId];
692         if (elementUpdate) {
693             elementUpdate.entry.paused = true;
694         }
695     },
696 
697     /**
698      * Resumes the target.<br/>
699      * The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again.<br/>
700      * If the target is not present, nothing happens.
701      * @param {cc.Class} target
702      */
703     resumeTarget:function (target) {
704 
705         cc.assert(target, cc._LogInfos.Scheduler_resumeTarget);
706 
707         // custom selectors
708         var self = this, element = self._hashForTimers[target.__instanceId];
709 
710         if (element) {
711             element.paused = false;
712         }
713 
714         //update callback
715         var elementUpdate = self._hashForUpdates[target.__instanceId];
716 
717         if (elementUpdate) {
718             elementUpdate.entry.paused = false;
719         }
720     },
721 
722     /**
723      * Returns whether or not the target is paused
724      * @param {cc.Class} target
725      * @return {Boolean}
726      */
727     isTargetPaused:function (target) {
728 
729         cc.assert(target, cc._LogInfos.Scheduler_isTargetPaused);
730 
731         // Custom selectors
732         var element = this._hashForTimers[target.__instanceId];
733         if (element) {
734             return element.paused;
735         }
736         return false;
737     }
738 });
739 /**
740  * Priority level reserved for system services.
741  * @constant
742  * @type Number
743  */
744 cc.Scheduler.PRIORITY_SYSTEM = (-2147483647 - 1);
745