mixedreality/com.microsoft.mixedreality..../Core/Providers/InputSimulation/ManualCameraControl.cs

147 lines
5.7 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// Class for manually controlling the camera in the Unity editor. Used by the Input Simulation Service.
/// </summary>
public class ManualCameraControl
{
private MixedRealityInputSimulationProfile profile;
private bool isGamepadLookEnabled = true;
private bool isFlyKeypressEnabled = true;
private Vector3 lastTrackerToUnityTranslation = Vector3.zero;
private Quaternion lastTrackerToUnityRotation = Quaternion.identity;
private static readonly KeyBinding cancelRotationKey = KeyBinding.FromKey(KeyCode.Escape);
private readonly MouseRotationProvider mouseRotation = new MouseRotationProvider();
public ManualCameraControl(MixedRealityInputSimulationProfile _profile)
{
profile = _profile;
}
private static float InputCurve(float x)
{
// smoothing input curve, converts from [-1,1] to [-2,2]
return Mathf.Sign(x) * (1.0f - Mathf.Cos(0.5f * Mathf.PI * Mathf.Clamp(x, -1.0f, 1.0f)));
}
/// <summary>
/// Moves the camera transform based on the profile's origin offset
/// </summary>
public void SetInitialTransform(Transform transform)
{
transform.Translate(profile.CameraOriginOffset);
}
/// <summary>
/// Translate and rotate the camera transform based on keyboard and mouse input.
/// </summary>
public void UpdateTransform(Transform transform, MouseDelta mouseDelta)
{
// Undo the last tracker to Unity transforms applied
transform.Translate(-this.lastTrackerToUnityTranslation, Space.World);
transform.Rotate(-this.lastTrackerToUnityRotation.eulerAngles, Space.World);
// Calculate and apply the camera control movement this frame
Vector3 rotate = GetCameraControlRotation(mouseDelta);
Vector3 translate = GetCameraControlTranslation(transform);
transform.Rotate(rotate.x, 0.0f, 0.0f);
transform.Rotate(0.0f, rotate.y, 0.0f, Space.World);
transform.Rotate(0.0f, 0.0f, rotate.z);
transform.Translate(translate, Space.World);
transform.Rotate(this.lastTrackerToUnityRotation.eulerAngles, Space.World);
transform.Translate(this.lastTrackerToUnityTranslation, Space.World);
}
private static float GetKeyDir(string neg, string pos)
{
return UnityEngine.Input.GetKey(neg) ? -1.0f : UnityEngine.Input.GetKey(pos) ? 1.0f : 0.0f;
}
private Vector3 GetCameraControlTranslation(Transform transform)
{
Vector3 deltaPosition = Vector3.zero;
// Support fly up/down keypresses if the current project maps it. This isn't a standard
// Unity InputManager mapping, so it has to gracefully fail if unavailable.
if (this.isFlyKeypressEnabled)
{
try
{
deltaPosition += InputCurve(UnityEngine.Input.GetAxis("Fly")) * transform.up;
}
catch (System.Exception)
{
this.isFlyKeypressEnabled = false;
}
}
else
{
// use page up/down in this case
deltaPosition += GetKeyDir("page down", "page up") * Vector3.up;
}
deltaPosition += InputCurve(UnityEngine.Input.GetAxis(profile.MoveHorizontal)) * transform.right;
Vector3 forward;
Vector3 up;
if (profile.CurrentControlMode == InputSimulationControlMode.Walk)
{
up = Vector3.up;
forward = Vector3.ProjectOnPlane(transform.forward, up).normalized;
}
else
{
forward = transform.forward;
up = transform.up;
}
deltaPosition += InputCurve(UnityEngine.Input.GetAxis(profile.MoveVertical)) * forward;
deltaPosition += InputCurve(UnityEngine.Input.GetAxis(profile.MoveUpDown)) * up;
float accel = KeyInputSystem.GetKey(profile.FastControlKey) ? profile.ControlFastSpeed : profile.ControlSlowSpeed;
return accel * deltaPosition * Time.deltaTime;
}
private Vector3 GetCameraControlRotation(MouseDelta mouseDelta)
{
float inversionFactor = profile.IsControllerLookInverted ? -1.0f : 1.0f;
Vector3 rot = Vector3.zero;
if (this.isGamepadLookEnabled)
{
try
{
// Get the axes information from the right stick of X360 controller
rot.x += InputCurve(UnityEngine.Input.GetAxis(profile.LookVertical)) * inversionFactor;
rot.y += InputCurve(UnityEngine.Input.GetAxis(profile.LookHorizontal));
}
catch (System.Exception)
{
this.isGamepadLookEnabled = false;
}
}
mouseRotation.Update(profile.MouseLookButton, cancelRotationKey, profile.MouseLookToggle);
if (mouseRotation.IsRotating)
{
rot.x += -InputCurve(mouseDelta.screenDelta.y * profile.MouseRotationSensitivity);
rot.y += InputCurve(mouseDelta.screenDelta.x * profile.MouseRotationSensitivity);
rot.z += InputCurve(mouseDelta.screenDelta.z * profile.MouseRotationSensitivity);
}
rot *= profile.MouseLookSpeed;
return rot;
}
}
}