private void UpdateDebugAxis(InteractionSourceState state)
        {
            Vector3 pointerForward = Vector3.zero, gripForward = Vector3.zero, gripPosition = Vector3.zero, pointerPosition = Vector3.zero;
            bool    hasPointerPosition = false, hasGripPosition = false, hasGripRotation = false,
                    hasPointerRotation = false, hasPointerForward = false, hasGripForward = false;
            Quaternion pointerRotation = Quaternion.identity, gripRotation = Quaternion.identity;
            Ray        pointerRay;

            //          TraceHelper.Log("Updating debug axis");

            if (
#if !UNITY_5
                (hasPointerPosition = state.sourcePose.TryGetPosition(out pointerPosition, InteractionSourceNode.Pointer)) &&
                (hasPointerForward = state.sourcePose.TryGetForward(out pointerForward, InteractionSourceNode.Pointer)) &&
                (hasPointerRotation = state.sourcePose.TryGetRotation(out pointerRotation, InteractionSourceNode.Pointer)) &&
                (hasGripForward = state.sourcePose.TryGetForward(out gripForward, InteractionSourceNode.Grip)) &&
                (hasGripPosition = state.sourcePose.TryGetPosition(out gripPosition, InteractionSourceNode.Grip)) &&
                (hasGripRotation = state.sourcePose.TryGetRotation(out gripRotation, InteractionSourceNode.Grip))
#else
                (hasPointerPosition = hasPointerForward = state.sourcePose.TryGetPointerRay(out pointerRay)) &&
                //(hasGripForward = state.sourcePose.TryGetForward(out gripForward )) &&
                (hasGripPosition = state.sourcePose.TryGetPosition(out gripPosition)) &&
                (hasGripRotation = state.sourcePose.TryGetRotation(out gripRotation))
#endif
                )
            {
#if UNITY_5
                if (hasPointerPosition && hasPointerForward)
                {
                    pointerPosition = pointerRay.origin;
                    pointerForward  = pointerRay.direction;
                }
#endif
                AxisRenderer axis = (state.IsLeftHand() ? axisRendererLeft : axisRendererRight);
                if (axis != null)
                {
                    if (hasPointerPosition && hasPointerRotation)
                    {
                        axis.SetValues(pointerPosition, pointerForward * 2, pointerRotation, AxisRenderer.ControllerElement.Pointer);
                    }
                    if (hasGripPosition && hasGripRotation)
                    {
                        axis.SetValues(gripPosition, gripForward * 2, gripRotation, AxisRenderer.ControllerElement.Grip);
                    }
                }
            }
#if DEBUG
            else
            {
                TraceHelper.LogModulus("Failed to update debug axis", TraceVariables.InteractionManagerLoop);
            }
#endif
            //TraceHelper.Assert(hasPointerForward && hasGripForward && hasGripPosition &&
            //                     hasPointerPosition && hasGripRotation && hasPointerRotation, "Show debug axis should not fail");


#if SKIPNPUTMODULE
            WinMRSnippets.Samples.Input.MotionControllerInputModule.Instance.SetPosition(state.source.id, pointerPosition);
            WinMRSnippets.Samples.Input.MotionControllerInputModule.Instance.SetForwardPointer(state.source.id, pointerForward);
            WinMRSnippets.Samples.Input.MotionControllerInputModule.Instance.SetButtonStates(state.source.id,
                                                                                             state.selectPressed, state.grasped, state.menuPressed);
#endif
        }
    private void UpdateInteractionSourceState(InteractionSourceState sourceState)
    {
        uint            id    = sourceState.source.id;
        ControllerState state = InputState.Current.GetController(sourceState);

        if (imDevices.ContainsKey(id))
        {
            var        sourcePose      = sourceState.sourcePose;
            Vector3    position        = Vector3.zero;
            Quaternion rotation        = Quaternion.identity;
            Vector3    pointerPosition = Vector3.zero;
            Quaternion pointerRotation = Quaternion.identity;

#if UNITY_5
            bool hasRotation = sourcePose.TryGetRotation(out rotation);
            bool hasPosition = sourcePose.TryGetPosition(out position);
#else
            bool hasRotation = sourcePose.TryGetRotation(out rotation, InteractionSourceNode.Grip);
            bool hasPosition = sourcePose.TryGetPosition(out position, InteractionSourceNode.Grip);
#endif

#if UNITY_5
            bool hasPointerPosition = sourcePose.TryGetPointerPosition(out pointerPosition);
            bool hasPointerRotation = sourcePose.TryGetPointerRotation(out pointerRotation);
#else
            bool hasPointerPosition = sourcePose.TryGetPosition(out pointerPosition, InteractionSourceNode.Pointer);
            bool hasPointerRotation = sourcePose.TryGetRotation(out pointerRotation, InteractionSourceNode.Pointer);
#endif

            if (hasPosition || hasRotation || hasPointerPosition || hasPointerRotation)
            {
#if VALIDATE_INPUT
                if (pointerPosition.IsDebugValid() && position.IsDebugValid() &&
                    pointerRotation.IsDebugValid() && rotation.IsDebugValid()
                    )
#endif
                {
                    state.Position = position;
                    state.Rotation = rotation;

                    if ((hasPosition && hasRotation) && ((FilterInput & PoseSource.Grip) != PoseSource.None))
                    {
                        SetTransform(imDevices[id], position, rotation);
                    }

                    else if ((hasPointerPosition && hasPointerRotation) && ((FilterInput & PoseSource.Pointer) != PoseSource.None))
                    {
                        SetTransform(imDevices[id], pointerPosition, pointerRotation);
                    }


                    if (hasPointerPosition)
                    {
                        Vector3 forward;
#if UNITY_5
                        Ray ray;
                        if (sourcePose.TryGetPointerRay(out ray))
                        {
                            forward         = ray.direction;
                            pointerPosition = ray.origin;
#else
                        if (sourcePose.TryGetForward(out forward, InteractionSourceNode.Pointer))
                        {
#endif
#if VERBOSE_POSITION
                            TraceHelper.LogDiff(string.Format("Pos:{0}, Fwd:{1}",
                                                              pointerPosition, forward), Cache.ForwardPosition);
#endif
                            if (cursor != null)
                            {
                                cursor.transform.position = pointerPosition + forward;
                            }
                        }
                        else
                        {
                            TraceHelper.Log("Failed get forward");
                        }
                    }
                }
#if VALIDATE_INPUT
                else
                {
                    invalidCoordsCount++;
                    TraceHelper.LogModulus(string.Format("Invalid: Pointer: {0}, Grip: {1}, count: {2}",
                                                         pointerPosition, position, invalidCoordsCount), TraceVariables.InteractionManagerLoop);
                }
#endif
            }
            else
            {
                TraceHelper.LogModulus(string.Format("No readings:{0}-- Grip: Pos-{1}, Rot-{2}, PointerPos-{3}, Rot-{4}",
#if UNITY_5
                                                     sourceState.source.sourceKind.ToString(),
#else
                                                     sourceState.source.kind.ToString(),
#endif
                                                     hasPosition, hasRotation,
                                                     hasPointerPosition, hasPointerRotation
                                                     ), TraceVariables.InteractionManagerLoop);
            }
            var rootproperties = sourceState;
#if UNITY_5
            state.SelectValue       = (float)rootproperties.selectPressedValue;
            state.TouchPadXValue    = (float)rootproperties.controllerProperties.touchpadX;
            state.TouchPadYValue    = (float)rootproperties.controllerProperties.touchpadY;
            state.ThumbstickXValue  = (float)rootproperties.controllerProperties.thumbstickX;
            state.ThumbstickYValue  = (float)rootproperties.controllerProperties.thumbstickY;
            state.TouchPadPressed   = rootproperties.controllerProperties.touchpadPressed;
            state.TouchPadTouched   = rootproperties.controllerProperties.touchpadTouched;
            state.ThumbstickPressed = rootproperties.controllerProperties.thumbstickPressed;
#else
            state.SelectValue       = rootproperties.selectPressedAmount;
            state.TouchPadXValue    = rootproperties.touchpadPosition.x;
            state.TouchPadYValue    = rootproperties.touchpadPosition.y;
            state.ThumbstickXValue  = rootproperties.thumbstickPosition.x;
            state.ThumbstickYValue  = rootproperties.thumbstickPosition.y;
            state.TouchPadPressed   = rootproperties.touchpadPressed;
            state.TouchPadTouched   = rootproperties.touchpadTouched;
            state.ThumbstickPressed = rootproperties.thumbstickPressed;
#endif

            state.SelectPressed   = rootproperties.selectPressed;
            state.MenuPressed     = rootproperties.menuPressed;
            state.GraspPressed    = rootproperties.grasped;
            state.Position        = position;
            state.PointerPosition = pointerPosition;
            state.Rotation        = rotation;
            state.PointerRotation = pointerRotation;
            state.IsLeftHand      = sourceState.source.handedness == InteractionSourceHandedness.Left;
            state.IsRightHand     = sourceState.source.handedness == InteractionSourceHandedness.Right;

#if VERBOSE_STATE
            state.TraceState(FilterInput);
#endif

            Vector3 pointerForward = Vector3.zero, gripForward = Vector3.zero;
            bool    hasPointerForward = false, hasGripForward = false;
#if !UNITY_5
            if ((hasPointerForward = sourcePose.TryGetForward(out pointerForward, InteractionSourceNode.Pointer)) &&
                (hasGripForward = sourcePose.TryGetForward(out gripForward, InteractionSourceNode.Grip)))
            {
#else
            Ray rayAxis;
            if ((hasPointerForward = hasPointerPosition = sourcePose.TryGetPointerRay(out rayAxis)))
            {
                pointerForward  = rayAxis.direction;
                pointerPosition = rayAxis.origin;
                hasGripForward  = true; //it is a zero vector.
#endif
                if (ShowDebugAxis)
                {
                    AxisRenderer axis = (state.IsLeftHand ? axisRendererLeft : axisRendererRight);
                    if (axis != null)
                    {
                        if (hasPointerForward && hasPointerPosition)
                        {
                            axis.SetValues(state.PointerPosition, pointerForward * 2, state.PointerRotation, AxisRenderer.ControllerElement.Pointer);
                        }
                        if (hasGripForward && hasPosition)
                        {
                            axis.SetValues(state.Position, gripForward * 2, state.Rotation, AxisRenderer.ControllerElement.Grip);
                        }
                    }
                }
            }
#if VERBOSE_STATE
            else
            {
                TraceHelper.LogModulus(string.Format("No Forward vectors. Grip: {0}, pointer:{1}",
                                                     hasPointerForward, hasGripForward), TraceVariables.InteractionManagerLoop);
            }
#endif


            if (AnimateControllerModel)
            {
                MotionControllerInfo currentController;
                if (controllerInfoForAnimation.TryGetValue(sourceState.source.id, out currentController))
                {
#if !UNITY_5
                    currentController.AnimateSelect(sourceState.selectPressedAmount);
                    if (sourceState.source.supportsGrasp)
                    {
                        currentController.AnimateGrasp(sourceState.grasped);
                    }

                    if (sourceState.source.supportsMenu)
                    {
                        currentController.AnimateMenu(sourceState.menuPressed);
                    }
                    if (sourceState.source.supportsThumbstick)
                    {
                        currentController.AnimateThumbstick(sourceState.thumbstickPressed, sourceState.thumbstickPosition);
                    }

                    if (sourceState.source.supportsTouchpad)
                    {
                        currentController.AnimateTouchpad(sourceState.touchpadPressed, sourceState.touchpadTouched, sourceState.touchpadPosition);
                    }
#else
                    currentController.AnimateSelect((float)sourceState.selectPressedValue);
                    if (sourceState.source.supportsGrasp)
                    {
                        currentController.AnimateGrasp(sourceState.grasped);
                    }

                    if (sourceState.source.supportsMenu)
                    {
                        currentController.AnimateMenu(sourceState.menuPressed);
                    }

                    InteractionController controller;
                    if (sourceState.source.TryGetController(out controller))
                    {
                        if (controller.hasThumbstick)
                        {
                            currentController.AnimateThumbstick(sourceState.controllerProperties.thumbstickPressed,
                                                                new Vector2((float)sourceState.controllerProperties.thumbstickX,
                                                                            (float)sourceState.controllerProperties.thumbstickY));
                        }

                        if (controller.hasTouchpad)
                        {
                            currentController.AnimateTouchpad(sourceState.controllerProperties.touchpadPressed,
                                                              sourceState.controllerProperties.touchpadTouched,
                                                              new Vector2((float)sourceState.controllerProperties.touchpadX,
                                                                          (float)sourceState.controllerProperties.touchpadX));
                        }
                    }
#endif
                }
                else
                {
                    TraceHelper.Log("Could not animate " + sourceState.source.id);
                }
            }

            if (state.ThumbstickPressed &&
                (Time.unscaledTime > (debounceThumbstickTime + 3f))
                )
            {
                ShowDebugAxis = !ShowDebugAxis;
                UpdateDebugAxis(ShowDebugAxis);
                debounceThumbstickTime = Time.unscaledTime;
            }
        }
    }

    float debounceThumbstickTime = 0f;
    private void UpdateUnityInput()
    {
        UpdateTrackedControllers();

        var left  = InputState.Current.GetController(XRNode.LeftHand);
        var right = InputState.Current.GetController(XRNode.RightHand);

        // Motion
        foreach (XRNode nodeType in uDevices.Keys)
        {
            ControllerState state;
            if (nodeType == XRNode.LeftHand)
            {
                state = left;
            }
            else if (nodeType == XRNode.RightHand)
            {
                state = right;
            }
            else
            {
                TraceHelper.Log("Ignoring nodetype" + nodeType);
                continue;
            }
            var position = InputTracking.GetLocalPosition(nodeType);
            var rotation = InputTracking.GetLocalRotation(nodeType);

            SetTransform(uDevices[nodeType], position, rotation);

            if (ShowDebugAxis)
            {
                AxisRenderer axis   = null;
                var          angles = rotation.eulerAngles;

                axis = (nodeType == XRNode.RightHand) ? axisRendererRight : axisRendererLeft;
                if (axis != null)
                {
                    axis.SetValues(position, 2f * (rotation * Vector3.forward), rotation, AxisRenderer.ControllerElement.Grip);
                }

                if (axis != null)
                {
                    position.y += .05f;
                    axis.SetValues(position, angles * 2f, rotation, AxisRenderer.ControllerElement.Pointer);
                }
            }

            state.Position = position;
            state.Rotation = rotation;
        }

        // Buttons
        if (Input.GetButtonDown(UnityInputAxis.MotionController_Select_Left))
        {
            left.SelectPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_Select_Right))
        {
            right.SelectPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_Menu_Left))
        {
            left.MenuPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_Menu_Right))
        {
            right.MenuPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_Grasp_Left))
        {
            left.GraspPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_Grasp_Right))
        {
            right.GraspPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_TouchpadTouched_Left))
        {
            left.TouchPadTouched = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_TouchpadTouched_Right))
        {
            right.TouchPadTouched = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_TouchpadPressed_Left))
        {
            left.TouchPadPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_TouchpadPressed_Right))
        {
            right.TouchPadPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_ThumbstickPressed_Left))
        {
            left.ThumbstickPressed = true;
        }
        if (Input.GetButtonDown(UnityInputAxis.MotionController_ThumbstickPressed_Right))
        {
            right.ThumbstickPressed = true;
        }

        // Axes

        left.SelectValue       = Input.GetAxis(UnityInputAxis.MotionController_SelectPressedValue_Left);
        right.SelectValue      = Input.GetAxis(UnityInputAxis.MotionController_SelectPressedValue_Right);
        left.TouchPadXValue    = Input.GetAxis(UnityInputAxis.MotionController_TouchpadX_Left);
        left.TouchPadYValue    = Input.GetAxis(UnityInputAxis.MotionController_TouchpadY_Left);
        right.TouchPadXValue   = Input.GetAxis(UnityInputAxis.MotionController_TouchpadX_Right);
        right.TouchPadYValue   = Input.GetAxis(UnityInputAxis.MotionController_TouchpadY_Right);
        left.ThumbstickXValue  = Input.GetAxis(UnityInputAxis.MotionController_ThumbstickX_Left);
        left.ThumbstickYValue  = Input.GetAxis(UnityInputAxis.MotionController_ThumbstickY_Left);
        right.ThumbstickXValue = Input.GetAxis(UnityInputAxis.MotionController_ThumbstickX_Right);
        right.ThumbstickYValue = Input.GetAxis(UnityInputAxis.MotionController_ThumbstickY_Right);

        right.TraceState(PoseSource.Any);
        left.TraceState(PoseSource.Any);
    }