147 lines
5.7 KiB
C#
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;
|
|
}
|
|
|
|
}
|
|
} |