/** Unschedules all selectors and blocks for a given target. * This also includes the "update" selector. * @since v0.99.3 */ public void unscheduleAllForTarget(System.Object target) { // explicit nil handling if (target == null) { return; } // Custom Selectors tHashTimerEntry element = hashForTimers.HASH_FIND_INT(target.GetHashCode()); if (element != null) { if (element.timers.Contains(element.currentTimer) && !element.currentTimerSalvaged) { element.currentTimerSalvaged = true; } element.timers.Clear(); if (currentTarget == element) { currentTargetSalvaged = true; } else { removeHashElement(element); } } // Update Selector unscheduleUpdateForTarget(target); }
public void unscheduleBlockForKey(string key, System.Object target) { // explicity handle nil arguments when removing an object if (target == null && key == null) { return; } NSUtils.Assert(target != null, "Target MUST not be nil"); NSUtils.Assert(key != null, "key MUST not be NULL"); tHashTimerEntry element = hashForTimers.HASH_FIND_INT(target.GetHashCode()); if (element != null) { for (int i = 0; i < element.timers.Count; i++) { CCTimer timer = element.timers[i]; if (timer is CCTimerBlock && key == ((CCTimerBlock)timer).key) { if (timer == element.currentTimer && !element.currentTimerSalvaged) { element.currentTimerSalvaged = true; } element.timers.RemoveAt(i); // update timerIndex in case we are in tick:, looping over the actions if (element.timerIndex >= i) { element.timerIndex--; } if (element.timers.Count == 0) { if (currentTarget == element) { currentTargetSalvaged = true; } else { removeHashElement(element); } } return; } } } // Not Found // NSLog(@"CCScheduler#unscheduleSelector:forTarget: selector not found: %@", selString); }
/** Pause all selectors and blocks from all targets with a minimum priority. * You should only call this with kCCPriorityNonSystemMin or higher. * @since v2.0.0 */ public HashSet <System.Object> pauseAllTargetsWithMinPriority(int minPriority) { HashSet <System.Object> idsWithSelectors = new HashSet <System.Object>(); // Custom Selectors { var enumerator = hashForTimers.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair <int, tHashTimerEntry> kv = enumerator.Current; tHashTimerEntry element = kv.Value; element.paused = true; idsWithSelectors.Add(element.target); } } // Updates selectors if (minPriority < 0) { for (utNode <tListEntry> tmp = updatesNeg.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (entry.obj.priority >= minPriority) { entry.obj.paused = true; idsWithSelectors.Add(entry.obj.target); } } } if (minPriority <= 0) { for (utNode <tListEntry> tmp = updates0.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; entry.obj.paused = true; idsWithSelectors.Add(entry.obj.target); } } { for (utNode <tListEntry> tmp = updatesPos.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (entry.obj.priority >= minPriority) { entry.obj.paused = true; idsWithSelectors.Add(entry.obj.target); } } } return(idsWithSelectors); }
/** Unshedules a selector for a given target. * If you want to unschedule the "update", use unscheudleUpdateForTarget. * @since v0.99.3 */ public void unscheduleSelector(TICK_IMP selector, System.Object target) { if (target == null && selector == null) { return; } NSUtils.Assert(target != null, "Target MUST not be nil"); NSUtils.Assert(selector != null, "Selector MUST not be NULL"); tHashTimerEntry element = hashForTimers.HASH_FIND_INT(target.GetHashCode()); if (element != null) { int timersCount = element.timers.Count; for (int i = 0; i < timersCount; i++) { CCTimer timer = element.timers[i]; if (timer is CCTimerTargetSelector && selector == ((CCTimerTargetSelector)timer).selector) { if (timer == element.currentTimer && !element.currentTimerSalvaged) { element.currentTimerSalvaged = true; } element.timers.RemoveAt(i); if (element.timerIndex >= i) { element.timerIndex--; } if (element.timers.Count == 0) { if (currentTarget == element) { currentTargetSalvaged = true; } else { removeHashElement(element); } } return; } } } // Not Found // NSLog(@"CCScheduler#unscheduleSelector:forTarget: selector not found: %@", selString); }
public void scheduleBlockForKey(string key, System.Object owner, float interval, uint repeat, float delay, bool paused, TICK_IMP block) { NSUtils.Assert(block != null, "Argument block must be non-nil"); NSUtils.Assert(owner != null, "Argument owner must be non-nil"); tHashTimerEntry element = hashForTimers.HASH_FIND_INT(owner.GetHashCode()); if (element == null) { element = new tHashTimerEntry(); element.target = owner; hashForTimers.HASH_ADD_INT(owner.GetHashCode(), element); // Is this the 1st element ? Then set the pause level to all the selectors of this target element.paused = paused; } else { NSUtils.Assert(element.paused == paused, "CCScheduler. Trying to schedule a block with a pause value different than the target"); } if (element.timers == null) { element.timers = new List <CCTimer> (10); } else { var enumerator = element.timers.GetEnumerator(); while (enumerator.MoveNext()) { CCTimer timer = enumerator.Current; if (timer is CCTimerBlock && key == ((CCTimerBlock)timer).key) { CCDebug.Log("CCScheduler#scheduleBlock. Block already scheduled. Updating interval from: {0:0.0000} to {1:0.0000}", timer.interval, interval); timer.interval = interval; return; } } } CCTimerBlock timerBlock = new CCTimerBlock(owner, interval, key, block, repeat, delay); element.timers.Add(timerBlock); }
/** The scheduled method will be called every 'interval' seconds. * If paused is YES, then it won't be called until it is resumed. * If 'interval' is 0, it will be called every frame, but if so, it recommended to use 'scheduleUpdateForTarget:' instead. * If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again. * repeat lets the action be repeated repeat + 1 times, use kCCRepeatForever to let the action run continuously * delay is the amount of time the action will wait before it'll start * * @since v0.99.3, repeat and delay added in v1.1 */ public void schedule(TICK_IMP selector, System.Object target, float interval, uint repeat, bool paused, float delay = 0) { NSUtils.Assert(selector != null, "Argument selector must be non-nil"); NSUtils.Assert(target != null, "Argument target must be non-nil"); tHashTimerEntry element = hashForTimers.HASH_FIND_INT(target.GetHashCode()); if (element == null) { element = new tHashTimerEntry(); element.target = target; hashForTimers.HASH_ADD_INT(target.GetHashCode(), element); // Is this the 1st element ? Then set the pause level to all the selectors of this target element.paused = paused; } else { NSUtils.Assert(element.paused == paused, "CCScheduler. Trying to schedule a selector with a pause value different than the target"); } if (element.timers == null) { element.timers = new List <CCTimer> (10); } else { var enumerator = element.timers.GetEnumerator(); while (enumerator.MoveNext()) { CCTimer timer = enumerator.Current; if (timer is CCTimerTargetSelector && selector == ((CCTimerTargetSelector)timer).selector) { CCDebug.Log("CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: {0:0.0000} to {1:0.0000}", timer.interval, interval); timer.interval = interval; return; } } } CCTimerTargetSelector timerSelector = new CCTimerTargetSelector(target, selector, interval, repeat, delay); element.timers.Add(timerSelector); }
/** Pauses the target. * All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed. * If the target is not present, nothing happens. * @since v0.99.3 */ public void pauseTarget(System.Object target) { NSUtils.Assert(target != null, "target must be non nil"); // Custom selectors tHashTimerEntry element = hashForTimers.HASH_FIND_INT(target.GetHashCode()); if (element != null) { element.paused = true; } // Update selector tHashUpdateEntry elementUpdate = hashForUpdates.HASH_FIND_INT(target.GetHashCode()); if (elementUpdate != null) { NSUtils.Assert(elementUpdate.entry != null, "pauseTarget: unknown error"); elementUpdate.entry.obj.paused = true; } }
//----------init------------ public CCScheduler() { _timeScale = 1.0f; // used to trigger CCTimer#update updateSelector = "update"; // impMethod = (TICK_IMP) [CCTimerTargetSelector instanceMethodForSelector:updateSelector]; // updates with priority updates0 = new utList <tListEntry>(); updatesNeg = new utList <tListEntry>(); updatesPos = new utList <tListEntry>(); hashForUpdates = new UTHash <int, tHashUpdateEntry>(); // selectors with interval currentTarget = null; currentTargetSalvaged = false; hashForTimers = new UTHash <int, tHashTimerEntry>(); updateHashLocked = false; _paused = false; }
/** Returns whether or not the target is paused * @since v1.0.0 */ public bool isTargetPaused(System.Object target) { NSUtils.Assert(target != null, "target must be non nil"); // Custom selectors tHashTimerEntry element = hashForTimers.HASH_FIND_INT(target.GetHashCode()); if (element != null) { return(element.paused); } // We should check update selectors if target does not have custom selectors tHashUpdateEntry elementUpdate = hashForUpdates.HASH_FIND_INT(target.GetHashCode()); if (elementUpdate != null) { return(elementUpdate.entry.obj.paused); } return(false); // should never get here }
//-------------update------------ /** 'update' the scheduler. * You should NEVER call this method, unless you know what you are doing. */ public void update(float dt) { if (_paused) { return; } updateHashLocked = true; if (!FloatUtils.EQ(_timeScale, 1.0f)) { dt *= _timeScale; } // Iterate all over the Updates selectors // updates with priority < 0 { for (utNode <tListEntry> tmp = updatesNeg.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (!entry.obj.paused && !entry.obj.markedForDeletion) { entry.obj.impMethod.Invoke(dt); } } } // updates with priority == 0 { for (utNode <tListEntry> tmp = updates0.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (!entry.obj.paused && !entry.obj.markedForDeletion) { entry.obj.impMethod.Invoke(dt); } } } // updates with priority > 0 { for (utNode <tListEntry> tmp = updatesPos.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (!entry.obj.paused && !entry.obj.markedForDeletion) { entry.obj.impMethod.Invoke(dt); } } } // Iterate all over the custom selectors (CCTimers) if (hashForTimers.Any()) { var enumerator = new Dictionary <int, tHashTimerEntry>(hashForTimers).GetEnumerator(); while (enumerator.MoveNext()) { var elt = enumerator.Current.Value; currentTarget = elt; currentTargetSalvaged = false; if (!currentTarget.paused) { for (elt.timerIndex = 0; elt.timerIndex < elt.timers.Count; elt.timerIndex++) { elt.currentTimer = elt.timers[elt.timerIndex]; elt.currentTimerSalvaged = false; elt.currentTimer.update(dt); elt.currentTimer = null; } } if (currentTargetSalvaged && currentTarget.timers.Count == 0) { removeHashElement(currentTarget); } } } for (utNode <tListEntry> tmp = updatesNeg.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (entry.obj.markedForDeletion) { removeUpdatesFromHash(entry); } } for (utNode <tListEntry> tmp = updates0.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (entry.obj.markedForDeletion) { removeUpdatesFromHash(entry); } } for (utNode <tListEntry> tmp = updatesPos.head; tmp != null; tmp = tmp.next) { utNode <tListEntry> entry = tmp; if (entry.obj.markedForDeletion) { removeUpdatesFromHash(entry); } } updateHashLocked = false; currentTarget = null; }
void removeHashElement(tHashTimerEntry element) { hashForTimers.HASH_DEL(element.target.GetHashCode()); element.timers = null; element.target = null; }