// 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
}
}