示例#1
0
                public InertiaProcessor(Manipulation owner, Point position, ManipulationDelta cumulative, ManipulationVelocities velocities)
                {
                    _owner       = owner;
                    _position0   = position;
                    _cumulative0 = cumulative;
                    _velocities0 = velocities;

                    _isTranslateInertiaXEnabled = _owner._isTranslateXEnabled &&
                                                  _owner._settings.HasFlag(Input.GestureSettings.ManipulationTranslateInertia) &&
                                                  Abs(velocities.Linear.X) > _owner._inertiaThresholds.TranslateX;
                    _isTranslateInertiaYEnabled = _owner._isTranslateYEnabled &&
                                                  _owner._settings.HasFlag(Input.GestureSettings.ManipulationTranslateInertia) &&
                                                  Abs(velocities.Linear.Y) > _owner._inertiaThresholds.TranslateY;
                    _isRotateInertiaEnabled = _owner._isRotateEnabled &&
                                              _owner._settings.HasFlag(Input.GestureSettings.ManipulationRotateInertia) &&
                                              Abs(velocities.Angular) > _owner._inertiaThresholds.Rotate;
                    _isScaleInertiaEnabled = _owner._isScaleEnabled &&
                                             _owner._settings.HasFlag(Input.GestureSettings.ManipulationScaleInertia) &&
                                             Abs(velocities.Expansion) > _owner._inertiaThresholds.Expansion;

                    global::System.Diagnostics.Debug.Assert(_isTranslateInertiaXEnabled || _isTranslateInertiaYEnabled || _isRotateInertiaEnabled || _isScaleInertiaEnabled);

                    // For better experience, as soon inertia kicked-in on an axis, we bypass threshold on the second axis.
                    _isTranslateInertiaXEnabled |= _isTranslateInertiaYEnabled && _owner._isTranslateXEnabled;
                    _isTranslateInertiaYEnabled |= _isTranslateInertiaXEnabled && _owner._isTranslateYEnabled;

                    _timer             = DispatcherQueue.GetForCurrentThread().CreateTimer();
                    _timer.Interval    = TimeSpan.FromMilliseconds(1000d / _framesPerSecond);
                    _timer.IsRepeating = true;
                    _timer.Tick       += (snd, e) => Process(snd.LastTickElapsed.TotalMilliseconds);
                }
示例#2
0
 internal ManipulationInertiaStartingEventArgs(PointerDeviceType pointerDeviceType, Point position, ManipulationDelta delta, ManipulationDelta cumulative)
 {
     PointerDeviceType = pointerDeviceType;
     Position          = position;
     Delta             = delta;
     Cumulative        = cumulative;
 }
            private void NotifyUpdate(bool pointerAdded = false)
            {
                // Note: Make sure to update the _sumOfPublishedDelta before raising the event, so if an exception is raised
                //		 or if the manipulation is Completed, the Complete event args can use the updated _sumOfPublishedDelta.

                var cumulative = GetCumulative();

                switch (_state)
                {
                case ManipulationState.Starting when pointerAdded:
                    _state = ManipulationState.Started;
                    _sumOfPublishedDelta = cumulative;

                    _recognizer.ManipulationStarted?.Invoke(
                        _recognizer,
                        new ManipulationStartedEventArgs(_deviceType, _currents.Center, cumulative));

                    // No needs to publish an update when we start the manipulation due to an additional pointer as cumulative will be empty.

                    break;

                case ManipulationState.Starting when cumulative.IsSignificant(_startThresholds):
                    _state = ManipulationState.Started;

                    _sumOfPublishedDelta = cumulative;

                    // Note: We first start with an empty delta, then invoke Update.
                    //		 This is required to patch a common issue in applications that are using only the
                    //		 ManipulationUpdated.Delta property to track the pointer (like the WCT GridSplitter).
                    //		 UWP seems to do that only for Touch and Pen (i.e. the Delta is not empty on start with a mouse),
                    //		 but there is no side effect to use the same behavior for all pointer types.
                    _recognizer.ManipulationStarted?.Invoke(
                        _recognizer,
                        new ManipulationStartedEventArgs(_deviceType, _origins.Center, ManipulationDelta.Empty));
                    _recognizer.ManipulationUpdated?.Invoke(
                        _recognizer,
                        new ManipulationUpdatedEventArgs(_deviceType, _currents.Center, cumulative, cumulative, isInertial: false));

                    break;

                case ManipulationState.Started:
                    // Even if Scale and Angle are expected to be default when we add a pointer (i.e. forceUpdate == true),
                    // the 'delta' and 'cumulative' might still contains some TranslateX|Y compared to the previous Pointer1 location.
                    var delta = GetDelta(cumulative);

                    if (pointerAdded || delta.IsSignificant(_deltaThresholds))
                    {
                        _sumOfPublishedDelta = _sumOfPublishedDelta.Add(delta);

                        _recognizer.ManipulationUpdated?.Invoke(
                            _recognizer,
                            new ManipulationUpdatedEventArgs(_deviceType, _currents.Center, delta, cumulative, isInertial: false));
                    }
                    break;
                }
            }
示例#4
0
 internal static ManipulationDelta Add(ManipulationDelta left, ManipulationDelta right)
 => new ManipulationDelta
 {
     Translation = new Point(
         left.Translation.X + right.Translation.X,
         left.Translation.Y + right.Translation.Y),
     Rotation  = left.Rotation + right.Rotation,
     Scale     = left.Scale * right.Scale,
     Expansion = left.Expansion + right.Expansion
 };
示例#5
0
 internal ManipulationCompletedEventArgs(
     PointerDeviceType pointerDeviceType,
     Point position,
     ManipulationDelta cumulative,
     bool isInertial)
 {
     PointerDeviceType = pointerDeviceType;
     Position          = position;
     Cumulative        = cumulative;
     IsInertial        = isInertial;
 }
示例#6
0
        internal ManipulationStartedEventArgs(
            PointerIdentifier[] pointers,
            Point position,
            ManipulationDelta cumulative,
            uint contactCount)
        {
            global::System.Diagnostics.Debug.Assert(contactCount == pointers.Length, "We should have the same number of pointers for the manip start.");
            global::System.Diagnostics.Debug.Assert(pointers.Length > 0 && pointers.All(p => p.Type == pointers[0].Type));

            Pointers          = pointers;
            PointerDeviceType = pointers[0].Type;
            Position          = position;
            Cumulative        = cumulative;
            ContactCount      = contactCount;
        }
示例#7
0
            private ManipulationDelta GetDelta(ManipulationDelta cumulative)
            {
                var deltaSum = _sumOfPublishedDelta;

                var translateX = _isTranslateXEnabled ? cumulative.Translation.X - deltaSum.Translation.X : 0;
                var translateY = _isTranslateYEnabled ? cumulative.Translation.Y - deltaSum.Translation.Y : 0;
                var rotate     = _isRotateEnabled ? cumulative.Rotation - deltaSum.Rotation : 0;
                var scale      = _isScaleEnabled ? cumulative.Scale / deltaSum.Scale : 1;
                var expansion  = _isScaleEnabled ? cumulative.Expansion - deltaSum.Expansion : 0;

                return(new ManipulationDelta
                {
                    Translation = new Point(translateX, translateY),
                    Rotation = (float)MathEx.NormalizeDegree(rotate),
                    Scale = scale,
                    Expansion = expansion
                });
            }
示例#8
0
                private ManipulationDelta GetInertiaCumulative(double t, ManipulationDelta previousCumulative)
                {
                    var linearX   = GetValue(_isTranslateInertiaXEnabled, _velocities0.Linear.X, DesiredDisplacementDeceleration, t, (float)previousCumulative.Translation.X);
                    var linearY   = GetValue(_isTranslateInertiaYEnabled, _velocities0.Linear.Y, DesiredDisplacementDeceleration, t, (float)previousCumulative.Translation.Y);
                    var angular   = GetValue(_isRotateInertiaEnabled, _velocities0.Angular, DesiredRotationDeceleration, t, previousCumulative.Rotation);
                    var expansion = GetValue(_isScaleInertiaEnabled, _velocities0.Expansion, DesiredExpansionDeceleration, t, previousCumulative.Expansion);

                    var scale = _isScaleInertiaEnabled ? (_owner._origins.Distance + expansion) / _owner._origins.Distance : 1;

                    var delta = new ManipulationDelta
                    {
                        Translation = new Point(linearX, linearY),
                        Rotation    = angular,
                        Expansion   = expansion,
                        Scale       = scale
                    };

                    return(delta);
                }
        internal ManipulationCompletedEventArgs(
            PointerIdentifier[] pointers,
            Point position,
            ManipulationDelta cumulative,
            ManipulationVelocities velocities,
            bool isInertial,
            uint contactCount,
            uint currentContactCount)
        {
            global::System.Diagnostics.Debug.Assert(pointers.Length > 0 && pointers.All(p => p.Type == pointers[0].Type));

            Pointers            = pointers;
            Position            = position;
            Cumulative          = cumulative;
            Velocities          = velocities;
            IsInertial          = isInertial;
            ContactCount        = contactCount;
            CurrentContactCount = currentContactCount;
        }
        internal ManipulationInertiaStartingEventArgs(
            PointerIdentifier[] pointers,
            Point position,
            ManipulationDelta delta,
            ManipulationDelta cumulative,
            ManipulationVelocities velocities,
            uint contactCount,
            GestureRecognizer.Manipulation.InertiaProcessor processor)
        {
            global::System.Diagnostics.Debug.Assert(pointers.Length > 0 && pointers.All(p => p.Type == pointers[0].Type));

            Pointers          = pointers;
            PointerDeviceType = pointers[0].Type;
            Position          = position;
            Delta             = delta;
            Cumulative        = cumulative;
            Velocities        = velocities;
            ContactCount      = contactCount;
            Processor         = processor;
        }
示例#11
0
                private void Process(double t)
                {
                    // First we update the internal state (i.e. the current cumulative manip delta for the current time)
                    var previous = _inertiaCumulative;
                    var current  = GetInertiaCumulative(t, previous);

                    _inertiaCumulative = current;

                    // Then we request to the owner to raise its events (will cause the GetCumulative())
                    // We notify in any cases in order to make sure to raise at least one ManipDelta (even if Delta.IsEmpty ^^) before stop the processor
                    _owner.NotifyUpdate();

                    if (previous.Translation.X == current.Translation.X &&
                        previous.Translation.Y == current.Translation.Y &&
                        previous.Rotation == current.Rotation &&
                        previous.Expansion == current.Expansion)                            // Note: we DO NOT compare the scaling, expansion is enough here!
                    {
                        _timer.Stop();
                        _owner.NotifyUpdate();
                    }
                }
示例#12
0
 public FlickingEventArgs(FlickDirection direction, ManipulationDelta delta)
 {
     Direction = direction;
     Delta = delta;
     CanContinue = true;
 }
示例#13
0
            private void NotifyUpdate(bool pointerAdded = false)
            {
                // Note: Make sure to update the _sumOfPublishedDelta before raising the event, so if an exception is raised
                //		 or if the manipulation is Completed, the Complete event args can use the updated _sumOfPublishedDelta.

                var cumulative = GetCumulative();

                switch (_state)
                {
                case ManipulationState.Starting when IsBeginningOfDragManipulation():
                    // On UWP if the element was configured to allow both Drag and Manipulations,
                    // both events are going to be raised (... until the drag "content" is being render an captures all pointers).
                    // This results as a manipulation started which is never completed.
                    // If user uses double touch the manipulation will however start and complete when user adds / remove the 2nd finger.
                    // On Uno, as allowing both Manipulations and drop on the same element is really a stretch case (and is bugish on UWP),
                    // we accept as a known limitation that once dragging started no manipulation event would be fired.
                    _state = ManipulationState.Started;

                    IsDragManipulation = true;

                    _recognizer.Dragging?.Invoke(
                        _recognizer,
                        new DraggingEventArgs(_currents.Pointer1, DraggingState.Started));
                    break;

                case ManipulationState.Starting when pointerAdded:
                    _state = ManipulationState.Started;
                    _sumOfPublishedDelta = cumulative;

                    _recognizer.ManipulationStarted?.Invoke(
                        _recognizer,
                        new ManipulationStartedEventArgs(_deviceType, _currents.Center, cumulative));

                    // No needs to publish an update when we start the manipulation due to an additional pointer as cumulative will be empty.

                    break;

                case ManipulationState.Starting when cumulative.IsSignificant(_startThresholds):
                    _state = ManipulationState.Started;

                    _sumOfPublishedDelta = cumulative;

                    // Note: We first start with an empty delta, then invoke Update.
                    //		 This is required to patch a common issue in applications that are using only the
                    //		 ManipulationUpdated.Delta property to track the pointer (like the WCT GridSplitter).
                    //		 UWP seems to do that only for Touch and Pen (i.e. the Delta is not empty on start with a mouse),
                    //		 but there is no side effect to use the same behavior for all pointer types.
                    _recognizer.ManipulationStarted?.Invoke(
                        _recognizer,
                        new ManipulationStartedEventArgs(_deviceType, _origins.Center, ManipulationDelta.Empty));
                    _recognizer.ManipulationUpdated?.Invoke(
                        _recognizer,
                        new ManipulationUpdatedEventArgs(_deviceType, _currents.Center, cumulative, cumulative, isInertial: false));

                    break;

                case ManipulationState.Started when IsDragManipulation:
                    _recognizer.Dragging?.Invoke(
                        _recognizer,
                        new DraggingEventArgs(_currents.Pointer1, DraggingState.Continuing));
                    break;

                case ManipulationState.Started:
                    // Even if Scale and Angle are expected to be default when we add a pointer (i.e. forceUpdate == true),
                    // the 'delta' and 'cumulative' might still contains some TranslateX|Y compared to the previous Pointer1 location.
                    var delta = GetDelta(cumulative);

                    if (pointerAdded || delta.IsSignificant(_deltaThresholds))
                    {
                        _sumOfPublishedDelta = _sumOfPublishedDelta.Add(delta);

                        _recognizer.ManipulationUpdated?.Invoke(
                            _recognizer,
                            new ManipulationUpdatedEventArgs(_deviceType, _currents.Center, delta, cumulative, isInertial: false));
                    }
                    break;
                }
            }
示例#14
0
 private bool IsSignificant(ManipulationDelta delta)
 => Math.Abs(delta.Translation.X) >= MinManipulationDeltaTranslateX ||
 Math.Abs(delta.Translation.Y) >= MinManipulationDeltaTranslateY ||
 delta.Rotation >= MinManipulationDeltaRotate ||                     // We used the ToDegreeNormalized, no need to check for negative angles
 Math.Abs(delta.Expansion) >= MinManipulationDeltaExpansion;
示例#15
0
 internal ManipulationStartedEventArgs(PointerDeviceType pointerDeviceType, Point position, ManipulationDelta cumulative)
 {
     PointerDeviceType = pointerDeviceType;
     Position          = position;
     Cumulative        = cumulative;
 }
示例#16
0
 private DragLock GetDragLockForMove(ManipulationDelta cumulative)
 {
     if (!this.dragging)
     {
         this.ReleaseMouseCaptureAtGestureOrigin();
     }
     this.dragging = true;
     if (this.dragLock == DragLock.Unset)
     {
         double num = GestureService.AngleFromVector(cumulative.Translation.X, cumulative.Translation.Y) % 180.0;
         this.dragLock = num <= 45.0 || num >= 135.0 ? DragLock.Horizontal : DragLock.Vertical;
     }
     return this.dragLock;
 }
示例#17
0
 protected virtual GestureEnd EndMove(bool isInertial, ManipulationDelta cumulative, ManipulationVelocities velocities, Point position)
 {
     this.dragLock = DragLock.Unset;
     this.dragging = false;
     double angle = 0.0;
     if (isInertial)
     {
         angle = GestureService.AngleFromVector(velocities.Linear.X, velocities.Linear.Y);
         if (angle <= 45.0 || angle >= 315.0)
         {
             angle = 0.0;
         }
         else if (angle >= 135.0 && angle <= 225.0)
         {
             angle = 180.0;
         }
         this.ReleaseMouseCaptureAtGestureOrigin();
     }
     return new GestureEnd(angle, isInertial, cumulative.Translation, position);
 }
示例#18
0
 internal ManipulationDelta Add(ManipulationDelta right) => Add(this, right);