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.

843 lines
41 KiB

  1. // Unity Controller|SDK_Unity|003
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. using System;
  6. using System.Collections.Generic;
  7. /// <summary>
  8. /// The Unity Controller SDK script provides a bridge to the base Unity input device support.
  9. /// </summary>
  10. [SDK_Description(typeof(SDK_UnitySystem))]
  11. [SDK_Description(typeof(SDK_UnitySystem), 1)]
  12. [SDK_Description(typeof(SDK_UnitySystem), 2)]
  13. [SDK_Description(typeof(SDK_UnitySystem), 3)]
  14. [SDK_Description(typeof(SDK_UnitySystem), 4)]
  15. [SDK_Description(typeof(SDK_UnitySystem), 5)]
  16. public class SDK_UnityController : SDK_BaseController
  17. {
  18. protected VRTK_TrackedController cachedLeftController;
  19. protected VRTK_TrackedController cachedRightController;
  20. protected SDK_UnityControllerTracker cachedLeftTracker;
  21. protected SDK_UnityControllerTracker cachedRightTracker;
  22. protected VRTK_VelocityEstimator cachedLeftVelocityEstimator;
  23. protected VRTK_VelocityEstimator cachedRightVelocityEstimator;
  24. protected Vector2 buttonPressThreshold = new Vector2(0.2f, 0.5f);
  25. protected Dictionary<ButtonTypes, bool> rightAxisButtonPressState = new Dictionary<ButtonTypes, bool>()
  26. {
  27. { ButtonTypes.Trigger, false },
  28. { ButtonTypes.Grip, false },
  29. };
  30. protected Dictionary<ButtonTypes, bool> leftAxisButtonPressState = new Dictionary<ButtonTypes, bool>()
  31. {
  32. { ButtonTypes.Trigger, false },
  33. { ButtonTypes.Grip, false },
  34. };
  35. protected List<string> validRightHands = new List<string>()
  36. {
  37. "OpenVR Controller - Right",
  38. "OpenVR Controller(Vive. Controller MV) - Right",
  39. "OpenVR Controller(VIVE Controller Pro MV) - Right",
  40. "Oculus Touch - Right",
  41. "Oculus Remote"
  42. };
  43. protected List<string> validLeftHands = new List<string>()
  44. {
  45. "OpenVR Controller - Left",
  46. "OpenVR Controller(Vive. Controller MV) - Left",
  47. "OpenVR Controller(VIVE Controller Pro MV) - Left",
  48. "Oculus Touch - Left"
  49. };
  50. /*
  51. Axis Codes
  52. Left Trackpad Horizontal 1
  53. Left Trackpad Vertical 2
  54. Right Trackpad Horizontal 4
  55. Right Trackpad Vertical 5
  56. Left Trigger 9
  57. Right Trigger 10
  58. Left Grip 11
  59. Right Grip 12
  60. Left Trigger NearTouch 13
  61. Right Trigger NearTouch 14
  62. Left Trackpad NearTouch 15
  63. Right Trackpad NearTouch 16
  64. */
  65. protected int[] rightControllerTouchCodes = new int[] { 15, 17, 10, 11 };
  66. protected int[] rightControllerPressCodes = new int[] { 9, 1, 0, 7 };
  67. protected int[] rightOculusRemotePressCodes = new int[] { 9, 0, 1, 7 };
  68. protected int[] leftControllerTouchCodes = new int[] { 14, 16, 12, 13 };
  69. protected int[] leftControllerPressCodes = new int[] { 8, 3, 2, 7 };
  70. protected ControllerType cachedControllerType = ControllerType.Custom;
  71. protected Dictionary<ButtonTypes, KeyCode?> rightControllerTouchKeyCodes = new Dictionary<ButtonTypes, KeyCode?>()
  72. {
  73. { ButtonTypes.Trigger, KeyCode.JoystickButton15 },
  74. { ButtonTypes.TriggerHairline, null },
  75. { ButtonTypes.Grip, null },
  76. { ButtonTypes.GripHairline, null },
  77. { ButtonTypes.Touchpad, KeyCode.JoystickButton17 },
  78. { ButtonTypes.ButtonOne, KeyCode.JoystickButton10 },
  79. { ButtonTypes.ButtonTwo, KeyCode.JoystickButton11 },
  80. { ButtonTypes.StartMenu, null }
  81. };
  82. protected Dictionary<ButtonTypes, KeyCode?> rightControllerPressKeyCodes = new Dictionary<ButtonTypes, KeyCode?>()
  83. {
  84. { ButtonTypes.Trigger, null },
  85. { ButtonTypes.TriggerHairline, null },
  86. { ButtonTypes.Grip, null },
  87. { ButtonTypes.GripHairline, null },
  88. { ButtonTypes.Touchpad, KeyCode.JoystickButton9 },
  89. { ButtonTypes.ButtonOne, KeyCode.JoystickButton1 },
  90. { ButtonTypes.ButtonTwo, KeyCode.JoystickButton0 },
  91. { ButtonTypes.StartMenu, KeyCode.JoystickButton7 }
  92. };
  93. protected Dictionary<ButtonTypes, KeyCode?> leftControllerTouchKeyCodes = new Dictionary<ButtonTypes, KeyCode?>()
  94. {
  95. { ButtonTypes.Trigger, KeyCode.JoystickButton14 },
  96. { ButtonTypes.TriggerHairline, null },
  97. { ButtonTypes.Grip, null },
  98. { ButtonTypes.GripHairline, null },
  99. { ButtonTypes.Touchpad, KeyCode.JoystickButton16 },
  100. { ButtonTypes.ButtonOne, KeyCode.JoystickButton12 },
  101. { ButtonTypes.ButtonTwo, KeyCode.JoystickButton13 },
  102. { ButtonTypes.StartMenu, null }
  103. };
  104. protected Dictionary<ButtonTypes, KeyCode?> leftControllerPressKeyCodes = new Dictionary<ButtonTypes, KeyCode?>()
  105. {
  106. { ButtonTypes.Trigger, null },
  107. { ButtonTypes.TriggerHairline, null },
  108. { ButtonTypes.Grip, null },
  109. { ButtonTypes.GripHairline, null },
  110. { ButtonTypes.Touchpad, KeyCode.JoystickButton8 },
  111. { ButtonTypes.ButtonOne, KeyCode.JoystickButton3 },
  112. { ButtonTypes.ButtonTwo, KeyCode.JoystickButton2 },
  113. { ButtonTypes.StartMenu, KeyCode.JoystickButton7 }
  114. };
  115. private bool settingCaches = false;
  116. /// <summary>
  117. /// The ProcessUpdate method enables an SDK to run logic for every Unity Update
  118. /// </summary>
  119. /// <param name="controllerReference">The reference for the controller.</param>
  120. /// <param name="options">A dictionary of generic options that can be used to within the update.</param>
  121. public override void ProcessUpdate(VRTK_ControllerReference controllerReference, Dictionary<string, object> options)
  122. {
  123. }
  124. /// <summary>
  125. /// The ProcessFixedUpdate method enables an SDK to run logic for every Unity FixedUpdate
  126. /// </summary>
  127. /// <param name="controllerReference">The reference for the controller.</param>
  128. /// <param name="options">A dictionary of generic options that can be used to within the fixed update.</param>
  129. public override void ProcessFixedUpdate(VRTK_ControllerReference controllerReference, Dictionary<string, object> options)
  130. {
  131. }
  132. /// <summary>
  133. /// The GetCurrentControllerType method returns the current used ControllerType based on the SDK and headset being used.
  134. /// </summary>
  135. /// <param name="controllerReference">The reference to the controller to get type of.</param>
  136. /// <returns>The ControllerType based on the SDK and headset being used.</returns>
  137. public override ControllerType GetCurrentControllerType(VRTK_ControllerReference controllerReference = null)
  138. {
  139. SetTrackedControllerCaches();
  140. return cachedControllerType;
  141. }
  142. /// <summary>
  143. /// The GetControllerDefaultColliderPath returns the path to the prefab that contains the collider objects for the default controller of this SDK.
  144. /// </summary>
  145. /// <param name="hand">The controller hand to check for</param>
  146. /// <returns>A path to the resource that contains the collider GameObject.</returns>
  147. public override string GetControllerDefaultColliderPath(ControllerHand hand)
  148. {
  149. return "ControllerColliders/Fallback";
  150. }
  151. /// <summary>
  152. /// The GetControllerElementPath returns the path to the game object that the given controller element for the given hand resides in.
  153. /// </summary>
  154. /// <param name="element">The controller element to look up.</param>
  155. /// <param name="hand">The controller hand to look up.</param>
  156. /// <param name="fullPath">Whether to get the initial path or the full path to the element.</param>
  157. /// <returns>A string containing the path to the game object that the controller element resides in.</returns>
  158. public override string GetControllerElementPath(ControllerElements element, ControllerHand hand, bool fullPath = false)
  159. {
  160. switch (element)
  161. {
  162. case ControllerElements.AttachPoint:
  163. return "AttachPoint";
  164. }
  165. return "";
  166. }
  167. /// <summary>
  168. /// The GetControllerIndex method returns the index of the given controller.
  169. /// </summary>
  170. /// <param name="controller">The GameObject containing the controller.</param>
  171. /// <returns>The index of the given controller.</returns>
  172. public override uint GetControllerIndex(GameObject controller)
  173. {
  174. VRTK_TrackedController trackedObject = GetTrackedObject(controller);
  175. return (trackedObject != null ? trackedObject.index : uint.MaxValue);
  176. }
  177. /// <summary>
  178. /// The GetControllerByIndex method returns the GameObject of a controller with a specific index.
  179. /// </summary>
  180. /// <param name="index">The index of the controller to find.</param>
  181. /// <param name="actual">If true it will return the actual controller, if false it will return the script alias controller GameObject.</param>
  182. /// <returns>The GameObject of the controller</returns>
  183. public override GameObject GetControllerByIndex(uint index, bool actual = false)
  184. {
  185. SetTrackedControllerCaches();
  186. VRTK_SDKManager sdkManager = VRTK_SDKManager.instance;
  187. if (sdkManager != null)
  188. {
  189. if (cachedLeftController != null && cachedLeftController.index == index)
  190. {
  191. return (actual ? sdkManager.loadedSetup.actualLeftController : sdkManager.scriptAliasLeftController);
  192. }
  193. if (cachedRightController != null && cachedRightController.index == index)
  194. {
  195. return (actual ? sdkManager.loadedSetup.actualRightController : sdkManager.scriptAliasRightController);
  196. }
  197. }
  198. return null;
  199. }
  200. /// <summary>
  201. /// The GetControllerOrigin method returns the origin of the given controller.
  202. /// </summary>
  203. /// <param name="controllerReference">The reference to the controller to retrieve the origin from.</param>
  204. /// <returns>A Transform containing the origin of the controller.</returns>
  205. public override Transform GetControllerOrigin(VRTK_ControllerReference controllerReference)
  206. {
  207. return VRTK_SDK_Bridge.GetPlayArea();
  208. }
  209. /// <summary>
  210. /// The GenerateControllerPointerOrigin method can create a custom pointer origin Transform to represent the pointer position and forward.
  211. /// </summary>
  212. /// <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>
  213. /// <returns>A generated Transform that contains the custom pointer origin.</returns>
  214. [System.Obsolete("GenerateControllerPointerOrigin has been deprecated and will be removed in a future version of VRTK.")]
  215. public override Transform GenerateControllerPointerOrigin(GameObject parent)
  216. {
  217. return null;
  218. }
  219. /// <summary>
  220. /// The GetControllerLeftHand method returns the GameObject containing the representation of the left hand controller.
  221. /// </summary>
  222. /// <param name="actual">If true it will return the actual controller, if false it will return the script alias controller GameObject.</param>
  223. /// <returns>The GameObject containing the left hand controller.</returns>
  224. public override GameObject GetControllerLeftHand(bool actual = false)
  225. {
  226. GameObject controller = GetSDKManagerControllerLeftHand(actual);
  227. if (controller == null && actual)
  228. {
  229. controller = VRTK_SharedMethods.FindEvenInactiveGameObject<SDK_UnityCameraRig>("LeftHandAnchor", true);
  230. }
  231. return controller;
  232. }
  233. /// <summary>
  234. /// The GetControllerRightHand method returns the GameObject containing the representation of the right hand controller.
  235. /// </summary>
  236. /// <param name="actual">If true it will return the actual controller, if false it will return the script alias controller GameObject.</param>
  237. /// <returns>The GameObject containing the right hand controller.</returns>
  238. public override GameObject GetControllerRightHand(bool actual = false)
  239. {
  240. GameObject controller = GetSDKManagerControllerRightHand(actual);
  241. if (controller == null && actual)
  242. {
  243. controller = VRTK_SharedMethods.FindEvenInactiveGameObject<SDK_UnityCameraRig>("RightHandAnchor", true);
  244. }
  245. return controller;
  246. }
  247. /// <summary>
  248. /// The IsControllerLeftHand/1 method is used to check if the given controller is the the left hand controller.
  249. /// </summary>
  250. /// <param name="controller">The GameObject to check.</param>
  251. /// <returns>Returns true if the given controller is the left hand controller.</returns>
  252. public override bool IsControllerLeftHand(GameObject controller)
  253. {
  254. return CheckActualOrScriptAliasControllerIsLeftHand(controller);
  255. }
  256. /// <summary>
  257. /// The IsControllerRightHand/1 method is used to check if the given controller is the the right hand controller.
  258. /// </summary>
  259. /// <param name="controller">The GameObject to check.</param>
  260. /// <returns>Returns true if the given controller is the right hand controller.</returns>
  261. public override bool IsControllerRightHand(GameObject controller)
  262. {
  263. return CheckActualOrScriptAliasControllerIsRightHand(controller);
  264. }
  265. /// <summary>
  266. /// The IsControllerLeftHand/2 method is used to check if the given controller is the the left hand controller.
  267. /// </summary>
  268. /// <param name="controller">The GameObject to check.</param>
  269. /// <param name="actual">If true it will check the actual controller, if false it will check the script alias controller.</param>
  270. /// <returns>Returns true if the given controller is the left hand controller.</returns>
  271. public override bool IsControllerLeftHand(GameObject controller, bool actual)
  272. {
  273. return CheckControllerLeftHand(controller, actual);
  274. }
  275. /// <summary>
  276. /// The IsControllerRightHand/2 method is used to check if the given controller is the the right hand controller.
  277. /// </summary>
  278. /// <param name="controller">The GameObject to check.</param>
  279. /// <param name="actual">If true it will check the actual controller, if false it will check the script alias controller.</param>
  280. /// <returns>Returns true if the given controller is the right hand controller.</returns>
  281. public override bool IsControllerRightHand(GameObject controller, bool actual)
  282. {
  283. return CheckControllerRightHand(controller, actual);
  284. }
  285. /// <summary>
  286. /// The WaitForControllerModel method determines whether the controller model for the given hand requires waiting to load in on scene start.
  287. /// </summary>
  288. /// <param name="hand">The hand to determine if the controller model will be ready for.</param>
  289. /// <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>
  290. public override bool WaitForControllerModel(ControllerHand hand)
  291. {
  292. return false;
  293. }
  294. /// <summary>
  295. /// The GetControllerModel method returns the model alias for the given GameObject.
  296. /// </summary>
  297. /// <param name="controller">The GameObject to get the model alias for.</param>
  298. /// <returns>The GameObject that has the model alias within it.</returns>
  299. public override GameObject GetControllerModel(GameObject controller)
  300. {
  301. return GetControllerModelFromController(controller);
  302. }
  303. /// <summary>
  304. /// The GetControllerModel method returns the model alias for the given controller hand.
  305. /// </summary>
  306. /// <param name="hand">The hand enum of which controller model to retrieve.</param>
  307. /// <returns>The GameObject that has the model alias within it.</returns>
  308. public override GameObject GetControllerModel(ControllerHand hand)
  309. {
  310. GameObject model = GetSDKManagerControllerModelForHand(hand);
  311. if (model == null)
  312. {
  313. GameObject controller = null;
  314. switch (hand)
  315. {
  316. case ControllerHand.Left:
  317. controller = GetControllerLeftHand(true);
  318. break;
  319. case ControllerHand.Right:
  320. controller = GetControllerRightHand(true);
  321. break;
  322. }
  323. if (controller != null)
  324. {
  325. model = controller.transform.Find("Model").gameObject;
  326. }
  327. }
  328. return model;
  329. }
  330. /// <summary>
  331. /// The GetControllerRenderModel method gets the game object that contains the given controller's render model.
  332. /// </summary>
  333. /// <param name="controllerReference">The reference to the controller to check.</param>
  334. /// <returns>A GameObject containing the object that has a render model for the controller.</returns>
  335. public override GameObject GetControllerRenderModel(VRTK_ControllerReference controllerReference)
  336. {
  337. return null;
  338. }
  339. /// <summary>
  340. /// The SetControllerRenderModelWheel method sets the state of the scroll wheel on the controller render model.
  341. /// </summary>
  342. /// <param name="renderModel">The GameObject containing the controller render model.</param>
  343. /// <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>
  344. public override void SetControllerRenderModelWheel(GameObject renderModel, bool state)
  345. {
  346. }
  347. /// <summary>
  348. /// The HapticPulse/2 method is used to initiate a simple haptic pulse on the tracked object of the given controller reference.
  349. /// </summary>
  350. /// <param name="controllerReference">The reference to the tracked object to initiate the haptic pulse on.</param>
  351. /// <param name="strength">The intensity of the rumble of the controller motor. `0` to `1`.</param>
  352. public override void HapticPulse(VRTK_ControllerReference controllerReference, float strength = 0.5f)
  353. {
  354. }
  355. /// <summary>
  356. /// 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.
  357. /// </summary>
  358. /// <param name="controllerReference">The reference to the tracked object to initiate the haptic pulse on.</param>
  359. /// <param name="clip">The audio clip to use for the haptic pattern.</param>
  360. public override bool HapticPulse(VRTK_ControllerReference controllerReference, AudioClip clip)
  361. {
  362. //Return true so it just always prevents doing a fallback routine.
  363. return true;
  364. }
  365. /// <summary>
  366. /// The GetHapticModifiers method is used to return modifiers for the duration and interval if the SDK handles it slightly differently.
  367. /// </summary>
  368. /// <returns>An SDK_ControllerHapticModifiers object with a given `durationModifier` and an `intervalModifier`.</returns>
  369. public override SDK_ControllerHapticModifiers GetHapticModifiers()
  370. {
  371. return new SDK_ControllerHapticModifiers();
  372. }
  373. /// <summary>
  374. /// The GetVelocity method is used to determine the current velocity of the tracked object on the given controller reference.
  375. /// </summary>
  376. /// <param name="controllerReference">The reference to the tracked object to check for.</param>
  377. /// <returns>A Vector3 containing the current velocity of the tracked object.</returns>
  378. public override Vector3 GetVelocity(VRTK_ControllerReference controllerReference)
  379. {
  380. if (VRTK_ControllerReference.IsValid(controllerReference))
  381. {
  382. if (controllerReference.hand == ControllerHand.Left && cachedLeftVelocityEstimator != null)
  383. {
  384. return cachedLeftVelocityEstimator.GetVelocityEstimate();
  385. }
  386. else if (controllerReference.hand == ControllerHand.Right && cachedRightVelocityEstimator != null)
  387. {
  388. return cachedRightVelocityEstimator.GetVelocityEstimate();
  389. }
  390. }
  391. return Vector3.zero;
  392. }
  393. /// <summary>
  394. /// The GetAngularVelocity method is used to determine the current angular velocity of the tracked object on the given controller reference.
  395. /// </summary>
  396. /// <param name="controllerReference">The reference to the tracked object to check for.</param>
  397. /// <returns>A Vector3 containing the current angular velocity of the tracked object.</returns>
  398. public override Vector3 GetAngularVelocity(VRTK_ControllerReference controllerReference)
  399. {
  400. if (VRTK_ControllerReference.IsValid(controllerReference))
  401. {
  402. if (controllerReference.hand == ControllerHand.Left && cachedLeftVelocityEstimator != null)
  403. {
  404. return cachedLeftVelocityEstimator.GetAngularVelocityEstimate();
  405. }
  406. else if (controllerReference.hand == ControllerHand.Right && cachedRightVelocityEstimator != null)
  407. {
  408. return cachedRightVelocityEstimator.GetAngularVelocityEstimate();
  409. }
  410. }
  411. return Vector3.zero;
  412. }
  413. /// <summary>
  414. /// The IsTouchpadStatic method is used to determine if the touchpad is currently not being moved.
  415. /// </summary>
  416. /// <param name="currentAxisValues"></param>
  417. /// <param name="previousAxisValues"></param>
  418. /// <param name="compareFidelity"></param>
  419. /// <returns>Returns true if the touchpad is not currently being touched or moved.</returns>
  420. public override bool IsTouchpadStatic(bool isTouched, Vector2 currentAxisValues, Vector2 previousAxisValues, int compareFidelity)
  421. {
  422. return (!isTouched || VRTK_SharedMethods.Vector2ShallowCompare(currentAxisValues, previousAxisValues, compareFidelity));
  423. }
  424. /// <summary>
  425. /// The GetButtonAxis method retrieves the current X/Y axis values for the given button type on the given controller reference.
  426. /// </summary>
  427. /// <param name="buttonType">The type of button to check for the axis on.</param>
  428. /// <param name="controllerReference">The reference to the controller to check the button axis on.</param>
  429. /// <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>
  430. public override Vector2 GetButtonAxis(ButtonTypes buttonType, VRTK_ControllerReference controllerReference)
  431. {
  432. if (!VRTK_ControllerReference.IsValid(controllerReference))
  433. {
  434. return Vector2.zero;
  435. }
  436. bool isRightController = (controllerReference.hand == ControllerHand.Right);
  437. if ((isRightController && cachedRightTracker == null) || (!isRightController && cachedLeftTracker == null))
  438. {
  439. return Vector2.zero;
  440. }
  441. switch (buttonType)
  442. {
  443. case ButtonTypes.Trigger:
  444. return new Vector2(GetAxisValue((isRightController ? cachedRightTracker.triggerAxisName : cachedLeftTracker.triggerAxisName)), 0f);
  445. case ButtonTypes.Grip:
  446. return new Vector2(GetAxisValue((isRightController ? cachedRightTracker.gripAxisName : cachedLeftTracker.gripAxisName)), 0f);
  447. case ButtonTypes.Touchpad:
  448. return new Vector2(GetAxisValue((isRightController ? cachedRightTracker.touchpadHorizontalAxisName : cachedLeftTracker.touchpadHorizontalAxisName)), GetAxisValue((isRightController ? cachedRightTracker.touchpadVerticalAxisName : cachedLeftTracker.touchpadVerticalAxisName)));
  449. }
  450. return Vector2.zero;
  451. }
  452. /// <summary>
  453. /// The GetButtonSenseAxis method retrieves the current sense axis value for the given button type on the given controller reference.
  454. /// </summary>
  455. /// <param name="buttonType">The type of button to check for the sense axis on.</param>
  456. /// <param name="controllerReference">The reference to the controller to check the sense axis on.</param>
  457. /// <returns>The current sense axis value.</returns>
  458. public override float GetButtonSenseAxis(ButtonTypes buttonType, VRTK_ControllerReference controllerReference)
  459. {
  460. return 0f;
  461. }
  462. /// <summary>
  463. /// The GetButtonHairlineDelta method is used to get the difference between the current button press and the previous frame button press.
  464. /// </summary>
  465. /// <param name="buttonType">The type of button to get the hairline delta for.</param>
  466. /// <param name="controllerReference">The reference to the controller to get the hairline delta for.</param>
  467. /// <returns>The delta between the button presses.</returns>
  468. public override float GetButtonHairlineDelta(ButtonTypes buttonType, VRTK_ControllerReference controllerReference)
  469. {
  470. return 0f;
  471. }
  472. /// <summary>
  473. /// 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.
  474. /// </summary>
  475. /// <param name="buttonType">The type of button to check for the state of.</param>
  476. /// <param name="pressType">The button state to check for.</param>
  477. /// <param name="controllerReference">The reference to the controller to check the button state on.</param>
  478. /// <returns>Returns true if the given button is in the state of the given press type on the given controller reference.</returns>
  479. public override bool GetControllerButtonState(ButtonTypes buttonType, ButtonPressTypes pressType, VRTK_ControllerReference controllerReference)
  480. {
  481. if (!VRTK_ControllerReference.IsValid(controllerReference))
  482. {
  483. return false;
  484. }
  485. bool isRightController = (controllerReference.hand == ControllerHand.Right);
  486. KeyCode? touchButton = VRTK_SharedMethods.GetDictionaryValue((isRightController ? rightControllerTouchKeyCodes : leftControllerTouchKeyCodes), buttonType);
  487. KeyCode? pressButton = VRTK_SharedMethods.GetDictionaryValue((isRightController ? rightControllerPressKeyCodes : leftControllerPressKeyCodes), buttonType);
  488. switch (buttonType)
  489. {
  490. case ButtonTypes.Trigger:
  491. switch (pressType)
  492. {
  493. case ButtonPressTypes.Touch:
  494. case ButtonPressTypes.TouchDown:
  495. case ButtonPressTypes.TouchUp:
  496. return IsButtonPressed(pressType, touchButton, pressButton);
  497. case ButtonPressTypes.Press:
  498. case ButtonPressTypes.PressDown:
  499. case ButtonPressTypes.PressUp:
  500. return (IsMouseAliasPress(isRightController, buttonType, pressType) || IsAxisButtonPress(controllerReference, buttonType, pressType));
  501. }
  502. break;
  503. case ButtonTypes.Grip:
  504. return (IsMouseAliasPress(isRightController, buttonType, pressType) || IsAxisButtonPress(controllerReference, buttonType, pressType));
  505. case ButtonTypes.Touchpad:
  506. return IsButtonPressed(pressType, touchButton, pressButton);
  507. case ButtonTypes.ButtonOne:
  508. return IsButtonPressed(pressType, touchButton, pressButton);
  509. case ButtonTypes.ButtonTwo:
  510. return IsButtonPressed(pressType, touchButton, pressButton);
  511. case ButtonTypes.StartMenu:
  512. return IsButtonPressed(pressType, touchButton, pressButton);
  513. }
  514. return false;
  515. }
  516. protected virtual bool IsMouseAliasPress(bool validController, ButtonTypes buttonType, ButtonPressTypes pressType)
  517. {
  518. if (validController)
  519. {
  520. switch (buttonType)
  521. {
  522. case ButtonTypes.Trigger:
  523. return MousePressType(pressType, 0);
  524. case ButtonTypes.Grip:
  525. return MousePressType(pressType, 1);
  526. }
  527. }
  528. return false;
  529. }
  530. protected virtual bool MousePressType(ButtonPressTypes pressType, int buttonIndex)
  531. {
  532. switch (pressType)
  533. {
  534. case ButtonPressTypes.Press:
  535. return Input.GetMouseButton(buttonIndex);
  536. case ButtonPressTypes.PressDown:
  537. return Input.GetMouseButtonDown(buttonIndex);
  538. case ButtonPressTypes.PressUp:
  539. return Input.GetMouseButtonUp(buttonIndex);
  540. }
  541. return false;
  542. }
  543. protected virtual float GetAxisValue(string axisName)
  544. {
  545. try
  546. {
  547. return Input.GetAxis(axisName);
  548. }
  549. catch (ArgumentException)
  550. {
  551. //Don't do any logging here because it will spam the console
  552. }
  553. return 0f;
  554. }
  555. protected virtual bool IsAxisOnHandButtonPress(Dictionary<ButtonTypes, bool> axisHandState, ButtonTypes buttonType, ButtonPressTypes pressType, Vector2 axisValue)
  556. {
  557. bool previousAxisState = VRTK_SharedMethods.GetDictionaryValue(axisHandState, buttonType);
  558. if (pressType == ButtonPressTypes.PressDown && !previousAxisState)
  559. {
  560. bool currentAxisState = GetAxisPressState(previousAxisState, axisValue.x);
  561. VRTK_SharedMethods.AddDictionaryValue(axisHandState, buttonType, currentAxisState, true);
  562. return currentAxisState;
  563. }
  564. if (pressType == ButtonPressTypes.PressUp && previousAxisState)
  565. {
  566. bool currentAxisState = GetAxisPressState(previousAxisState, axisValue.x);
  567. VRTK_SharedMethods.AddDictionaryValue(axisHandState, buttonType, currentAxisState, true);
  568. return !currentAxisState;
  569. }
  570. return false;
  571. }
  572. protected virtual bool IsAxisButtonPress(VRTK_ControllerReference controllerReference, ButtonTypes buttonType, ButtonPressTypes pressType)
  573. {
  574. bool isRightController = (controllerReference.hand == ControllerHand.Right);
  575. Vector2 axisValue = GetButtonAxis(buttonType, controllerReference);
  576. return IsAxisOnHandButtonPress((isRightController ? rightAxisButtonPressState : leftAxisButtonPressState), buttonType, pressType, axisValue);
  577. }
  578. protected virtual bool GetAxisPressState(bool currentState, float axisValue)
  579. {
  580. if (currentState && axisValue <= buttonPressThreshold.x)
  581. {
  582. currentState = false;
  583. }
  584. else if (!currentState && axisValue >= buttonPressThreshold.y)
  585. {
  586. currentState = true;
  587. }
  588. return currentState;
  589. }
  590. protected virtual bool IsButtonPressed(ButtonPressTypes pressType, KeyCode? touchKey, KeyCode? pressKey)
  591. {
  592. switch (pressType)
  593. {
  594. case ButtonPressTypes.Touch:
  595. return (touchKey != null && Input.GetKey((KeyCode)touchKey));
  596. case ButtonPressTypes.TouchDown:
  597. return (touchKey != null && Input.GetKeyDown((KeyCode)touchKey));
  598. case ButtonPressTypes.TouchUp:
  599. return (touchKey != null && Input.GetKeyUp((KeyCode)touchKey));
  600. case ButtonPressTypes.Press:
  601. return (pressKey != null && Input.GetKey((KeyCode)pressKey));
  602. case ButtonPressTypes.PressDown:
  603. return (pressKey != null && Input.GetKeyDown((KeyCode)pressKey));
  604. case ButtonPressTypes.PressUp:
  605. return (pressKey != null && Input.GetKeyUp((KeyCode)pressKey));
  606. }
  607. return false;
  608. }
  609. protected virtual void SetTrackedControllerCaches(bool forceRefresh = false)
  610. {
  611. if (settingCaches)
  612. {
  613. return;
  614. }
  615. settingCaches = true;
  616. if (forceRefresh)
  617. {
  618. cachedLeftController = null;
  619. cachedRightController = null;
  620. }
  621. VRTK_SDKManager sdkManager = VRTK_SDKManager.instance;
  622. if (sdkManager != null && sdkManager.loadedSetup != null)
  623. {
  624. if (cachedLeftController == null && sdkManager.loadedSetup.actualLeftController != null)
  625. {
  626. cachedLeftController = sdkManager.loadedSetup.actualLeftController.GetComponent<VRTK_TrackedController>();
  627. SetControllerIndex(ref cachedLeftController);
  628. if (cachedLeftController != null)
  629. {
  630. cachedLeftTracker = cachedLeftController.GetComponent<SDK_UnityControllerTracker>();
  631. cachedLeftVelocityEstimator = cachedLeftController.GetComponent<VRTK_VelocityEstimator>();
  632. SetControllerButtons(ControllerHand.Left);
  633. }
  634. }
  635. if (cachedRightController == null && sdkManager.loadedSetup.actualRightController != null)
  636. {
  637. cachedRightController = sdkManager.loadedSetup.actualRightController.GetComponent<VRTK_TrackedController>();
  638. SetControllerIndex(ref cachedRightController);
  639. if (cachedRightController != null)
  640. {
  641. cachedRightTracker = cachedRightController.GetComponent<SDK_UnityControllerTracker>();
  642. cachedRightVelocityEstimator = cachedRightController.GetComponent<VRTK_VelocityEstimator>();
  643. SetControllerButtons(ControllerHand.Right);
  644. }
  645. }
  646. }
  647. settingCaches = false;
  648. }
  649. protected virtual void SetControllerButtons(ControllerHand hand)
  650. {
  651. List<string> checkhands = (hand == ControllerHand.Right ? validRightHands : validLeftHands);
  652. bool joystickFound = false;
  653. int validJoystickIndex = 0;
  654. string[] availableJoysticks = Input.GetJoystickNames();
  655. for (int i = 0; i < availableJoysticks.Length; i++)
  656. {
  657. if (checkhands.Contains(availableJoysticks[i]))
  658. {
  659. SetCachedControllerType(availableJoysticks[i]);
  660. joystickFound = true;
  661. validJoystickIndex = i + 1;
  662. }
  663. }
  664. //If the joystick isn't found then try and match on headset type
  665. if (!joystickFound)
  666. {
  667. switch (VRTK_DeviceFinder.GetHeadsetType())
  668. {
  669. case SDK_BaseHeadset.HeadsetType.GoogleDaydream:
  670. SetCachedControllerType("googledaydream");
  671. joystickFound = true;
  672. validJoystickIndex = 1;
  673. break;
  674. }
  675. }
  676. if (joystickFound)
  677. {
  678. if (hand == ControllerHand.Right)
  679. {
  680. var pressCodes = cachedControllerType == ControllerType.Oculus_OculusRemote ? rightOculusRemotePressCodes : rightControllerPressCodes;
  681. SetControllerButtonValues(ref rightControllerTouchKeyCodes, ref rightControllerPressKeyCodes, validJoystickIndex, rightControllerTouchCodes, pressCodes);
  682. }
  683. else
  684. {
  685. SetControllerButtonValues(ref leftControllerTouchKeyCodes, ref leftControllerPressKeyCodes, validJoystickIndex, leftControllerTouchCodes, leftControllerPressCodes);
  686. }
  687. }
  688. else if (availableJoysticks.Length > 0 && VRTK_ControllerReference.GetControllerReference(hand) != null && VRTK_ControllerReference.GetControllerReference(hand).actual.gameObject.activeInHierarchy)
  689. {
  690. VRTK_Logger.Warn("Failed setting controller buttons on [" + hand + "] due to no valid joystick type found in `GetJoyStickNames` -> " + string.Join(", ", availableJoysticks));
  691. }
  692. }
  693. protected virtual void SetCachedControllerType(string givenType)
  694. {
  695. givenType = givenType.ToLower();
  696. //try direct matching
  697. switch (givenType)
  698. {
  699. case "googledaydream":
  700. cachedControllerType = ControllerType.Daydream_Controller;
  701. return;
  702. case "oculus remote":
  703. cachedControllerType = ControllerType.Oculus_OculusRemote;
  704. return;
  705. }
  706. //fallback to fuzzy matching
  707. if (givenType.Contains("openvr controller"))
  708. {
  709. switch (VRTK_DeviceFinder.GetHeadsetType())
  710. {
  711. case SDK_BaseHeadset.HeadsetType.HTCVive:
  712. cachedControllerType = ControllerType.SteamVR_ViveWand;
  713. break;
  714. case SDK_BaseHeadset.HeadsetType.OculusRift:
  715. cachedControllerType = ControllerType.SteamVR_OculusTouch;
  716. break;
  717. }
  718. }
  719. else if (givenType.Contains("oculus touch"))
  720. {
  721. cachedControllerType = ControllerType.Oculus_OculusTouch;
  722. }
  723. }
  724. protected virtual void SetControllerButtonValues(ref Dictionary<ButtonTypes, KeyCode?> touchKeyCodes, ref Dictionary<ButtonTypes, KeyCode?> pressKeyCodes, int joystickIndex, int[] touchCodes, int[] pressCodes)
  725. {
  726. VRTK_SharedMethods.AddDictionaryValue(touchKeyCodes, ButtonTypes.Trigger, StringToKeyCode(joystickIndex, touchCodes[0]), true);
  727. VRTK_SharedMethods.AddDictionaryValue(touchKeyCodes, ButtonTypes.Touchpad, StringToKeyCode(joystickIndex, touchCodes[1]), true);
  728. VRTK_SharedMethods.AddDictionaryValue(touchKeyCodes, ButtonTypes.ButtonOne, StringToKeyCode(joystickIndex, touchCodes[2]), true);
  729. VRTK_SharedMethods.AddDictionaryValue(touchKeyCodes, ButtonTypes.ButtonTwo, StringToKeyCode(joystickIndex, touchCodes[3]), true);
  730. VRTK_SharedMethods.AddDictionaryValue(pressKeyCodes, ButtonTypes.Touchpad, StringToKeyCode(joystickIndex, pressCodes[0]), true);
  731. VRTK_SharedMethods.AddDictionaryValue(pressKeyCodes, ButtonTypes.ButtonOne, StringToKeyCode(joystickIndex, pressCodes[1]), true);
  732. VRTK_SharedMethods.AddDictionaryValue(pressKeyCodes, ButtonTypes.ButtonTwo, StringToKeyCode(joystickIndex, pressCodes[2]), true);
  733. VRTK_SharedMethods.AddDictionaryValue(pressKeyCodes, ButtonTypes.StartMenu, StringToKeyCode(joystickIndex, pressCodes[3]), true);
  734. }
  735. protected virtual KeyCode StringToKeyCode(int index, int code)
  736. {
  737. return (KeyCode)Enum.Parse(typeof(KeyCode), "Joystick" + index + "Button" + code);
  738. }
  739. protected virtual void SetControllerIndex(ref VRTK_TrackedController trackedController)
  740. {
  741. if (trackedController != null)
  742. {
  743. SDK_UnityControllerTracker tracker = trackedController.GetComponent<SDK_UnityControllerTracker>();
  744. if (tracker != null)
  745. {
  746. trackedController.index = tracker.index;
  747. }
  748. }
  749. }
  750. protected virtual VRTK_TrackedController GetTrackedObject(GameObject controller)
  751. {
  752. SetTrackedControllerCaches();
  753. VRTK_TrackedController trackedObject = null;
  754. if (IsControllerLeftHand(controller))
  755. {
  756. trackedObject = cachedLeftController;
  757. }
  758. else if (IsControllerRightHand(controller))
  759. {
  760. trackedObject = cachedRightController;
  761. }
  762. return trackedObject;
  763. }
  764. }
  765. }