/// <summary>
 /// Populates the event with data.
 /// </summary>
 /// <param name="inputSource"></param>
 /// <param name="controller"></param>
 /// <param name="pose"></param>
 public void Initialize(IMixedRealityInputSource inputSource, IMixedRealityController controller, MixedRealityPose pose)
 {
     Initialize(inputSource, controller);
     ThreeDofPosition = pose.Position;
     ThreeDofRotation = pose.Rotation;
     MixedRealityPose = pose;
 }
Beispiel #2
0
        /// <inheritdoc />
        public override void SolverUpdate()
        {
            // Determine the new active hand.
            IMixedRealityController newActivehand = null;

            foreach (var hand in handStack)
            {
                if (IsHandActive(hand))
                {
                    newActivehand = hand;
                    break;
                }
            }

            // Track the new active hand.
            if (trackedHand == null || trackedHand != newActivehand)
            {
                ChangeTrackedObjectType(newActivehand);
            }

            // Update the goal position and rotation if a tracked hand is present.
            if (trackedHand != null && SolverHandler.TransformTarget != null)
            {
                if (updateWhenOppositeHandNear || !IsOppositeHandNear(trackedHand))
                {
                    GoalPosition = CalculateGoalPosition();
                    GoalRotation = CalculateGoalRotation();
                }
            }


            UpdateWorkingPositionToGoal();
            UpdateWorkingRotationToGoal();
        }
Beispiel #3
0
        private static T CreatePointerPrefab <T>(string prefabPath,
                                                 out IMixedRealityInputSource inputSource,
                                                 out IMixedRealityController controller)
            where T : IMixedRealityPointer
        {
            var pointerPrefab = AssetDatabase.LoadAssetAtPath <Object>(prefabPath);
            var result        = PrefabUtility.InstantiatePrefab(pointerPrefab) as GameObject;
            T   pointer       = result.GetComponent <T>();

            inputSource = CoreServices.InputSystem.RequestNewGenericInputSource(
                pointer.PointerName,
                new IMixedRealityPointer[] { pointer });

            // use MouseController as dummy wrapper controller
            controller = new MouseController(TrackingState.Tracked, Handedness.Right, inputSource);

            if (inputSource != null)
            {
                for (int i = 0; i < inputSource.Pointers.Length; i++)
                {
                    inputSource.Pointers[i].Controller = controller;
                }
            }

            CoreServices.InputSystem.RaiseSourceDetected(inputSource, controller);
            CoreServices.InputSystem?.RaiseSourceTrackingStateChanged(inputSource, controller, TrackingState.Tracked);

            return(pointer);
        }
 protected void RemoveController(IMixedRealityController controller)
 {
     if (controller != null)
     {
         activeControllers.Remove(controller);
     }
 }
    private static bool IsGgvOrDesktopController(IMixedRealityController controller)
    {
        return(controller is WindowsMixedRealityGGVHand ||
               controller is MouseController
# if UNITY_EDITOR
//                        || controller is SimulatedArticulatedHand
#endif
               );
    }
        private MixedRealityInteractionMapping GetSpatialGripInfoForController(IMixedRealityController controller)
        {
            if (controller == null)
            {
                return(null);
            }

            return(controller.Interactions?.First(x => x.InputType == DeviceInputType.SpatialGrip));
        }
        /// <summary>
        /// Starts to track the passed in controller's transform, assuming it meets the previously set handedness criteria.
        /// </summary>
        /// <param name="newController">The new controller to be tracked.</param>
        protected virtual void AddControllerTransform(IMixedRealityController newController)
        {
            if (newController.ControllerHandedness == handedness && newController.Visualizer.GameObjectProxy.transform != null && !newController.Visualizer.GameObjectProxy.transform.Equals(ControllerTransform))
            {
                ControllerTransform = newController.Visualizer.GameObjectProxy.transform;

                OnControllerFound();
            }
        }
Beispiel #8
0
        protected override void OnEnable()
        {
            base.OnEnable();

            handBounds = GetComponent <HandBounds>();

            // Initially no hands are tacked or active.
            trackedController = null;
            OnLastHandLost.Invoke();
            OnHandDeactivate.Invoke();
        }
Beispiel #9
0
        protected override void OnEnable()
        {
            base.OnEnable();
            InputSystem?.RegisterHandler <IMixedRealitySourceStateHandler>(this);

            handBounds = GetComponent <HandBounds>();

            // Initially no hands are tacked or active.
            trackedHand = null;
            onLastHandLost?.Invoke();
            onHandDeactivate?.Invoke();
        }
Beispiel #10
0
        private static bool IsPalmFacingCamera(IMixedRealityController hand)
        {
            MixedRealityPose palmPose;
            var jointedHand = hand as IMixedRealityHand;

            if ((jointedHand != null) && jointedHand.TryGetJoint(TrackedHandJoint.Palm, out palmPose))
            {
                return(Vector3.Dot(palmPose.Up, CameraCache.Main.transform.forward) > 0.0f);
            }

            return(false);
        }
    public bool GetTransForm(out Vector3 _fingerposition)
    {
        IMixedRealityController c = GetController(Handedness.Left);
        var jointedHand           = c as IMixedRealityHand;
        MixedRealityPose MiddleDistalParm;

        if (jointedHand.TryGetJoint(handjoint, out MiddleDistalParm))
        {
            _fingerposition = MiddleDistalParm.Position;
            return(true);
        }
        _fingerposition = new Vector3(0, 0, 0);
        return(false);
    }
        /// <summary>
        /// Gets the <seealso cref="MixedRealityInteractionMapping"/> matching the <seealso cref="DeviceInputType"/> for
        /// the specified controller.
        /// </summary>
        /// <param name="controller">The <seealso cref="IMixedRealityController"/> instance</param>
        /// <param name="inputType">The type of device input</param>
        /// <param name="mapping">The <seealso cref="MixedRealityInteractionMapping"/> being returned</param>
        /// <returns>
        /// True if the interaction mapping is being returned, false otherwise.
        /// </returns>
        private static bool TryGetInteractionMapping(IMixedRealityController controller, DeviceInputType inputType, out MixedRealityInteractionMapping mapping)
        {
            mapping = null;

            MixedRealityInteractionMapping[] mappings = controller.Interactions;
            for (int i = 0; i < mappings.Length; i++)
            {
                if (mappings[i].InputType == inputType)
                {
                    mapping = mappings[i];
                    return(true);
                }
            }

            return(false);
        }
    private void SetController(IMixedRealityController controller)
    {
        IMixedRealityHand       hand         = controller as IMixedRealityHand;
        IMixedRealityController mrcontroller = controller as IMixedRealityController;

        if (hand != null)
        {
            try
            {
                detectedHand = hand;

                if (controller.ControllerHandedness == Handedness.Left)
                {
                    leftHand = hand;
                }
                else if (controller.ControllerHandedness == Handedness.Right)
                {
                    rightHand = hand;
                }
            }
            catch (Exception)
            {
                //Debug.Log("Missed a hand, retrying");
            }
        }
        else if (mrcontroller != null)
        {
            try
            {
                detectedController = mrcontroller;

                if (controller.ControllerHandedness == Handedness.Left)
                {
                    leftController = mrcontroller;
                }
                else if (controller.ControllerHandedness == Handedness.Right)
                {
                    rightController = mrcontroller;
                }
            }
            catch (Exception)
            {
                //Debug.Log("Missed a controller, retrying");
            }
        }
    }
Beispiel #14
0
        private static Ray CalculateProjectedSafeZoneRay(Vector3 origin, IMixedRealityController hand, SolverSafeZone handSafeZone)
        {
            Vector3 direction;

            switch (handSafeZone)
            {
            default:
            case SolverSafeZone.UlnarSide:
            {
                direction = Vector3.Cross(CameraCache.Main.transform.forward, Vector3.up);
                direction = IsPalmFacingCamera(hand) ? direction : -direction;

                if (hand.ControllerHandedness == Handedness.Left)
                {
                    direction = -direction;
                }
            }
            break;

            case SolverSafeZone.RadialSide:
            {
                direction = Vector3.Cross(CameraCache.Main.transform.forward, Vector3.up);
                direction = IsPalmFacingCamera(hand) ? direction : -direction;

                if (hand.ControllerHandedness == Handedness.Right)
                {
                    direction = -direction;
                }
            }
            break;

            case SolverSafeZone.AboveFingerTips:
            {
                direction = CameraCache.Main.transform.up;
            }
            break;

            case SolverSafeZone.BelowWrist:
            {
                direction = -CameraCache.Main.transform.up;
            }
            break;
            }

            return(new Ray(origin + direction, -direction));
        }
        /// <inheritdoc />
        public override void Update()
        {
            using (UpdatePerfMarker.Auto())
            {
                if (!IsEnabled)
                {
                    return;
                }

                base.Update();

                // Ensure that touch up and source lost events are at least one frame apart.
                for (int i = 0; i < touchesToRemove.Count; i++)
                {
                    IMixedRealityController controller = touchesToRemove[i];
                    Service?.RaiseSourceLost(controller.InputSource, controller);
                }
                touchesToRemove.Clear();

                int touchCount = UInput.touchCount;
                for (int i = 0; i < touchCount; i++)
                {
                    Touch touch = UInput.touches[i];

                    // Construct a ray from the current touch coordinates
                    Ray ray = CameraCache.Main.ScreenPointToRay(touch.position);

                    switch (touch.phase)
                    {
                    case TouchPhase.Began:
                        AddTouchController(touch, ray);
                        break;

                    case TouchPhase.Moved:
                    case TouchPhase.Stationary:
                        UpdateTouchData(touch, ray);
                        break;

                    case TouchPhase.Ended:
                    case TouchPhase.Canceled:
                        RemoveTouchController(touch);
                        break;
                    }
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Swaps out the currently tracked hand while triggered appropriate events.
        /// </summary>
        /// <param name="hand">Which hand to track now.</param>
        private void ChangeTrackedObjectType(IMixedRealityController hand)
        {
            if (hand != null)
            {
                if (SolverHandler.TrackedTargetType == TrackedObjectType.HandJoint ||
                    SolverHandler.TrackedTargetType == TrackedObjectType.MotionController)
                {
                    if (SolverHandler.TrackedHandness != hand.ControllerHandedness)
                    {
                        SolverHandler.TrackedHandness = hand.ControllerHandedness;

                        // Move the currently tracked hand to the top of the stack.
                        handStack.Remove(hand);
                        handStack.Insert(0, hand);
                    }

                    if (trackedHand == null)
                    {
                        trackedHand = hand;
                        onHandActivate?.Invoke();
                    }
                    else
                    {
                        StartCoroutine(ToggleCursor(true));
                        trackedHand = hand;
                    }

                    // Wait one frame to disable the cursor in case one hasn't been instantiated yet.
                    StartCoroutine(ToggleCursor(false, true));
                }
                else
                {
                    Debug.LogWarning("ChangeTrackedObjectType failed because TrackedTargetType is not of type HandJoint or MotionController.");
                }
            }
            else
            {
                if (trackedHand != null)
                {
                    StartCoroutine(ToggleCursor(true));
                    trackedHand = null;
                    onHandDeactivate?.Invoke();
                }
            }
        }
        /// <summary>
        /// Determines if a controller meets the requirements for use with constraining the tracked object and determines if the
        /// palm is currently facing the user.
        /// </summary>
        /// <param name="controller">The hand to check against.</param>
        /// <returns>True if this hand should be used from tracking.</returns>
        protected override bool IsValidController(IMixedRealityController controller)
        {
            if (!base.IsValidController(controller))
            {
                return(false);
            }

            MixedRealityPose palmPose;

            var jointedHand = controller as IMixedRealityHand;

            if (jointedHand != null)
            {
                if (jointedHand.TryGetJoint(TrackedHandJoint.Palm, out palmPose))
                {
                    if (requireFlatHand)
                    {
                        // Check if the triangle's normal formed from the palm, to index, to ring finger tip roughly matches the palm normal.
                        MixedRealityPose indexTipPose, ringTipPose;

                        if (jointedHand.TryGetJoint(TrackedHandJoint.IndexTip, out indexTipPose) &&
                            jointedHand.TryGetJoint(TrackedHandJoint.RingTip, out ringTipPose))
                        {
                            var handNormal = Vector3.Cross(indexTipPose.Position - palmPose.Position,
                                                           ringTipPose.Position - indexTipPose.Position).normalized;
                            handNormal *= (jointedHand.ControllerHandedness == Handedness.Right) ? 1.0f : -1.0f;

                            if (Vector3.Angle(palmPose.Up, handNormal) > flatHandThreshold)
                            {
                                return(false);
                            }
                        }
                    }
                }
                else
                {
                    Debug.LogError("HandConstraintPalmUp requires controllers of type IMixedRealityHand to perform hand activation tests.");
                }

                return(Vector3.Angle(palmPose.Up, CameraCache.Main.transform.forward) < facingThreshold);
            }

            return(true);
        }
        /// <inheritdoc />
        public override void Update()
        {
            Profiler.BeginSample("[MRTK] UnityTouchDeviceManager.Update");

            base.Update();

            // Ensure that touch up and source lost events are at least one frame apart.
            for (int i = 0; i < touchesToRemove.Count; i++)
            {
                IMixedRealityController controller = touchesToRemove[i];
                Service?.RaiseSourceLost(controller.InputSource, controller);
            }
            touchesToRemove.Clear();

            int touchCount = UInput.touchCount;

            for (int i = 0; i < touchCount; i++)
            {
                Touch touch = UInput.touches[i];

                // Construct a ray from the current touch coordinates
                Ray ray = CameraCache.Main.ScreenPointToRay(touch.position);

                switch (touch.phase)
                {
                case TouchPhase.Began:
                    AddTouchController(touch, ray);
                    break;

                case TouchPhase.Moved:
                case TouchPhase.Stationary:
                    UpdateTouchData(touch, ray);
                    break;

                case TouchPhase.Ended:
                case TouchPhase.Canceled:
                    RemoveTouchController(touch);
                    break;
                }
            }

            Profiler.EndSample(); // Update
        }
    public bool TryGetSpecificControllerPose(Handedness handedness, TrackedHandJoint handJointToTrack, out Vector3 position, out Quaternion rotation)
    {
        bool retrieved = false;

        position = Vector3.zero;
        rotation = Quaternion.identity;

        IMixedRealityHand       currentHand       = detectedHand;
        IMixedRealityController currentController = detectedController;

        if (handedness == Handedness.Left)
        {
            currentHand       = leftHand;
            currentController = leftController;
        }
        else if (handedness == Handedness.Right)
        {
            currentHand       = rightHand;
            currentController = rightController;
        }

        if (currentHand != null && currentHand.TryGetJoint(handJointToTrack, out handPose))
        {
            position  = handPose.Position;
            rotation  = handPose.Rotation;
            retrieved = true;
        }
        else if (currentController != null)
        {
            try
            {
                position  = currentController.InputSource.Pointers[0].Position;
                rotation  = currentController.InputSource.Pointers[0].Rotation;
                retrieved = true;
            }
            catch (Exception)
            {
                retrieved = false;
            }
        }

        return(retrieved);
    }
Beispiel #20
0
        /// <summary>
        /// Determines if a hand meets the requirements for use with constraining the tracked object.
        /// </summary>
        /// <param name="controller">The controller to check against.</param>
        /// <returns>True if this hand should be used from tracking.</returns>
        protected virtual bool IsValidController(IMixedRealityController controller)
        {
            if (controller == null)
            {
                return(false);
            }

            // Check to make sure none of the hand's pointer's a locked. We don't want to track a hand which is currently
            // interacting with something else.
            foreach (var pointer in controller.InputSource.Pointers)
            {
                if (pointer.IsFocusLocked)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #21
0
        /// <summary>
        /// Performs an intersection test to see if the left hand is near the right hand or vice versa.
        /// </summary>
        /// <param name="controller">The hand to check against.</param>
        /// <returns>True, when hands are near each other.</returns>
        protected virtual bool IsOppositeHandNear(IMixedRealityController controller)
        {
            if (controller != null)
            {
                if (handBounds.Bounds.TryGetValue(controller.ControllerHandedness.GetOppositeHandedness(), out Bounds oppositeHandBounds) &&
                    handBounds.Bounds.TryGetValue(controller.ControllerHandedness, out Bounds trackedHandBounds))
                {
                    // Double the size of the hand bounds to allow for greater tolerance.
                    trackedHandBounds.Expand(trackedHandBounds.extents);
                    oppositeHandBounds.Expand(oppositeHandBounds.extents);

                    if (trackedHandBounds.Intersects(oppositeHandBounds))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #22
0
        /// <summary>
        /// Enables/disables all cursors on the currently tracked hand.
        /// </summary>
        /// <param name="controller">Controller target to search for pointers</param>
        /// <param name="visible">Is the cursor visible?</param>
        /// <param name="frameDelay">Delay one frame before performing the toggle to allow the pointers to instantiate their cursors.</param>
        protected virtual IEnumerator ToggleCursors(IMixedRealityController controller, bool visible, bool frameDelay = false)
        {
            if (controller == null)
            {
                yield break;
            }

            if (hideHandCursorsOnActivate)
            {
                if (frameDelay)
                {
                    yield return(null);
                }

                foreach (var pointer in controller?.InputSource.Pointers)
                {
                    pointer?.BaseCursor?.SetVisibility(visible);
                }
            }
        }
Beispiel #23
0
        /// <summary>
        /// Performs an intersection test to see if the left hand is near the right hand or vice versa.
        /// </summary>
        /// <param name="hand">The hand to check against.</param>
        /// <returns>True, when hands are near each other.</returns>
        protected virtual bool IsOppositeHandNear(IMixedRealityController hand)
        {
            if (hand != null)
            {
                Bounds oppositeHandBounds, trackedHandBounds;

                if (handBounds.Bounds.TryGetValue((hand.ControllerHandedness == Handedness.Left) ? Handedness.Right : Handedness.Left, out oppositeHandBounds) &&
                    handBounds.Bounds.TryGetValue(hand.ControllerHandedness, out trackedHandBounds))
                {
                    // Double the size of the hand bounds to allow for greater tolerance.
                    trackedHandBounds.Expand(trackedHandBounds.extents);
                    oppositeHandBounds.Expand(oppositeHandBounds.extents);

                    if (trackedHandBounds.Intersects(oppositeHandBounds))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #24
0
        /// <summary>
        /// Determines if a hand meets the requirements for use with constraining the tracked object.
        /// </summary>
        /// <param name="hand">The hand to check against.</param>
        /// <returns>True if this hand should be used from tracking.</returns>
        protected virtual bool IsHandActive(IMixedRealityController hand)
        {
            // If transitioning between hands is not allowed, make sure the TrackedObjectType matches the hand.
            if (!autoTransitionBetweenHands)
            {
                return((SolverHandler.TrackedTargetType == TrackedObjectType.HandJoint ||
                        SolverHandler.TrackedTargetType == TrackedObjectType.MotionController) &&
                       (SolverHandler.TrackedHandness == Handedness.Both ||
                        hand.ControllerHandedness == SolverHandler.TrackedHandness));
            }

            // Check to make sure none of the hand's pointer's a locked. We don't want to track a hand which is currently
            // interacting with something else.
            foreach (var pointer in hand.InputSource.Pointers)
            {
                if (pointer.IsFocusLocked)
                {
                    return(false);
                }
            }

            return(true);
        }
 protected void AddController(IMixedRealityController controller)
 {
     activeControllers.Add(controller);
 }
Beispiel #26
0
 /// <summary>
 /// Populates the event with data.
 /// </summary>
 /// <param name="inputSource"></param>
 /// <param name="controller"></param>
 public void Initialize(IMixedRealityInputSource inputSource, IMixedRealityController controller)
 {
     // NOTE: Source State events do not have an associated Input Action.
     BaseInitialize(inputSource, Definitions.InputSystem.MixedRealityInputAction.None);
     Controller = controller;
 }
        /// <summary>
        /// Gets the <seealso cref="IMixedRealityController"/> instance matching the specified source type and hand.
        /// </summary>
        /// <param name="sourceType">Type type of the input source</param>
        /// <param name="hand">The handedness of the controller</param>
        /// <param name="controller">The <seealso cref="IMixedRealityController"/> instance being returned</param>
        /// <returns>
        /// True if the controller instance is beeing returned, false otherwise.
        /// </returns>
        private static bool TryGetControllerInstance(InputSourceType sourceType, Handedness hand, out IMixedRealityController controller)
        {
            controller = null;

            foreach (IMixedRealityController c in CoreServices.InputSystem.DetectedControllers)
            {
                if ((c.InputSource?.SourceType == sourceType) &&
                    (c.ControllerHandedness == hand))
                {
                    controller = c;
                    return(true);
                }
            }

            return(false);
        }
 /// <summary>
 /// Populates the event with data.
 /// </summary>
 /// <param name="inputSource"></param>
 /// <param name="controller"></param>
 /// <param name="data"></param>
 public void Initialize(IMixedRealityInputSource inputSource, IMixedRealityController controller, T data)
 {
     Initialize(inputSource, controller);
     SourceData = data;
 }
        /// <summary>
        /// Determines if a controller meets the requirements for use with constraining the tracked object and determines if the
        /// palm is currently facing the user.
        /// </summary>
        /// <param name="controller">The hand to check against.</param>
        /// <returns>True if this hand should be used from tracking.</returns>
        protected override bool IsValidController(IMixedRealityController controller)
        {
            if (!base.IsValidController(controller))
            {
                return(false);
            }

            MixedRealityPose palmPose;
            var jointedHand = controller as IMixedRealityHand;

            bool palmFacingThresholdMet = false;

            if (jointedHand != null)
            {
                if (jointedHand.TryGetJoint(TrackedHandJoint.Palm, out palmPose))
                {
                    float palmCameraAngle = Vector3.Angle(palmPose.Up, CameraCache.Main.transform.forward);

                    if (requireFlatHand)
                    {
                        // Check if the triangle's normal formed from the palm, to index, to ring finger tip roughly matches the palm normal.
                        MixedRealityPose indexTipPose, ringTipPose;

                        if (jointedHand.TryGetJoint(TrackedHandJoint.IndexTip, out indexTipPose) &&
                            jointedHand.TryGetJoint(TrackedHandJoint.RingTip, out ringTipPose))
                        {
                            var handNormal = Vector3.Cross(indexTipPose.Position - palmPose.Position,
                                                           ringTipPose.Position - indexTipPose.Position).normalized;
                            handNormal *= (jointedHand.ControllerHandedness == Handedness.Right) ? 1.0f : -1.0f;

                            if (Vector3.Angle(palmPose.Up, handNormal) > flatHandThreshold)
                            {
                                return(false);
                            }
                        }
                    }

                    // Check if the palm angle meets the prescribed threshold
                    palmFacingThresholdMet = palmCameraAngle < facingThreshold;

                    // If using hybrid hand rotation, we proceed with additional checks
                    if (useHybridHandRotation && palmFacingThresholdMet)
                    {
                        // If we are above the threshold angle, keep the menu mapped to the tracked object
                        if (palmCameraAngle > hybridHandRotationThresholdAngle)
                        {
                            RotationBehavior = SolverRotationBehavior.LookAtTrackedObject;
                        }
                        // If we are within the threshold angle, we snap to follow the camera
                        else
                        {
                            RotationBehavior = SolverRotationBehavior.LookAtMainCamera;
                        }
                    }
                }
                else
                {
                    Debug.LogError("HandConstraintPalmUp requires controllers of type IMixedRealityHand to perform hand activation tests.");
                }

                return(palmFacingThresholdMet);
            }

            return(true);
        }
Beispiel #30
0
 /// <summary>
 /// This function is called to fill the HandTrackingIntputEventData object with information
 /// </summary>
 /// <param name="inputSource">Reference to the HandTrackingInputSource that created the EventData</param>
 /// <param name="controller">Reference to the IMixedRealityController that created the EventData</param>
 /// <param name="sourceHandedness">Handedness of the HandTrackingInputSource that created the EventData</param>
 /// <param name="touchPoint">Global position of the HandTrackingInputSource that created the EventData</param>
 public void Initialize(IMixedRealityInputSource inputSource, IMixedRealityController controller, Handedness sourceHandedness, Vector3 touchPoint)
 {
     Initialize(inputSource, sourceHandedness, MixedRealityInputAction.None, touchPoint);
     Controller = controller;
 }