Beispiel #1
0
        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);

        }