You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
819 lines
36 KiB
819 lines
36 KiB
3 years ago
|
//========= Copyright 2016-2018, HTC Corporation. All rights reserved. ===========
|
||
|
|
||
|
using HTC.UnityPlugin.Vive;
|
||
|
using HTC.UnityPlugin.Utility;
|
||
|
using UnityEngine;
|
||
|
using System;
|
||
|
#if UNITY_2017_2_OR_NEWER
|
||
|
using UnityEngine.XR;
|
||
|
#else
|
||
|
using XRSettings = UnityEngine.VR.VRSettings;
|
||
|
using XRDevice = UnityEngine.VR.VRDevice;
|
||
|
#endif
|
||
|
|
||
|
namespace HTC.UnityPlugin.VRModuleManagement
|
||
|
{
|
||
|
public interface ISimulatorVRModule
|
||
|
{
|
||
|
event Action onActivated;
|
||
|
event Action onDeactivated;
|
||
|
event SimulatorVRModule.UpdateDeviceStateHandler onUpdateDeviceState;
|
||
|
}
|
||
|
|
||
|
public sealed class SimulatorVRModule : VRModule.ModuleBase, ISimulatorVRModule
|
||
|
{
|
||
|
public delegate void UpdateDeviceStateHandler(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState);
|
||
|
|
||
|
public const uint SIMULATOR_MAX_DEVICE_COUNT = 16u;
|
||
|
private const uint RIGHT_INDEX = 1;
|
||
|
private const uint LEFT_INDEX = 2;
|
||
|
|
||
|
private static readonly RigidPose s_initHmdPose = new RigidPose(new Vector3(0f, 1.75f, 0f), Quaternion.identity);
|
||
|
private static RigidPose s_offsetLeftController = RigidPose.identity;
|
||
|
private static RigidPose s_offsetRightController = RigidPose.identity;
|
||
|
private static RigidPose s_offsetTracker = RigidPose.identity;
|
||
|
|
||
|
private bool m_prevXREnabled;
|
||
|
private bool m_resetDevices;
|
||
|
private IMGUIHandle m_guiHandle;
|
||
|
|
||
|
public event Action onActivated;
|
||
|
public event Action onDeactivated;
|
||
|
public event UpdateDeviceStateHandler onUpdateDeviceState;
|
||
|
|
||
|
public uint selectedDeviceIndex { get; private set; }
|
||
|
|
||
|
public bool hasControlFocus { get; private set; }
|
||
|
|
||
|
public override bool ShouldActiveModule() { return VIUSettings.activateSimulatorModule; }
|
||
|
|
||
|
public override void OnActivated()
|
||
|
{
|
||
|
if (m_prevXREnabled = XRSettings.enabled)
|
||
|
{
|
||
|
XRSettings.enabled = false;
|
||
|
}
|
||
|
|
||
|
m_resetDevices = true;
|
||
|
hasControlFocus = true;
|
||
|
selectedDeviceIndex = VRModule.INVALID_DEVICE_INDEX;
|
||
|
|
||
|
// Simulator instructions GUI
|
||
|
m_guiHandle = VRModule.Instance.gameObject.GetComponent<IMGUIHandle>();
|
||
|
if (m_guiHandle == null)
|
||
|
{
|
||
|
m_guiHandle = VRModule.Instance.gameObject.AddComponent<IMGUIHandle>();
|
||
|
m_guiHandle.simulator = this;
|
||
|
}
|
||
|
|
||
|
if (onActivated != null)
|
||
|
{
|
||
|
onActivated();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void OnDeactivated()
|
||
|
{
|
||
|
if (m_guiHandle != null)
|
||
|
{
|
||
|
m_guiHandle.simulator = null;
|
||
|
UnityEngine.Object.Destroy(m_guiHandle);
|
||
|
m_guiHandle = null;
|
||
|
}
|
||
|
|
||
|
UpdateMainCamTracking();
|
||
|
|
||
|
XRSettings.enabled = m_prevXREnabled;
|
||
|
|
||
|
if (onDeactivated != null)
|
||
|
{
|
||
|
onDeactivated();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override uint GetRightControllerDeviceIndex() { return RIGHT_INDEX; }
|
||
|
|
||
|
public override uint GetLeftControllerDeviceIndex() { return LEFT_INDEX; }
|
||
|
|
||
|
public override void Update()
|
||
|
{
|
||
|
if (VIUSettings.enableSimulatorKeyboardMouseControl)
|
||
|
{
|
||
|
UpdateKeyDown();
|
||
|
|
||
|
Cursor.visible = !hasControlFocus;
|
||
|
Cursor.lockState = hasControlFocus ? CursorLockMode.Locked : CursorLockMode.None;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void UpdateDeviceState(IVRModuleDeviceState[] prevState, IVRModuleDeviceStateRW[] currState)
|
||
|
{
|
||
|
if (VIUSettings.enableSimulatorKeyboardMouseControl && hasControlFocus)
|
||
|
{
|
||
|
if (IsEscapeKeyDown())
|
||
|
{
|
||
|
if (IsDeviceSelected())
|
||
|
{
|
||
|
DeselectDevice();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//SetSimulatorActive(false);
|
||
|
hasControlFocus = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// reset to default state
|
||
|
if (m_resetDevices || IsResetAllKeyDown())
|
||
|
{
|
||
|
m_resetDevices = false;
|
||
|
|
||
|
foreach (var state in currState)
|
||
|
{
|
||
|
switch (state.deviceIndex)
|
||
|
{
|
||
|
case VRModule.HMD_DEVICE_INDEX:
|
||
|
case RIGHT_INDEX:
|
||
|
case LEFT_INDEX:
|
||
|
InitializeDevice(currState[VRModule.HMD_DEVICE_INDEX], state);
|
||
|
break;
|
||
|
default:
|
||
|
if (state.isConnected)
|
||
|
{
|
||
|
state.Reset();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DeselectDevice();
|
||
|
}
|
||
|
|
||
|
// align devices with hmd
|
||
|
if (IsResetDevicesKeyDown())
|
||
|
{
|
||
|
foreach (var state in currState)
|
||
|
{
|
||
|
switch (state.deviceIndex)
|
||
|
{
|
||
|
case VRModule.HMD_DEVICE_INDEX:
|
||
|
break;
|
||
|
case RIGHT_INDEX:
|
||
|
state.pose = currState[VRModule.HMD_DEVICE_INDEX].pose * s_offsetRightController;
|
||
|
break;
|
||
|
case LEFT_INDEX:
|
||
|
state.pose = currState[VRModule.HMD_DEVICE_INDEX].pose * s_offsetLeftController;
|
||
|
break;
|
||
|
default:
|
||
|
if (state.isConnected)
|
||
|
{
|
||
|
state.pose = currState[VRModule.HMD_DEVICE_INDEX].pose * s_offsetTracker;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// select/deselect device
|
||
|
IVRModuleDeviceStateRW keySelectDevice;
|
||
|
if (GetDeviceByInputDownKeyCode(currState, out keySelectDevice))
|
||
|
{
|
||
|
if (IsShiftKeyPressed())
|
||
|
{
|
||
|
// remove device
|
||
|
if (keySelectDevice.isConnected && keySelectDevice.deviceIndex != VRModule.HMD_DEVICE_INDEX)
|
||
|
{
|
||
|
if (IsSelectedDevice(keySelectDevice))
|
||
|
{
|
||
|
DeselectDevice();
|
||
|
}
|
||
|
|
||
|
keySelectDevice.Reset();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (IsSelectedDevice(keySelectDevice))
|
||
|
{
|
||
|
DeselectDevice();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// select device
|
||
|
if (!keySelectDevice.isConnected)
|
||
|
{
|
||
|
InitializeDevice(currState[VRModule.HMD_DEVICE_INDEX], keySelectDevice);
|
||
|
}
|
||
|
|
||
|
SelectDevice(keySelectDevice);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var selectedDevice = VRModule.IsValidDeviceIndex(selectedDeviceIndex) && currState[selectedDeviceIndex].isConnected ? currState[selectedDeviceIndex] : null;
|
||
|
if (selectedDevice != null)
|
||
|
{
|
||
|
// control selected device
|
||
|
ControlDevice(selectedDevice);
|
||
|
|
||
|
if (selectedDevice.deviceClass == VRModuleDeviceClass.Controller || selectedDevice.deviceClass == VRModuleDeviceClass.GenericTracker)
|
||
|
{
|
||
|
HandleDeviceInput(selectedDevice);
|
||
|
}
|
||
|
}
|
||
|
else if (hasControlFocus)
|
||
|
{
|
||
|
// control device group
|
||
|
ControlDeviceGroup(currState);
|
||
|
}
|
||
|
|
||
|
// control camera (TFGH)
|
||
|
if (currState[VRModule.HMD_DEVICE_INDEX].isConnected)
|
||
|
{
|
||
|
ControlCamera(currState[VRModule.HMD_DEVICE_INDEX]);
|
||
|
}
|
||
|
}
|
||
|
else if (IsDeviceSelected())
|
||
|
{
|
||
|
DeselectDevice();
|
||
|
}
|
||
|
|
||
|
if (onUpdateDeviceState != null)
|
||
|
{
|
||
|
onUpdateDeviceState(prevState, currState);
|
||
|
}
|
||
|
|
||
|
UpdateMainCamTracking();
|
||
|
}
|
||
|
|
||
|
private bool m_autoTrackMainCam;
|
||
|
private RigidPose m_mainCamStartPose;
|
||
|
private void UpdateMainCamTracking()
|
||
|
{
|
||
|
if (VIUSettings.simulatorAutoTrackMainCamera)
|
||
|
{
|
||
|
if (!m_autoTrackMainCam)
|
||
|
{
|
||
|
m_autoTrackMainCam = true;
|
||
|
m_mainCamStartPose = new RigidPose(Camera.main.transform, true);
|
||
|
}
|
||
|
|
||
|
if (Camera.main != null)
|
||
|
{
|
||
|
var hmd = VRModule.GetDeviceState(VRModule.HMD_DEVICE_INDEX);
|
||
|
if (hmd.isConnected)
|
||
|
{
|
||
|
RigidPose.SetPose(Camera.main.transform, hmd.pose);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (m_autoTrackMainCam)
|
||
|
{
|
||
|
m_autoTrackMainCam = false;
|
||
|
|
||
|
if (Camera.main != null)
|
||
|
{
|
||
|
RigidPose.SetPose(Camera.main.transform, m_mainCamStartPose);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool IsSelectedDevice(IVRModuleDeviceStateRW state)
|
||
|
{
|
||
|
return selectedDeviceIndex == state.deviceIndex;
|
||
|
}
|
||
|
|
||
|
private bool IsDeviceSelected()
|
||
|
{
|
||
|
return VRModule.IsValidDeviceIndex(selectedDeviceIndex);
|
||
|
}
|
||
|
|
||
|
private void SelectDevice(IVRModuleDeviceStateRW state)
|
||
|
{
|
||
|
selectedDeviceIndex = state.deviceIndex;
|
||
|
}
|
||
|
|
||
|
private void DeselectDevice()
|
||
|
{
|
||
|
selectedDeviceIndex = VRModule.INVALID_DEVICE_INDEX;
|
||
|
}
|
||
|
|
||
|
// Input.GetKeyDown in UpdateDeviceState is not working
|
||
|
private bool m_menuKeyPressed;
|
||
|
private bool m_resetDevicesKeyPressed;
|
||
|
private bool m_resetAllKeyPressed;
|
||
|
private bool m_escapeKeyPressed;
|
||
|
private bool m_shiftKeyPressed;
|
||
|
private bool[] m_alphaKeyDownState = new bool[10];
|
||
|
|
||
|
private void UpdateKeyDown()
|
||
|
{
|
||
|
m_menuKeyPressed = Input.GetKeyDown(KeyCode.M);
|
||
|
m_resetDevicesKeyPressed = Input.GetKeyDown(KeyCode.F2);
|
||
|
m_resetAllKeyPressed = Input.GetKeyDown(KeyCode.F3);
|
||
|
m_escapeKeyPressed = Input.GetKeyDown(KeyCode.Escape);
|
||
|
m_shiftKeyPressed = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
|
||
|
m_alphaKeyDownState[0] = Input.GetKeyDown(KeyCode.Alpha0) || Input.GetKeyDown(KeyCode.Keypad0);
|
||
|
m_alphaKeyDownState[1] = Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1);
|
||
|
m_alphaKeyDownState[2] = Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2);
|
||
|
m_alphaKeyDownState[3] = Input.GetKeyDown(KeyCode.Alpha3) || Input.GetKeyDown(KeyCode.Keypad3);
|
||
|
m_alphaKeyDownState[4] = Input.GetKeyDown(KeyCode.Alpha4) || Input.GetKeyDown(KeyCode.Keypad4);
|
||
|
m_alphaKeyDownState[5] = Input.GetKeyDown(KeyCode.Alpha5) || Input.GetKeyDown(KeyCode.Keypad5);
|
||
|
m_alphaKeyDownState[6] = Input.GetKeyDown(KeyCode.Alpha6) || Input.GetKeyDown(KeyCode.Keypad6);
|
||
|
m_alphaKeyDownState[7] = Input.GetKeyDown(KeyCode.Alpha7) || Input.GetKeyDown(KeyCode.Keypad7);
|
||
|
m_alphaKeyDownState[8] = Input.GetKeyDown(KeyCode.Alpha8) || Input.GetKeyDown(KeyCode.Keypad8);
|
||
|
m_alphaKeyDownState[9] = Input.GetKeyDown(KeyCode.Alpha9) || Input.GetKeyDown(KeyCode.Keypad9);
|
||
|
}
|
||
|
|
||
|
private bool IsMenuKeyDown() { return m_menuKeyPressed; }
|
||
|
private bool IsResetAllKeyDown() { return m_resetAllKeyPressed; }
|
||
|
private bool IsResetDevicesKeyDown() { return m_resetDevicesKeyPressed; }
|
||
|
private bool IsEscapeKeyDown() { return m_escapeKeyPressed; }
|
||
|
private bool IsShiftKeyPressed() { return m_shiftKeyPressed; }
|
||
|
private bool IsAlphaKeyDown(int num) { return m_alphaKeyDownState[num]; }
|
||
|
|
||
|
private bool GetDeviceByInputDownKeyCode(IVRModuleDeviceStateRW[] deviceStates, out IVRModuleDeviceStateRW deviceState)
|
||
|
{
|
||
|
var backQuotePressed = Input.GetKey(KeyCode.BackQuote);
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(0)) { deviceState = deviceStates[0]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(1)) { deviceState = deviceStates[1]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(2)) { deviceState = deviceStates[2]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(3)) { deviceState = deviceStates[3]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(4)) { deviceState = deviceStates[4]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(5)) { deviceState = deviceStates[5]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(6)) { deviceState = deviceStates[6]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(7)) { deviceState = deviceStates[7]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(8)) { deviceState = deviceStates[8]; return true; }
|
||
|
if (!backQuotePressed && IsAlphaKeyDown(9)) { deviceState = deviceStates[9]; return true; }
|
||
|
if (backQuotePressed && IsAlphaKeyDown(0)) { deviceState = deviceStates[10]; return true; }
|
||
|
if (backQuotePressed && IsAlphaKeyDown(1)) { deviceState = deviceStates[11]; return true; }
|
||
|
if (backQuotePressed && IsAlphaKeyDown(2)) { deviceState = deviceStates[12]; return true; }
|
||
|
if (backQuotePressed && IsAlphaKeyDown(3)) { deviceState = deviceStates[13]; return true; }
|
||
|
if (backQuotePressed && IsAlphaKeyDown(4)) { deviceState = deviceStates[14]; return true; }
|
||
|
if (backQuotePressed && IsAlphaKeyDown(5)) { deviceState = deviceStates[15]; return true; }
|
||
|
|
||
|
deviceState = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private void InitializeDevice(IVRModuleDeviceStateRW hmdState, IVRModuleDeviceStateRW deviceState)
|
||
|
{
|
||
|
switch (deviceState.deviceIndex)
|
||
|
{
|
||
|
case VRModule.HMD_DEVICE_INDEX:
|
||
|
{
|
||
|
deviceState.isConnected = true;
|
||
|
deviceState.deviceClass = VRModuleDeviceClass.HMD;
|
||
|
deviceState.serialNumber = "VIU Simulator HMD Device";
|
||
|
deviceState.modelNumber = deviceState.serialNumber;
|
||
|
deviceState.renderModelName = deviceState.serialNumber;
|
||
|
deviceState.deviceModel = VRModuleDeviceModel.ViveHMD;
|
||
|
|
||
|
deviceState.isPoseValid = true;
|
||
|
deviceState.pose = s_initHmdPose;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case RIGHT_INDEX:
|
||
|
{
|
||
|
deviceState.isConnected = true;
|
||
|
deviceState.deviceClass = VRModuleDeviceClass.Controller;
|
||
|
deviceState.serialNumber = "VIU Simulator Controller Device " + RIGHT_INDEX;
|
||
|
deviceState.modelNumber = deviceState.serialNumber;
|
||
|
deviceState.renderModelName = deviceState.serialNumber;
|
||
|
deviceState.deviceModel = VRModuleDeviceModel.ViveController;
|
||
|
|
||
|
var pose = new RigidPose(new Vector3(0.3f, -0.25f, 0.7f), Quaternion.identity);
|
||
|
deviceState.isPoseValid = true;
|
||
|
deviceState.pose = (hmdState.isConnected ? hmdState.pose : s_initHmdPose) * pose;
|
||
|
s_offsetRightController = RigidPose.FromToPose(hmdState.isConnected ? hmdState.pose : s_initHmdPose, deviceState.pose);
|
||
|
deviceState.buttonPressed = 0ul;
|
||
|
deviceState.buttonTouched = 0ul;
|
||
|
deviceState.ResetAxisValues();
|
||
|
break;
|
||
|
}
|
||
|
case LEFT_INDEX:
|
||
|
{
|
||
|
deviceState.isConnected = true;
|
||
|
deviceState.deviceClass = VRModuleDeviceClass.Controller;
|
||
|
deviceState.serialNumber = "VIU Simulator Controller Device " + LEFT_INDEX;
|
||
|
deviceState.modelNumber = deviceState.serialNumber;
|
||
|
deviceState.renderModelName = deviceState.serialNumber;
|
||
|
deviceState.deviceModel = VRModuleDeviceModel.ViveController;
|
||
|
|
||
|
var pose = new RigidPose(new Vector3(-0.3f, -0.25f, 0.7f), Quaternion.identity);
|
||
|
deviceState.isPoseValid = true;
|
||
|
deviceState.pose = (hmdState.isConnected ? hmdState.pose : s_initHmdPose) * pose;
|
||
|
s_offsetLeftController = RigidPose.FromToPose(hmdState.isConnected ? hmdState.pose : s_initHmdPose, deviceState.pose);
|
||
|
deviceState.buttonPressed = 0ul;
|
||
|
deviceState.buttonTouched = 0ul;
|
||
|
deviceState.ResetAxisValues();
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
deviceState.isConnected = true;
|
||
|
deviceState.deviceClass = VRModuleDeviceClass.GenericTracker;
|
||
|
deviceState.serialNumber = "VIU Simulator Generic Tracker Device " + deviceState.deviceIndex;
|
||
|
deviceState.modelNumber = deviceState.serialNumber;
|
||
|
deviceState.renderModelName = deviceState.serialNumber;
|
||
|
deviceState.deviceModel = VRModuleDeviceModel.ViveTracker;
|
||
|
|
||
|
var pose = new RigidPose(new Vector3(0f, -0.25f, 0.7f), Quaternion.identity);
|
||
|
deviceState.isPoseValid = true;
|
||
|
deviceState.pose = (hmdState.isConnected ? hmdState.pose : s_initHmdPose) * pose;
|
||
|
s_offsetTracker = RigidPose.FromToPose(hmdState.isConnected ? hmdState.pose : s_initHmdPose, deviceState.pose);
|
||
|
deviceState.buttonPressed = 0ul;
|
||
|
deviceState.buttonTouched = 0ul;
|
||
|
deviceState.ResetAxisValues();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ControlDevice(IVRModuleDeviceStateRW deviceState)
|
||
|
{
|
||
|
var pose = deviceState.pose;
|
||
|
var poseEuler = pose.rot.eulerAngles;
|
||
|
var deltaAngle = Time.unscaledDeltaTime * VIUSettings.simulatorMouseRotateSpeed;
|
||
|
var deltaKeyAngle = Time.unscaledDeltaTime * VIUSettings.simulatorKeyRotateSpeed;
|
||
|
|
||
|
poseEuler.x = Mathf.Repeat(poseEuler.x + 180f, 360f) - 180f;
|
||
|
|
||
|
if (!IsShiftKeyPressed())
|
||
|
{
|
||
|
var pitchDelta = -Input.GetAxisRaw("Mouse Y") * deltaAngle;
|
||
|
if (pitchDelta > 0f)
|
||
|
{
|
||
|
if (poseEuler.x < 90f && poseEuler.x > -180f)
|
||
|
{
|
||
|
poseEuler.x = Mathf.Min(90f, poseEuler.x + pitchDelta);
|
||
|
}
|
||
|
}
|
||
|
else if (pitchDelta < 0f)
|
||
|
{
|
||
|
if (poseEuler.x < 180f && poseEuler.x > -90f)
|
||
|
{
|
||
|
poseEuler.x = Mathf.Max(-90f, poseEuler.x + pitchDelta);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
poseEuler.y += Input.GetAxisRaw("Mouse X") * deltaAngle;
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.DownArrow))
|
||
|
{
|
||
|
if (poseEuler.x < 90f && poseEuler.x > -180f)
|
||
|
{
|
||
|
poseEuler.x = Mathf.Min(90f, poseEuler.x + deltaKeyAngle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.UpArrow))
|
||
|
{
|
||
|
if (poseEuler.x < 180f && poseEuler.x > -90f)
|
||
|
{
|
||
|
poseEuler.x = Mathf.Max(-90f, poseEuler.x - deltaKeyAngle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.RightArrow)) { poseEuler.y += deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.LeftArrow)) { poseEuler.y -= deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.C)) { poseEuler.z += deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.Z)) { poseEuler.z -= deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.X)) { poseEuler.z = 0f; }
|
||
|
|
||
|
pose.rot = Quaternion.Euler(poseEuler);
|
||
|
|
||
|
var deltaMove = Time.unscaledDeltaTime * VIUSettings.simulatorKeyMoveSpeed;
|
||
|
var moveForward = Quaternion.Euler(0f, poseEuler.y, 0f) * Vector3.forward;
|
||
|
var moveRight = Quaternion.Euler(0f, poseEuler.y, 0f) * Vector3.right;
|
||
|
if (Input.GetKey(KeyCode.D)) { pose.pos += moveRight * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.A)) { pose.pos -= moveRight * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.E)) { pose.pos += Vector3.up * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.Q)) { pose.pos -= Vector3.up * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.W)) { pose.pos += moveForward * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.S)) { pose.pos -= moveForward * deltaMove; }
|
||
|
|
||
|
deviceState.pose = pose;
|
||
|
}
|
||
|
|
||
|
private void ControlDeviceGroup(IVRModuleDeviceStateRW[] deviceStates)
|
||
|
{
|
||
|
var hmdPose = deviceStates[VRModule.HMD_DEVICE_INDEX].pose;
|
||
|
var hmdPoseEuler = hmdPose.rot.eulerAngles;
|
||
|
|
||
|
var oldRigPose = new RigidPose(hmdPose.pos, Quaternion.Euler(0f, hmdPoseEuler.y, 0f));
|
||
|
|
||
|
var deltaAngle = Time.unscaledDeltaTime * VIUSettings.simulatorMouseRotateSpeed;
|
||
|
var deltaKeyAngle = Time.unscaledDeltaTime * VIUSettings.simulatorKeyRotateSpeed;
|
||
|
|
||
|
// translate and rotate HMD
|
||
|
hmdPoseEuler.x = Mathf.Repeat(hmdPoseEuler.x + 180f, 360f) - 180f;
|
||
|
|
||
|
var pitchDelta = -Input.GetAxisRaw("Mouse Y") * deltaAngle;
|
||
|
if (pitchDelta > 0f)
|
||
|
{
|
||
|
if (hmdPoseEuler.x < 90f && hmdPoseEuler.x > -180f)
|
||
|
{
|
||
|
hmdPoseEuler.x = Mathf.Min(90f, hmdPoseEuler.x + pitchDelta);
|
||
|
}
|
||
|
}
|
||
|
else if (pitchDelta < 0f)
|
||
|
{
|
||
|
if (hmdPoseEuler.x < 180f && hmdPoseEuler.x > -90f)
|
||
|
{
|
||
|
hmdPoseEuler.x = Mathf.Max(-90f, hmdPoseEuler.x + pitchDelta);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.DownArrow))
|
||
|
{
|
||
|
if (hmdPoseEuler.x < 90f && hmdPoseEuler.x > -180f)
|
||
|
{
|
||
|
hmdPoseEuler.x = Mathf.Min(90f, hmdPoseEuler.x + deltaKeyAngle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.UpArrow))
|
||
|
{
|
||
|
if (hmdPoseEuler.x < 180f && hmdPoseEuler.x > -90f)
|
||
|
{
|
||
|
hmdPoseEuler.x = Mathf.Max(-90f, hmdPoseEuler.x - deltaKeyAngle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.RightArrow)) { hmdPoseEuler.y += deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.LeftArrow)) { hmdPoseEuler.y -= deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.C)) { hmdPoseEuler.z += deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.Z)) { hmdPoseEuler.z -= deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.X)) { hmdPoseEuler.z = 0f; }
|
||
|
|
||
|
hmdPoseEuler.y += Input.GetAxisRaw("Mouse X") * deltaAngle;
|
||
|
|
||
|
hmdPose.rot = Quaternion.Euler(hmdPoseEuler);
|
||
|
|
||
|
var deltaMove = Time.unscaledDeltaTime * VIUSettings.simulatorKeyMoveSpeed;
|
||
|
var moveForward = Quaternion.Euler(0f, hmdPoseEuler.y, 0f) * Vector3.forward;
|
||
|
var moveRight = Quaternion.Euler(0f, hmdPoseEuler.y, 0f) * Vector3.right;
|
||
|
if (Input.GetKey(KeyCode.D)) { hmdPose.pos += moveRight * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.A)) { hmdPose.pos -= moveRight * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.E)) { hmdPose.pos += Vector3.up * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.Q)) { hmdPose.pos -= Vector3.up * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.W)) { hmdPose.pos += moveForward * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.S)) { hmdPose.pos -= moveForward * deltaMove; }
|
||
|
|
||
|
deviceStates[VRModule.HMD_DEVICE_INDEX].pose = hmdPose;
|
||
|
|
||
|
var rigPoseOffset = new RigidPose(hmdPose.pos, Quaternion.Euler(0f, hmdPose.rot.eulerAngles.y, 0f)) * oldRigPose.GetInverse();
|
||
|
|
||
|
for (int i = deviceStates.Length - 1; i >= 0; --i)
|
||
|
{
|
||
|
if (i == VRModule.HMD_DEVICE_INDEX) { continue; }
|
||
|
|
||
|
var state = deviceStates[i];
|
||
|
if (!state.isConnected) { continue; }
|
||
|
|
||
|
state.pose = rigPoseOffset * state.pose;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ControlCamera(IVRModuleDeviceStateRW deviceState)
|
||
|
{
|
||
|
var pose = deviceState.pose;
|
||
|
var poseEuler = pose.rot.eulerAngles;
|
||
|
var deltaKeyAngle = Time.unscaledDeltaTime * VIUSettings.simulatorKeyRotateSpeed;
|
||
|
|
||
|
poseEuler.x = Mathf.Repeat(poseEuler.x + 180f, 360f) - 180f;
|
||
|
|
||
|
if (Input.GetKey(KeyCode.K))
|
||
|
{
|
||
|
if (poseEuler.x < 90f && poseEuler.x > -180f)
|
||
|
{
|
||
|
poseEuler.x = Mathf.Min(90f, poseEuler.x + deltaKeyAngle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.I))
|
||
|
{
|
||
|
if (poseEuler.x < 180f && poseEuler.x > -90f)
|
||
|
{
|
||
|
poseEuler.x = Mathf.Max(-90f, poseEuler.x - deltaKeyAngle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Input.GetKey(KeyCode.L)) { poseEuler.y += deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.J)) { poseEuler.y -= deltaKeyAngle; }
|
||
|
|
||
|
if (Input.GetKey(KeyCode.N)) { poseEuler.z += deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.V)) { poseEuler.z -= deltaKeyAngle; }
|
||
|
if (Input.GetKey(KeyCode.B)) { poseEuler.z = 0f; }
|
||
|
|
||
|
pose.rot = Quaternion.Euler(poseEuler);
|
||
|
|
||
|
var deltaMove = Time.unscaledDeltaTime * VIUSettings.simulatorKeyMoveSpeed;
|
||
|
var moveForward = Quaternion.Euler(0f, poseEuler.y, 0f) * Vector3.forward;
|
||
|
var moveRight = Quaternion.Euler(0f, poseEuler.y, 0f) * Vector3.right;
|
||
|
if (Input.GetKey(KeyCode.H)) { pose.pos += moveRight * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.F)) { pose.pos -= moveRight * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.Y)) { pose.pos += Vector3.up * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.R)) { pose.pos -= Vector3.up * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.T)) { pose.pos += moveForward * deltaMove; }
|
||
|
if (Input.GetKey(KeyCode.G)) { pose.pos -= moveForward * deltaMove; }
|
||
|
|
||
|
deviceState.pose = pose;
|
||
|
}
|
||
|
|
||
|
private void HandleDeviceInput(IVRModuleDeviceStateRW deviceState)
|
||
|
{
|
||
|
var leftPressed = Input.GetMouseButton(0);
|
||
|
var rightPressed = Input.GetMouseButton(1);
|
||
|
var midPressed = Input.GetMouseButton(2);
|
||
|
|
||
|
deviceState.SetButtonPress(VRModuleRawButton.Trigger, leftPressed);
|
||
|
deviceState.SetButtonTouch(VRModuleRawButton.Trigger, leftPressed);
|
||
|
deviceState.SetAxisValue(VRModuleRawAxis.Trigger, leftPressed ? 1f : 0f);
|
||
|
|
||
|
deviceState.SetButtonPress(VRModuleRawButton.Grip, midPressed);
|
||
|
deviceState.SetButtonTouch(VRModuleRawButton.Grip, midPressed);
|
||
|
deviceState.SetAxisValue(VRModuleRawAxis.CapSenseGrip, midPressed ? 1f : 0f);
|
||
|
|
||
|
deviceState.SetButtonPress(VRModuleRawButton.Touchpad, rightPressed);
|
||
|
|
||
|
deviceState.SetButtonPress(VRModuleRawButton.ApplicationMenu, IsMenuKeyDown());
|
||
|
deviceState.SetButtonTouch(VRModuleRawButton.ApplicationMenu, IsMenuKeyDown());
|
||
|
|
||
|
if (VIUSettings.simulateTrackpadTouch && IsShiftKeyPressed())
|
||
|
{
|
||
|
deviceState.SetButtonTouch(VRModuleRawButton.Touchpad, true);
|
||
|
deviceState.SetAxisValue(VRModuleRawAxis.TouchpadX, deviceState.GetAxisValue(VRModuleRawAxis.TouchpadX) + (Input.GetAxisRaw("Mouse X") * 0.1f));
|
||
|
deviceState.SetAxisValue(VRModuleRawAxis.TouchpadY, deviceState.GetAxisValue(VRModuleRawAxis.TouchpadY) + (Input.GetAxisRaw("Mouse Y") * 0.1f));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
deviceState.SetButtonTouch(VRModuleRawButton.Touchpad, rightPressed);
|
||
|
deviceState.SetAxisValue(VRModuleRawAxis.TouchpadX, 0f);
|
||
|
deviceState.SetAxisValue(VRModuleRawAxis.TouchpadY, 0f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private class IMGUIHandle : MonoBehaviour
|
||
|
{
|
||
|
public SimulatorVRModule simulator { get; set; }
|
||
|
|
||
|
private bool showGUI { get; set; }
|
||
|
|
||
|
private void Start()
|
||
|
{
|
||
|
showGUI = true;
|
||
|
}
|
||
|
|
||
|
private void Update()
|
||
|
{
|
||
|
if (Input.GetKeyDown(KeyCode.F1))
|
||
|
{
|
||
|
showGUI = !showGUI;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static string Bold(string s) { return "<b>" + s + "</b>"; }
|
||
|
|
||
|
private static string SetColor(string s, string color) { return "<color=" + color + ">" + s + "</color>"; }
|
||
|
|
||
|
private void OnGUI()
|
||
|
{
|
||
|
if (!VIUSettings.enableSimulatorKeyboardMouseControl) { return; }
|
||
|
|
||
|
if (!showGUI || simulator == null) { return; }
|
||
|
|
||
|
var hints = string.Empty;
|
||
|
|
||
|
if (simulator.hasControlFocus)
|
||
|
{
|
||
|
GUI.skin.box.stretchWidth = false;
|
||
|
GUI.skin.box.stretchHeight = false;
|
||
|
GUI.skin.box.alignment = TextAnchor.UpperLeft;
|
||
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||
|
GUI.skin.box.normal.textColor = Color.white;
|
||
|
|
||
|
// device status grids
|
||
|
GUI.skin.box.padding = new RectOffset(10, 10, 5, 5);
|
||
|
|
||
|
GUILayout.BeginArea(new Rect(5f, 5f, Screen.width, 30f));
|
||
|
GUILayout.BeginHorizontal();
|
||
|
|
||
|
for (uint i = 0u; i < SIMULATOR_MAX_DEVICE_COUNT; ++i)
|
||
|
{
|
||
|
var isHmd = i == VRModule.HMD_DEVICE_INDEX;
|
||
|
var isSelectedDevice = i == simulator.selectedDeviceIndex;
|
||
|
var isConndected = VRModule.GetCurrentDeviceState(i).isConnected;
|
||
|
|
||
|
var deviceName = isHmd ? "HMD 0" : i.ToString();
|
||
|
var colorName = !isConndected ? "grey" : isSelectedDevice ? "lime" : "white";
|
||
|
|
||
|
GUILayout.Box(SetColor(Bold(deviceName), colorName));
|
||
|
}
|
||
|
|
||
|
GUILayout.EndHorizontal();
|
||
|
GUILayout.EndArea();
|
||
|
|
||
|
var selectedDeviceClass = VRModule.GetCurrentDeviceState(simulator.selectedDeviceIndex).deviceClass;
|
||
|
// instructions
|
||
|
if (selectedDeviceClass == VRModuleDeviceClass.Invalid)
|
||
|
{
|
||
|
hints += "Pause simulator: " + Bold("ESC") + "\n";
|
||
|
hints += "Toggle instructions: " + Bold("F1") + "\n";
|
||
|
hints += "Align devices to HMD: " + Bold("F2") + "\n";
|
||
|
hints += "Reset all devices to initial state: " + Bold("F3") + "\n\n";
|
||
|
|
||
|
hints += "Move: " + Bold("WASD / QE") + "\n";
|
||
|
hints += "Rotate: " + Bold("Mouse") + "\n";
|
||
|
hints += "Add and select a device: \n";
|
||
|
hints += " [N] " + Bold("Num 0~9") + "\n";
|
||
|
hints += " [10+N] " + Bold("` + Num 0~5") + "\n";
|
||
|
hints += "Remove and deselect a device: \n";
|
||
|
hints += " [N] " + Bold("Shift + Num 0~9") + "\n";
|
||
|
hints += " [10+N] " + Bold("Shift + ` + Num 0~5") + "\n";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hints += "Toggle instructions: " + Bold("F1") + "\n";
|
||
|
hints += "Align devices with HMD: " + Bold("F2") + "\n";
|
||
|
hints += "Reset all devices to initial state: " + Bold("F3") + "\n\n";
|
||
|
|
||
|
hints += "Currently controlling ";
|
||
|
hints += SetColor(Bold("Device " + simulator.selectedDeviceIndex.ToString()) + " " + Bold("(" + selectedDeviceClass.ToString() + ")") + "\n", "lime");
|
||
|
if (simulator.selectedDeviceIndex <= 9)
|
||
|
{
|
||
|
hints += "Deselect this device: " + Bold("ESC") + " / " + Bold("Num " + simulator.selectedDeviceIndex) + "\n";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hints += "Deselect this device: " + Bold("ESC") + " / " + Bold("` + Num " + simulator.selectedDeviceIndex) + "\n";
|
||
|
}
|
||
|
hints += "Add and select a device: \n";
|
||
|
hints += " [N] " + Bold("Num 0~9") + "\n";
|
||
|
hints += " [10+N] " + Bold("` + Num 0~5") + "\n";
|
||
|
hints += "Remove and deselect a device: \n";
|
||
|
hints += " [N] " + Bold("Shift + Num 0~9") + "\n";
|
||
|
hints += " [10+N] " + Bold("Shift + ` + Num 0~5") + "\n";
|
||
|
|
||
|
hints += "\n";
|
||
|
hints += "Move: " + Bold("WASD / QE") + "\n";
|
||
|
hints += "Rotate (pitch and yaw): " + Bold("Mouse") + " or " + Bold("Arrow Keys") + "\n";
|
||
|
hints += "Rotate (roll): " + Bold("ZC") + "\n";
|
||
|
hints += "Reset roll: " + Bold("X") + "\n";
|
||
|
|
||
|
if (selectedDeviceClass == VRModuleDeviceClass.Controller || selectedDeviceClass == VRModuleDeviceClass.GenericTracker)
|
||
|
{
|
||
|
hints += "\n";
|
||
|
hints += "Trigger press: " + Bold("Mouse Left") + "\n";
|
||
|
hints += "Grip press: " + Bold("Mouse Middle") + "\n";
|
||
|
hints += "Trackpad press: " + Bold("Mouse Right") + "\n";
|
||
|
hints += "Trackpad touch: " + Bold("Hold Shift") + " + " + Bold("Mouse") + "\n";
|
||
|
hints += "Menu button press: " + Bold("M") + "\n";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hints += "\n";
|
||
|
hints += "HMD Move: " + Bold("TFGH / RY") + "\n";
|
||
|
hints += "HMD Rotate (pitch and yaw): " + Bold("IJKL") + "\n";
|
||
|
hints += "HMD Rotate (roll): " + Bold("VN") + "\n";
|
||
|
hints += "HMD Reset roll: " + Bold("B");
|
||
|
|
||
|
GUI.skin.box.padding = new RectOffset(10, 10, 10, 10);
|
||
|
|
||
|
GUILayout.BeginArea(new Rect(5f, 35f, Screen.width, Screen.height));
|
||
|
GUILayout.Box(hints);
|
||
|
GUILayout.EndArea();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// simulator resume button
|
||
|
int buttonHeight = 30;
|
||
|
int buttonWidth = 130;
|
||
|
Rect ButtonRect = new Rect((Screen.width * 0.5f) - (buttonWidth * 0.5f), (Screen.height * 0.5f) - buttonHeight, buttonWidth, buttonHeight);
|
||
|
|
||
|
if (GUI.Button(ButtonRect, Bold("Back to simulator")))
|
||
|
{
|
||
|
simulator.hasControlFocus = true;
|
||
|
}
|
||
|
|
||
|
GUI.skin.box.padding = new RectOffset(10, 10, 5, 5);
|
||
|
|
||
|
GUILayout.BeginArea(new Rect(5f, 5f, Screen.width, 30f));
|
||
|
GUILayout.BeginHorizontal();
|
||
|
|
||
|
hints += "Toggle instructions: " + Bold("F1");
|
||
|
GUILayout.Box(hints);
|
||
|
|
||
|
GUILayout.EndHorizontal();
|
||
|
GUILayout.EndArea();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|