Assignment for RMIT Mixed Reality in 2020
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.

896 lines
44 KiB

  1. // SteamVR Controller|SDK_SteamVR|004
  2. namespace VRTK
  3. {
  4. #if VRTK_DEFINE_SDK_STEAMVR
  5. using UnityEngine;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. using Valve.VR;
  9. using System;
  10. #if !VRTK_DEFINE_STEAMVR_PLUGIN_1_2_2_OR_NEWER
  11. using System;
  12. using System.Reflection;
  13. #endif
  14. #endif
  15. /// <summary>
  16. /// The SteamVR Controller SDK script provides a bridge to SDK methods that deal with the input devices.
  17. /// </summary>
  18. [SDK_Description(typeof(SDK_SteamVRSystem))]
  19. public class SDK_SteamVRController
  20. #if VRTK_DEFINE_SDK_STEAMVR
  21. : SDK_BaseController
  22. #else
  23. : SDK_FallbackController
  24. #endif
  25. {
  26. #if VRTK_DEFINE_SDK_STEAMVR
  27. protected SteamVR_TrackedObject cachedLeftTrackedObject;
  28. protected SteamVR_TrackedObject cachedRightTrackedObject;
  29. protected Dictionary<GameObject, SteamVR_TrackedObject> cachedTrackedObjectsByGameObject = new Dictionary<GameObject, SteamVR_TrackedObject>();
  30. protected Dictionary<uint, SteamVR_TrackedObject> cachedTrackedObjectsByIndex = new Dictionary<uint, SteamVR_TrackedObject>();
  31. protected Dictionary<EVRButtonId, bool> axisTouchStates = new Dictionary<EVRButtonId, bool>();
  32. protected Dictionary<EVRButtonId, float> axisTouchFidelity = new Dictionary<EVRButtonId, float>() { { EVRButtonId.k_EButton_SteamVR_Touchpad, 0f }, { EVRButtonId.k_EButton_Axis2, 0.25f } };
  33. protected ushort maxHapticVibration = 3999;
  34. #if !VRTK_DEFINE_STEAMVR_PLUGIN_1_2_2_OR_NEWER
  35. /// <summary>
  36. /// This method is called just after unloading the VRTK_SDKSetup that's using this SDK.
  37. /// </summary>
  38. /// <param name="setup">The SDK Setup which is using this SDK.</param>
  39. public override void OnAfterSetupUnload(VRTK_SDKSetup setup)
  40. {
  41. base.OnAfterSetupUnload(setup);
  42. SteamVR_ControllerManager controllerManager = setup.actualLeftController.transform.parent.GetComponent<SteamVR_ControllerManager>();
  43. FieldInfo connectedField = typeof(SteamVR_ControllerManager).GetField(
  44. "connected",
  45. BindingFlags.NonPublic | BindingFlags.Instance
  46. );
  47. if (connectedField == null)
  48. {
  49. return;
  50. }
  51. bool[] connected = (bool[])connectedField.GetValue(controllerManager);
  52. Array.Clear(connected, 0, connected.Length);
  53. connectedField.SetValue(controllerManager, connected);
  54. }
  55. #endif
  56. /// <summary>
  57. /// The ProcessUpdate method enables an SDK to run logic for every Unity Update
  58. /// </summary>
  59. /// <param name="controllerReference">The reference for the controller.</param>
  60. /// <param name="options">A dictionary of generic options that can be used to within the update.</param>
  61. public override void ProcessUpdate(VRTK_ControllerReference controllerReference, Dictionary<string, object> options)
  62. {
  63. }
  64. /// <summary>
  65. /// The ProcessFixedUpdate method enables an SDK to run logic for every Unity FixedUpdate
  66. /// </summary>
  67. /// <param name="controllerReference">The reference for the controller.</param>
  68. /// <param name="options">A dictionary of generic options that can be used to within the fixed update.</param>
  69. public override void ProcessFixedUpdate(VRTK_ControllerReference controllerReference, Dictionary<string, object> options)
  70. {
  71. }
  72. /// <summary>
  73. /// The GetCurrentControllerType method returns the current used ControllerType based on the SDK and headset being used.
  74. /// </summary>
  75. /// <param name="controllerReference">The reference to the controller to get type of.</param>
  76. /// <returns>The ControllerType based on the SDK and headset being used.</returns>
  77. public override ControllerType GetCurrentControllerType(VRTK_ControllerReference controllerReference = null)
  78. {
  79. uint checkIndex = uint.MaxValue;
  80. if (VRTK_ControllerReference.IsValid(controllerReference))
  81. {
  82. checkIndex = controllerReference.index;
  83. }
  84. else
  85. {
  86. VRTK_ControllerReference leftHand = VRTK_ControllerReference.GetControllerReference(GetControllerLeftHand());
  87. VRTK_ControllerReference rightHand = VRTK_ControllerReference.GetControllerReference(GetControllerRightHand());
  88. if (!VRTK_ControllerReference.IsValid(leftHand) && !VRTK_ControllerReference.IsValid(rightHand))
  89. {
  90. return ControllerType.Undefined;
  91. }
  92. checkIndex = (VRTK_ControllerReference.IsValid(rightHand) ? rightHand.index : leftHand.index);
  93. }
  94. ControllerType returnType = ControllerType.Undefined;
  95. if (checkIndex < uint.MaxValue)
  96. {
  97. string controllerModelNumber = GetModelNumber(checkIndex);
  98. returnType = MatchControllerTypeByString(controllerModelNumber);
  99. }
  100. return returnType;
  101. }
  102. /// <summary>
  103. /// The GetControllerDefaultColliderPath returns the path to the prefab that contains the collider objects for the default controller of this SDK.
  104. /// </summary>
  105. /// <param name="hand">The controller hand to check for</param>
  106. /// <returns>A path to the resource that contains the collider GameObject.</returns>
  107. public override string GetControllerDefaultColliderPath(ControllerHand hand)
  108. {
  109. switch (GetCurrentControllerType())
  110. {
  111. case ControllerType.SteamVR_ViveWand:
  112. return "ControllerColliders/HTCVive";
  113. case ControllerType.SteamVR_OculusTouch:
  114. return (hand == ControllerHand.Left ? "ControllerColliders/SteamVROculusTouch_Left" : "ControllerColliders/SteamVROculusTouch_Right");
  115. case ControllerType.SteamVR_ValveKnuckles:
  116. return (hand == ControllerHand.Left ? "ControllerColliders/ValveKnuckles_Left" : "ControllerColliders/ValveKnuckles_Right");
  117. case ControllerType.SteamVR_WindowsMRController:
  118. return (hand == ControllerHand.Left ? "ControllerColliders/SteamVRWindowsMRController_Left" : "ControllerColliders/SteamVRWindowsMRController_Right");
  119. default:
  120. return "ControllerColliders/Fallback";
  121. }
  122. }
  123. /// <summary>
  124. /// The GetControllerElementPath returns the path to the game object that the given controller element for the given hand resides in.
  125. /// </summary>
  126. /// <param name="element">The controller element to look up.</param>
  127. /// <param name="hand">The controller hand to look up.</param>
  128. /// <param name="fullPath">Whether to get the initial path or the full path to the element.</param>
  129. /// <returns>A string containing the path to the game object that the controller element resides in.</returns>
  130. public override string GetControllerElementPath(ControllerElements element, ControllerHand hand, bool fullPath = false)
  131. {
  132. string suffix = (fullPath ? "/attach" : "");
  133. switch (element)
  134. {
  135. case ControllerElements.AttachPoint:
  136. return "tip/attach";
  137. case ControllerElements.Trigger:
  138. return "trigger" + suffix;
  139. case ControllerElements.GripLeft:
  140. return GetControllerGripPath(hand, suffix, ControllerHand.Left);
  141. case ControllerElements.GripRight:
  142. return GetControllerGripPath(hand, suffix, ControllerHand.Right);
  143. case ControllerElements.Touchpad:
  144. return GetControllerTouchpadPath(hand, suffix);
  145. case ControllerElements.ButtonOne:
  146. return GetControllerButtonOnePath(hand, suffix);
  147. case ControllerElements.ButtonTwo:
  148. return GetControllerButtonTwoPath(hand, suffix);
  149. case ControllerElements.SystemMenu:
  150. return GetControllerSystemMenuPath(hand, suffix);
  151. case ControllerElements.StartMenu:
  152. return GetControllerStartMenuPath(hand, suffix);
  153. case ControllerElements.Body:
  154. return "body";
  155. }
  156. return "";
  157. }
  158. /// <summary>
  159. /// The GetControllerIndex method returns the index of the given controller.
  160. /// </summary>
  161. /// <param name="controller">The GameObject containing the controller.</param>
  162. /// <returns>The index of the given controller.</returns>
  163. public override uint GetControllerIndex(GameObject controller)
  164. {
  165. SteamVR_TrackedObject trackedObject = GetTrackedObject(controller);
  166. return (trackedObject != null ? (uint)trackedObject.index : uint.MaxValue);
  167. }
  168. /// <summary>
  169. /// The GetControllerByIndex method returns the GameObject of a controller with a specific index.
  170. /// </summary>
  171. /// <param name="index">The index of the controller to find.</param>
  172. /// <param name="actual">If true it will return the actual controller, if false it will return the script alias controller GameObject.</param>
  173. /// <returns>The GameObject of the controller</returns>
  174. public override GameObject GetControllerByIndex(uint index, bool actual = false)
  175. {
  176. SetTrackedControllerCaches();
  177. if (index < uint.MaxValue)
  178. {
  179. VRTK_SDKManager sdkManager = VRTK_SDKManager.instance;
  180. if (sdkManager != null)
  181. {
  182. if (cachedLeftTrackedObject != null && (uint)cachedLeftTrackedObject.index == index)
  183. {
  184. return (actual ? sdkManager.loadedSetup.actualLeftController : sdkManager.scriptAliasLeftController);
  185. }
  186. if (cachedRightTrackedObject != null && (uint)cachedRightTrackedObject.index == index)
  187. {
  188. return (actual ? sdkManager.loadedSetup.actualRightController : sdkManager.scriptAliasRightController);
  189. }
  190. }
  191. SteamVR_TrackedObject currentTrackedObjectByIndex = VRTK_SharedMethods.GetDictionaryValue(cachedTrackedObjectsByIndex, index);
  192. if (currentTrackedObjectByIndex != null)
  193. {
  194. return currentTrackedObjectByIndex.gameObject;
  195. }
  196. }
  197. return null;
  198. }
  199. /// <summary>
  200. /// The GetControllerOrigin method returns the origin of the given controller.
  201. /// </summary>
  202. /// <param name="controllerReference">The reference to the controller to retrieve the origin from.</param>
  203. /// <returns>A Transform containing the origin of the controller.</returns>
  204. public override Transform GetControllerOrigin(VRTK_ControllerReference controllerReference)
  205. {
  206. SteamVR_TrackedObject trackedObject = GetTrackedObject(controllerReference.actual);
  207. if (trackedObject != null)
  208. {
  209. return (trackedObject.origin != null ? trackedObject.origin : trackedObject.transform.parent);
  210. }
  211. return null;
  212. }
  213. /// <summary>
  214. /// The GenerateControllerPointerOrigin method can create a custom pointer origin Transform to represent the pointer position and forward.
  215. /// </summary>
  216. /// <param name="parent">The GameObject that the origin will become parent of. If it is a controller then it will also be used to determine the hand if required.</param>
  217. /// <returns>A generated Transform that contains the custom pointer origin.</returns>
  218. [System.Obsolete("GenerateControllerPointerOrigin has been deprecated and will be removed in a future version of VRTK.")]
  219. public override Transform GenerateControllerPointerOrigin(GameObject parent)
  220. {
  221. switch (GetCurrentControllerType())
  222. {
  223. case ControllerType.SteamVR_OculusTouch:
  224. if (IsControllerLeftHand(parent) || IsControllerRightHand(parent))
  225. {
  226. GameObject generatedOrigin = new GameObject(parent.name + " _CustomPointerOrigin");
  227. generatedOrigin.transform.SetParent(parent.transform);
  228. generatedOrigin.transform.localEulerAngles = new Vector3(40f, 0f, 0f);
  229. generatedOrigin.transform.localPosition = new Vector3((IsControllerLeftHand(parent) ? 0.0081f : -0.0081f), -0.0273f, -0.0311f);
  230. return generatedOrigin.transform;
  231. }
  232. break;
  233. }
  234. return null;
  235. }
  236. /// <summary>
  237. /// The GetControllerLeftHand method returns the GameObject containing the representation of the left hand controller.
  238. /// </summary>
  239. /// <param name="actual">If true it will return the actual controller, if false it will return the script alias controller GameObject.</param>
  240. /// <returns>The GameObject containing the left hand controller.</returns>
  241. public override GameObject GetControllerLeftHand(bool actual = false)
  242. {
  243. GameObject controller = GetSDKManagerControllerLeftHand(actual);
  244. if (controller == null && actual)
  245. {
  246. controller = VRTK_SharedMethods.FindEvenInactiveGameObject<SteamVR_ControllerManager>("Controller (left)", true);
  247. }
  248. return controller;
  249. }
  250. /// <summary>
  251. /// The GetControllerRightHand method returns the GameObject containing the representation of the right hand controller.
  252. /// </summary>
  253. /// <param name="actual">If true it will return the actual controller, if false it will return the script alias controller GameObject.</param>
  254. /// <returns>The GameObject containing the right hand controller.</returns>
  255. public override GameObject GetControllerRightHand(bool actual = false)
  256. {
  257. GameObject controller = GetSDKManagerControllerRightHand(actual);
  258. if (controller == null && actual)
  259. {
  260. controller = VRTK_SharedMethods.FindEvenInactiveGameObject<SteamVR_ControllerManager>("Controller (right)", true);
  261. }
  262. return controller;
  263. }
  264. /// <summary>
  265. /// The IsControllerLeftHand/1 method is used to check if the given controller is the the left hand controller.
  266. /// </summary>
  267. /// <param name="controller">The GameObject to check.</param>
  268. /// <returns>Returns true if the given controller is the left hand controller.</returns>
  269. public override bool IsControllerLeftHand(GameObject controller)
  270. {
  271. return CheckActualOrScriptAliasControllerIsLeftHand(controller);
  272. }
  273. /// <summary>
  274. /// The IsControllerRightHand/1 method is used to check if the given controller is the the right hand controller.
  275. /// </summary>
  276. /// <param name="controller">The GameObject to check.</param>
  277. /// <returns>Returns true if the given controller is the right hand controller.</returns>
  278. public override bool IsControllerRightHand(GameObject controller)
  279. {
  280. return CheckActualOrScriptAliasControllerIsRightHand(controller);
  281. }
  282. /// <summary>
  283. /// The IsControllerLeftHand/2 method is used to check if the given controller is the the left hand controller.
  284. /// </summary>
  285. /// <param name="controller">The GameObject to check.</param>
  286. /// <param name="actual">If true it will check the actual controller, if false it will check the script alias controller.</param>
  287. /// <returns>Returns true if the given controller is the left hand controller.</returns>
  288. public override bool IsControllerLeftHand(GameObject controller, bool actual)
  289. {
  290. return CheckControllerLeftHand(controller, actual);
  291. }
  292. /// <summary>
  293. /// The IsControllerRightHand/2 method is used to check if the given controller is the the right hand controller.
  294. /// </summary>
  295. /// <param name="controller">The GameObject to check.</param>
  296. /// <param name="actual">If true it will check the actual controller, if false it will check the script alias controller.</param>
  297. /// <returns>Returns true if the given controller is the right hand controller.</returns>
  298. public override bool IsControllerRightHand(GameObject controller, bool actual)
  299. {
  300. return CheckControllerRightHand(controller, actual);
  301. }
  302. /// <summary>
  303. /// The WaitForControllerModel method determines whether the controller model for the given hand requires waiting to load in on scene start.
  304. /// </summary>
  305. /// <param name="hand">The hand to determine if the controller model will be ready for.</param>
  306. /// <returns>Returns true if the controller model requires loading in at runtime and therefore needs waiting for. Returns false if the controller model will be available at start.</returns>
  307. public override bool WaitForControllerModel(ControllerHand hand)
  308. {
  309. return ShouldWaitForControllerModel(hand, false);
  310. }
  311. /// <summary>
  312. /// The GetControllerModel method returns the model alias for the given GameObject.
  313. /// </summary>
  314. /// <param name="controller">The GameObject to get the model alias for.</param>
  315. /// <returns>The GameObject that has the model alias within it.</returns>
  316. public override GameObject GetControllerModel(GameObject controller)
  317. {
  318. return GetControllerModelFromController(controller);
  319. }
  320. /// <summary>
  321. /// The GetControllerModel method returns the model alias for the given controller hand.
  322. /// </summary>
  323. /// <param name="hand">The hand enum of which controller model to retrieve.</param>
  324. /// <returns>The GameObject that has the model alias within it.</returns>
  325. public override GameObject GetControllerModel(ControllerHand hand)
  326. {
  327. GameObject model = GetSDKManagerControllerModelForHand(hand);
  328. if (model == null)
  329. {
  330. switch (hand)
  331. {
  332. case ControllerHand.Left:
  333. model = (defaultSDKLeftControllerModel != null ? defaultSDKLeftControllerModel.gameObject : null);
  334. break;
  335. case ControllerHand.Right:
  336. model = (defaultSDKRightControllerModel != null ? defaultSDKRightControllerModel.gameObject : null);
  337. break;
  338. }
  339. }
  340. return model;
  341. }
  342. /// <summary>
  343. /// The GetControllerRenderModel method gets the game object that contains the given controller's render model.
  344. /// </summary>
  345. /// <param name="controllerReference">The reference to the controller to check.</param>
  346. /// <returns>A GameObject containing the object that has a render model for the controller.</returns>
  347. public override GameObject GetControllerRenderModel(VRTK_ControllerReference controllerReference)
  348. {
  349. SteamVR_RenderModel renderModel = controllerReference.actual.GetComponentInChildren<SteamVR_RenderModel>();
  350. return (renderModel != null ? renderModel.gameObject : null);
  351. }
  352. /// <summary>
  353. /// The SetControllerRenderModelWheel method sets the state of the scroll wheel on the controller render model.
  354. /// </summary>
  355. /// <param name="renderModel">The GameObject containing the controller render model.</param>
  356. /// <param name="state">If true and the render model has a scroll wheen then it will be displayed, if false then the scroll wheel will be hidden.</param>
  357. public override void SetControllerRenderModelWheel(GameObject renderModel, bool state)
  358. {
  359. SteamVR_RenderModel model = renderModel.GetComponent<SteamVR_RenderModel>();
  360. if (model != null)
  361. {
  362. model.controllerModeState.bScrollWheelVisible = state;
  363. }
  364. }
  365. /// <summary>
  366. /// The HapticPulse/2 method is used to initiate a simple haptic pulse on the tracked object of the given controller reference.
  367. /// </summary>
  368. /// <param name="controllerReference">The reference to the tracked object to initiate the haptic pulse on.</param>
  369. /// <param name="strength">The intensity of the rumble of the controller motor. `0` to `1`.</param>
  370. public override void HapticPulse(VRTK_ControllerReference controllerReference, float strength = 0.5f)
  371. {
  372. uint index = VRTK_ControllerReference.GetRealIndex(controllerReference);
  373. if (index < OpenVR.k_unTrackedDeviceIndexInvalid)
  374. {
  375. float convertedStrength = maxHapticVibration * strength;
  376. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  377. device.TriggerHapticPulse((ushort)convertedStrength, EVRButtonId.k_EButton_Axis0);
  378. }
  379. }
  380. /// <summary>
  381. /// The HapticPulse/2 method is used to initiate a haptic pulse based on an audio clip on the tracked object of the given controller reference.
  382. /// </summary>
  383. /// <param name="controllerReference">The reference to the tracked object to initiate the haptic pulse on.</param>
  384. /// <param name="clip">The audio clip to use for the haptic pattern.</param>
  385. public override bool HapticPulse(VRTK_ControllerReference controllerReference, AudioClip clip)
  386. {
  387. //SteamVR doesn't support audio haptics so return false to do a fallback.
  388. return false;
  389. }
  390. /// <summary>
  391. /// The GetHapticModifiers method is used to return modifiers for the duration and interval if the SDK handles it slightly differently.
  392. /// </summary>
  393. /// <returns>An SDK_ControllerHapticModifiers object with a given `durationModifier` and an `intervalModifier`.</returns>
  394. public override SDK_ControllerHapticModifiers GetHapticModifiers()
  395. {
  396. SDK_ControllerHapticModifiers modifiers = new SDK_ControllerHapticModifiers();
  397. modifiers.maxHapticVibration = maxHapticVibration;
  398. return modifiers;
  399. }
  400. /// <summary>
  401. /// The GetVelocity method is used to determine the current velocity of the tracked object on the given controller reference.
  402. /// </summary>
  403. /// <param name="controllerReference">The reference to the tracked object to check for.</param>
  404. /// <returns>A Vector3 containing the current velocity of the tracked object.</returns>
  405. public override Vector3 GetVelocity(VRTK_ControllerReference controllerReference)
  406. {
  407. uint index = VRTK_ControllerReference.GetRealIndex(controllerReference);
  408. if (index <= (uint)SteamVR_TrackedObject.EIndex.Hmd || index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  409. {
  410. return Vector3.zero;
  411. }
  412. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  413. return device.velocity;
  414. }
  415. /// <summary>
  416. /// The GetAngularVelocity method is used to determine the current angular velocity of the tracked object on the given controller reference.
  417. /// </summary>
  418. /// <param name="controllerReference">The reference to the tracked object to check for.</param>
  419. /// <returns>A Vector3 containing the current angular velocity of the tracked object.</returns>
  420. public override Vector3 GetAngularVelocity(VRTK_ControllerReference controllerReference)
  421. {
  422. uint index = VRTK_ControllerReference.GetRealIndex(controllerReference);
  423. if (index <= (uint)SteamVR_TrackedObject.EIndex.Hmd || index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  424. {
  425. return Vector3.zero;
  426. }
  427. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  428. return device.angularVelocity;
  429. }
  430. /// <summary>
  431. /// The IsTouchpadStatic method is used to determine if the touchpad is currently not being moved.
  432. /// </summary>
  433. /// <param name="currentAxisValues"></param>
  434. /// <param name="previousAxisValues"></param>
  435. /// <param name="compareFidelity"></param>
  436. /// <returns>Returns true if the touchpad is not currently being touched or moved.</returns>
  437. public override bool IsTouchpadStatic(bool isTouched, Vector2 currentAxisValues, Vector2 previousAxisValues, int compareFidelity)
  438. {
  439. return (!isTouched || VRTK_SharedMethods.Vector2ShallowCompare(currentAxisValues, previousAxisValues, compareFidelity));
  440. }
  441. /// <summary>
  442. /// The GetButtonAxis method retrieves the current X/Y axis values for the given button type on the given controller reference.
  443. /// </summary>
  444. /// <param name="buttonType">The type of button to check for the axis on.</param>
  445. /// <param name="controllerReference">The reference to the controller to check the button axis on.</param>
  446. /// <returns>A Vector2 of the X/Y values of the button axis. If no axis values exist for the given button, then a Vector2.Zero is returned.</returns>
  447. public override Vector2 GetButtonAxis(ButtonTypes buttonType, VRTK_ControllerReference controllerReference)
  448. {
  449. uint index = VRTK_ControllerReference.GetRealIndex(controllerReference);
  450. if (index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  451. {
  452. return Vector2.zero;
  453. }
  454. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  455. switch (buttonType)
  456. {
  457. case ButtonTypes.Touchpad:
  458. return device.GetAxis();
  459. case ButtonTypes.TouchpadTwo:
  460. return (VRTK_DeviceFinder.GetCurrentControllerType() == ControllerType.SteamVR_WindowsMRController ? device.GetAxis(EVRButtonId.k_EButton_Axis2) : Vector2.zero);
  461. case ButtonTypes.Trigger:
  462. return device.GetAxis(EVRButtonId.k_EButton_SteamVR_Trigger);
  463. case ButtonTypes.Grip:
  464. switch (GetCurrentControllerType())
  465. {
  466. case ControllerType.SteamVR_OculusTouch:
  467. case ControllerType.SteamVR_ValveKnuckles:
  468. return device.GetAxis(EVRButtonId.k_EButton_Axis2);
  469. default:
  470. return new Vector2((GetControllerButtonState(buttonType, ButtonPressTypes.Press, controllerReference) ? 1f : 0f), 0f);
  471. }
  472. }
  473. return Vector2.zero;
  474. }
  475. /// <summary>
  476. /// The GetButtonSenseAxis method retrieves the current sense axis value for the given button type on the given controller reference.
  477. /// </summary>
  478. /// <param name="buttonType">The type of button to check for the sense axis on.</param>
  479. /// <param name="controllerReference">The reference to the controller to check the sense axis on.</param>
  480. /// <returns>The current sense axis value.</returns>
  481. public override float GetButtonSenseAxis(ButtonTypes buttonType, VRTK_ControllerReference controllerReference)
  482. {
  483. uint index = VRTK_ControllerReference.GetRealIndex(controllerReference);
  484. if (index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  485. {
  486. return 0f;
  487. }
  488. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  489. switch (buttonType)
  490. {
  491. case ButtonTypes.Trigger:
  492. return device.GetAxis(EVRButtonId.k_EButton_Axis3).x;
  493. case ButtonTypes.Grip:
  494. return device.GetAxis(EVRButtonId.k_EButton_Axis2).x;
  495. case ButtonTypes.MiddleFinger:
  496. return device.GetAxis(EVRButtonId.k_EButton_Axis3).y;
  497. case ButtonTypes.RingFinger:
  498. return device.GetAxis(EVRButtonId.k_EButton_Axis4).x;
  499. case ButtonTypes.PinkyFinger:
  500. return device.GetAxis(EVRButtonId.k_EButton_Axis4).y;
  501. }
  502. return 0f;
  503. }
  504. /// <summary>
  505. /// The GetButtonHairlineDelta method is used to get the difference between the current button press and the previous frame button press.
  506. /// </summary>
  507. /// <param name="buttonType">The type of button to get the hairline delta for.</param>
  508. /// <param name="controllerReference">The reference to the controller to get the hairline delta for.</param>
  509. /// <returns>The delta between the button presses.</returns>
  510. public override float GetButtonHairlineDelta(ButtonTypes buttonType, VRTK_ControllerReference controllerReference)
  511. {
  512. uint index = VRTK_ControllerReference.GetRealIndex(controllerReference);
  513. if (index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  514. {
  515. return 0f;
  516. }
  517. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  518. return (buttonType == ButtonTypes.Trigger || buttonType == ButtonTypes.TriggerHairline ? device.hairTriggerDelta : 0f);
  519. }
  520. /// <summary>
  521. /// The GetControllerButtonState method is used to determine if the given controller button for the given press type on the given controller reference is currently taking place.
  522. /// </summary>
  523. /// <param name="buttonType">The type of button to check for the state of.</param>
  524. /// <param name="pressType">The button state to check for.</param>
  525. /// <param name="controllerReference">The reference to the controller to check the button state on.</param>
  526. /// <returns>Returns true if the given button is in the state of the given press type on the given controller reference.</returns>
  527. public override bool GetControllerButtonState(ButtonTypes buttonType, ButtonPressTypes pressType, VRTK_ControllerReference controllerReference)
  528. {
  529. uint index = VRTK_ControllerReference.GetRealIndex(controllerReference);
  530. if (index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  531. {
  532. return false;
  533. }
  534. switch (buttonType)
  535. {
  536. case ButtonTypes.Trigger:
  537. return IsButtonPressed(index, pressType, SteamVR_Controller.ButtonMask.Trigger);
  538. case ButtonTypes.TriggerHairline:
  539. if (pressType == ButtonPressTypes.PressDown)
  540. {
  541. return SteamVR_Controller.Input((int)index).GetHairTriggerDown();
  542. }
  543. else if (pressType == ButtonPressTypes.PressUp)
  544. {
  545. return SteamVR_Controller.Input((int)index).GetHairTriggerUp();
  546. }
  547. break;
  548. case ButtonTypes.Grip:
  549. return IsButtonPressed(index, pressType, SteamVR_Controller.ButtonMask.Grip);
  550. case ButtonTypes.Touchpad:
  551. return IsButtonPressed(index, pressType, SteamVR_Controller.ButtonMask.Touchpad);
  552. case ButtonTypes.ButtonOne:
  553. return IsButtonPressed(index, pressType, (1ul << (int)EVRButtonId.k_EButton_A));
  554. case ButtonTypes.ButtonTwo:
  555. return IsButtonPressed(index, pressType, SteamVR_Controller.ButtonMask.ApplicationMenu);
  556. case ButtonTypes.StartMenu:
  557. return IsButtonPressed(index, pressType, SteamVR_Controller.ButtonMask.System);
  558. case ButtonTypes.TouchpadTwo:
  559. return (VRTK_DeviceFinder.GetCurrentControllerType() == ControllerType.SteamVR_WindowsMRController ? CheckAxisTouch(index, pressType, EVRButtonId.k_EButton_Axis2) : false);
  560. }
  561. return false;
  562. }
  563. protected virtual void Awake()
  564. {
  565. defaultSDKLeftControllerModel = (GetControllerLeftHand(true) != null ? GetControllerLeftHand(true).transform.Find("Model") : null);
  566. defaultSDKRightControllerModel = (GetControllerRightHand(true) != null ? GetControllerRightHand(true).transform.Find("Model") : null);
  567. #if VRTK_DEFINE_STEAMVR_PLUGIN_1_1_1_OR_OLDER
  568. //SteamVR_Utils.Event.Listen("TrackedDeviceRoleChanged", OnTrackedDeviceRoleChanged);
  569. //SteamVR_Utils.Event.Listen("render_model_loaded", OnRenderModelLoaded);
  570. #elif VRTK_DEFINE_STEAMVR_PLUGIN_1_2_0
  571. SteamVR_Events.System("TrackedDeviceRoleChanged").Listen(OnTrackedDeviceRoleChanged);
  572. SteamVR_Events.RenderModelLoaded.Listen(OnRenderModelLoaded);
  573. #elif VRTK_DEFINE_STEAMVR_PLUGIN_1_2_1_OR_NEWER
  574. SteamVR_Events.System(EVREventType.VREvent_TrackedDeviceRoleChanged).Listen(OnTrackedDeviceRoleChanged);
  575. SteamVR_Events.RenderModelLoaded.Listen(OnRenderModelLoaded);
  576. #endif
  577. SetTrackedControllerCaches(true);
  578. }
  579. protected virtual void OnTrackedDeviceRoleChanged<T>(T ignoredArgument)
  580. {
  581. SetTrackedControllerCaches(true);
  582. }
  583. protected virtual void OnRenderModelLoaded(SteamVR_RenderModel givenControllerRenderModel, bool successfullyLoaded)
  584. {
  585. if (successfullyLoaded)
  586. {
  587. SteamVR_RenderModel leftControllerRenderModel = (GetControllerLeftHand(true) != null ? GetControllerLeftHand(true).GetComponentInChildren<SteamVR_RenderModel>() : null);
  588. SteamVR_RenderModel rightControllerRenderModel = (GetControllerRightHand(true) != null ? GetControllerRightHand(true).GetComponentInChildren<SteamVR_RenderModel>() : null);
  589. ControllerHand selectedHand = ControllerHand.None;
  590. if (givenControllerRenderModel == leftControllerRenderModel)
  591. {
  592. selectedHand = ControllerHand.Left;
  593. }
  594. else if (givenControllerRenderModel == rightControllerRenderModel)
  595. {
  596. selectedHand = ControllerHand.Right;
  597. }
  598. OnControllerModelReady(selectedHand, VRTK_ControllerReference.GetControllerReference((uint)givenControllerRenderModel.index));
  599. }
  600. }
  601. protected virtual void SetTrackedControllerCaches(bool forceRefresh = false)
  602. {
  603. if (forceRefresh)
  604. {
  605. cachedLeftTrackedObject = null;
  606. cachedRightTrackedObject = null;
  607. cachedTrackedObjectsByGameObject.Clear();
  608. cachedTrackedObjectsByIndex.Clear();
  609. }
  610. VRTK_SDKManager sdkManager = VRTK_SDKManager.instance;
  611. if (sdkManager != null)
  612. {
  613. if (cachedLeftTrackedObject == null && sdkManager.loadedSetup.actualLeftController)
  614. {
  615. cachedLeftTrackedObject = sdkManager.loadedSetup.actualLeftController.GetComponent<SteamVR_TrackedObject>();
  616. }
  617. if (cachedRightTrackedObject == null && sdkManager.loadedSetup.actualRightController)
  618. {
  619. cachedRightTrackedObject = sdkManager.loadedSetup.actualRightController.GetComponent<SteamVR_TrackedObject>();
  620. }
  621. }
  622. }
  623. protected virtual SteamVR_TrackedObject GetTrackedObject(GameObject controller)
  624. {
  625. SetTrackedControllerCaches();
  626. if (IsControllerLeftHand(controller))
  627. {
  628. return cachedLeftTrackedObject;
  629. }
  630. else if (IsControllerRightHand(controller))
  631. {
  632. return cachedRightTrackedObject;
  633. }
  634. if (controller == null)
  635. {
  636. return null;
  637. }
  638. SteamVR_TrackedObject currentTrackedObjectByGameObject = VRTK_SharedMethods.GetDictionaryValue(cachedTrackedObjectsByGameObject, controller);
  639. if (currentTrackedObjectByGameObject != null)
  640. {
  641. return currentTrackedObjectByGameObject;
  642. }
  643. else
  644. {
  645. SteamVR_TrackedObject trackedObject = controller.GetComponent<SteamVR_TrackedObject>();
  646. if (trackedObject != null)
  647. {
  648. VRTK_SharedMethods.AddDictionaryValue(cachedTrackedObjectsByGameObject, controller, trackedObject, true);
  649. VRTK_SharedMethods.AddDictionaryValue(cachedTrackedObjectsByIndex, (uint)trackedObject.index, trackedObject, true);
  650. }
  651. return trackedObject;
  652. }
  653. }
  654. protected virtual bool IsButtonPressed(uint index, ButtonPressTypes type, ulong button)
  655. {
  656. if (index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  657. {
  658. return false;
  659. }
  660. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  661. switch (type)
  662. {
  663. case ButtonPressTypes.Press:
  664. return device.GetPress(button);
  665. case ButtonPressTypes.PressDown:
  666. return device.GetPressDown(button);
  667. case ButtonPressTypes.PressUp:
  668. return device.GetPressUp(button);
  669. case ButtonPressTypes.Touch:
  670. return device.GetTouch(button);
  671. case ButtonPressTypes.TouchDown:
  672. return device.GetTouchDown(button);
  673. case ButtonPressTypes.TouchUp:
  674. return device.GetTouchUp(button);
  675. }
  676. return false;
  677. }
  678. protected virtual bool CheckAxisTouch(uint index, ButtonPressTypes type, EVRButtonId axisId)
  679. {
  680. if (index >= OpenVR.k_unTrackedDeviceIndexInvalid)
  681. {
  682. return false;
  683. }
  684. SteamVR_Controller.Device device = SteamVR_Controller.Input((int)index);
  685. Vector2 axisValue = device.GetAxis(axisId);
  686. bool currentAxisPressState = VRTK_SharedMethods.GetDictionaryValue(axisTouchStates, axisId, false, true);
  687. float axisFidelity = VRTK_SharedMethods.GetDictionaryValue(axisTouchFidelity, axisId);
  688. switch (type)
  689. {
  690. case ButtonPressTypes.Touch:
  691. return (!VRTK_SharedMethods.Vector3ShallowCompare(axisValue, Vector2.zero, axisFidelity));
  692. case ButtonPressTypes.TouchDown:
  693. if (!currentAxisPressState && !VRTK_SharedMethods.Vector3ShallowCompare(axisValue, Vector2.zero, axisFidelity))
  694. {
  695. VRTK_SharedMethods.AddDictionaryValue(axisTouchStates, axisId, true, true);
  696. return true;
  697. }
  698. return false;
  699. case ButtonPressTypes.TouchUp:
  700. if (currentAxisPressState && VRTK_SharedMethods.Vector3ShallowCompare(axisValue, Vector2.zero, axisFidelity))
  701. {
  702. VRTK_SharedMethods.AddDictionaryValue(axisTouchStates, axisId, false, true);
  703. return true;
  704. }
  705. return false;
  706. }
  707. return false;
  708. }
  709. protected virtual string GetControllerGripPath(ControllerHand hand, string suffix, ControllerHand forceHand)
  710. {
  711. switch (GetCurrentControllerType())
  712. {
  713. case ControllerType.SteamVR_ViveWand:
  714. return (forceHand == ControllerHand.Left ? "lgrip" : "rgrip") + suffix;
  715. case ControllerType.SteamVR_ValveKnuckles:
  716. return "button_b" + suffix;
  717. case ControllerType.SteamVR_OculusTouch:
  718. return "grip" + suffix;
  719. case ControllerType.SteamVR_WindowsMRController:
  720. return "handgrip" + suffix;
  721. }
  722. return null;
  723. }
  724. protected virtual string GetControllerTouchpadPath(ControllerHand hand, string suffix)
  725. {
  726. switch (GetCurrentControllerType())
  727. {
  728. case ControllerType.SteamVR_ViveWand:
  729. case ControllerType.SteamVR_ValveKnuckles:
  730. case ControllerType.SteamVR_WindowsMRController:
  731. return "trackpad" + suffix;
  732. case ControllerType.SteamVR_OculusTouch:
  733. return "thumbstick" + suffix;
  734. }
  735. return null;
  736. }
  737. protected virtual string GetControllerButtonOnePath(ControllerHand hand, string suffix)
  738. {
  739. switch (GetCurrentControllerType())
  740. {
  741. case ControllerType.SteamVR_OculusTouch:
  742. return (hand == ControllerHand.Left ? "x_button" : "a_button") + suffix;
  743. }
  744. return null;
  745. }
  746. protected virtual string GetControllerButtonTwoPath(ControllerHand hand, string suffix)
  747. {
  748. switch (GetCurrentControllerType())
  749. {
  750. case ControllerType.SteamVR_ViveWand:
  751. case ControllerType.SteamVR_ValveKnuckles:
  752. case ControllerType.SteamVR_WindowsMRController:
  753. return "button" + suffix;
  754. case ControllerType.SteamVR_OculusTouch:
  755. return (hand == ControllerHand.Left ? "y_button" : "b_button") + suffix;
  756. }
  757. return null;
  758. }
  759. protected virtual string GetControllerSystemMenuPath(ControllerHand hand, string suffix)
  760. {
  761. switch (GetCurrentControllerType())
  762. {
  763. case ControllerType.SteamVR_ViveWand:
  764. case ControllerType.SteamVR_ValveKnuckles:
  765. return "sys_button" + suffix;
  766. case ControllerType.SteamVR_OculusTouch:
  767. return (hand == ControllerHand.Left ? "enter_button" : "home_button") + suffix;
  768. }
  769. return null;
  770. }
  771. protected virtual string GetControllerStartMenuPath(ControllerHand hand, string suffix)
  772. {
  773. switch (GetCurrentControllerType())
  774. {
  775. case ControllerType.SteamVR_OculusTouch:
  776. return (hand == ControllerHand.Left ? "enter_button" : "home_button") + suffix;
  777. }
  778. return null;
  779. }
  780. protected virtual ControllerType MatchControllerTypeByString(string controllerModelNumber)
  781. {
  782. //Direct string matches for speed
  783. switch (controllerModelNumber)
  784. {
  785. case "vive controller mv":
  786. case "vive controller dvt":
  787. return ControllerType.SteamVR_ViveWand;
  788. case "knuckles ev1.3":
  789. return ControllerType.SteamVR_ValveKnuckles;
  790. case "oculus rift cv1 (right controller)":
  791. case "oculus rift cv1 (left controller)":
  792. return ControllerType.SteamVR_OculusTouch;
  793. case "windowsmr: 0x045e/0x065b/0/2":
  794. return ControllerType.SteamVR_WindowsMRController;
  795. }
  796. return FuzzyMatchControllerTypeByString(controllerModelNumber);
  797. }
  798. protected virtual ControllerType FuzzyMatchControllerTypeByString(string controllerModelNumber)
  799. {
  800. //Fallback to fuzzy matching
  801. if (controllerModelNumber.Contains("knuckles"))
  802. {
  803. return ControllerType.SteamVR_ValveKnuckles;
  804. }
  805. else if (controllerModelNumber.Contains("vive"))
  806. {
  807. return ControllerType.SteamVR_ViveWand;
  808. }
  809. else if (controllerModelNumber.Contains("oculus rift"))
  810. {
  811. return ControllerType.SteamVR_OculusTouch;
  812. }
  813. else if (controllerModelNumber.Contains("windowsmr"))
  814. {
  815. return ControllerType.SteamVR_WindowsMRController;
  816. }
  817. return ControllerType.Undefined;
  818. }
  819. protected virtual string GetModelNumber(uint index)
  820. {
  821. return (SteamVR.instance != null ? SteamVR.instance.GetStringProperty(ETrackedDeviceProperty.Prop_ModelNumber_String, index) : "").ToLower();
  822. }
  823. #endif
  824. }
  825. }