void SetActiveMovementSystem(HandControllerSetup controller)
 {
     if (controller.enabledMovements.Count > 0)
     {
         controller.activeMovement = controller.enabledMovements[0];
         if (debugMode)
         {
             Debug.Log("Controller | Active Locomotion options: " + controller.enabledMovements.Count);
         }
     }
     else
     {
         Debug.LogWarning("No motion system attached to controller");
     }
 }
        void MotionOptionSwitcher(HandControllerSetup c)
        {
            InputDevice device = InputDevices.GetDeviceAtXRNode(c.xrNode);

            device.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out bool prevPrimary2DAxisPressed);
            if (prevPrimary2DAxisPressed != c.inputs.primary2DAxis.isPressed)
            {
                if (prevPrimary2DAxisPressed)
                {
                    if (c.activeMovement == HandControllerSetup.ActiveMovement.continuous)
                    {
                        motionRam.continuousMovement = false;
                    }

                    int msi = c.enabledMovements.IndexOf(c.activeMovement);
                    if (debugMode)
                    {
                        Debug.Log("Switched motion system for " + c.xrNode.ToString() + "C index: " + msi + " / " + c.enabledMovements.Count);
                    }
                    msi = (msi < c.enabledMovements.Count - 1) ? (msi + 1) : 0;
                    c.activeMovement = c.enabledMovements[msi];

                    // Activate / deactivate objects
                    if (c.snapTurning.enabled)
                    {
                        this.gameObject.GetComponent <SnapTurnProvider>().enabled = (c.activeMovement == HandControllerSetup.ActiveMovement.snap);
                    }

                    if (c.activeMotionUI != null)
                    {
                        c.activeMotionUI.text = "Locomotion:" + c.activeMovement.ToString();
                        StartCoroutine(MotionUi(c.activeMotionUI.transform.parent.gameObject));
                    }
                }
                c.inputs.primary2DAxis.isPressed = prevPrimary2DAxisPressed;
            }
        }
        void ManageMovement(HandControllerSetup c)
        {
            InputDevice device = InputDevices.GetDeviceAtXRNode(c.xrNode);

            // continuous / jump
            switch (c.activeMovement)
            {
            case HandControllerSetup.ActiveMovement.teleportation:
                if (c.teleportation.enabled)
                {
                    Vector2 primary2DAxisValue;
                    device.TryGetFeatureValue(CommonUsages.primary2DAxis, out primary2DAxisValue);     // update input axis
                    bool isActivated = (Math.Abs(primary2DAxisValue.x) >= c.teleportation.activeThreshold || Math.Abs(primary2DAxisValue.y) >= c.teleportation.activeThreshold);
                    if (isActivated)
                    {
                        Quaternion headYaw        = Quaternion.Euler(0, xrRig.cameraGameObject.transform.eulerAngles.y, 0);
                        Transform  teleportCircle = c.teleportation.rayInteractor.transform.Find("teleport-circle");
                        if (teleportCircle != null)
                        {
                            float angle = 0f;

                            if (primary2DAxisValue.x < 0)
                            {
                                angle = 360 - (Mathf.Atan2(primary2DAxisValue.x, primary2DAxisValue.y) * Mathf.Rad2Deg * -1);
                            }
                            else
                            {
                                angle = Mathf.Atan2(primary2DAxisValue.x, primary2DAxisValue.y) * Mathf.Rad2Deg;
                            }

                            if (debugMode)
                            {
                                Debug.Log("angle " + angle);
                            }
                            teleportCircle.gameObject.transform.rotation = Quaternion.AngleAxis(angle, Vector3.up);
                        }
                    }
                    c.teleportation.isActive = isActivated;
                    c.teleportation.rayInteractor.SetActive(isActivated);
                }
                break;

            case HandControllerSetup.ActiveMovement.continuous:
                device.TryGetFeatureValue(CommonUsages.primary2DAxis, out motionRam.continuousInputAxis);     // update input axis
                if (Math.Abs(motionRam.continuousInputAxis.x) >= c.continuousMovement.activeThreshold || Math.Abs(motionRam.continuousInputAxis.y) >= c.continuousMovement.activeThreshold)
                {
                    motionRam.activeContinuousMovement = c.continuousMovement;
                    motionRam.continuousMovement       = true;
                }
                else
                {
                    motionRam.continuousMovement = false;
                }
                break;

            case HandControllerSetup.ActiveMovement.jump:
                device.TryGetFeatureValue(CommonUsages.primary2DAxis, out Vector2 jumpInputDirection);     // update input axis
                bool isTouched = (Math.Abs(jumpInputDirection.x) >= c.jumpMovement.activeThreshold || Math.Abs(jumpInputDirection.y) >= c.jumpMovement.activeThreshold);
                if (isTouched != c.inputs.primary2DAxis.isTouched)
                {
                    c.inputs.primary2DAxis.isTouched = isTouched;
                    if (isTouched)
                    {
                        Quaternion headYaw   = Quaternion.Euler(0, xrRig.cameraGameObject.transform.eulerAngles.y, 0);
                        Vector3    direction = headYaw * new Vector3(jumpInputDirection.x + c.jumpMovement.distance, 0, jumpInputDirection.y + c.jumpMovement.distance);
                        Move(direction);
                    }
                }
                break;
            }
        }