//Init: private void Start() { //sets: _previousHand = handedness; //startup: if (!MLInput.IsStarted) { MLResult result = MLInput.Start(); if (!result.IsOk) { enabled = false; } } GetControl(); //hooks: MLInput.OnControllerConnected += HandleControlConnected; MLInput.OnControllerDisconnected += HandleControlDisconnected; }
//Loops: private void Update() { if (_previousHand != handedness) { _previousHand = handedness; GetControl(); } //no control? if (Control == null) { return; } //control pose: Position = Control.Position; Orientation = Control.Orientation; if (followControl) { transform.position = Position; transform.rotation = Orientation; } //touch cache: if (Control.Touch1Active) { _activeTouch = GetTouch1Info(); } //touch down: if (!Touch && Control.Touch1Active) { Touch = true; StartCoroutine("TouchHold"); //resets: TouchMoved = false; TouchRadialDelta = 0; //double - must be close to last touch and quick enough: float distanceFromLastTouchDown = Vector2.Distance(_activeTouch, TouchValue); float durationSinceLastTouch = Time.realtimeSinceStartup - _lastTouchTime; if (distanceFromLastTouchDown <= _maxDoubleTouchDistance && durationSinceLastTouch < _touchDoubleDuration) { OnDoubleTap?.Invoke(TouchValue); } //cache: TouchValue = _activeTouch; _touchBeganValue = TouchValue; _touchBeganTime = Time.realtimeSinceStartup; _lastTouchTime = Time.realtimeSinceStartup; OnTouchDown?.Invoke(TouchValue); } //touch movement: if (Touch) { //touch force delta tracking: if (_activeTouch.z != TouchValue.z) { //pressed enough to be a change? float delta = Mathf.Abs(_activeTouch.z - TouchValue.z); if (delta > _minForceDelta) { if (_activeTouch.z > TouchValue.z) { //touch is getting stronger: if (!ForceTouch && _activeTouch.z >= _forceTouchDownThreshold) { ForceTouch = true; _wasForceTouched = true; OnForceTouchDown?.Invoke(); } } else { //touch is getting weaker: if (ForceTouch && _activeTouch.z <= _forceTouchUpThreshold + _minForceDelta) { ForceTouch = false; OnForceTouchUp?.Invoke(); } } } } //since force touch can make values go crazy we ignore everything if it happened: if (!_wasForceTouched) { //did we have an intentional initial move? if (!TouchMoved) { //did we initially move far enough? float movedFromInitialTouchDistance = Vector2.Distance(_activeTouch, _touchBeganValue); if (movedFromInitialTouchDistance > _touchBeganMovingThreshold) { TouchMoved = true; OnTouchBeganMoving?.Invoke(); } } //only track subsequent moves if we initially began moving: if (TouchMoved) { //did we have an intentional move? float movedDistance = Vector2.Distance(TouchValue, _activeTouch); if (TouchValue != _activeTouch && movedDistance > 0 && movedDistance > _minTouchMove) { //moved: OnTouchMove?.Invoke(TouchValue); //radial move: float angleDelta = _activeTouch.w - TouchValue.w; if (OnTouchRadialMove != null) { TouchRadialDelta = angleDelta; OnTouchRadialMove?.Invoke(angleDelta); } //cache: TouchValue = _activeTouch; } } } } //touch up: if (!Control.Touch1Active && Touch) { //status: Touch = false; TouchMoved = false; TouchValue = _activeTouch; StopCoroutine("TouchHold"); //meta on touch sequence: Vector2 start = _touchBeganValue; Vector2 end = TouchValue; float distanceFromTouchStart = Vector2.Distance(start, end); float durationFromTouchStart = Time.realtimeSinceStartup - _touchBeganTime; //since force touch can make values go crazy we ignore everything if it happened: if (!_wasForceTouched) { //swipe determinations: if (distanceFromTouchStart >= _minSwipeDistance) { //swiped - we only calculate if the event is registered: if (OnSwipe != null) { //swipes must be quicker than _maxSwipeDuration: if (durationFromTouchStart < _maxSwipeDuration) { //get angle: Vector2 swipe = (end - start).normalized; float swipeAngle = Vector2.Angle(Vector2.up, swipe); //swiped to the left? then we need to continue to 360 degrees: if (end.x < start.x) { swipeAngle = 360 - swipeAngle; } //determine swipe direction: MLInputControllerTouchpadGestureDirection direction = MLInputControllerTouchpadGestureDirection.Left; if (swipeAngle > 315 || swipeAngle <= 45) { direction = MLInputControllerTouchpadGestureDirection.Up; } else if (swipeAngle > 45 && swipeAngle <= 135) { direction = MLInputControllerTouchpadGestureDirection.Right; } else if (swipeAngle > 135 && swipeAngle <= 225) { direction = MLInputControllerTouchpadGestureDirection.Down; } //radial swipe? if (Control.TouchpadGesture.Type == MLInputControllerTouchpadGestureType.RadialScroll) { direction = Control.TouchpadGesture.Direction; } OnSwipe?.Invoke(direction); } } } else { //tapped - we only calculate if the event is registered: if (OnTapped != null) { //taps must be quicker than _maxTapDuration: if (durationFromTouchStart < _maxTapDuration) { //determine tap location: MLInputControllerTouchpadGestureDirection direction = MLInputControllerTouchpadGestureDirection.Left; if (TouchValue.w > 315 || TouchValue.w <= 45) { direction = MLInputControllerTouchpadGestureDirection.Up; } else if (TouchValue.w > 45 && TouchValue.w <= 135) { direction = MLInputControllerTouchpadGestureDirection.Right; } else if (TouchValue.w > 135 && TouchValue.w <= 225) { direction = MLInputControllerTouchpadGestureDirection.Down; } OnTapped?.Invoke(direction); } } } } //we ultimately released so fire that event: OnTouchUp?.Invoke(TouchValue); //reset force touch activity on full release only to avoid any slight swipes at the end of release: _wasForceTouched = false; //if a user releases rapidly after a force press this will catch the release: if (ForceTouch) { ForceTouch = false; OnForceTouchUp?.Invoke(); } } //trigger: if (TriggerValue != Control.TriggerValue) { //trigger began moving: if (TriggerValue == 0) { OnTriggerPressBegan?.Invoke(); } //trigger moved: OnTriggerMove?.Invoke(Control.TriggerValue - TriggerValue); //trigger released: if (Control.TriggerValue == 0) { OnTriggerPressEnded?.Invoke(); } TriggerValue = Control.TriggerValue; } }