void ProcessTouch(CCWindow window) { if (window.EventDispatcher.IsEventListenersFor(CCEventListenerTouchOneByOne.LISTENER_ID) || window.EventDispatcher.IsEventListenersFor(CCEventListenerTouchAllAtOnce.LISTENER_ID)) { newTouches.Clear(); movedTouches.Clear(); endedTouches.Clear(); CCPoint pos = CCPoint.Zero; // TODO: allow configuration to treat the game pad as a touch device. #if WINDOWS || WINDOWSGL || MACOS pos = new CCPoint(lastMouseState.X, lastMouseState.Y); prevMouseState = lastMouseState; lastMouseState = Mouse.GetState(); if (prevMouseState.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed) { lastMouseId++; touches.AddLast(new CCTouch(lastMouseId, pos.X, pos.Y)); touchMap.Add(lastMouseId, touches.Last); newTouches.Add(touches.Last.Value); } else if (prevMouseState.LeftButton == ButtonState.Pressed && lastMouseState.LeftButton == ButtonState.Pressed) { if (touchMap.ContainsKey(lastMouseId)) { if (prevMouseState.X != lastMouseState.X || prevMouseState.Y != lastMouseState.Y) { movedTouches.Add(touchMap[lastMouseId].Value); touchMap[lastMouseId].Value.SetTouchInfo(lastMouseId, pos.X, pos.Y); } } } else if (prevMouseState.LeftButton == ButtonState.Pressed && lastMouseState.LeftButton == ButtonState.Released) { if (touchMap.ContainsKey(lastMouseId)) { endedTouches.Add(touchMap[lastMouseId].Value); touches.Remove(touchMap[lastMouseId]); touchMap.Remove(lastMouseId); } } #endif TouchCollection touchCollection = TouchPanel.GetState(); foreach (TouchLocation touch in touchCollection) { switch (touch.State) { case TouchLocationState.Pressed: if (touchMap.ContainsKey(touch.Id)) { break; } pos = new CCPoint(touch.Position.X, touch.Position.Y); touches.AddLast(new CCTouch(touch.Id, pos.X, pos.Y)); touchMap.Add(touch.Id, touches.Last); newTouches.Add(touches.Last.Value); break; case TouchLocationState.Moved: LinkedListNode<CCTouch> existingTouch; if (touchMap.TryGetValue(touch.Id, out existingTouch)) { pos = new CCPoint(touch.Position.X, touch.Position.Y); var delta = existingTouch.Value.LocationOnScreen - pos; if (delta.LengthSquared > 1.0f) { movedTouches.Add(existingTouch.Value); existingTouch.Value.SetTouchInfo(touch.Id, pos.X, pos.Y); } } break; case TouchLocationState.Released: if (touchMap.TryGetValue(touch.Id, out existingTouch)) { endedTouches.Add(existingTouch.Value); touches.Remove(existingTouch); touchMap.Remove(touch.Id); } break; default: throw new ArgumentOutOfRangeException(); } } var touchEvent = new CCEventTouch(CCEventCode.BEGAN); if (newTouches.Count > 0) { touchEvent.Touches = newTouches; //m_pDelegate.TouchesBegan(newTouches); window.EventDispatcher.DispatchEvent(touchEvent); } if (movedTouches.Count > 0) { touchEvent.EventCode = CCEventCode.MOVED; touchEvent.Touches = movedTouches; window.EventDispatcher.DispatchEvent(touchEvent); } if (endedTouches.Count > 0) { touchEvent.EventCode = CCEventCode.ENDED; touchEvent.Touches = endedTouches; window.EventDispatcher.DispatchEvent(touchEvent); } } }
/// <summary> /// Touch event needs to be processed different with other events since it needs support ALL_AT_ONCE and ONE_BY_NONE mode. /// </summary> /// <param name="touchEvent"></param> void DispatchTouchEvent(CCEventTouch touchEvent) { SortEventListeners(CCEventListenerTouchOneByOne.LISTENER_ID); SortEventListeners(CCEventListenerTouchAllAtOnce.LISTENER_ID); var oneByOneListeners = GetListeners(CCEventListenerTouchOneByOne.LISTENER_ID); var allAtOnceListeners = GetListeners(CCEventListenerTouchAllAtOnce.LISTENER_ID); // If there aren't any touch listeners, return directly. if (oneByOneListeners == null && allAtOnceListeners == null) return; bool isNeedsMutableSet = (oneByOneListeners != null && allAtOnceListeners != null); var originalTouches = touchEvent.Touches; var mutableTouchesArray = new CCTouch[originalTouches.Count]; originalTouches.CopyTo (mutableTouchesArray); var mutableTouchesIter = 0; var mutableTouches = new List<CCTouch>(mutableTouchesArray); // // process the target handlers 1st // if (oneByOneListeners != null) { foreach (var touchesIter in originalTouches) { bool isSwallowed = false; Func<CCEventListener, bool> onTouchEvent = delegate(CCEventListener l) { var listener = (CCEventListenerTouchOneByOne)l; // Skip if the listener was removed. if (!listener.IsRegistered) return false; touchEvent.CurrentTarget = listener.SceneGraphPriority; bool isClaimed = false; var removed = new List<CCTouch>(); var eventCode = touchEvent.EventCode; if (eventCode == CCEventCode.BEGAN) { if (listener.OnTouchBegan != null) { isClaimed = listener.OnTouchBegan(touchesIter, touchEvent); if (isClaimed && listener.IsRegistered) { listener.ClaimedTouches.Add(touchesIter); } } } else if (listener.ClaimedTouches.Count > 0 && (removed = listener.ClaimedTouches.FindAll(t => t == touchesIter)).Count > 0) { isClaimed = true; switch (eventCode) { case CCEventCode.MOVED: if (listener.OnTouchMoved != null) { listener.OnTouchMoved(touchesIter, touchEvent); } break; case CCEventCode.ENDED: if (listener.OnTouchEnded != null) { listener.OnTouchEnded(touchesIter, touchEvent); } if (listener.IsRegistered) { listener.ClaimedTouches.RemoveAll(t => removed.Contains(t)); } break; case CCEventCode.CANCELLED: if (listener.OnTouchCancelled != null) { listener.OnTouchCancelled(touchesIter, touchEvent); } if (listener.IsRegistered) { listener.ClaimedTouches.RemoveAll(t => removed.Contains(t)); } break; default: Debug.Assert(false, "The eventcode is invalid."); break; } } // If the event was stopped, return directly. if (touchEvent.IsStopped) { UpdateListeners(touchEvent); return true; } Debug.Assert(touchesIter.Id == mutableTouches[mutableTouchesIter].Id, ""); if (isClaimed && listener.IsRegistered && listener.IsSwallowTouches) { if (isNeedsMutableSet) { mutableTouches.RemoveAt(mutableTouchesIter); //++mutableTouchesIter; isSwallowed = true; } return true; } return false; }; // DispatchEventToListeners(oneByOneListeners, onTouchEvent); if (touchEvent.IsStopped) { return; } if (!isSwallowed) ++mutableTouchesIter; } } // process standard handlers 2nd if (allAtOnceListeners != null && mutableTouches.Count > 0) { Func<CCEventListener, bool> onTouchesEvent = delegate(CCEventListener l) { var listener = (CCEventListenerTouchAllAtOnce)l; // Skip if the listener was removed. if (!listener.IsRegistered) return false; touchEvent.CurrentTarget = listener.SceneGraphPriority; switch (touchEvent.EventCode) { case CCEventCode.BEGAN: if (listener.OnTouchesBegan != null) { listener.OnTouchesBegan(mutableTouches, touchEvent); } break; case CCEventCode.MOVED: if (listener.OnTouchesMoved != null) { listener.OnTouchesMoved(mutableTouches, touchEvent); } break; case CCEventCode.ENDED: if (listener.OnTouchesEnded != null) { listener.OnTouchesEnded(mutableTouches, touchEvent); } break; case CCEventCode.CANCELLED: if (listener.OnTouchesCancelled != null) { listener.OnTouchesCancelled(mutableTouches, touchEvent); } break; default: Debug.Assert(false, "The eventcode is invalid."); break; } // If the event was stopped, return directly. if (touchEvent.IsStopped) { UpdateListeners(touchEvent); return true; } return false; }; DispatchEventToListeners(allAtOnceListeners, onTouchesEvent); if (touchEvent.IsStopped) { return; } } UpdateListeners(touchEvent); }