2021년 4학년 1학기 기업연계프로젝트2 컴퓨터소프트웨어공학과 <원광투어팀> 팀장 : 송유진 팀원 : 김나영, 이경희, 한유진
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.

712 lines
30 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. #if VIU_STEAMVR && UNITY_STANDALONE
  3. using HTC.UnityPlugin.Utility;
  4. using HTC.UnityPlugin.Vive;
  5. using System.Text;
  6. using UnityEngine;
  7. using Valve.VR;
  8. using System;
  9. using System.Runtime.InteropServices;
  10. using System.Collections.Generic;
  11. using System.Collections;
  12. #if UNITY_2017_2_OR_NEWER
  13. using UnityEngine.XR;
  14. #elif UNITY_5_4_OR_NEWER
  15. using XRSettings = UnityEngine.VR.VRSettings;
  16. #endif
  17. #if VIU_XR_GENERAL_SETTINGS
  18. using UnityEngine.XR.Management;
  19. #endif
  20. #endif
  21. namespace HTC.UnityPlugin.VRModuleManagement
  22. {
  23. public sealed partial class SteamVRModule : VRModule.ModuleBase
  24. {
  25. public const string OPENVR_XR_LOADER_NAME = "Open VR Loader";
  26. public const string OPENVR_XR_LOADER_CLASS_NAME = "OpenVRLoader";
  27. #if VIU_STEAMVR_2_0_0_OR_NEWER && UNITY_STANDALONE
  28. public class ActionArray<T> where T : struct
  29. {
  30. private static readonly EnumUtils.EnumDisplayInfo s_enumInfo;
  31. private static readonly T[] s_enums;
  32. private static readonly ulong[] s_actionOrigins;
  33. public static readonly int Len;
  34. private string m_pathPrefix;
  35. private string m_dataType;
  36. private string[] m_aliases;
  37. private string[] m_paths;
  38. private ulong[] m_handles;
  39. private int m_iterator = -1;
  40. private int m_originIterator = -1;
  41. static ActionArray()
  42. {
  43. s_enumInfo = EnumUtils.GetDisplayInfo(typeof(T));
  44. Len = s_enumInfo.maxValue - s_enumInfo.minValue + 1;
  45. var ints = new int[Len];
  46. for (int i = 0; i < Len; ++i)
  47. {
  48. ints[i] = s_enumInfo.minValue + i;
  49. }
  50. s_enums = ints as T[];
  51. s_actionOrigins = new ulong[OpenVR.k_unMaxActionOriginCount];
  52. }
  53. public ActionArray(string pathPrefix, string dataType)
  54. {
  55. m_pathPrefix = pathPrefix;
  56. m_dataType = dataType;
  57. m_aliases = new string[Len];
  58. m_paths = new string[Len];
  59. m_handles = new ulong[Len];
  60. }
  61. public string DataType { get { return m_dataType; } }
  62. public T Current { get { return s_enums[m_iterator]; } }
  63. public string CurrentAlias { get { return m_aliases[m_iterator]; } }
  64. public string CurrentPath { get { return m_paths[m_iterator]; } }
  65. public ulong CurrentHandle { get { return m_handles[m_iterator]; } }
  66. public void MoveNext() { ++m_iterator; }
  67. public bool IsCurrentValid() { return m_iterator >= 0 && m_iterator < Len; }
  68. public void Reset() { m_iterator = 0; }
  69. public ulong CurrentOrigin { get { return s_actionOrigins[m_originIterator]; } }
  70. public void MoveNextOrigin() { ++m_originIterator; }
  71. public bool IsCurrentOriginValid() { return m_originIterator >= 0 && m_originIterator < s_actionOrigins.Length && s_actionOrigins[m_originIterator] != OpenVR.k_ulInvalidInputValueHandle; }
  72. public void ResetOrigins(CVRInput vrInput)
  73. {
  74. if (CurrentHandle == OpenVR.k_ulInvalidActionHandle)
  75. {
  76. m_originIterator = -1;
  77. return;
  78. }
  79. m_originIterator = 0;
  80. var error = vrInput.GetActionOrigins(s_actionSetHandle, CurrentHandle, s_actionOrigins);
  81. if (error != EVRInputError.None)
  82. {
  83. Debug.LogError("GetActionOrigins failed! action=" + CurrentPath + " error=" + error);
  84. }
  85. }
  86. public bool TryGetCurrentDigitalData(CVRInput vrInput, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState, ref InputDigitalActionData_t data)
  87. {
  88. ulong originDevicePath;
  89. if (!TryGetCurrentOriginDataAndDeviceState(vrInput, out prevState, out currState, out originDevicePath)) { return false; }
  90. var error = vrInput.GetDigitalActionData(CurrentHandle, ref data, s_moduleInstance.m_digitalDataSize, originDevicePath);
  91. if (error != EVRInputError.None)
  92. {
  93. Debug.LogError("GetDigitalActionData failed! action=" + CurrentPath + " error=" + error);
  94. return false;
  95. }
  96. return true;
  97. }
  98. public bool TryGetCurrentAnalogData(CVRInput vrInput, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState, ref InputAnalogActionData_t data)
  99. {
  100. ulong originDevicePath;
  101. if (!TryGetCurrentOriginDataAndDeviceState(vrInput, out prevState, out currState, out originDevicePath)) { return false; }
  102. var error = vrInput.GetAnalogActionData(CurrentHandle, ref data, s_moduleInstance.m_analogDataSize, originDevicePath);
  103. if (error != EVRInputError.None)
  104. {
  105. Debug.LogError("GetAnalogActionData failed! action=" + CurrentPath + " error=" + error);
  106. return false;
  107. }
  108. return true;
  109. }
  110. private bool TryGetCurrentOriginDataAndDeviceState(CVRInput vrInput, out IVRModuleDeviceState prevState, out IVRModuleDeviceStateRW currState, out ulong originDevicePath)
  111. {
  112. OriginData originData;
  113. EVRInputError error;
  114. if (!s_moduleInstance.TryGetDeviceIndexFromOrigin(vrInput, CurrentOrigin, out originData, out error))
  115. {
  116. Debug.LogError("GetOriginTrackedDeviceInfo failed! error=" + error + " action=" + pressActions.CurrentPath);
  117. prevState = null;
  118. currState = null;
  119. originDevicePath = 0ul;
  120. return false;
  121. }
  122. originDevicePath = originData.devicePath;
  123. return s_moduleInstance.TryGetValidDeviceState(originData.deviceIndex, out prevState, out currState) && currState.isConnected;
  124. }
  125. public void Set(T e, string pathName, string alias)
  126. {
  127. var index = EqualityComparer<T>.Default.GetHashCode(e) - s_enumInfo.minValue;
  128. m_aliases[index] = alias;
  129. m_paths[index] = ACTION_SET_PATH + m_pathPrefix + pathName;
  130. }
  131. public void InitiateHandles(CVRInput vrInput)
  132. {
  133. for (int i = 0; i < Len; ++i)
  134. {
  135. m_handles[i] = SafeGetActionHandle(vrInput, m_paths[i]);
  136. }
  137. }
  138. }
  139. public enum HapticStruct { Haptic }
  140. public const string ACTION_SET_NAME = "htc_viu";
  141. public const string ACTION_SET_PATH = "/actions/" + ACTION_SET_NAME;
  142. private static bool s_pathInitialized;
  143. private static bool s_actionInitialized;
  144. public static ActionArray<VRModuleRawButton> pressActions { get; private set; }
  145. public static ActionArray<VRModuleRawButton> touchActions { get; private set; }
  146. public static ActionArray<VRModuleRawAxis> v1Actions { get; private set; }
  147. public static ActionArray<VRModuleRawAxis> v2Actions { get; private set; }
  148. public static ActionArray<HapticStruct> vibrateActions { get; private set; }
  149. private static ulong[] s_devicePathHandles;
  150. private static ulong s_actionSetHandle;
  151. private uint m_digitalDataSize;
  152. private uint m_analogDataSize;
  153. private uint m_originInfoSize;
  154. private ETrackingUniverseOrigin m_prevTrackingSpace;
  155. private bool m_hasInputFocus = true;
  156. private TrackedDevicePose_t[] m_poses;
  157. private TrackedDevicePose_t[] m_gamePoses;
  158. private VRActiveActionSet_t[] m_activeActionSets;
  159. private struct OriginData
  160. {
  161. public ulong devicePath;
  162. public uint deviceIndex;
  163. }
  164. private Dictionary<ulong, OriginData> m_originDataCache;
  165. private static ETrackingUniverseOrigin trackingSpace
  166. {
  167. get
  168. {
  169. var compositor = OpenVR.Compositor;
  170. if (compositor == null) { return default(ETrackingUniverseOrigin); }
  171. return compositor.GetTrackingSpace();
  172. }
  173. set
  174. {
  175. var compositor = OpenVR.Compositor;
  176. if (compositor == null) { return; }
  177. compositor.SetTrackingSpace(value);
  178. }
  179. }
  180. private static bool inputFocus
  181. {
  182. get
  183. {
  184. var system = OpenVR.System;
  185. if (system == null) { return false; }
  186. return system.IsInputAvailable();
  187. }
  188. }
  189. public static void InitializePaths()
  190. {
  191. if (s_pathInitialized) { return; }
  192. s_pathInitialized = true;
  193. pressActions = new ActionArray<VRModuleRawButton>("/in/viu_press_", "boolean");
  194. pressActions.Set(VRModuleRawButton.System, "00", "Press00 (System)");
  195. pressActions.Set(VRModuleRawButton.ApplicationMenu, "01", "Press01 (ApplicationMenu)");
  196. pressActions.Set(VRModuleRawButton.Grip, "02", "Press02 (Grip)");
  197. pressActions.Set(VRModuleRawButton.DPadLeft, "03", "Press03 (DPadLeft)");
  198. pressActions.Set(VRModuleRawButton.DPadUp, "04", "Press04 (DPadUp)");
  199. pressActions.Set(VRModuleRawButton.DPadRight, "05", "Press05 (DPadRight)");
  200. pressActions.Set(VRModuleRawButton.DPadDown, "06", "Press06 (DPadDown)");
  201. pressActions.Set(VRModuleRawButton.A, "07", "Press07 (A)");
  202. pressActions.Set(VRModuleRawButton.ProximitySensor, "31", "Press31 (ProximitySensor)");
  203. pressActions.Set(VRModuleRawButton.Touchpad, "32", "Press32 (Touchpad)");
  204. pressActions.Set(VRModuleRawButton.Trigger, "33", "Press33 (Trigger)");
  205. pressActions.Set(VRModuleRawButton.CapSenseGrip, "34", "Press34 (CapSenseGrip)");
  206. pressActions.Set(VRModuleRawButton.Bumper, "35", "Press35 (Bumper)");
  207. touchActions = new ActionArray<VRModuleRawButton>("/in/viu_touch_", "boolean");
  208. touchActions.Set(VRModuleRawButton.System, "00", "Touch00 (System)");
  209. touchActions.Set(VRModuleRawButton.ApplicationMenu, "01", "Touch01 (ApplicationMenu)");
  210. touchActions.Set(VRModuleRawButton.Grip, "02", "Touch02 (Grip)");
  211. touchActions.Set(VRModuleRawButton.DPadLeft, "03", "Touch03 (DPadLeft)");
  212. touchActions.Set(VRModuleRawButton.DPadUp, "04", "Touch04 (DPadUp)");
  213. touchActions.Set(VRModuleRawButton.DPadRight, "05", "Touch05 (DPadRight)");
  214. touchActions.Set(VRModuleRawButton.DPadDown, "06", "Touch06 (DPadDown)");
  215. touchActions.Set(VRModuleRawButton.A, "07", "Touch07 (A)");
  216. touchActions.Set(VRModuleRawButton.ProximitySensor, "31", "Touch31 (ProximitySensor)");
  217. touchActions.Set(VRModuleRawButton.Touchpad, "32", "Touch32 (Touchpad)");
  218. touchActions.Set(VRModuleRawButton.Trigger, "33", "Touch33 (Trigger)");
  219. touchActions.Set(VRModuleRawButton.CapSenseGrip, "34", "Touch34 (CapSenseGrip)");
  220. touchActions.Set(VRModuleRawButton.Bumper, "35", "Touch35 (Bumper)");
  221. v1Actions = new ActionArray<VRModuleRawAxis>("/in/viu_axis_", "vector1");
  222. v1Actions.Set(VRModuleRawAxis.Axis0X, "0x", "Axis0 X (TouchpadX)");
  223. v1Actions.Set(VRModuleRawAxis.Axis0Y, "0y", "Axis0 Y (TouchpadY)");
  224. v1Actions.Set(VRModuleRawAxis.Axis1X, "1x", "Axis1 X (Trigger)");
  225. v1Actions.Set(VRModuleRawAxis.Axis1Y, "1y", "Axis1 Y");
  226. v1Actions.Set(VRModuleRawAxis.Axis2X, "2x", "Axis2 X (CapSenseGrip)");
  227. v1Actions.Set(VRModuleRawAxis.Axis2Y, "2y", "Axis2 Y");
  228. v1Actions.Set(VRModuleRawAxis.Axis3X, "3x", "Axis3 X (IndexCurl)");
  229. v1Actions.Set(VRModuleRawAxis.Axis3Y, "3y", "Axis3 Y (MiddleCurl)");
  230. v1Actions.Set(VRModuleRawAxis.Axis4X, "4x", "Axis4 X (RingCurl)");
  231. v1Actions.Set(VRModuleRawAxis.Axis4Y, "4y", "Axis4 Y (PinkyCurl)");
  232. v2Actions = new ActionArray<VRModuleRawAxis>("/in/viu_axis_", "vector2");
  233. v2Actions.Set(VRModuleRawAxis.Axis0X, "0xy", "Axis0 X&Y (Touchpad)");
  234. v2Actions.Set(VRModuleRawAxis.Axis1X, "1xy", "Axis1 X&Y");
  235. v2Actions.Set(VRModuleRawAxis.Axis2X, "2xy", "Axis2 X&Y (Thumbstick)");
  236. v2Actions.Set(VRModuleRawAxis.Axis3X, "3xy", "Axis3 X&Y");
  237. v2Actions.Set(VRModuleRawAxis.Axis4X, "4xy", "Axis4 X&Y");
  238. vibrateActions = new ActionArray<HapticStruct>("/out/viu_vib_", "vibration");
  239. vibrateActions.Set(HapticStruct.Haptic, "01", "Vibration");
  240. }
  241. public static void InitializeHandles()
  242. {
  243. if (!Application.isPlaying || s_actionInitialized) { return; }
  244. s_actionInitialized = true;
  245. InitializePaths();
  246. SteamVR.Initialize();
  247. #if VIU_STEAMVR_2_2_0_OR_NEWER
  248. SteamVR_ActionSet_Manager.UpdateActionStates();
  249. #elif VIU_STEAMVR_2_1_0_OR_NEWER
  250. SteamVR_ActionSet_Manager.UpdateActionSetsState();
  251. #else
  252. SteamVR_ActionSet.UpdateActionSetsState();
  253. #endif
  254. var vrInput = OpenVR.Input;
  255. if (vrInput == null)
  256. {
  257. Debug.LogError("Fail loading OpenVR.Input");
  258. return;
  259. }
  260. pressActions.InitiateHandles(vrInput);
  261. touchActions.InitiateHandles(vrInput);
  262. v1Actions.InitiateHandles(vrInput);
  263. v2Actions.InitiateHandles(vrInput);
  264. vibrateActions.InitiateHandles(vrInput);
  265. s_actionSetHandle = SafeGetActionSetHandle(vrInput, ACTION_SET_PATH);
  266. }
  267. private static ulong SafeGetActionSetHandle(CVRInput vrInput, string path)
  268. {
  269. if (string.IsNullOrEmpty(path)) { return 0ul; }
  270. var handle = OpenVR.k_ulInvalidActionHandle;
  271. var error = vrInput.GetActionSetHandle(path, ref handle);
  272. if (error != EVRInputError.None)
  273. {
  274. Debug.LogError("Load " + path + " action failed! error=" + error);
  275. return OpenVR.k_ulInvalidActionHandle;
  276. }
  277. else
  278. {
  279. return handle;
  280. }
  281. }
  282. private static ulong SafeGetActionHandle(CVRInput vrInput, string path)
  283. {
  284. if (string.IsNullOrEmpty(path)) { return 0ul; }
  285. var handle = OpenVR.k_ulInvalidActionHandle;
  286. var error = vrInput.GetActionHandle(path, ref handle);
  287. if (error != EVRInputError.None)
  288. {
  289. Debug.LogError("Load " + path + " action failed! error=" + error);
  290. return OpenVR.k_ulInvalidActionHandle;
  291. }
  292. else
  293. {
  294. return handle;
  295. }
  296. }
  297. public static ulong GetInputSourceHandleForDevice(uint deviceIndex)
  298. {
  299. if (s_devicePathHandles == null || deviceIndex >= s_devicePathHandles.Length)
  300. {
  301. return OpenVR.k_ulInvalidInputValueHandle;
  302. }
  303. else
  304. {
  305. return s_devicePathHandles[deviceIndex];
  306. }
  307. }
  308. public override bool ShouldActiveModule()
  309. {
  310. #if UNITY_2019_3_OR_NEWER && VIU_XR_GENERAL_SETTINGS
  311. return VIUSettings.activateSteamVRModule && (UnityXRModule.HasActiveLoader(OPENVR_XR_LOADER_NAME) ||
  312. (XRSettings.enabled && XRSettings.loadedDeviceName == "OpenVR"));
  313. #elif UNITY_5_4_OR_NEWER
  314. return VIUSettings.activateSteamVRModule && XRSettings.enabled && XRSettings.loadedDeviceName == "OpenVR";
  315. #else
  316. return VIUSettings.activateSteamVRModule && SteamVR.enabled;
  317. #endif
  318. }
  319. public override void OnActivated()
  320. {
  321. m_digitalDataSize = (uint)Marshal.SizeOf(new InputDigitalActionData_t());
  322. m_analogDataSize = (uint)Marshal.SizeOf(new InputAnalogActionData_t());
  323. m_originInfoSize = (uint)Marshal.SizeOf(new InputOriginInfo_t());
  324. m_poses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount];
  325. m_gamePoses = new TrackedDevicePose_t[0];
  326. m_originDataCache = new Dictionary<ulong, OriginData>((int)OpenVR.k_unMaxActionOriginCount);
  327. InitializeHandles();
  328. #if VIU_STEAMVR_2_1_0_OR_NEWER
  329. SteamVR_Input.GetActionSet(ACTION_SET_NAME).Activate(SteamVR_Input_Sources.Any, 0, false);
  330. #else
  331. var actionSet = SteamVR_Input.GetActionSetFromPath(ACTION_SET_PATH);
  332. if (actionSet != null)
  333. {
  334. actionSet.ActivatePrimary();
  335. }
  336. #endif
  337. #if !VIU_STEAMVR_2_1_0_OR_NEWER
  338. m_activeActionSets = new VRActiveActionSet_t[1] { new VRActiveActionSet_t() { ulActionSet = s_actionSetHandle, } };
  339. #endif
  340. #if VIU_STEAMVR_2_2_0_OR_NEWER
  341. SteamVR_Input.onNonVisualActionsUpdated += UpdateDeviceInput;
  342. SteamVR_Input.onPosesUpdated += UpdateDevicePose;
  343. #else
  344. SteamVR_Input.OnNonVisualActionsUpdated += UpdateDeviceInput;
  345. SteamVR_Input.OnPosesUpdated += UpdateDevicePose;
  346. #endif
  347. s_devicePathHandles = new ulong[OpenVR.k_unMaxTrackedDeviceCount];
  348. EnsureDeviceStateLength(OpenVR.k_unMaxTrackedDeviceCount);
  349. // preserve previous tracking space
  350. m_prevTrackingSpace = trackingSpace;
  351. m_hasInputFocus = inputFocus;
  352. SteamVR_Events.InputFocus.AddListener(OnInputFocus);
  353. SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).AddListener(OnTrackedDeviceRoleChanged);
  354. s_moduleInstance = this;
  355. }
  356. public override void OnDeactivated()
  357. {
  358. SteamVR_Events.InputFocus.RemoveListener(OnInputFocus);
  359. SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).RemoveListener(OnTrackedDeviceRoleChanged);
  360. #if VIU_STEAMVR_2_2_0_OR_NEWER
  361. SteamVR_Input.onNonVisualActionsUpdated -= UpdateDeviceInput;
  362. SteamVR_Input.onPosesUpdated -= UpdateDevicePose;
  363. #else
  364. SteamVR_Input.OnNonVisualActionsUpdated -= UpdateDeviceInput;
  365. SteamVR_Input.OnPosesUpdated -= UpdateDevicePose;
  366. #endif
  367. trackingSpace = m_prevTrackingSpace;
  368. s_moduleInstance = null;
  369. }
  370. private void UpdateDeviceInput()
  371. {
  372. IVRModuleDeviceState prevState;
  373. IVRModuleDeviceStateRW currState;
  374. var vrInput = OpenVR.Input;
  375. if (vrInput == null)
  376. {
  377. for (uint i = 0, iMax = GetDeviceStateLength(); i < iMax; ++i)
  378. {
  379. if (TryGetValidDeviceState(i, out prevState, out currState) && currState.isConnected)
  380. {
  381. currState.buttonPressed = 0ul;
  382. currState.buttonTouched = 0ul;
  383. currState.ResetAxisValues();
  384. }
  385. }
  386. }
  387. else
  388. {
  389. m_originDataCache.Clear();
  390. for (pressActions.Reset(); pressActions.IsCurrentValid(); pressActions.MoveNext())
  391. {
  392. for (pressActions.ResetOrigins(vrInput); pressActions.IsCurrentOriginValid(); pressActions.MoveNextOrigin())
  393. {
  394. var data = default(InputDigitalActionData_t);
  395. if (pressActions.TryGetCurrentDigitalData(vrInput, out prevState, out currState, ref data))
  396. {
  397. currState.SetButtonPress(pressActions.Current, data.bState);
  398. }
  399. }
  400. }
  401. for (touchActions.Reset(); touchActions.IsCurrentValid(); touchActions.MoveNext())
  402. {
  403. for (touchActions.ResetOrigins(vrInput); touchActions.IsCurrentOriginValid(); touchActions.MoveNextOrigin())
  404. {
  405. var data = default(InputDigitalActionData_t);
  406. if (touchActions.TryGetCurrentDigitalData(vrInput, out prevState, out currState, ref data))
  407. {
  408. currState.SetButtonTouch(touchActions.Current, data.bState);
  409. }
  410. }
  411. }
  412. for (v1Actions.Reset(); v1Actions.IsCurrentValid(); v1Actions.MoveNext())
  413. {
  414. for (v1Actions.ResetOrigins(vrInput); v1Actions.IsCurrentOriginValid(); v1Actions.MoveNextOrigin())
  415. {
  416. var data = default(InputAnalogActionData_t);
  417. if (v1Actions.TryGetCurrentAnalogData(vrInput, out prevState, out currState, ref data))
  418. {
  419. currState.SetAxisValue(v1Actions.Current, data.x);
  420. }
  421. }
  422. }
  423. for (v2Actions.Reset(); v2Actions.IsCurrentValid(); v2Actions.MoveNext())
  424. {
  425. for (v2Actions.ResetOrigins(vrInput); v2Actions.IsCurrentOriginValid(); v2Actions.MoveNextOrigin())
  426. {
  427. var data = default(InputAnalogActionData_t);
  428. if (v2Actions.TryGetCurrentAnalogData(vrInput, out prevState, out currState, ref data))
  429. {
  430. currState.SetAxisValue(v2Actions.Current, data.x);
  431. currState.SetAxisValue(v2Actions.Current + 1, data.y);
  432. }
  433. }
  434. }
  435. }
  436. ProcessDeviceInputChanged();
  437. }
  438. private void UpdateDevicePose(bool obj)
  439. {
  440. IVRModuleDeviceState prevState;
  441. IVRModuleDeviceStateRW currState;
  442. FlushDeviceState();
  443. var vrSystem = OpenVR.System;
  444. var vrCompositor = OpenVR.Compositor;
  445. if (vrSystem == null || vrCompositor == null)
  446. {
  447. for (uint i = 0, imax = GetDeviceStateLength(); i < imax; ++i)
  448. {
  449. if (TryGetValidDeviceState(i, out prevState, out currState) && currState.isConnected)
  450. {
  451. currState.Reset();
  452. }
  453. }
  454. return;
  455. }
  456. vrCompositor.GetLastPoses(m_poses, m_gamePoses);
  457. for (uint i = 0u, imax = (uint)m_poses.Length; i < imax; ++i)
  458. {
  459. if (!m_poses[i].bDeviceIsConnected)
  460. {
  461. if (TryGetValidDeviceState(i, out prevState, out currState) && prevState.isConnected)
  462. {
  463. s_devicePathHandles[i] = OpenVR.k_ulInvalidInputValueHandle;
  464. currState.Reset();
  465. }
  466. }
  467. else
  468. {
  469. EnsureValidDeviceState(i, out prevState, out currState);
  470. if (!prevState.isConnected)
  471. {
  472. currState.isConnected = true;
  473. currState.deviceClass = (VRModuleDeviceClass)vrSystem.GetTrackedDeviceClass(i);
  474. currState.serialNumber = QueryDeviceStringProperty(vrSystem, i, ETrackedDeviceProperty.Prop_SerialNumber_String);
  475. currState.modelNumber = QueryDeviceStringProperty(vrSystem, i, ETrackedDeviceProperty.Prop_ModelNumber_String);
  476. currState.renderModelName = QueryDeviceStringProperty(vrSystem, i, ETrackedDeviceProperty.Prop_RenderModelName_String);
  477. SetupKnownDeviceModel(currState);
  478. m_originDataCache.Clear();
  479. }
  480. // update device status
  481. currState.isPoseValid = m_poses[i].bPoseIsValid;
  482. currState.isOutOfRange = m_poses[i].eTrackingResult == ETrackingResult.Running_OutOfRange || m_poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange;
  483. currState.isCalibrating = m_poses[i].eTrackingResult == ETrackingResult.Calibrating_InProgress || m_poses[i].eTrackingResult == ETrackingResult.Calibrating_OutOfRange;
  484. currState.isUninitialized = m_poses[i].eTrackingResult == ETrackingResult.Uninitialized;
  485. currState.velocity = new Vector3(m_poses[i].vVelocity.v0, m_poses[i].vVelocity.v1, -m_poses[i].vVelocity.v2);
  486. currState.angularVelocity = new Vector3(-m_poses[i].vAngularVelocity.v0, -m_poses[i].vAngularVelocity.v1, m_poses[i].vAngularVelocity.v2);
  487. var rigidTransform = new SteamVR_Utils.RigidTransform(m_poses[i].mDeviceToAbsoluteTracking);
  488. currState.position = rigidTransform.pos;
  489. currState.rotation = rigidTransform.rot;
  490. }
  491. }
  492. ProcessConnectedDeviceChanged();
  493. ProcessDevicePoseChanged();
  494. }
  495. public override void Update()
  496. {
  497. if (SteamVR.active)
  498. {
  499. SteamVR_Settings.instance.lockPhysicsUpdateRateToRenderFrequency = VRModule.lockPhysicsUpdateRateToRenderFrequency;
  500. }
  501. }
  502. public override void UpdateTrackingSpaceType()
  503. {
  504. switch (VRModule.trackingSpaceType)
  505. {
  506. case VRModuleTrackingSpaceType.RoomScale:
  507. trackingSpace = ETrackingUniverseOrigin.TrackingUniverseStanding;
  508. break;
  509. case VRModuleTrackingSpaceType.Stationary:
  510. trackingSpace = ETrackingUniverseOrigin.TrackingUniverseSeated;
  511. break;
  512. }
  513. }
  514. private bool TryGetDeviceIndexFromOrigin(CVRInput vrInput, ulong origin, out OriginData originData, out EVRInputError error)
  515. {
  516. if (!m_originDataCache.TryGetValue(origin, out originData))
  517. {
  518. var originInfo = default(InputOriginInfo_t);
  519. error = vrInput.GetOriginTrackedDeviceInfo(origin, ref originInfo, m_originInfoSize);
  520. if (error != EVRInputError.None)
  521. {
  522. originData = new OriginData()
  523. {
  524. devicePath = OpenVR.k_ulInvalidInputValueHandle,
  525. deviceIndex = OpenVR.k_unTrackedDeviceIndexInvalid,
  526. };
  527. return false;
  528. }
  529. else
  530. {
  531. originData = new OriginData()
  532. {
  533. devicePath = originInfo.devicePath,
  534. deviceIndex = originInfo.trackedDeviceIndex,
  535. };
  536. s_devicePathHandles[originInfo.trackedDeviceIndex] = originInfo.devicePath;
  537. //Debug.Log("Set device path " + originInfo.trackedDeviceIndex + " to " + originInfo.devicePath);
  538. m_originDataCache.Add(origin, originData);
  539. return true;
  540. }
  541. }
  542. else
  543. {
  544. error = EVRInputError.None;
  545. return true;
  546. }
  547. }
  548. private void OnInputFocus(bool value)
  549. {
  550. m_hasInputFocus = value;
  551. InvokeInputFocusEvent(value);
  552. }
  553. public override bool HasInputFocus() { return m_hasInputFocus; }
  554. private void OnTrackedDeviceRoleChanged(VREvent_t arg)
  555. {
  556. InvokeControllerRoleChangedEvent();
  557. }
  558. public override uint GetLeftControllerDeviceIndex()
  559. {
  560. var system = OpenVR.System;
  561. return system == null ? INVALID_DEVICE_INDEX : system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
  562. }
  563. public override uint GetRightControllerDeviceIndex()
  564. {
  565. var system = OpenVR.System;
  566. return system == null ? INVALID_DEVICE_INDEX : system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand);
  567. }
  568. private StringBuilder m_sb;
  569. private string QueryDeviceStringProperty(CVRSystem system, uint deviceIndex, ETrackedDeviceProperty prop)
  570. {
  571. var error = default(ETrackedPropertyError);
  572. var capacity = (int)system.GetStringTrackedDeviceProperty(deviceIndex, prop, null, 0, ref error);
  573. if (capacity <= 1 || capacity > 128) { return string.Empty; }
  574. if (m_sb == null) { m_sb = new StringBuilder(capacity); }
  575. else { m_sb.EnsureCapacity(capacity); }
  576. system.GetStringTrackedDeviceProperty(deviceIndex, prop, m_sb, (uint)m_sb.Capacity, ref error);
  577. if (error != ETrackedPropertyError.TrackedProp_Success) { return string.Empty; }
  578. var result = m_sb.ToString();
  579. m_sb.Length = 0;
  580. return result;
  581. }
  582. public override void TriggerViveControllerHaptic(uint deviceIndex, ushort durationMicroSec = 500)
  583. {
  584. TriggerHapticVibration(deviceIndex, 0.01f, 85f, Mathf.InverseLerp(0, 4000, durationMicroSec), 0f);
  585. }
  586. public override void TriggerHapticVibration(uint deviceIndex, float durationSeconds = 0.01f, float frequency = 85f, float amplitude = 0.125f, float startSecondsFromNow = 0f)
  587. {
  588. var handle = GetInputSourceHandleForDevice(deviceIndex);
  589. if (handle == OpenVR.k_ulInvalidDriverHandle) { return; }
  590. var vrInput = OpenVR.Input;
  591. if (vrInput != null)
  592. {
  593. vibrateActions.Reset();
  594. var error = vrInput.TriggerHapticVibrationAction(vibrateActions.CurrentHandle, startSecondsFromNow, durationSeconds, frequency, amplitude, handle);
  595. if (error != EVRInputError.None)
  596. {
  597. Debug.LogError("TriggerViveControllerHaptic failed! error=" + error);
  598. }
  599. }
  600. }
  601. #endif
  602. }
  603. }