// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.Utilities; using System; using UnityEngine; using UnityEngine.Serialization; namespace Microsoft.MixedReality.Toolkit.Input { [CreateAssetMenu(menuName = "Mixed Reality/Toolkit/Profiles/Mixed Reality Simulated Input Profile", fileName = "MixedRealityInputSimulationProfile", order = (int)CreateProfileMenuItemIndices.InputSimulation)] [MixedRealityServiceProfile(typeof(IInputSimulationService))] [HelpURL("https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/input-simulation/input-simulation-service")] public class MixedRealityInputSimulationProfile : BaseMixedRealityProfile { [SerializeField] [Tooltip("Indicator buttons to show input simulation state in the viewport")] private GameObject indicatorsPrefab = null; /// /// Indicator buttons to show input simulation state in the viewport /// public GameObject IndicatorsPrefab => indicatorsPrefab; [Header("Common Input")] [SerializeField] [Tooltip("Sensitivity when using the mouse for rotation")] [FormerlySerializedAs("defaultMouseSensitivity")] private float mouseRotationSensitivity = 0.1f; /// /// Sensitivity when using the mouse for rotation /// public float MouseRotationSensitivity => mouseRotationSensitivity; [SerializeField] [Tooltip("Mouse Movement X-axis")] private string mouseX = "Mouse X"; /// /// Mouse Movement X-axis /// public string MouseX => mouseX; [SerializeField] [Tooltip("Mouse Movement Y-axis")] private string mouseY = "Mouse Y"; /// /// Mouse Movement Y-axis /// public string MouseY => mouseY; [SerializeField] [Tooltip("Mouse Scroll Wheel")] private string mouseScroll = "Mouse ScrollWheel"; /// /// Mouse Scroll Wheel /// public string MouseScroll => mouseScroll; [SerializeField] [Tooltip("Button pressed to interact with objects")] [FormerlySerializedAs("Interaction Button")] private KeyBinding interactionButton = KeyBinding.FromMouseButton(KeyBinding.MouseButton.Left); /// /// Button pressed to interact with objects /// public KeyBinding InteractionButton => interactionButton; [SerializeField] [Tooltip("Maximum time interval for double press")] private float doublePressTime = 0.4f; /// /// Maximum time interval for double press /// public float DoublePressTime => doublePressTime; [SerializeField] [Tooltip("Enable hands free input")] private bool isHandsFreeInputEnabled = true; /// /// Enable hands free input /// public bool IsHandsFreeInputEnabled => isHandsFreeInputEnabled; [Header("Camera Control")] [SerializeField] [Tooltip("Enable manual camera control")] private bool isCameraControlEnabled = true; /// /// Enable manual camera control /// public bool IsCameraControlEnabled => isCameraControlEnabled; [SerializeField] [Tooltip("Additional rotation factor after input smoothing has been applied")] [FormerlySerializedAs("extraMouseSensitivityScale")] private float mouseLookSpeed = 3.0f; /// /// Additional rotation factor after input smoothing has been applied /// public float MouseLookSpeed => mouseLookSpeed; [SerializeField] [Tooltip("Controls how mouse look control is activated")] private KeyBinding mouseLookButton = KeyBinding.FromMouseButton(KeyBinding.MouseButton.Right); /// /// Controls how mouse look control is activated /// public KeyBinding MouseLookButton => mouseLookButton; [SerializeField] [Tooltip("Toggle mouse look on with the mouse look button, press escape to release")] private bool mouseLookToggle = false; /// /// Toggle mouse look on with the mouse look button, press escape to release /// public bool MouseLookToggle => mouseLookToggle; [SerializeField] [Tooltip("Invert the vertical rotation")] private bool isControllerLookInverted = true; /// /// Invert the vertical rotation /// public bool IsControllerLookInverted => isControllerLookInverted; [SerializeField] [Tooltip("Amount to offset the starting position of the camera from the origin")] private Vector3 cameraOriginOffset = Vector3.zero; /// /// Amount to offset the starting position of the camera from the origin /// public Vector3 CameraOriginOffset => cameraOriginOffset; [SerializeField] [Tooltip("Camera movement mode")] private InputSimulationControlMode currentControlMode = InputSimulationControlMode.Fly; /// /// Camera movement mode /// public InputSimulationControlMode CurrentControlMode => currentControlMode; [SerializeField] [Tooltip("Key to speed up camera movement")] private KeyBinding fastControlKey = KeyBinding.FromKey(KeyCode.RightControl); /// /// Key to speed up camera movement /// public KeyBinding FastControlKey => fastControlKey; [SerializeField] [Tooltip("Slow camera translation speed")] private float controlSlowSpeed = 0.1f; /// /// Slow camera translation speed /// public float ControlSlowSpeed => controlSlowSpeed; [SerializeField] [Tooltip("Fast camera translation speed")] private float controlFastSpeed = 1.0f; /// /// Fast camera translation speed /// public float ControlFastSpeed => controlFastSpeed; // Input axes to coordinate with the Input Manager (Project Settings -> Input) // Horizontal movement string for keyboard and left stick of game controller [SerializeField] [Tooltip("Horizontal movement Axis ")] private string moveHorizontal = "Horizontal"; /// /// Horizontal movement Axis /// public string MoveHorizontal => moveHorizontal; // Vertical movement string for keyboard and left stick of game controller [SerializeField] [Tooltip("Vertical movement Axis ")] private string moveVertical = "Vertical"; /// /// Vertical movement Axis /// public string MoveVertical => moveVertical; [SerializeField] [Tooltip("Up/Down movement Axis ")] private string moveUpDown = "UpDown"; /// /// Up/Down movement Axis /// public string MoveUpDown => moveUpDown; // Look horizontal string for right stick of game controller // The right stick has no default settings in the Input Manager and will need to be setup for a game controller to look [SerializeField] [Tooltip("Look Horizontal Axis - Right Stick On Controller")] private string lookHorizontal = ControllerMappingLibrary.AXIS_4; /// /// Look Horizontal Axis - Right Stick On Controller /// public string LookHorizontal => lookHorizontal; // Look vertical string for right stick of game controller [SerializeField] [Tooltip("Look Vertical Axis - Right Stick On Controller ")] private string lookVertical = ControllerMappingLibrary.AXIS_5; /// /// Look Vertical Axis - Right Stick On Controller /// public string LookVertical => lookVertical; /// /// Enable eye gaze simulation /// [Obsolete("Check the EyeGazeSimulationMode instead")] public bool SimulateEyePosition => defaultEyeGazeSimulationMode != EyeGazeSimulationMode.Disabled; [Header("Eye Gaze Simulation")] [SerializeField] [Tooltip("Enable eye gaze simulation")] [FormerlySerializedAs("simulateEyePosition")] private EyeGazeSimulationMode defaultEyeGazeSimulationMode = EyeGazeSimulationMode.Disabled; /// /// Enable eye gaze simulation /// public EyeGazeSimulationMode DefaultEyeGazeSimulationMode => defaultEyeGazeSimulationMode; [Header("Controller Simulation")] [SerializeField] [Tooltip("Enable controller simulation")] [FormerlySerializedAs("handSimulationMode")] [FormerlySerializedAs("defaultHandSimulationMode")] private ControllerSimulationMode defaultControllerSimulationMode = ControllerSimulationMode.ArticulatedHand; /// /// Enable controller simulation /// public ControllerSimulationMode DefaultControllerSimulationMode => defaultControllerSimulationMode; [Header("Controller Control Settings")] [SerializeField] [Tooltip("Key to toggle persistent mode for the left controller")] [FormerlySerializedAs("toggleLeftHandKey")] private KeyBinding toggleLeftControllerKey = KeyBinding.FromKey(KeyCode.T); /// /// Key to toggle persistent mode for the left controller /// public KeyBinding ToggleLeftControllerKey => toggleLeftControllerKey; [SerializeField] [Tooltip("Key to toggle persistent mode for the right controller")] [FormerlySerializedAs("toggleRightHandKey")] private KeyBinding toggleRightControllerKey = KeyBinding.FromKey(KeyCode.Y); /// /// Key to toggle persistent mode for the right controller /// public KeyBinding ToggleRightControllerKey => toggleRightControllerKey; [SerializeField] [Tooltip("Time after which uncontrolled controllers are hidden")] [FormerlySerializedAs("handHideTimeout")] private float controllerHideTimeout = 0.2f; /// /// Time after which uncontrolled controllers are hidden /// public float ControllerHideTimeout => controllerHideTimeout; [SerializeField] [Tooltip("Key to manipulate the left controller")] [FormerlySerializedAs("leftHandManipulationKey")] private KeyBinding leftControllerManipulationKey = KeyBinding.FromKey(KeyCode.LeftShift); /// /// Key to manipulate the left controller /// public KeyBinding LeftControllerManipulationKey => leftControllerManipulationKey; [SerializeField] [Tooltip("Key to manipulate the right controller")] [FormerlySerializedAs("rightHandManipulationKey")] private KeyBinding rightControllerManipulationKey = KeyBinding.FromKey(KeyCode.Space); /// /// Key to manipulate the right controller /// public KeyBinding RightControllerManipulationKey => rightControllerManipulationKey; [SerializeField] [Tooltip("Additional rotation factor after input smoothing has been applied")] [FormerlySerializedAs("mouseHandRotationSpeed")] private float mouseControllerRotationSpeed = 6.0f; /// /// Additional rotation factor after input smoothing has been applied /// public float MouseControllerRotationSpeed => mouseControllerRotationSpeed; [SerializeField] [Tooltip("Controls how controller rotation is activated")] [FormerlySerializedAs("handRotateButton")] private KeyBinding controllerRotateButton = KeyBinding.FromKey(KeyCode.LeftControl); /// /// Controls how controller rotation is activated /// public KeyBinding ControllerRotateButton => controllerRotateButton; [Header("Hand Gesture Settings")] [SerializeField] [Tooltip("Hand joint pose on first show or reset")] private ArticulatedHandPose.GestureId defaultHandGesture = ArticulatedHandPose.GestureId.Open; /// /// Hand joint pose on first show or reset /// public ArticulatedHandPose.GestureId DefaultHandGesture => defaultHandGesture; [SerializeField] [Tooltip("Hand joint pose when pressing the left mouse button")] private ArticulatedHandPose.GestureId leftMouseHandGesture = ArticulatedHandPose.GestureId.Pinch; /// /// Hand joint pose when pressing the left mouse button /// public ArticulatedHandPose.GestureId LeftMouseHandGesture => leftMouseHandGesture; [SerializeField] [Tooltip("Hand joint pose when pressing the middle mouse button")] private ArticulatedHandPose.GestureId middleMouseHandGesture = ArticulatedHandPose.GestureId.None; /// /// Hand joint pose when pressing the middle mouse button /// public ArticulatedHandPose.GestureId MiddleMouseHandGesture => middleMouseHandGesture; [SerializeField] [Tooltip("Hand joint pose when pressing the right mouse button")] private ArticulatedHandPose.GestureId rightMouseHandGesture = ArticulatedHandPose.GestureId.None; /// /// Hand joint pose when pressing the right mouse button /// public ArticulatedHandPose.GestureId RightMouseHandGesture => rightMouseHandGesture; [SerializeField] [Tooltip("Gesture interpolation per second")] private float handGestureAnimationSpeed = 8.0f; /// /// Gesture interpolation per second /// public float HandGestureAnimationSpeed => handGestureAnimationSpeed; [SerializeField] [Tooltip("Time until hold gesture starts")] private float holdStartDuration = 0.5f; /// /// Time until hold gesture starts /// public float HoldStartDuration => holdStartDuration; [SerializeField] [Tooltip("The total amount of input source movement that needs to happen to start navigation")] [UnityEngine.Serialization.FormerlySerializedAs("manipulationStartThreshold")] private float navigationStartThreshold = 0.03f; /// /// The total amount of input source movement that needs to happen to start navigation /// public float NavigationStartThreshold => navigationStartThreshold; [Header("Controller Placement Settings")] [SerializeField] [Tooltip("Default distance of the controller from the camera")] [FormerlySerializedAs("defaultHandDistance")] private float defaultControllerDistance = 0.5f; /// /// Default distance of the controller from the camera /// public float DefaultControllerDistance => defaultControllerDistance; [SerializeField] [Tooltip("Depth change when scrolling the mouse wheel")] [FormerlySerializedAs("handDepthMultiplier")] private float controllerDepthMultiplier = 0.03f; /// /// Depth change when scrolling the mouse wheel /// public float ControllerDepthMultiplier => controllerDepthMultiplier; [SerializeField] [Tooltip("Apply random offset to the controller position")] [FormerlySerializedAs("handJitterAmount")] private float controllerJitterAmount = 0.0f; /// /// Apply random offset to the controller position /// public float ControllerJitterAmount => controllerJitterAmount; [Header("Motion Controller Settings")] [SerializeField] [Tooltip("Key to simulate a trigger press (select) on the motion controller")] private KeyBinding motionControllerTriggerKey = KeyBinding.FromMouseButton(KeyBinding.MouseButton.Left); /// /// Key to simulate a trigger press (select) on the motion controller /// public KeyBinding MotionControllerTriggerKey => motionControllerTriggerKey; [SerializeField] [Tooltip("Key to simulate a grab on the motion controller")] private KeyBinding motionControllerGrabKey = KeyBinding.FromKey(KeyCode.G); /// /// Key to simulate a grab on the motion controller /// public KeyBinding MotionControllerGrabKey => motionControllerGrabKey; [SerializeField] [Tooltip("Key to simulate a menu press on the motion controller")] private KeyBinding motionControllerMenuKey = KeyBinding.FromKey(KeyCode.M); /// /// Key to simulate a menu press on the motion controller /// public KeyBinding MotionControllerMenuKey => motionControllerMenuKey; #region Obsolete Properties /// /// Enable controller simulation /// [Obsolete("Use DefaultControllerSimulationMode instead.")] public ControllerSimulationMode DefaultHandSimulationMode => DefaultControllerSimulationMode; /// /// Key to toggle persistent mode for the left controller /// [Obsolete("Use ToggleLeftControllerKey instead.")] public KeyBinding ToggleLeftHandKey => ToggleLeftControllerKey; /// /// Key to toggle persistent mode for the right controller /// [Obsolete("Use ToggleRightControllerKey instead.")] public KeyBinding ToggleRightHandKey => ToggleRightControllerKey; /// /// Time after which uncontrolled hands are hidden /// [Obsolete("Use ControllerHideTimeout instead.")] public float HandHideTimeout => ControllerHideTimeout; /// /// Key to manipulate the left hand /// [Obsolete("Use LeftControllerManipulationKey instead.")] public KeyBinding LeftHandManipulationKey => LeftControllerManipulationKey; /// /// Key to manipulate the right hand /// [Obsolete("Use RightControllerManipulationKey instead.")] public KeyBinding RightHandManipulationKey => RightControllerManipulationKey; /// /// Additional rotation factor after input smoothing has been applied /// [Obsolete("Use MouseControllerRotationSpeed instead.")] public float MouseHandRotationSpeed => MouseControllerRotationSpeed; /// /// Controls how hand rotation is activated /// [Obsolete("Use ControllerRotateButton instead.")] public KeyBinding HandRotateButton => ControllerRotateButton; /// /// Default distance of the hand from the camera /// [Obsolete("Use DefaultControllerDistance instead.")] public float DefaultHandDistance => DefaultControllerDistance; /// /// Depth change when scrolling the mouse wheel /// [Obsolete("Use ControllerDepthMultiplier instead.")] public float HandDepthMultiplier => ControllerDepthMultiplier; /// /// Apply random offset to the hand position /// [Obsolete("Use ControllerJitterAmount instead.")] public float HandJitterAmount => ControllerJitterAmount; #endregion } }