private bool ProcessDoubleTap(TouchLocation touch) { if (!GestureIsEnabled(GestureType.DoubleTap) || _tapDisabled || _lastTap.State == TouchLocationState.Invalid) { return(false); } // If the new tap is too far away from the last then // this cannot be a double tap event. var dist = Vector2.Distance(touch.Position, _lastTap.Position); if (dist > TapJitterTolerance) { return(false); } // Check that this tap happened within the standard // double tap time threshold of 300 milliseconds. var elapsed = touch.Timestamp - _lastTap.Timestamp; if (elapsed.TotalMilliseconds > 300) { return(false); } GestureList.Enqueue(new GestureSample( GestureType.DoubleTap, touch.Timestamp, touch.Position, Vector2.Zero, Vector2.Zero, Vector2.Zero)); // Disable taps until after the next release. _tapDisabled = true; return(true); }
/// <summary> /// Apply the given new touch to the state. If it is a Pressed it will be added as a new touch, otherwise we update the existing touch it matches /// </summary> private void ApplyTouch(List <TouchLocation> state, TouchLocation touch) { if (touch.State == TouchLocationState.Pressed) { state.Add(touch); return; } //Find the matching touch for (var i = 0; i < state.Count; i++) { var existingTouch = state[i]; if (existingTouch.Id == touch.Id) { //If we are moving straight from Pressed to Released and we've existed for multiple frames, that means we've never been seen, so just get rid of us if (existingTouch.State == TouchLocationState.Pressed && touch.State == TouchLocationState.Released && existingTouch.PressTimestamp != touch.Timestamp) { state.RemoveAt(i); } else { //Otherwise update the touch based on the new one existingTouch.UpdateState(touch); state[i] = existingTouch; } break; } } }
private void ProcessTap(TouchLocation touch) { if (_tapDisabled) { return; } // If the release is too far away from the press // position then this cannot be a tap event. var dist = Vector2.Distance(touch.PressPosition, touch.Position); if (dist > TapJitterTolerance) { return; } // If we pressed and held too long then don't // generate a tap event for it. var elapsed = CurrentTimestamp - touch.PressTimestamp; if (elapsed > TimeRequiredForHold) { return; } // Store the last tap for // double tap processing. _lastTap = touch; // Fire off the tap event immediately. if (GestureIsEnabled(GestureType.Tap)) { var tap = new GestureSample( GestureType.Tap, touch.Timestamp, touch.Position, Vector2.Zero, Vector2.Zero, Vector2.Zero); GestureList.Enqueue(tap); } }
private void ProcessHold(TouchLocation touch) { if (!GestureIsEnabled(GestureType.Hold) || _holdDisabled) { return; } var elapsed = CurrentTimestamp - touch.PressTimestamp; if (elapsed < TimeRequiredForHold) { return; } _holdDisabled = true; GestureList.Enqueue( new GestureSample(GestureType.Hold, touch.Timestamp, touch.Position, Vector2.Zero, Vector2.Zero, Vector2.Zero)); }
private void ProcessDrag(TouchLocation touch) { var dragH = GestureIsEnabled(GestureType.HorizontalDrag); var dragV = GestureIsEnabled(GestureType.VerticalDrag); var dragF = GestureIsEnabled(GestureType.FreeDrag); if (!dragH && !dragV && !dragF) { return; } // Make sure this is a move event and that we have // a previous touch location. TouchLocation prevTouch; if (touch.State != TouchLocationState.Moved || !touch.TryGetPreviousLocation(out prevTouch)) { return; } var delta = touch.Position - prevTouch.Position; // If we're free dragging then stick to it. if (_dragGestureStarted != GestureType.FreeDrag) { var isHorizontalDelta = Math.Abs(delta.X) > Math.Abs(delta.Y * 2.0f); var isVerticalDelta = Math.Abs(delta.Y) > Math.Abs(delta.X * 2.0f); var classify = _dragGestureStarted == GestureType.None; // Once we enter either vertical or horizontal drags // we stick to it... regardless of the delta. if (dragH && ((classify && isHorizontalDelta) || _dragGestureStarted == GestureType.HorizontalDrag)) { delta.Y = 0; _dragGestureStarted = GestureType.HorizontalDrag; } else if (dragV && ((classify && isVerticalDelta) || _dragGestureStarted == GestureType.VerticalDrag)) { delta.X = 0; _dragGestureStarted = GestureType.VerticalDrag; } // If the delta isn't either horizontal or vertical //then it could be a free drag if not classified. else if (dragF && classify) { _dragGestureStarted = GestureType.FreeDrag; } else { // If we couldn't classify the drag then // it is nothing... set it to complete. _dragGestureStarted = GestureType.DragComplete; } } // If the drag could not be classified then no gesture. if (_dragGestureStarted == GestureType.None || _dragGestureStarted == GestureType.DragComplete) { return; } _tapDisabled = true; _holdDisabled = true; GestureList.Enqueue(new GestureSample( _dragGestureStarted, touch.Timestamp, touch.Position, Vector2.Zero, delta, Vector2.Zero)); }
internal void AddEvent(int id, TouchLocationState state, Vector2 position, bool isMouse) { // Different platforms return different touch identifiers // based on the specifics of their implementation and the // system drivers. // // Sometimes these ids are suitable for our use, but other // times it can recycle ids or do cute things like return // the same id for double tap events. // // We instead provide consistent ids by generating them // ourselves on the press and looking them up on move // and release events. // if (state == TouchLocationState.Pressed) { if (isMouse) { // Mouse pointing devices always use a reserved Id _touchIds[id] = MouseTouchId; } else { _touchIds[id] = _nextTouchId++; } } // Try to find the touch id. int touchId; if (!_touchIds.TryGetValue(id, out touchId)) { // If we got here that means either the device is sending // us bad, out of order, or old touch events. In any case // just ignore them. return; } if (!isMouse || EnableMouseTouchPoint || EnableMouseGestures) { // Add the new touch event keeping the list from getting // too large if no one happens to be requesting the state. var evt = new TouchLocation(touchId, state, position * _touchScale, CurrentTimestamp); if (!isMouse || EnableMouseTouchPoint) { ApplyTouch(_touchState, evt); } //If we have gestures enabled then collect events for those too. //We also have to keep tracking any touches while we know about touches so we don't miss releases even if gesture recognition is disabled if ((EnabledGestures != GestureType.None || _gestureState.Count > 0) && (!isMouse || EnableMouseGestures)) { ApplyTouch(_gestureState, evt); if (EnabledGestures != GestureType.None) { UpdateGestures(true); } AgeTouches(_gestureState); } } // If this is a release unmap the hardware id. if (state == TouchLocationState.Released) { _touchIds.Remove(id); } }