/** Unschedules all selectors for a given target. * This also includes the "update" selector. * @since v0.99.3 */ public void unscheduleAllSelectors() { tHashSelectorEntry[] hashSelectorToDelete = new tHashSelectorEntry[m_pHashForSelectors.Values.Count]; m_pHashForSelectors.Values.CopyTo(hashSelectorToDelete, 0); for (int i = 0; i < hashSelectorToDelete.Length; i++) { unscheduleAllSelectorsForTarget(hashSelectorToDelete[i].target); } // Updates selectors tListEntry[] listEntryToDelete = m_pUpdates0List.ToArray(); for (int i = 0; i < listEntryToDelete.Length; i++) { unscheduleAllSelectorsForTarget(listEntryToDelete[i].target); } listEntryToDelete = m_pUpdatesNegList.ToArray(); for (int i = 0; i < listEntryToDelete.Length; i++) { unscheduleAllSelectorsForTarget(listEntryToDelete[i].target); } listEntryToDelete = m_pUpdatesPosList.ToArray(); for (int i = 0; i < listEntryToDelete.Length; i++) { unscheduleAllSelectorsForTarget(listEntryToDelete[i].target); } }
/** Unschedules all selectors for a given target. * This also includes the "update" selector. * @since v0.99.3 */ public void unscheduleAllSelectorsForTarget(SelectorProtocol target) { // explicit NULL handling if (target == null) { return; } // custom selectors if (m_pHashForSelectors.ContainsKey(target)) { tHashSelectorEntry element = m_pHashForSelectors[target]; if (element.timers.Contains(element.currentTimer)) { element.currentTimerSalvaged = true; } element.timers.Clear(); if (m_pCurrentTarget == element) { m_bCurrentTargetSalvaged = true; } else { removeHashElement(element); } } // update selector unscheduleUpdateForTarget(target); }
/** 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 recommened to use 'scheduleUpdateForTarget:' instead. * If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again. * * @since v0.99.3 */ public void scheduleSelector(SEL_SCHEDULE selector, SelectorProtocol target, float fInterval, bool bPaused) { if (selector == null) { throw (new ArgumentNullException("selector", "Schedule selector can not be null")); } if (target == null) { throw (new ArgumentNullException("target", "Schedule target must be set.")); } tHashSelectorEntry element = null; if (!m_pHashForSelectors.ContainsKey(target)) { element = new tHashSelectorEntry(); element.target = target; m_pHashForSelectors[target] = element; // Is this the 1st element ? Then set the pause level to all the selectors of this target element.paused = bPaused; } else { element = m_pHashForSelectors[target]; Debug.Assert(element.paused == bPaused); } if (element.timers == null) { element.timers = new List <CCTimer>(); } else { foreach (CCTimer timer in element.timers) { if (selector == timer.m_pfnSelector) { CCLog.Log("CCSheduler#scheduleSelector. Selector already scheduled."); timer.m_fInterval = fInterval; return; } } } CCTimer timer2 = new CCTimer(); timer2.initWithTarget(target, selector, fInterval); element.timers.Add(timer2); }
/** Unschedule a selector for a given target. * If you want to unschedule the "update", use unscheudleUpdateForTarget. * @since v0.99.3 */ public void unscheduleSelector(SEL_SCHEDULE selector, SelectorProtocol target) { // explicity handle nil arguments when removing an object if (selector == null || target == null) { return; } if (m_pHashForSelectors.ContainsKey(target)) { tHashSelectorEntry element = m_pHashForSelectors[target]; for (int i = 0; i < element.timers.Count; i++) { CCTimer timer = element.timers[i]; if (selector == timer.m_pfnSelector) { 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 (m_pCurrentTarget == element) { m_bCurrentTargetSalvaged = true; } else { removeHashElement(element); } } return; } } } }
private void removeHashElement(tHashSelectorEntry element) { element.timers.Clear(); element.target = null; SelectorProtocol target = null; foreach (KeyValuePair <SelectorProtocol, tHashSelectorEntry> kvp in m_pHashForSelectors) { if (element == kvp.Value) { target = kvp.Key; break; } } m_pHashForSelectors.Remove(target); }
/** 'tick' the scheduler. * You should NEVER call this method, unless you know what you are doing. */ public void tick(float dt) { m_bUpdateHashLocked = true; if (m_fTimeScale != 1.0f) { dt *= m_fTimeScale; } // updates with priority < 0 // Jiri Formanek // http://www.cocos2d-x.org/boards/17/topics/10592 for (int i = 0; i < m_pUpdatesNegList.Count; i++) { tListEntry entry = m_pUpdatesNegList[i]; if ((!entry.paused) && (!entry.markedForDeletion)) { entry.target.update(dt); } } // updates with priority == 0 // Jiri Formanek // http://www.cocos2d-x.org/boards/17/topics/10592 for (int i = 0; i < m_pUpdates0List.Count; i++) { tListEntry entry = m_pUpdates0List[i]; if ((!entry.paused) && (!entry.markedForDeletion)) { entry.target.update(dt); } } // updates with priority > 0 // Jiri Formanek // http://www.cocos2d-x.org/boards/17/topics/10592 for (int i = 0; i < m_pUpdatesPosList.Count; i++) { tListEntry entry = m_pUpdatesPosList[i]; if ((!entry.paused) && (!entry.markedForDeletion)) { entry.target.update(dt); } } // Iterate all over the custom selectors SelectorProtocol[] keys = new SelectorProtocol[m_pHashForSelectors.Keys.Count]; m_pHashForSelectors.Keys.CopyTo(keys, 0); for (int i = 0; i < keys.Length; i++) { if (!m_pHashForSelectors.ContainsKey(keys[i])) { // Concurrent modification continue; } tHashSelectorEntry elt = m_pHashForSelectors[keys[i]]; m_pCurrentTarget = elt; m_bCurrentTargetSalvaged = false; if (!m_pCurrentTarget.paused) { // The 'timers' array may change while inside this loop for (elt.timerIndex = 0; elt.timerIndex < elt.timers.Count; ++(elt.timerIndex)) { elt.currentTimer = elt.timers[(int)elt.timerIndex]; elt.currentTimerSalvaged = false; elt.currentTimer.update(dt); /* not needed * if (elt.currentTimerSalvaged) * { * // The currentTimer told the remove itself. To prevent the timer from * // accidentally deallocating itself before finishing its step, we retained * // it. Now that step is done, it's safe to release it. * elt->currentTimer->release(); * } * */ elt.currentTimer = null; } } // not needed // elt = (tHashSelectorEntry*)elt->hh.next; // only delete currentTarget if no actions were scheduled during the cycle (issue #481) if (m_bCurrentTargetSalvaged && m_pCurrentTarget.timers.Count == 0) { removeHashElement(m_pCurrentTarget); } } // delete all updates that are morked for deletion // updates with priority < 0 for (int i = 0; i < m_pUpdatesNegList.Count; i++) { tListEntry entry = m_pUpdatesNegList[i]; if (entry.markedForDeletion) { //removeUpdateFromHash(entry); m_listToDelete.Add(entry); } } // updates with priority == 0 for (int i = 0; i < m_pUpdates0List.Count; i++) { tListEntry entry = m_pUpdates0List[i]; if (entry.markedForDeletion) { //removeUpdateFromHash(entry); m_listToDelete.Add(entry); } } // updates with priority > 0 for (int i = 0; i < m_pUpdatesPosList.Count; i++) { tListEntry entry = m_pUpdatesPosList[i]; if (entry.markedForDeletion) { //removeUpdateFromHash(entry); m_listToDelete.Add(entry); } } // do the delete foreach (tListEntry entry in m_listToDelete) { removeUpdateFromHash(entry); } m_listToDelete.Clear(); }