Пример #1
0
        public override void Update(GameTime gameTime)
        {
            bool checkForKeyPress;

#if NETCOREAPP
            MouseState mouseState = XnaMouse.GetState();

            checkForKeyPress = prevMouseState.LeftButton == XnaButtonState.Pressed &&
                               mouseState.LeftButton == XnaButtonState.Released;
#endif

#if ANDROID
            TouchCollection touchCollection = XnaTouchPanel.GetState();
            checkForKeyPress = touchCollection.Count > 0 && touchCollection[0].State == TouchLocationState.Released;
            // TODO multi-touch support?
            Vector2 touchPos = touchCollection.Count > 0 ? touchCollection[0].Position : Vector2.Zero;
#endif

            foreach (VirtualKey key in keys)
            {
                if (checkForKeyPress)
                {
#if WINDOWS
                    if (mouseState.Y > Y + key.Y && mouseState.Y < Y + key.Y + key.Height &&
                        mouseState.X > X + key.X && mouseState.X < X + key.X + key.Width)
                    {
                        HandleKeyPress(key);
                        checkForKeyPress = false;
                    }
#endif

#if ANDROID
                    if (touchPos.Y > Y + key.Y && touchPos.Y < Y + key.Y + key.Height &&
                        touchPos.X > X + key.X && touchPos.X < X + key.X + key.Width)
                    {
                        HandleKeyPress(key);
                        checkForKeyPress = false;
                    }
#endif
                }

                key.Update(gameTime);
            }

#if WINDOWS
            prevMouseState = mouseState;
#endif

            base.Update(gameTime);
        }
Пример #2
0
        internal static void OnReleased(int fingerId, Vector2 touchPosition)
        {
            fingerIds.Remove(fingerId);

            // Handle release events seperately for Pinch gestures
            if (state == GestureState.PINCHING)
            {
                OnReleased_Pinch(fingerId, touchPosition);
                return;
            }

            // Did the user lift the active finger?
            if (fingerId == activeFingerId)
            {
                activeFingerId = TouchPanel.NO_FINGER;
            }

            // We're only interested in the very last finger to leave
            if (FNAPlatform.GetNumTouchFingers() > 0)
            {
                return;
            }

            #region Tap Detection

            if (state == GestureState.HOLDING)
            {
                // Which Tap gestures are enabled?
                bool tapEnabled  = IsGestureEnabled(GestureType.Tap);
                bool dtapEnabled = IsGestureEnabled(GestureType.DoubleTap);

                if (tapEnabled || dtapEnabled)
                {
                    // How long did the user hold the touch?
                    TimeSpan timeHeld = DateTime.Now - eventTimestamp;
                    if (timeHeld < TimeSpan.FromSeconds(1))
                    {
                        // Don't register a Tap immediately after a Double Tap
                        if (!justDoubleTapped)
                        {
                            if (tapEnabled)
                            {
                                // Tap!
                                TouchPanel.EnqueueGesture(new GestureSample(
                                                              GestureType.Tap,
                                                              GetGestureTimestamp(),
                                                              touchPosition,
                                                              Vector2.Zero,
                                                              Vector2.Zero,
                                                              Vector2.Zero,
                                                              fingerId,
                                                              TouchPanel.NO_FINGER
                                                              ));
                            }

                            /* Even if Tap isn't enabled, we still
                             * need this for Double Tap detection.
                             */
                            state = GestureState.JUST_TAPPED;
                        }
                    }
                }
            }

            // Reset this flag so we can catch Taps in the future
            justDoubleTapped = false;

            #endregion

            #region Flick Detection

            if (IsGestureEnabled(GestureType.Flick))
            {
                // Only flick if the finger is outside the threshold and moving fast
                float distanceFromPress = (touchPosition - pressPosition).Length();
                if (distanceFromPress > MOVE_THRESHOLD &&
                    velocity.Length() >= MIN_FLICK_VELOCITY)
                {
                    // Flick!
                    TouchPanel.EnqueueGesture(new GestureSample(
                                                  GestureType.Flick,
                                                  GetGestureTimestamp(),
                                                  Vector2.Zero,
                                                  Vector2.Zero,
                                                  velocity,
                                                  Vector2.Zero,
                                                  fingerId,
                                                  TouchPanel.NO_FINGER
                                                  ));
                }

                // Reset velocity calculation variables
                velocity           = Vector2.Zero;
                lastUpdatePosition = Vector2.Zero;
                updateTimestamp    = DateTime.MinValue;
            }

            #endregion

            #region Drag Complete Detection

            if (IsGestureEnabled(GestureType.DragComplete))
            {
                bool wasDragging = (state == GestureState.DRAGGING_H ||
                                    state == GestureState.DRAGGING_V ||
                                    state == GestureState.DRAGGING_FREE);
                if (wasDragging)
                {
                    // Drag Complete!
                    TouchPanel.EnqueueGesture(new GestureSample(
                                                  GestureType.DragComplete,
                                                  GetGestureTimestamp(),
                                                  Vector2.Zero,
                                                  Vector2.Zero,
                                                  Vector2.Zero,
                                                  Vector2.Zero,
                                                  fingerId,
                                                  TouchPanel.NO_FINGER
                                                  ));
                }
            }

            #endregion

            #region Belated Pinch Complete Detection

            if (callBelatedPinchComplete && IsGestureEnabled(GestureType.PinchComplete))
            {
                TouchPanel.EnqueueGesture(new GestureSample(
                                              GestureType.PinchComplete,
                                              GetGestureTimestamp(),
                                              Vector2.Zero,
                                              Vector2.Zero,
                                              Vector2.Zero,
                                              Vector2.Zero,
                                              TouchPanel.NO_FINGER,
                                              TouchPanel.NO_FINGER
                                              ));
            }
            callBelatedPinchComplete = false;

            #endregion

            // Reset the state if we're not anticipating a Double Tap
            if (state != GestureState.JUST_TAPPED)
            {
                state = GestureState.NONE;
            }

            eventTimestamp = DateTime.Now;
        }
Пример #3
0
        internal static void OnPressed(int fingerId, Vector2 touchPosition)
        {
            fingerIds.Add(fingerId);

            if (state == GestureState.PINCHING)
            {
                // None of this method applies to active pinches
                return;
            }

            // Set the active finger if there isn't one already
            if (activeFingerId == TouchPanel.NO_FINGER)
            {
                activeFingerId       = fingerId;
                activeFingerPosition = touchPosition;
            }
            else
            {
                #region Pinch Initialization

                if (IsGestureEnabled(GestureType.Pinch))
                {
                    // Initialize a Pinch
                    secondFingerId       = fingerId;
                    secondFingerPosition = touchPosition;

                    state = GestureState.PINCHING;
                }

                #endregion

                // No need to do anything more
                return;
            }

            #region Double Tap Detection

            if (state == GestureState.JUST_TAPPED)
            {
                if (IsGestureEnabled(GestureType.DoubleTap))
                {
                    // Must tap again within 300ms of original tap's release
                    TimeSpan timeSinceRelease = DateTime.Now - eventTimestamp;
                    if (timeSinceRelease <= TimeSpan.FromMilliseconds(300))
                    {
                        // If the new tap is close to the original tap
                        float distance = (touchPosition - pressPosition).Length();
                        if (distance <= MOVE_THRESHOLD)
                        {
                            // Double Tap!
                            TouchPanel.EnqueueGesture(new GestureSample(
                                                          GestureType.DoubleTap,
                                                          GetGestureTimestamp(),
                                                          touchPosition,
                                                          Vector2.Zero,
                                                          Vector2.Zero,
                                                          Vector2.Zero,
                                                          fingerId,
                                                          TouchPanel.NO_FINGER
                                                          ));

                            justDoubleTapped = true;
                        }
                    }
                }
            }

            #endregion

            state          = GestureState.HOLDING;
            pressPosition  = touchPosition;
            eventTimestamp = DateTime.Now;
        }
Пример #4
0
        internal static void OnUpdate()
        {
            if (state == GestureState.PINCHING)
            {
                /* Handle the case where the Pinch gesture
                 * was disabled *while* the user was pinching.
                 */
                if (!IsGestureEnabled(GestureType.Pinch))
                {
                    state          = GestureState.HELD;
                    secondFingerId = TouchPanel.NO_FINGER;

                    // Still might need to trigger a PinchComplete
                    callBelatedPinchComplete = true;
                }

                // No pinches allowed in the rest of this method!
                return;
            }

            // Must have an active finger to proceed
            if (activeFingerId == TouchPanel.NO_FINGER)
            {
                return;
            }

            #region Flick Velocity Calculation

            if (IsGestureEnabled(GestureType.Flick))
            {
                // We need one frame to pass so we can calculate delta time
                if (updateTimestamp != DateTime.MinValue)
                {
                    /* The calculation below is mostly taken from MonoGame.
                     * It accumulates velocity after running it through
                     * a low-pass filter to mitigate the effect of
                     * acceleration spikes. This works pretty well,
                     * but on rare occasions the velocity will still
                     * spike by an order of magnitude.
                     *
                     * In practice this tends to be a non-issue, but
                     * if you *really* need to avoid any spikes, you
                     * may want to consider normalizing the delta
                     * reported in the GestureSample and then scaling it
                     * to min(actualVectorLength, preferredMaxLength).
                     *
                     * -caleb
                     */

                    float   dt           = (float)(DateTime.Now - updateTimestamp).TotalSeconds;
                    Vector2 delta        = activeFingerPosition - lastUpdatePosition;
                    Vector2 instVelocity = delta / (0.001f + dt);
                    velocity += (instVelocity - velocity) * 0.45f;
                }

                lastUpdatePosition = activeFingerPosition;
                updateTimestamp    = DateTime.Now;
            }

            #endregion

            #region Hold Detection

            if (IsGestureEnabled(GestureType.Hold) && state == GestureState.HOLDING)
            {
                TimeSpan timeSincePress = DateTime.Now - eventTimestamp;
                if (timeSincePress >= TimeSpan.FromSeconds(1))
                {
                    // Hold!
                    TouchPanel.EnqueueGesture(new GestureSample(
                                                  Vector2.Zero,
                                                  Vector2.Zero,
                                                  GestureType.Hold,
                                                  activeFingerPosition,
                                                  Vector2.Zero,
                                                  GetGestureTimestamp(),
                                                  activeFingerId,
                                                  TouchPanel.NO_FINGER
                                                  ));

                    state = GestureState.HELD;
                }
            }

            #endregion
        }
Пример #5
0
        internal static void OnMoved(int fingerId, Vector2 touchPosition, Vector2 delta)
        {
            // Handle move events separately for Pinch gestures
            if (state == GestureState.PINCHING)
            {
                OnMoved_Pinch(fingerId, touchPosition, delta);
                return;
            }

            // Replace the active finger if we lost it
            if (activeFingerId == TouchPanel.NO_FINGER)
            {
                activeFingerId = fingerId;
            }

            // If this finger isn't the active finger
            if (fingerId != activeFingerId)
            {
                // We don't care about it
                return;
            }

            // Update the position
            activeFingerPosition = touchPosition;

            #region Prepare for Dragging

            // Determine which drag gestures are enabled
            bool hdrag = IsGestureEnabled(GestureType.HorizontalDrag);
            bool vdrag = IsGestureEnabled(GestureType.VerticalDrag);
            bool fdrag = IsGestureEnabled(GestureType.FreeDrag);

            if (state == GestureState.HOLDING || state == GestureState.HELD)
            {
                // Prevent accidental drags
                float distanceFromPress = (touchPosition - pressPosition).Length();
                if (distanceFromPress > MOVE_THRESHOLD)
                {
                    if (hdrag && (Math.Abs(delta.X) > Math.Abs(delta.Y)))
                    {
                        // Horizontal Drag!
                        state = GestureState.DRAGGING_H;
                    }
                    else if (vdrag && (Math.Abs(delta.Y) > Math.Abs(delta.X)))
                    {
                        // Vertical Drag!
                        state = GestureState.DRAGGING_V;
                    }
                    else if (fdrag)
                    {
                        // Free Drag!
                        state = GestureState.DRAGGING_FREE;
                    }
                    else
                    {
                        // No drag...
                        state = GestureState.NONE;
                    }
                }
            }

            #endregion

            #region Drag Detection

            if (state == GestureState.DRAGGING_H && hdrag)
            {
                // Horizontal Dragging!
                TouchPanel.EnqueueGesture(new GestureSample(
                                              new Vector2(delta.X, 0),
                                              Vector2.Zero,
                                              GestureType.HorizontalDrag,
                                              touchPosition,
                                              Vector2.Zero,
                                              GetGestureTimestamp(),
                                              fingerId,
                                              TouchPanel.NO_FINGER
                                              ));
            }
            else if (state == GestureState.DRAGGING_V && vdrag)
            {
                // Vertical Dragging!
                TouchPanel.EnqueueGesture(new GestureSample(
                                              new Vector2(0, delta.Y),
                                              Vector2.Zero,
                                              GestureType.VerticalDrag,
                                              touchPosition,
                                              Vector2.Zero,
                                              GetGestureTimestamp(),
                                              fingerId,
                                              TouchPanel.NO_FINGER
                                              ));
            }
            else if (state == GestureState.DRAGGING_FREE && fdrag)
            {
                // Free Dragging!
                TouchPanel.EnqueueGesture(new GestureSample(
                                              delta,
                                              Vector2.Zero,
                                              GestureType.FreeDrag,
                                              touchPosition,
                                              Vector2.Zero,
                                              GetGestureTimestamp(),
                                              fingerId,
                                              TouchPanel.NO_FINGER
                                              ));
            }

            #endregion

            #region Handle Disabled Drags

            /* Handle the case where the current drag type
             * was disabled *while* the user was dragging.
             */
            if ((state == GestureState.DRAGGING_H && !hdrag) ||
                (state == GestureState.DRAGGING_V && !vdrag) ||
                (state == GestureState.DRAGGING_FREE && !fdrag))
            {
                // Reset the state
                state = GestureState.HELD;
            }

            #endregion
        }
Пример #6
0
        private static void UpdateGestures(bool stateChanged)
        {
            int num1 = 0;

            foreach (TouchLocation touchLocation in TouchPanel._gestureState)
            {
                num1 += touchLocation.State != TouchLocationState.Released ? 1 : 0;
            }
            if (num1 > 1)
            {
                TouchPanel._tapDisabled  = true;
                TouchPanel._holdDisabled = true;
            }
            foreach (TouchLocation touch in TouchPanel._gestureState)
            {
                switch (touch.State)
                {
                case TouchLocationState.Moved:
                case TouchLocationState.Pressed:
                    if (touch.State != TouchLocationState.Pressed || !TouchPanel.ProcessDoubleTap(touch))
                    {
                        if (TouchPanel.GestureIsEnabled(GestureType.Pinch) && num1 > 1)
                        {
                            if (TouchPanel._pinchTouch[0].State == TouchLocationState.Invalid || TouchPanel._pinchTouch[0].Id == touch.Id)
                            {
                                TouchPanel._pinchTouch[0] = touch;
                                continue;
                            }
                            else if (TouchPanel._pinchTouch[1].State == TouchLocationState.Invalid || TouchPanel._pinchTouch[1].Id == touch.Id)
                            {
                                TouchPanel._pinchTouch[1] = touch;
                                continue;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            float num2 = Vector2.Distance(touch.Position, touch.PressPosition);
                            if (TouchPanel._dragGestureStarted == GestureType.None && (double)num2 < 35.0)
                            {
                                TouchPanel.ProcessHold(touch);
                                continue;
                            }
                            else if (stateChanged)
                            {
                                TouchPanel.ProcessDrag(touch);
                                continue;
                            }
                            else
                            {
                                continue;
                            }
                        }
                    }
                    else
                    {
                        continue;
                    }

                case TouchLocationState.Released:
                    if (stateChanged)
                    {
                        if (TouchPanel._pinchGestureStarted && (touch.Id == TouchPanel._pinchTouch[0].Id || touch.Id == TouchPanel._pinchTouch[1].Id))
                        {
                            if (TouchPanel.GestureIsEnabled(GestureType.PinchComplete))
                            {
                                TouchPanel.GestureList.Enqueue(new GestureSample(GestureType.PinchComplete, touch.Timestamp, Vector2.Zero, Vector2.Zero, Vector2.Zero, Vector2.Zero));
                            }
                            TouchPanel._pinchGestureStarted = false;
                            TouchPanel._pinchTouch[0]       = TouchLocation.Invalid;
                            TouchPanel._pinchTouch[1]       = TouchLocation.Invalid;
                            continue;
                        }
                        else if (num1 == 0)
                        {
                            if ((double)Vector2.Distance(touch.Position, touch.PressPosition) > 35.0 && ((double)touch.Velocity.Length() > 100.0 && TouchPanel.GestureIsEnabled(GestureType.Flick)))
                            {
                                TouchPanel.GestureList.Enqueue(new GestureSample(GestureType.Flick, touch.Timestamp, Vector2.Zero, Vector2.Zero, touch.Velocity, Vector2.Zero));
                                TouchPanel._dragGestureStarted = GestureType.None;
                                continue;
                            }
                            else if (TouchPanel._dragGestureStarted != GestureType.None)
                            {
                                if (TouchPanel.GestureIsEnabled(GestureType.DragComplete))
                                {
                                    TouchPanel.GestureList.Enqueue(new GestureSample(GestureType.DragComplete, touch.Timestamp, Vector2.Zero, Vector2.Zero, Vector2.Zero, Vector2.Zero));
                                }
                                TouchPanel._dragGestureStarted = GestureType.None;
                                continue;
                            }
                            else
                            {
                                TouchPanel.ProcessTap(touch);
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }

                default:
                    continue;
                }
            }
            if (!stateChanged)
            {
                return;
            }
            if (TouchPanel.GestureIsEnabled(GestureType.Pinch) && TouchPanel._pinchTouch[0].State != TouchLocationState.Invalid && TouchPanel._pinchTouch[1].State != TouchLocationState.Invalid)
            {
                TouchPanel.ProcessPinch(TouchPanel._pinchTouch);
            }
            else
            {
                TouchPanel._pinchGestureStarted = false;
                TouchPanel._pinchTouch[0]       = TouchLocation.Invalid;
                TouchPanel._pinchTouch[1]       = TouchLocation.Invalid;
            }
            if (num1 != 0)
            {
                return;
            }
            TouchPanel._tapDisabled        = false;
            TouchPanel._holdDisabled       = false;
            TouchPanel._dragGestureStarted = GestureType.None;
        }
Пример #7
0
 internal static void AddEvent(int id, TouchLocationState state, Vector2 position)
 {
     TouchPanel.AddEvent(id, state, position, false);
 }