/// <summary>
        /// Retrieve the source controller from the Active Store, or create a new device and register it
        /// </summary>
        /// <param name="interactionSource">Source State provided by the SDK</param>
        /// <param name="addController">Should the Source be added as a controller if it isn't found?</param>
        /// <returns>New or Existing Controller Input Source</returns>
        private BaseWindowsMixedRealitySource GetOrAddController(InteractionSource interactionSource, bool addController = true)
        {
            //If a device is already registered with the ID provided, just return it.
            if (activeControllers.ContainsKey(interactionSource.id))
            {
                var controller = activeControllers[interactionSource.id] as BaseWindowsMixedRealitySource;
                Debug.Assert(controller != null);
                return(controller);
            }

            if (!addController)
            {
                return(null);
            }

            Handedness controllingHand;

            switch (interactionSource.handedness)
            {
            default:
                controllingHand = Handedness.None;
                break;

            case InteractionSourceHandedness.Left:
                controllingHand = Handedness.Left;
                break;

            case InteractionSourceHandedness.Right:
                controllingHand = Handedness.Right;
                break;
            }

            IMixedRealityPointer[] pointers        = null;
            InputSourceType        inputSourceType = InputSourceType.Other;

            switch (interactionSource.kind)
            {
            case InteractionSourceKind.Controller:
                if (interactionSource.supportsPointing)
                {
                    pointers = RequestPointers(SupportedControllerType.WindowsMixedReality, controllingHand);
                }
                else
                {
                    pointers = RequestPointers(SupportedControllerType.GGVHand, controllingHand);
                }
                inputSourceType = InputSourceType.Controller;
                break;

            case InteractionSourceKind.Hand:
                if (interactionSource.supportsPointing)
                {
                    pointers = RequestPointers(SupportedControllerType.ArticulatedHand, controllingHand);
                }
                else
                {
                    pointers = RequestPointers(SupportedControllerType.GGVHand, controllingHand);
                }
                inputSourceType = InputSourceType.Hand;
                break;

            case InteractionSourceKind.Voice:
                // set to null: when pointers are null we use head gaze, which is what we want for voice
                break;

            default:
                Debug.LogError($"Unknown new type in WindowsMixedRealityDeviceManager {interactionSource.kind}, make sure to add a SupportedControllerType");
                break;
            }

            string nameModifier = controllingHand == Handedness.None ? interactionSource.kind.ToString() : controllingHand.ToString();
            var    inputSource  = Service?.RequestNewGenericInputSource($"Mixed Reality Controller {nameModifier}", pointers, inputSourceType);

            BaseWindowsMixedRealitySource detectedController;

            if (interactionSource.supportsPointing)
            {
                if (interactionSource.kind == InteractionSourceKind.Hand)
                {
                    detectedController = new WindowsMixedRealityArticulatedHand(TrackingState.NotTracked, controllingHand, inputSource);
                    if (!detectedController.Enabled)
                    {
                        // Controller failed to be setup correctly.
                        // Return null so we don't raise the source detected.
                        return(null);
                    }
                }
                else if (interactionSource.kind == InteractionSourceKind.Controller)
                {
                    detectedController = new WindowsMixedRealityController(TrackingState.NotTracked, controllingHand, inputSource);
                    if (!detectedController.Enabled)
                    {
                        // Controller failed to be setup correctly.
                        // Return null so we don't raise the source detected.
                        return(null);
                    }
                }
                else
                {
                    Debug.Log($"Unhandled source type {interactionSource.kind} detected.");
                    return(null);
                }
            }
            else
            {
                detectedController = new WindowsMixedRealityGGVHand(TrackingState.NotTracked, controllingHand, inputSource);
                if (!detectedController.Enabled)
                {
                    // Controller failed to be setup correctly.
                    // Return null so we don't raise the source detected.
                    return(null);
                }
            }

            for (int i = 0; i < detectedController.InputSource?.Pointers?.Length; i++)
            {
                detectedController.InputSource.Pointers[i].Controller = detectedController;
            }

            activeControllers.Add(interactionSource.id, detectedController);
            return(detectedController);
        }
        /// <summary>
        /// Retrieve the source controller from the Active Store, or create a new device and register it
        /// </summary>
        /// <param name="interactionSource">Source State provided by the SDK</param>
        /// <param name="addController">Should the Source be added as a controller if it isn't found?</param>
        /// <returns>New or Existing Controller Input Source</returns>
        private BaseWindowsMixedRealitySource GetOrAddController(InteractionSource interactionSource, bool addController = true)
        {
            uint controllerId = GetControllerId(interactionSource);

            // If a device is already registered with the ID provided, just return it.
            if (activeControllers.ContainsKey(controllerId))
            {
                var controller = activeControllers[controllerId] as BaseWindowsMixedRealitySource;
                Debug.Assert(controller != null);
                return(controller);
            }

            if (!addController)
            {
                return(null);
            }

            Handedness controllingHand;

            switch (interactionSource.handedness)
            {
            default:
                controllingHand = Handedness.None;
                break;

            case InteractionSourceHandedness.Left:
                controllingHand = Handedness.Left;
                break;

            case InteractionSourceHandedness.Right:
                controllingHand = Handedness.Right;
                break;
            }

            IMixedRealityPointer[] pointers        = null;
            InputSourceType        inputSourceType = InputSourceType.Other;

            switch (interactionSource.kind)
            {
            case InteractionSourceKind.Controller:
                if (interactionSource.supportsPointing)
                {
                    pointers = RequestPointers(SupportedControllerType.WindowsMixedReality, controllingHand);
                }
                else
                {
                    pointers = RequestPointers(SupportedControllerType.GGVHand, controllingHand);
                }
                inputSourceType = InputSourceType.Controller;
                break;

            case InteractionSourceKind.Hand:
                if (interactionSource.supportsPointing)
                {
                    pointers = RequestPointers(SupportedControllerType.ArticulatedHand, controllingHand);
                }
                else
                {
                    pointers = RequestPointers(SupportedControllerType.GGVHand, controllingHand);
                }
                inputSourceType = InputSourceType.Hand;
                break;

            case InteractionSourceKind.Voice:
                // set to null: when pointers are null we use head gaze, which is what we want for voice
                break;

            default:
                Debug.LogError($"Unknown new type in WindowsMixedRealityDeviceManager {interactionSource.kind}, make sure to add a SupportedControllerType");
                break;
            }

            bool isHPController = !interactionSource.supportsTouchpad && interactionSource.kind == InteractionSourceKind.Controller;

            string kindModifier       = interactionSource.kind.ToString();
            string handednessModifier = controllingHand == Handedness.None ? string.Empty : controllingHand.ToString();

            string inputSourceName = isHPController ? $"HP Motion {kindModifier} {handednessModifier}" : $"Mixed Reality {kindModifier} {handednessModifier}";

            var inputSource = Service?.RequestNewGenericInputSource(inputSourceName, pointers, inputSourceType);

            BaseWindowsMixedRealitySource detectedController;

            if (interactionSource.supportsPointing)
            {
                if (interactionSource.kind == InteractionSourceKind.Hand)
                {
                    detectedController = new WindowsMixedRealityArticulatedHand(TrackingState.NotTracked, controllingHand, inputSource);
                    if (!detectedController.Enabled)
                    {
                        // Controller failed to be setup correctly.
                        // Return null so we don't raise the source detected.
                        return(null);
                    }
                }
                else if (interactionSource.kind == InteractionSourceKind.Controller)
                {
                    if (isHPController)
                    {
                        // Add the controller as a HP Motion Controller
                        HPMotionController hpController = new HPMotionController(TrackingState.NotTracked, controllingHand, inputSource);

#if HP_CONTROLLER_ENABLED
                        lock (trackedMotionControllerStates)
                        {
                            if (trackedMotionControllerStates.ContainsKey(controllerId))
                            {
                                hpController.MotionControllerState = trackedMotionControllerStates[controllerId];
                            }
                        }
#endif

                        detectedController = hpController;
                    }
                    else
                    {
                        detectedController = new WindowsMixedRealityController(TrackingState.NotTracked, controllingHand, inputSource);
                    }
                }
                else
                {
                    Debug.Log($"Unhandled source type {interactionSource.kind} detected.");
                    return(null);
                }
            }
            else
            {
                detectedController = new WindowsMixedRealityGGVHand(TrackingState.NotTracked, controllingHand, inputSource);
            }

            if (!detectedController.Enabled)
            {
                // Controller failed to be setup correctly.
                // Return null so we don't raise the source detected.
                return(null);
            }

            for (int i = 0; i < detectedController.InputSource?.Pointers?.Length; i++)
            {
                detectedController.InputSource.Pointers[i].Controller = detectedController;
            }

            activeControllers.Add(controllerId, detectedController);
            return(detectedController);
        }