public TwoFingerGesture(NSSet touches, ARSCNView view, VirtualObject parentObject, VirtualObjectManager manager) : base(touches, view, parentObject, manager) { var tArray = touches.ToArray <UITouch>(); FirstTouch = tArray[0]; SecondTouch = tArray[1]; var firstTouchPoint = FirstTouch.LocationInView(SceneView); var secondTouchPoint = SecondTouch.LocationInView(SceneView); InitialMidpoint = firstTouchPoint.Add(secondTouchPoint).Divide(2f); // Compute the two other corners of the rectangle defined by the two fingers // and compute the points in between. var thirdCorner = new CGPoint(firstTouchPoint.X, secondTouchPoint.Y); var fourthCorner = new CGPoint(secondTouchPoint.X, firstTouchPoint.Y); // Compute points in between. var midpoints = new[] { thirdCorner.Add(firstTouchPoint).Divide(2f), thirdCorner.Add(secondTouchPoint).Divide(2f), fourthCorner.Add(firstTouchPoint).Divide(2f), fourthCorner.Add(secondTouchPoint).Divide(2f), InitialMidpoint.Add(firstTouchPoint).Divide(2f), InitialMidpoint.Add(secondTouchPoint).Divide(2f), InitialMidpoint.Add(thirdCorner).Divide(2f), InitialMidpoint.Add(fourthCorner).Divide(2f) }; // Check if any of the two fingers or their midpoint is touching the object. // Based on that, translation, rotation and scale will be enabled or disabled. var allPoints = new List <CGPoint>(new[] { firstTouchPoint, secondTouchPoint, thirdCorner, fourthCorner, InitialMidpoint }); allPoints.AddRange(midpoints); FirstTouchedObject = allPoints.Select(pt => this.VirtualObjectAt(pt)).Where(vo => vo != null).FirstOrDefault(); if (FirstTouchedObject != null) { ObjectBaseScale = FirstTouchedObject.Scale.X; AllowTranslation = true; AllowRotation = true; InitialDistanceBetweenFingers = (firstTouchPoint.Subtract(secondTouchPoint)).Length(); InitialFingerAngle = Math.Atan2(InitialMidpoint.X, InitialMidpoint.Y); InitialObjectAngle = FirstTouchedObject.EulerAngles.Y; } else { AllowTranslation = false; AllowRotation = false; } }
override protected void UpdateGesture(object state) { // Two finger touch enables combined translation, rotation and scale. if (FirstTouchedObject == null) { return; } var virtualObject = FirstTouchedObject; // First: Update the touches. if (currentTouches.Count < 2) { return; } var tAry = currentTouches.ToArray <UITouch>(); var newTouch1 = tAry[0]; var newTouch2 = tAry[1]; if (newTouch1.GetHashCode() == FirstTouch.GetHashCode()) { FirstTouch = newTouch1; SecondTouch = newTouch2; } else { FirstTouch = newTouch2; SecondTouch = newTouch1; } InvokeOnMainThread(() => { var loc1 = FirstTouch.LocationInView(SceneView); var loc2 = SecondTouch.LocationInView(SceneView); if (AllowTranslation) { // 1. Translation using the midpoint between the two fingers. UpdateTranslation(virtualObject, loc1.MidPoint(loc2)); } var spanBetweenTouches = loc1.Subtract(loc2); if (AllowRotation) { // 2. Rotation based on the relative rotation of the fingers on a unit circle. UpdateRotation(virtualObject, spanBetweenTouches); } }); }