SteamVR_Input.cs 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. using UnityEngine;
  3. using Valve.VR;
  4. using System.IO;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Reflection;
  8. using System.Linq;
  9. using Valve.Newtonsoft.Json;
  10. using System.Text;
  11. namespace Valve.VR
  12. {
  13. public partial class SteamVR_Input
  14. {
  15. public const string defaultInputGameObjectName = "[SteamVR Input]";
  16. private const string localizationKeyName = "localization";
  17. public static string actionsFilePath;
  18. /// <summary>True if the actions file has been initialized</summary>
  19. public static bool fileInitialized = false;
  20. /// <summary>True if the steamvr input system initialization process has completed successfully</summary>
  21. public static bool initialized = false;
  22. /// <summary>True if the preinitialization process (setting up dictionaries, etc) has completed successfully</summary>
  23. public static bool preInitialized = false;
  24. /// <summary>The serialized version of the actions file we're currently using (only used in editor)</summary>
  25. public static SteamVR_Input_ActionFile actionFile;
  26. /// <summary>The hash of the current action file on disk</summary>
  27. public static string actionFileHash;
  28. /// <summary>An event that fires when the non visual actions (everything except poses / skeletons) have been updated</summary>
  29. public static event Action onNonVisualActionsUpdated;
  30. /// <summary>An event that fires when the pose actions have been updated</summary>
  31. public static event PosesUpdatedHandler onPosesUpdated;
  32. public delegate void PosesUpdatedHandler(bool skipSendingEvents);
  33. /// <summary>An event that fires when the skeleton actions have been updated</summary>
  34. public static event SkeletonsUpdatedHandler onSkeletonsUpdated;
  35. public delegate void SkeletonsUpdatedHandler(bool skipSendingEvents);
  36. protected static bool initializing = false;
  37. protected static int startupFrame = 0;
  38. public static bool isStartupFrame
  39. {
  40. get
  41. {
  42. return Time.frameCount >= (startupFrame-1) && Time.frameCount <= (startupFrame+1);
  43. }
  44. }
  45. #region array accessors
  46. /// <summary>An array of all action sets</summary>
  47. public static SteamVR_ActionSet[] actionSets;
  48. /// <summary>An array of all actions (in all action sets)</summary>
  49. public static SteamVR_Action[] actions;
  50. /// <summary>An array of all input actions</summary>
  51. public static ISteamVR_Action_In[] actionsIn;
  52. /// <summary>An array of all output actions (haptic)</summary>
  53. public static ISteamVR_Action_Out[] actionsOut;
  54. /// <summary>An array of all the boolean actions</summary>
  55. public static SteamVR_Action_Boolean[] actionsBoolean;
  56. /// <summary>An array of all the single actions</summary>
  57. public static SteamVR_Action_Single[] actionsSingle;
  58. /// <summary>An array of all the vector2 actions</summary>
  59. public static SteamVR_Action_Vector2[] actionsVector2;
  60. /// <summary>An array of all the vector3 actions</summary>
  61. public static SteamVR_Action_Vector3[] actionsVector3;
  62. /// <summary>An array of all the pose actions</summary>
  63. public static SteamVR_Action_Pose[] actionsPose;
  64. /// <summary>An array of all the skeleton actions</summary>
  65. public static SteamVR_Action_Skeleton[] actionsSkeleton;
  66. /// <summary>An array of all the vibration (haptic) actions</summary>
  67. public static SteamVR_Action_Vibration[] actionsVibration;
  68. /// <summary>An array of all the input actions that are not pose or skeleton actions (boolean, single, vector2, vector3)</summary>
  69. public static ISteamVR_Action_In[] actionsNonPoseNonSkeletonIn;
  70. protected static Dictionary<string, SteamVR_ActionSet> actionSetsByPath = new Dictionary<string, SteamVR_ActionSet>();
  71. protected static Dictionary<string, SteamVR_ActionSet> actionSetsByPathLowered = new Dictionary<string, SteamVR_ActionSet>();
  72. protected static Dictionary<string, SteamVR_Action> actionsByPath = new Dictionary<string, SteamVR_Action>();
  73. protected static Dictionary<string, SteamVR_Action> actionsByPathLowered = new Dictionary<string, SteamVR_Action>();
  74. protected static Dictionary<string, SteamVR_ActionSet> actionSetsByPathCache = new Dictionary<string, SteamVR_ActionSet>();
  75. protected static Dictionary<string, SteamVR_Action> actionsByPathCache = new Dictionary<string, SteamVR_Action>();
  76. protected static Dictionary<string, SteamVR_Action> actionsByNameCache = new Dictionary<string, SteamVR_Action>();
  77. protected static Dictionary<string, SteamVR_ActionSet> actionSetsByNameCache = new Dictionary<string, SteamVR_ActionSet>();
  78. #endregion
  79. static SteamVR_Input()
  80. {
  81. #if !UNITY_EDITOR
  82. //If you want a single frame of performance increase on application start and have already generated your actions uncomment the following two lines
  83. //SteamVR_Actions.Preinitialize();
  84. //return;
  85. #endif
  86. FindPreinitializeMethod();
  87. }
  88. public static void ForcePreinitialize()
  89. {
  90. FindPreinitializeMethod();
  91. }
  92. private static void FindPreinitializeMethod()
  93. {
  94. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  95. for (int assemblyIndex = 0; assemblyIndex < assemblies.Length; assemblyIndex++)
  96. {
  97. Assembly assembly = assemblies[assemblyIndex];
  98. Type type = assembly.GetType(SteamVR_Input_Generator_Names.fullActionsClassName);
  99. if (type != null)
  100. {
  101. MethodInfo preinitMethodInfo = type.GetMethod(SteamVR_Input_Generator_Names.preinitializeMethodName);
  102. if (preinitMethodInfo != null)
  103. {
  104. preinitMethodInfo.Invoke(null, null);
  105. return;
  106. }
  107. }
  108. }
  109. }
  110. /// <summary>
  111. /// Get all the handles for actions and action sets.
  112. /// Initialize our dictionaries of action / action set names.
  113. /// Setup the tracking space universe origin
  114. /// </summary>
  115. public static void Initialize(bool force = false)
  116. {
  117. if (initialized == true && force == false)
  118. return;
  119. #if UNITY_EDITOR
  120. CheckSetup();
  121. if (IsOpeningSetup())
  122. return;
  123. #endif
  124. //Debug.Log("<b>[SteamVR]</b> Initializing SteamVR input...");
  125. initializing = true;
  126. startupFrame = Time.frameCount;
  127. SteamVR_ActionSet_Manager.Initialize();
  128. SteamVR_Input_Source.Initialize();
  129. for (int actionIndex = 0; actionIndex < actions.Length; actionIndex++)
  130. {
  131. SteamVR_Action action = actions[actionIndex];
  132. action.Initialize(true);
  133. }
  134. for (int actionSetIndex = 0; actionSetIndex < actionSets.Length; actionSetIndex++)
  135. {
  136. SteamVR_ActionSet set = actionSets[actionSetIndex];
  137. set.Initialize(true);
  138. }
  139. if (SteamVR_Settings.instance.activateFirstActionSetOnStart)
  140. {
  141. if (actionSets.Length > 0)
  142. actionSets[0].Activate();
  143. else
  144. {
  145. Debug.LogError("<b>[SteamVR]</b> No action sets to activate.");
  146. }
  147. }
  148. SteamVR_Action_Pose.SetTrackingUniverseOrigin(SteamVR_Settings.instance.trackingSpace);
  149. initialized = true;
  150. initializing = false;
  151. //Debug.Log("<b>[SteamVR]</b> Input initialization complete.");
  152. }
  153. public static void PreinitializeFinishActionSets()
  154. {
  155. for (int actionSetIndex = 0; actionSetIndex < actionSets.Length; actionSetIndex++)
  156. {
  157. SteamVR_ActionSet actionSet = actionSets[actionSetIndex];
  158. actionSet.FinishPreInitialize();
  159. }
  160. }
  161. public static void PreinitializeActionSetDictionaries()
  162. {
  163. actionSetsByPath.Clear();
  164. actionSetsByPathLowered.Clear();
  165. actionSetsByPathCache.Clear();
  166. for (int actionSetIndex = 0; actionSetIndex < actionSets.Length; actionSetIndex++)
  167. {
  168. SteamVR_ActionSet actionSet = actionSets[actionSetIndex];
  169. actionSetsByPath.Add(actionSet.fullPath, actionSet);
  170. actionSetsByPathLowered.Add(actionSet.fullPath.ToLower(), actionSet);
  171. }
  172. }
  173. public static void PreinitializeActionDictionaries()
  174. {
  175. actionsByPath.Clear();
  176. actionsByPathLowered.Clear();
  177. actionsByPathCache.Clear();
  178. for (int actionIndex = 0; actionIndex < actions.Length; actionIndex++)
  179. {
  180. SteamVR_Action action = actions[actionIndex];
  181. actionsByPath.Add(action.fullPath, action);
  182. actionsByPathLowered.Add(action.fullPath.ToLower(), action);
  183. }
  184. }
  185. /// <summary>Gets called by SteamVR_Behaviour every Update and updates actions if the steamvr settings are configured to update then.</summary>
  186. public static void Update()
  187. {
  188. if (initialized == false || isStartupFrame)
  189. return;
  190. if (SteamVR.settings.IsInputUpdateMode(SteamVR_UpdateModes.OnUpdate))
  191. {
  192. UpdateNonVisualActions();
  193. }
  194. if (SteamVR.settings.IsPoseUpdateMode(SteamVR_UpdateModes.OnUpdate))
  195. {
  196. UpdateVisualActions();
  197. }
  198. }
  199. /// <summary>
  200. /// Gets called by SteamVR_Behaviour every LateUpdate and updates actions if the steamvr settings are configured to update then.
  201. /// Also updates skeletons regardless of settings are configured to so we can account for animations on the skeletons.
  202. /// </summary>
  203. public static void LateUpdate()
  204. {
  205. if (initialized == false || isStartupFrame)
  206. return;
  207. if (SteamVR.settings.IsInputUpdateMode(SteamVR_UpdateModes.OnLateUpdate))
  208. {
  209. UpdateNonVisualActions();
  210. }
  211. if (SteamVR.settings.IsPoseUpdateMode(SteamVR_UpdateModes.OnLateUpdate))
  212. {
  213. //update poses and skeleton
  214. UpdateVisualActions();
  215. }
  216. else
  217. {
  218. //force skeleton update so animation blending sticks
  219. UpdateSkeletonActions(true);
  220. }
  221. }
  222. /// <summary>Gets called by SteamVR_Behaviour every FixedUpdate and updates actions if the steamvr settings are configured to update then.</summary>
  223. public static void FixedUpdate()
  224. {
  225. if (initialized == false || isStartupFrame)
  226. return;
  227. if (SteamVR.settings.IsInputUpdateMode(SteamVR_UpdateModes.OnFixedUpdate))
  228. {
  229. UpdateNonVisualActions();
  230. }
  231. if (SteamVR.settings.IsPoseUpdateMode(SteamVR_UpdateModes.OnFixedUpdate))
  232. {
  233. UpdateVisualActions();
  234. }
  235. }
  236. /// <summary>Gets called by SteamVR_Behaviour every OnPreCull and updates actions if the steamvr settings are configured to update then.</summary>
  237. public static void OnPreCull()
  238. {
  239. if (initialized == false || isStartupFrame)
  240. return;
  241. if (SteamVR.settings.IsInputUpdateMode(SteamVR_UpdateModes.OnPreCull))
  242. {
  243. UpdateNonVisualActions();
  244. }
  245. if (SteamVR.settings.IsPoseUpdateMode(SteamVR_UpdateModes.OnPreCull))
  246. {
  247. UpdateVisualActions();
  248. }
  249. }
  250. /// <summary>
  251. /// Updates the states of all the visual actions (pose / skeleton)
  252. /// </summary>
  253. /// <param name="skipStateAndEventUpdates">Controls whether or not events are fired from this update call</param>
  254. public static void UpdateVisualActions(bool skipStateAndEventUpdates = false)
  255. {
  256. if (initialized == false)
  257. return;
  258. SteamVR_ActionSet_Manager.UpdateActionStates();
  259. UpdatePoseActions(skipStateAndEventUpdates);
  260. UpdateSkeletonActions(skipStateAndEventUpdates);
  261. }
  262. /// <summary>
  263. /// Updates the states of all the pose actions
  264. /// </summary>
  265. /// <param name="skipSendingEvents">Controls whether or not events are fired from this update call</param>
  266. public static void UpdatePoseActions(bool skipSendingEvents = false)
  267. {
  268. if (initialized == false)
  269. return;
  270. for (int actionIndex = 0; actionIndex < actionsPose.Length; actionIndex++)
  271. {
  272. SteamVR_Action_Pose action = actionsPose[actionIndex];
  273. action.UpdateValues(skipSendingEvents);
  274. }
  275. if (onPosesUpdated != null)
  276. onPosesUpdated(false);
  277. }
  278. /// <summary>
  279. /// Updates the states of all the skeleton actions
  280. /// </summary>
  281. /// <param name="skipSendingEvents">Controls whether or not events are fired from this update call</param>
  282. public static void UpdateSkeletonActions(bool skipSendingEvents = false)
  283. {
  284. if (initialized == false)
  285. return;
  286. for (int actionIndex = 0; actionIndex < actionsSkeleton.Length; actionIndex++)
  287. {
  288. SteamVR_Action_Skeleton action = actionsSkeleton[actionIndex];
  289. action.UpdateValue(skipSendingEvents);
  290. }
  291. if (onSkeletonsUpdated != null)
  292. onSkeletonsUpdated(skipSendingEvents);
  293. }
  294. /// <summary>
  295. /// Updates the states of all the non visual actions (boolean, single, vector2, vector3)
  296. /// </summary>
  297. public static void UpdateNonVisualActions()
  298. {
  299. if (initialized == false)
  300. return;
  301. SteamVR_ActionSet_Manager.UpdateActionStates();
  302. for (int actionIndex = 0; actionIndex < actionsNonPoseNonSkeletonIn.Length; actionIndex++)
  303. {
  304. ISteamVR_Action_In action = actionsNonPoseNonSkeletonIn[actionIndex];
  305. action.UpdateValues();
  306. }
  307. if (onNonVisualActionsUpdated != null)
  308. onNonVisualActionsUpdated();
  309. }
  310. #region String accessor helpers
  311. #region action accessors
  312. /// <summary>
  313. /// Get an action's action data by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  314. /// </summary>
  315. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  316. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  317. /// <param name="caseSensitive">case sensitive searches are faster</param>
  318. public static T GetActionDataFromPath<T>(string path, bool caseSensitive = false) where T : SteamVR_Action_Source_Map
  319. {
  320. SteamVR_Action action = GetBaseActionFromPath(path, caseSensitive);
  321. if (action != null)
  322. {
  323. T actionData = (T)action.GetSourceMap();
  324. return actionData;
  325. }
  326. return null;
  327. }
  328. /// <summary>
  329. /// Get an action set's data by the full path to that action. Action set paths are in the format /actions/[actionSet]
  330. /// </summary>
  331. /// <param name="path">The full path to the action you want (Action set paths are in the format /actions/[actionSet])</param>
  332. /// <param name="caseSensitive">case sensitive searches are faster</param>
  333. public static SteamVR_ActionSet_Data GetActionSetDataFromPath(string path, bool caseSensitive = false)
  334. {
  335. SteamVR_ActionSet actionSet = GetActionSetFromPath(path, caseSensitive);
  336. if (actionSet != null)
  337. {
  338. return actionSet.GetActionSetData();
  339. }
  340. return null;
  341. }
  342. /// <summary>
  343. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  344. /// </summary>
  345. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  346. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  347. /// <param name="caseSensitive">case sensitive searches are faster</param>
  348. public static T GetActionFromPath<T>(string path, bool caseSensitive = false, bool returnNulls = false) where T : SteamVR_Action, new()
  349. {
  350. SteamVR_Action foundAction = GetBaseActionFromPath(path, caseSensitive);
  351. if (foundAction != null)
  352. return foundAction.GetCopy<T>();
  353. if (returnNulls)
  354. return null;
  355. return CreateFakeAction<T>(path, caseSensitive);
  356. }
  357. // non-copy version
  358. public static SteamVR_Action GetBaseActionFromPath(string path, bool caseSensitive = false)
  359. {
  360. if (string.IsNullOrEmpty(path))
  361. return null;
  362. if (caseSensitive)
  363. {
  364. if (actionsByPath.ContainsKey(path))
  365. {
  366. return actionsByPath[path];
  367. }
  368. }
  369. else
  370. {
  371. if (actionsByPathCache.ContainsKey(path))
  372. {
  373. return actionsByPathCache[path];
  374. }
  375. else if (actionsByPath.ContainsKey(path))
  376. {
  377. actionsByPathCache.Add(path, actionsByPath[path]);
  378. return actionsByPath[path];
  379. }
  380. else
  381. {
  382. string loweredPath = path.ToLower();
  383. if (actionsByPathLowered.ContainsKey(loweredPath))
  384. {
  385. actionsByPathCache.Add(path, actionsByPathLowered[loweredPath]);
  386. return actionsByPath[loweredPath];
  387. }
  388. else
  389. {
  390. actionsByPathCache.Add(path, null);
  391. }
  392. }
  393. }
  394. return null;
  395. }
  396. public static bool HasActionPath(string path, bool caseSensitive = false)
  397. {
  398. SteamVR_Action action = GetBaseActionFromPath(path, caseSensitive);
  399. return action != null;
  400. }
  401. public static bool HasAction(string actionName, bool caseSensitive = false)
  402. {
  403. SteamVR_Action action = GetBaseAction(null, actionName, caseSensitive);
  404. return action != null;
  405. }
  406. public static bool HasAction(string actionSetName, string actionName, bool caseSensitive = false)
  407. {
  408. SteamVR_Action action = GetBaseAction(actionSetName, actionName, caseSensitive);
  409. return action != null;
  410. }
  411. /// <summary>
  412. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  413. /// </summary>
  414. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  415. /// <param name="caseSensitive">case sensitive searches are faster</param>
  416. public static SteamVR_Action_Boolean GetBooleanActionFromPath(string path, bool caseSensitive = false)
  417. {
  418. return GetActionFromPath<SteamVR_Action_Boolean>(path, caseSensitive);
  419. }
  420. /// <summary>
  421. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  422. /// </summary>
  423. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  424. /// <param name="caseSensitive">case sensitive searches are faster</param>
  425. public static SteamVR_Action_Single GetSingleActionFromPath(string path, bool caseSensitive = false)
  426. {
  427. return GetActionFromPath<SteamVR_Action_Single>(path, caseSensitive);
  428. }
  429. /// <summary>
  430. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  431. /// </summary>
  432. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  433. /// <param name="caseSensitive">case sensitive searches are faster</param>
  434. public static SteamVR_Action_Vector2 GetVector2ActionFromPath(string path, bool caseSensitive = false)
  435. {
  436. return GetActionFromPath<SteamVR_Action_Vector2>(path, caseSensitive);
  437. }
  438. /// <summary>
  439. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  440. /// </summary>
  441. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  442. /// <param name="caseSensitive">case sensitive searches are faster</param>
  443. public static SteamVR_Action_Vector3 GetVector3ActionFromPath(string path, bool caseSensitive = false)
  444. {
  445. return GetActionFromPath<SteamVR_Action_Vector3>(path, caseSensitive);
  446. }
  447. /// <summary>
  448. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  449. /// </summary>
  450. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  451. /// <param name="caseSensitive">case sensitive searches are faster</param>
  452. public static SteamVR_Action_Vibration GetVibrationActionFromPath(string path, bool caseSensitive = false)
  453. {
  454. return GetActionFromPath<SteamVR_Action_Vibration>(path, caseSensitive);
  455. }
  456. /// <summary>
  457. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  458. /// </summary>
  459. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  460. /// <param name="caseSensitive">case sensitive searches are faster</param>
  461. public static SteamVR_Action_Pose GetPoseActionFromPath(string path, bool caseSensitive = false)
  462. {
  463. return GetActionFromPath<SteamVR_Action_Pose>(path, caseSensitive);
  464. }
  465. /// <summary>
  466. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  467. /// </summary>
  468. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  469. /// <param name="caseSensitive">case sensitive searches are faster</param>
  470. public static SteamVR_Action_Skeleton GetSkeletonActionFromPath(string path, bool caseSensitive = false)
  471. {
  472. return GetActionFromPath<SteamVR_Action_Skeleton>(path, caseSensitive);
  473. }
  474. /// <summary>
  475. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  476. /// </summary>
  477. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  478. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  479. /// <param name="caseSensitive">case sensitive searches are faster</param>
  480. /// <param name="returnNulls">returns null if the action does not exist</param>
  481. public static T GetAction<T>(string actionSetName, string actionName, bool caseSensitive = false, bool returnNulls = false) where T : SteamVR_Action, new()
  482. {
  483. SteamVR_Action action = GetBaseAction(actionSetName, actionName, caseSensitive);
  484. if (action != null)
  485. return (T)action.GetCopy<T>();
  486. if (returnNulls)
  487. return null;
  488. return CreateFakeAction<T>(actionSetName, actionName, caseSensitive);
  489. }
  490. public static SteamVR_Action GetBaseAction(string actionSetName, string actionName, bool caseSensitive = false)
  491. {
  492. if (actions == null)
  493. {
  494. return null;
  495. }
  496. if (string.IsNullOrEmpty(actionSetName))
  497. {
  498. for (int actionIndex = 0; actionIndex < actions.Length; actionIndex++)
  499. {
  500. if (caseSensitive)
  501. {
  502. if (actions[actionIndex].GetShortName() == actionName)
  503. return actions[actionIndex];
  504. }
  505. else
  506. {
  507. if (string.Equals(actions[actionIndex].GetShortName(), actionName, StringComparison.CurrentCultureIgnoreCase))
  508. return actions[actionIndex];
  509. }
  510. }
  511. }
  512. else
  513. {
  514. SteamVR_ActionSet actionSet = GetActionSet(actionSetName, caseSensitive, true);
  515. if (actionSet != null)
  516. {
  517. for (int actionIndex = 0; actionIndex < actionSet.allActions.Length; actionIndex++)
  518. {
  519. if (caseSensitive)
  520. {
  521. if (actionSet.allActions[actionIndex].GetShortName() == actionName)
  522. return actionSet.allActions[actionIndex];
  523. }
  524. else
  525. {
  526. if (string.Equals(actionSet.allActions[actionIndex].GetShortName(), actionName, StringComparison.CurrentCultureIgnoreCase))
  527. return actionSet.allActions[actionIndex];
  528. }
  529. }
  530. }
  531. }
  532. return null;
  533. }
  534. private static T CreateFakeAction<T>(string actionSetName, string actionName, bool caseSensitive) where T : SteamVR_Action, new()
  535. {
  536. if (typeof(T) == typeof(SteamVR_Action_Vibration))
  537. {
  538. return SteamVR_Action.CreateUninitialized<T>(actionSetName, SteamVR_ActionDirections.Out, actionName, caseSensitive);
  539. }
  540. else
  541. {
  542. return SteamVR_Action.CreateUninitialized<T>(actionSetName, SteamVR_ActionDirections.In, actionName, caseSensitive);
  543. }
  544. }
  545. private static T CreateFakeAction<T>(string actionPath, bool caseSensitive) where T : SteamVR_Action, new()
  546. {
  547. return SteamVR_Action.CreateUninitialized<T>(actionPath, caseSensitive);
  548. }
  549. /// <summary>
  550. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  551. /// </summary>
  552. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  553. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  554. /// <param name="caseSensitive">case sensitive searches are faster</param>
  555. public static T GetAction<T>(string actionName, bool caseSensitive = false) where T : SteamVR_Action, new()
  556. {
  557. return GetAction<T>(null, actionName, caseSensitive);
  558. }
  559. /// <summary>
  560. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  561. /// </summary>
  562. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  563. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  564. /// <param name="caseSensitive">case sensitive searches are faster</param>
  565. public static SteamVR_Action_Boolean GetBooleanAction(string actionSetName, string actionName, bool caseSensitive = false)
  566. {
  567. return GetAction<SteamVR_Action_Boolean>(actionSetName, actionName, caseSensitive);
  568. }
  569. /// <summary>
  570. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  571. /// </summary>
  572. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  573. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  574. /// <param name="caseSensitive">case sensitive searches are faster</param>
  575. public static SteamVR_Action_Boolean GetBooleanAction(string actionName, bool caseSensitive = false)
  576. {
  577. return GetAction<SteamVR_Action_Boolean>(null, actionName, caseSensitive);
  578. }
  579. /// <summary>
  580. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  581. /// </summary>
  582. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  583. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  584. /// <param name="caseSensitive">case sensitive searches are faster</param>
  585. public static SteamVR_Action_Single GetSingleAction(string actionSetName, string actionName, bool caseSensitive = false)
  586. {
  587. return GetAction<SteamVR_Action_Single>(actionSetName, actionName, caseSensitive);
  588. }
  589. /// <summary>
  590. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  591. /// </summary>
  592. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  593. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  594. /// <param name="caseSensitive">case sensitive searches are faster</param>
  595. public static SteamVR_Action_Single GetSingleAction(string actionName, bool caseSensitive = false)
  596. {
  597. return GetAction<SteamVR_Action_Single>(null, actionName, caseSensitive);
  598. }
  599. /// <summary>
  600. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  601. /// </summary>
  602. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  603. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  604. /// <param name="caseSensitive">case sensitive searches are faster</param>
  605. public static SteamVR_Action_Vector2 GetVector2Action(string actionSetName, string actionName, bool caseSensitive = false)
  606. {
  607. return GetAction<SteamVR_Action_Vector2>(actionSetName, actionName, caseSensitive);
  608. }
  609. /// <summary>
  610. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  611. /// </summary>
  612. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  613. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  614. /// <param name="caseSensitive">case sensitive searches are faster</param>
  615. public static SteamVR_Action_Vector2 GetVector2Action(string actionName, bool caseSensitive = false)
  616. {
  617. return GetAction<SteamVR_Action_Vector2>(null, actionName, caseSensitive);
  618. }
  619. /// <summary>
  620. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  621. /// </summary>
  622. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  623. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  624. /// <param name="caseSensitive">case sensitive searches are faster</param>
  625. public static SteamVR_Action_Vector3 GetVector3Action(string actionSetName, string actionName, bool caseSensitive = false)
  626. {
  627. return GetAction<SteamVR_Action_Vector3>(actionSetName, actionName, caseSensitive);
  628. }
  629. /// <summary>
  630. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  631. /// </summary>
  632. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  633. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  634. /// <param name="caseSensitive">case sensitive searches are faster</param>
  635. public static SteamVR_Action_Vector3 GetVector3Action(string actionName, bool caseSensitive = false)
  636. {
  637. return GetAction<SteamVR_Action_Vector3>(null, actionName, caseSensitive);
  638. }
  639. /// <summary>
  640. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  641. /// </summary>
  642. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  643. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  644. /// <param name="caseSensitive">case sensitive searches are faster</param>
  645. public static SteamVR_Action_Pose GetPoseAction(string actionSetName, string actionName, bool caseSensitive = false)
  646. {
  647. return GetAction<SteamVR_Action_Pose>(actionSetName, actionName, caseSensitive);
  648. }
  649. /// <summary>
  650. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  651. /// </summary>
  652. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  653. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  654. /// <param name="caseSensitive">case sensitive searches are faster</param>
  655. public static SteamVR_Action_Pose GetPoseAction(string actionName, bool caseSensitive = false)
  656. {
  657. return GetAction<SteamVR_Action_Pose>(null, actionName, caseSensitive);
  658. }
  659. /// <summary>
  660. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  661. /// </summary>
  662. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  663. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  664. /// <param name="caseSensitive">case sensitive searches are faster</param>
  665. public static SteamVR_Action_Skeleton GetSkeletonAction(string actionSetName, string actionName, bool caseSensitive = false)
  666. {
  667. return GetAction<SteamVR_Action_Skeleton>(actionSetName, actionName, caseSensitive);
  668. }
  669. /// <summary>
  670. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  671. /// </summary>
  672. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  673. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  674. /// <param name="caseSensitive">case sensitive searches are faster</param>
  675. public static SteamVR_Action_Skeleton GetSkeletonAction(string actionName, bool caseSensitive = false)
  676. {
  677. return GetAction<SteamVR_Action_Skeleton>(null, actionName, caseSensitive);
  678. }
  679. /// <summary>
  680. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  681. /// </summary>
  682. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  683. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  684. /// <param name="caseSensitive">case sensitive searches are faster</param>
  685. public static SteamVR_Action_Vibration GetVibrationAction(string actionSetName, string actionName, bool caseSensitive = false)
  686. {
  687. return GetAction<SteamVR_Action_Vibration>(actionSetName, actionName, caseSensitive);
  688. }
  689. /// <summary>
  690. /// Get an action by the full path to that action. Action paths are in the format /actions/[actionSet]/[direction]/[actionName]
  691. /// </summary>
  692. /// <typeparam name="T">The type of action you're expecting to get back</typeparam>
  693. /// <param name="path">The full path to the action you want (Action paths are in the format /actions/[actionSet]/[direction]/[actionName])</param>
  694. /// <param name="caseSensitive">case sensitive searches are faster</param>
  695. public static SteamVR_Action_Vibration GetVibrationAction(string actionName, bool caseSensitive = false)
  696. {
  697. return GetAction<SteamVR_Action_Vibration>(null, actionName, caseSensitive);
  698. }
  699. /// <summary>
  700. /// Get an action set by the full path to that action set. Action set paths are in the format /actions/[actionSet]
  701. /// </summary>
  702. /// <typeparam name="T">The type of action set you're expecting to get back</typeparam>
  703. /// <param name="actionSetName">The name to the action set you want</param>
  704. /// <param name="caseSensitive">case sensitive searches are faster</param>
  705. /// <param name="returnNulls">returns a null if the set does not exist</param>
  706. public static T GetActionSet<T>(string actionSetName, bool caseSensitive = false, bool returnNulls = false) where T : SteamVR_ActionSet, new()
  707. {
  708. if (actionSets == null)
  709. {
  710. if (returnNulls)
  711. return null;
  712. return SteamVR_ActionSet.CreateFromName<T>(actionSetName);
  713. }
  714. for (int actionSetIndex = 0; actionSetIndex < actionSets.Length; actionSetIndex++)
  715. {
  716. if (caseSensitive)
  717. {
  718. if (actionSets[actionSetIndex].GetShortName() == actionSetName)
  719. return actionSets[actionSetIndex].GetCopy<T>();
  720. }
  721. else
  722. {
  723. if (string.Equals(actionSets[actionSetIndex].GetShortName(), actionSetName, StringComparison.CurrentCultureIgnoreCase))
  724. return actionSets[actionSetIndex].GetCopy<T>();
  725. }
  726. }
  727. if (returnNulls)
  728. return null;
  729. return SteamVR_ActionSet.CreateFromName<T>(actionSetName);
  730. }
  731. /// <summary>
  732. /// Get an action set by the full path to that action set. Action set paths are in the format /actions/[actionSet]
  733. /// </summary>
  734. /// <typeparam name="T">The type of action set you're expecting to get back</typeparam>
  735. /// <param name="actionSetName">The name to the action set you want</param>
  736. /// <param name="caseSensitive">case sensitive searches are faster</param>
  737. public static SteamVR_ActionSet GetActionSet(string actionSetName, bool caseSensitive = false, bool returnsNulls = false)
  738. {
  739. return GetActionSet<SteamVR_ActionSet>(actionSetName, caseSensitive, returnsNulls);
  740. }
  741. protected static bool HasActionSet(string name, bool caseSensitive = false)
  742. {
  743. SteamVR_ActionSet actionSet = GetActionSet(name, caseSensitive, true);
  744. return actionSet != null;
  745. }
  746. /// <summary>
  747. /// Get an action set by the full path to that action set. Action set paths are in the format /actions/[actionSet]
  748. /// </summary>
  749. /// <typeparam name="T">The type of action set you're expecting to get back</typeparam>
  750. /// <param name="path">The full path to the action set you want (Action paths are in the format /actions/[actionSet])</param>
  751. /// <param name="caseSensitive">case sensitive searches are faster</param>
  752. public static T GetActionSetFromPath<T>(string path, bool caseSensitive = false, bool returnsNulls = false) where T : SteamVR_ActionSet, new()
  753. {
  754. if (actionSets == null || actionSets[0] == null || string.IsNullOrEmpty(path))
  755. {
  756. if (returnsNulls)
  757. return null;
  758. return SteamVR_ActionSet.Create<T>(path);
  759. }
  760. if (caseSensitive)
  761. {
  762. if (actionSetsByPath.ContainsKey(path))
  763. {
  764. return actionSetsByPath[path].GetCopy<T>();
  765. }
  766. }
  767. else
  768. {
  769. if (actionSetsByPathCache.ContainsKey(path))
  770. {
  771. SteamVR_ActionSet set = actionSetsByPathCache[path];
  772. if (set == null)
  773. return null;
  774. else
  775. return set.GetCopy<T>();
  776. }
  777. else if (actionSetsByPath.ContainsKey(path))
  778. {
  779. actionSetsByPathCache.Add(path, actionSetsByPath[path]);
  780. return actionSetsByPath[path].GetCopy<T>();
  781. }
  782. else
  783. {
  784. string loweredPath = path.ToLower();
  785. if (actionSetsByPathLowered.ContainsKey(loweredPath))
  786. {
  787. actionSetsByPathCache.Add(path, actionSetsByPathLowered[loweredPath]);
  788. return actionSetsByPath[loweredPath].GetCopy<T>();
  789. }
  790. else
  791. {
  792. actionSetsByPathCache.Add(path, null);
  793. }
  794. }
  795. }
  796. if (returnsNulls)
  797. return null;
  798. return SteamVR_ActionSet.Create<T>(path);
  799. }
  800. /// <summary>
  801. /// Get an action set by the full path to that action set. Action set paths are in the format /actions/[actionSet]
  802. /// </summary>
  803. /// <param name="path">The full path to the action set you want (Action paths are in the format /actions/[actionSet])</param>
  804. /// <param name="caseSensitive">case sensitive searches are faster</param>
  805. public static SteamVR_ActionSet GetActionSetFromPath(string path, bool caseSensitive = false)
  806. {
  807. return GetActionSetFromPath<SteamVR_ActionSet>(path, caseSensitive);
  808. }
  809. #endregion
  810. #region digital string accessors
  811. /// <summary>
  812. /// Get the state of an action by the action set name, action name, and input source. Optionally case sensitive (for faster results)
  813. /// </summary>
  814. /// <param name="actionSet">The name of the action set the action is contained in</param>
  815. /// <param name="action">The name of the action to get the state of</param>
  816. /// <param name="inputSource">The input source to get the action state from</param>
  817. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  818. public static bool GetState(string actionSet, string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  819. {
  820. SteamVR_Action_Boolean booleanAction = GetAction<SteamVR_Action_Boolean>(actionSet, action, caseSensitive);
  821. if (booleanAction != null)
  822. {
  823. return booleanAction.GetState(inputSource);
  824. }
  825. return false;
  826. }
  827. /// <summary>
  828. /// Get the state of an action by the action name and input source. Optionally case sensitive (for faster results)
  829. /// </summary>
  830. /// <param name="action">The name of the action to get the state of</param>
  831. /// <param name="inputSource">The input source to get the action state from</param>
  832. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  833. public static bool GetState(string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  834. {
  835. return GetState(null, action, inputSource, caseSensitive);
  836. }
  837. /// <summary>
  838. /// Get the state down of an action by the action set name, action name, and input source. Optionally case sensitive (for faster results)
  839. /// </summary>
  840. /// <param name="actionSet">The name of the action set the action is contained in</param>
  841. /// <param name="action">The name of the action to get the state of</param>
  842. /// <param name="inputSource">The input source to get the action state from</param>
  843. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  844. /// <returns>True when the action was false last update and is now true. Returns false again afterwards.</returns>
  845. public static bool GetStateDown(string actionSet, string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  846. {
  847. SteamVR_Action_Boolean booleanAction = GetAction<SteamVR_Action_Boolean>(actionSet, action, caseSensitive);
  848. if (booleanAction != null)
  849. {
  850. return booleanAction.GetStateDown(inputSource);
  851. }
  852. return false;
  853. }
  854. /// <summary>
  855. /// Get the state down of an action by the action name and input source. Optionally case sensitive (for faster results)
  856. /// </summary>
  857. /// <param name="action">The name of the action to get the state of</param>
  858. /// <param name="inputSource">The input source to get the action state from</param>
  859. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  860. /// <returns>True when the action was false last update and is now true. Returns false again afterwards.</returns>
  861. public static bool GetStateDown(string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  862. {
  863. return GetStateDown(null, action, inputSource, caseSensitive);
  864. }
  865. /// <summary>
  866. /// Get the state up of an action by the action set name, action name, and input source. Optionally case sensitive (for faster results)
  867. /// </summary>
  868. /// <param name="actionSet">The name of the action set the action is contained in</param>
  869. /// <param name="action">The name of the action to get the state of</param>
  870. /// <param name="inputSource">The input source to get the action state from</param>
  871. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  872. /// <returns>True when the action was true last update and is now false. Returns false again afterwards.</returns>
  873. public static bool GetStateUp(string actionSet, string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  874. {
  875. SteamVR_Action_Boolean booleanAction = GetAction<SteamVR_Action_Boolean>(actionSet, action, caseSensitive);
  876. if (booleanAction != null)
  877. {
  878. return booleanAction.GetStateUp(inputSource);
  879. }
  880. return false;
  881. }
  882. /// <summary>
  883. /// Get the state up of an action by the action name and input source. Optionally case sensitive (for faster results)
  884. /// </summary>
  885. /// <param name="action">The name of the action to get the state of</param>
  886. /// <param name="inputSource">The input source to get the action state from</param>
  887. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  888. /// <returns>True when the action was true last update and is now false. Returns false again afterwards.</returns>
  889. public static bool GetStateUp(string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  890. {
  891. return GetStateDown(null, action, inputSource, caseSensitive);
  892. }
  893. #endregion
  894. #region analog string accessors
  895. /// <summary>
  896. /// Get the float value of an action by the action set name, action name, and input source. Optionally case sensitive (for faster results). (same as GetSingle)
  897. /// </summary>
  898. /// <param name="actionSet">The name of the action set the action is contained in</param>
  899. /// <param name="action">The name of the action to get the state of</param>
  900. /// <param name="inputSource">The input source to get the action state from</param>
  901. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  902. public static float GetFloat(string actionSet, string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  903. {
  904. SteamVR_Action_Single singleAction = GetAction<SteamVR_Action_Single>(actionSet, action, caseSensitive);
  905. if (singleAction != null)
  906. {
  907. return singleAction.GetAxis(inputSource);
  908. }
  909. return 0;
  910. }
  911. /// <summary>
  912. /// Get the float value of an action by the action name and input source. Optionally case sensitive (for faster results). (same as GetSingle)
  913. /// </summary>
  914. /// <param name="action">The name of the action to get the state of</param>
  915. /// <param name="inputSource">The input source to get the action state from</param>
  916. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  917. public static float GetFloat(string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  918. {
  919. return GetFloat(null, action, inputSource, caseSensitive);
  920. }
  921. /// <summary>
  922. /// Get the float value of an action by the action set name, action name, and input source. Optionally case sensitive (for faster results). (same as GetFloat)
  923. /// </summary>
  924. /// <param name="actionSet">The name of the action set the action is contained in</param>
  925. /// <param name="action">The name of the action to get the state of</param>
  926. /// <param name="inputSource">The input source to get the action state from</param>
  927. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  928. public static float GetSingle(string actionSet, string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  929. {
  930. SteamVR_Action_Single singleAction = GetAction<SteamVR_Action_Single>(actionSet, action, caseSensitive);
  931. if (singleAction != null)
  932. {
  933. return singleAction.GetAxis(inputSource);
  934. }
  935. return 0;
  936. }
  937. /// <summary>
  938. /// Get the float value of an action by the action name and input source. Optionally case sensitive (for faster results). (same as GetFloat)
  939. /// </summary>
  940. /// <param name="action">The name of the action to get the state of</param>
  941. /// <param name="inputSource">The input source to get the action state from</param>
  942. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  943. public static float GetSingle(string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  944. {
  945. return GetFloat(null, action, inputSource, caseSensitive);
  946. }
  947. /// <summary>
  948. /// Get the Vector2 value of an action by the action set name, action name, and input source. Optionally case sensitive (for faster results)
  949. /// </summary>
  950. /// <param name="actionSet">The name of the action set the action is contained in</param>
  951. /// <param name="action">The name of the action to get the state of</param>
  952. /// <param name="inputSource">The input source to get the action state from</param>
  953. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  954. public static Vector2 GetVector2(string actionSet, string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  955. {
  956. SteamVR_Action_Vector2 vectorAction = GetAction<SteamVR_Action_Vector2>(actionSet, action, caseSensitive);
  957. if (vectorAction != null)
  958. {
  959. return vectorAction.GetAxis(inputSource);
  960. }
  961. return Vector2.zero;
  962. }
  963. /// <summary>
  964. /// Get the Vector2 value of an action by the action name and input source. Optionally case sensitive (for faster results)
  965. /// </summary>
  966. /// <param name="action">The name of the action to get the state of</param>
  967. /// <param name="inputSource">The input source to get the action state from</param>
  968. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  969. public static Vector2 GetVector2(string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  970. {
  971. return GetVector2(null, action, inputSource, caseSensitive);
  972. }
  973. /// <summary>
  974. /// Get the Vector3 value of an action by the action set name, action name, and input source. Optionally case sensitive (for faster results)
  975. /// </summary>
  976. /// <param name="actionSet">The name of the action set the action is contained in</param>
  977. /// <param name="action">The name of the action to get the state of</param>
  978. /// <param name="inputSource">The input source to get the action state from</param>
  979. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  980. public static Vector3 GetVector3(string actionSet, string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  981. {
  982. SteamVR_Action_Vector3 vectorAction = GetAction<SteamVR_Action_Vector3>(actionSet, action, caseSensitive);
  983. if (vectorAction != null)
  984. {
  985. return vectorAction.GetAxis(inputSource);
  986. }
  987. return Vector3.zero;
  988. }
  989. /// <summary>
  990. /// Get the Vector3 value of an action by the action name and input source. Optionally case sensitive (for faster results)
  991. /// </summary>
  992. /// <param name="action">The name of the action to get the state of</param>
  993. /// <param name="inputSource">The input source to get the action state from</param>
  994. /// <param name="caseSensitive">Whether or not the action set and action name searches should be case sensitive (case sensitive searches are faster)</param>
  995. public static Vector3 GetVector3(string action, SteamVR_Input_Sources inputSource, bool caseSensitive = false)
  996. {
  997. return GetVector3(null, action, inputSource, caseSensitive);
  998. }
  999. #endregion
  1000. #endregion
  1001. /// <summary>
  1002. /// Returns all of the action sets. If we're in the editor, doesn't rely on the actionSets field being filled.
  1003. /// </summary>
  1004. public static SteamVR_ActionSet[] GetActionSets()
  1005. {
  1006. return actionSets;
  1007. }
  1008. /// <summary>
  1009. /// Returns all of the actions of the specified type. If we're in the editor, doesn't rely on the arrays being filled.
  1010. /// </summary>
  1011. /// <typeparam name="T">The type of actions you want to get</typeparam>
  1012. public static T[] GetActions<T>() where T : SteamVR_Action
  1013. {
  1014. Type type = typeof(T);
  1015. if (type == typeof(SteamVR_Action))
  1016. {
  1017. return actions as T[];
  1018. }
  1019. else if (type == typeof(ISteamVR_Action_In))
  1020. {
  1021. return actionsIn as T[];
  1022. }
  1023. else if (type == typeof(ISteamVR_Action_Out))
  1024. {
  1025. return actionsOut as T[];
  1026. }
  1027. else if (type == typeof(SteamVR_Action_Boolean))
  1028. {
  1029. return actionsBoolean as T[];
  1030. }
  1031. else if (type == typeof(SteamVR_Action_Single))
  1032. {
  1033. return actionsSingle as T[];
  1034. }
  1035. else if (type == typeof(SteamVR_Action_Vector2))
  1036. {
  1037. return actionsVector2 as T[];
  1038. }
  1039. else if (type == typeof(SteamVR_Action_Vector3))
  1040. {
  1041. return actionsVector3 as T[];
  1042. }
  1043. else if (type == typeof(SteamVR_Action_Pose))
  1044. {
  1045. return actionsPose as T[];
  1046. }
  1047. else if (type == typeof(SteamVR_Action_Skeleton))
  1048. {
  1049. return actionsSkeleton as T[];
  1050. }
  1051. else if (type == typeof(SteamVR_Action_Vibration))
  1052. {
  1053. return actionsVibration as T[];
  1054. }
  1055. else
  1056. {
  1057. Debug.Log("<b>[SteamVR]</b> Wrong type.");
  1058. }
  1059. return null;
  1060. }
  1061. /// <summary>
  1062. /// Gets the localized name of the device that the action corresponds to.
  1063. /// </summary>
  1064. /// <param name="inputSource"></param>
  1065. /// <param name="localizedParts">
  1066. /// <list type="bullet">
  1067. /// <item><description>VRInputString_Hand - Which hand the origin is in. E.g. "Left Hand"</description></item>
  1068. /// <item><description>VRInputString_ControllerType - What kind of controller the user has in that hand.E.g. "Vive Controller"</description></item>
  1069. /// <item><description>VRInputString_InputSource - What part of that controller is the origin. E.g. "Trackpad"</description></item>
  1070. /// <item><description>VRInputString_All - All of the above. E.g. "Left Hand Vive Controller Trackpad"</description></item>
  1071. /// </list>
  1072. /// </param>
  1073. public static string GetLocalizedName(ulong originHandle, params EVRInputStringBits[] localizedParts)
  1074. {
  1075. int localizedPartsMask = 0;
  1076. for (int partIndex = 0; partIndex < localizedParts.Length; partIndex++)
  1077. localizedPartsMask |= (int)localizedParts[partIndex];
  1078. StringBuilder stringBuilder = new StringBuilder(500);
  1079. OpenVR.Input.GetOriginLocalizedName(originHandle, stringBuilder, 500, localizedPartsMask);
  1080. return stringBuilder.ToString();
  1081. }
  1082. /// <summary>Tell SteamVR that we're using the actions file at the path defined in SteamVR_Settings.</summary>
  1083. public static void IdentifyActionsFile(bool showLogs = true)
  1084. {
  1085. string currentPath = Application.dataPath;
  1086. int lastIndex = currentPath.LastIndexOf('/');
  1087. currentPath = currentPath.Remove(lastIndex, currentPath.Length - lastIndex);
  1088. string fullPath = System.IO.Path.Combine(currentPath, SteamVR_Settings.instance.actionsFilePath);
  1089. fullPath = fullPath.Replace("\\", "/");
  1090. if (File.Exists(fullPath))
  1091. {
  1092. EVRInputError err = OpenVR.Input.SetActionManifestPath(fullPath);
  1093. if (err != EVRInputError.None)
  1094. Debug.LogError("<b>[SteamVR]</b> Error loading action manifest into SteamVR: " + err.ToString());
  1095. else
  1096. {
  1097. int numActions = 0;
  1098. if (SteamVR_Input.actions != null)
  1099. {
  1100. numActions = SteamVR_Input.actions.Length;
  1101. if (showLogs)
  1102. Debug.Log(string.Format("<b>[SteamVR]</b> Successfully loaded {0} actions from action manifest into SteamVR ({1})", numActions, fullPath));
  1103. }
  1104. else
  1105. {
  1106. if (showLogs)
  1107. Debug.LogWarning("<b>[SteamVR]</b> No actions found, but the action manifest was loaded. This usually means you haven't generated actions. Window -> SteamVR Input -> Save and Generate.");
  1108. }
  1109. }
  1110. }
  1111. else
  1112. {
  1113. if (showLogs)
  1114. Debug.LogError("<b>[SteamVR]</b> Could not find actions file at: " + fullPath);
  1115. }
  1116. }
  1117. /// <summary>
  1118. /// Does the actions file in memory differ from the one on disk as determined by a md5 hash
  1119. /// </summary>
  1120. public static bool HasFileInMemoryBeenModified()
  1121. {
  1122. string projectPath = Application.dataPath;
  1123. int lastIndex = projectPath.LastIndexOf("/");
  1124. projectPath = projectPath.Remove(lastIndex, projectPath.Length - lastIndex);
  1125. actionsFilePath = Path.Combine(projectPath, SteamVR_Settings.instance.actionsFilePath);
  1126. string jsonText = null;
  1127. if (File.Exists(actionsFilePath))
  1128. {
  1129. jsonText = System.IO.File.ReadAllText(actionsFilePath);
  1130. }
  1131. else
  1132. {
  1133. return true;
  1134. }
  1135. string newHashFromFile = SteamVR_Utils.GetBadMD5Hash(jsonText);
  1136. string newJSON = JsonConvert.SerializeObject(SteamVR_Input.actionFile, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
  1137. string newHashFromMemory = SteamVR_Utils.GetBadMD5Hash(newJSON);
  1138. return newHashFromFile != newHashFromMemory;
  1139. }
  1140. public static bool CreateEmptyActionsFile(bool completelyEmpty = false)
  1141. {
  1142. string projectPath = Application.dataPath;
  1143. int lastIndex = projectPath.LastIndexOf("/");
  1144. projectPath = projectPath.Remove(lastIndex, projectPath.Length - lastIndex);
  1145. actionsFilePath = Path.Combine(projectPath, SteamVR_Settings.instance.actionsFilePath);
  1146. if (File.Exists(actionsFilePath))
  1147. {
  1148. Debug.LogErrorFormat("<b>[SteamVR]</b> Actions file already exists in project root: {0}", actionsFilePath);
  1149. return false;
  1150. }
  1151. actionFile = new SteamVR_Input_ActionFile();
  1152. if (completelyEmpty == false)
  1153. {
  1154. actionFile.action_sets.Add(SteamVR_Input_ActionFile_ActionSet.CreateNew());
  1155. actionFile.actions.Add(SteamVR_Input_ActionFile_Action.CreateNew(actionFile.action_sets[0].shortName,
  1156. SteamVR_ActionDirections.In, SteamVR_Input_ActionFile_ActionTypes.boolean));
  1157. }
  1158. string newJSON = JsonConvert.SerializeObject(actionFile, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
  1159. File.WriteAllText(actionsFilePath, newJSON);
  1160. actionFile.InitializeHelperLists();
  1161. fileInitialized = true;
  1162. return true;
  1163. }
  1164. public static bool DoesActionsFileExist()
  1165. {
  1166. string projectPath = Application.dataPath;
  1167. int lastIndex = projectPath.LastIndexOf("/");
  1168. projectPath = projectPath.Remove(lastIndex, projectPath.Length - lastIndex);
  1169. actionsFilePath = Path.Combine(projectPath, SteamVR_Settings.instance.actionsFilePath);
  1170. return File.Exists(actionsFilePath);
  1171. }
  1172. /// <summary>
  1173. /// Load from disk and deserialize the actions file
  1174. /// </summary>
  1175. /// <param name="force">Force a refresh of this file from disk</param>
  1176. public static bool InitializeFile(bool force = false, bool showErrors = true)
  1177. {
  1178. bool actionsFileExists = DoesActionsFileExist();
  1179. string jsonText = null;
  1180. if (actionsFileExists)
  1181. {
  1182. jsonText = System.IO.File.ReadAllText(actionsFilePath);
  1183. }
  1184. else
  1185. {
  1186. if (showErrors)
  1187. Debug.LogErrorFormat("<b>[SteamVR]</b> Actions file does not exist in project root: {0}", actionsFilePath);
  1188. return false;
  1189. }
  1190. if (fileInitialized == true || (fileInitialized == true && force == false))
  1191. {
  1192. string newHash = SteamVR_Utils.GetBadMD5Hash(jsonText);
  1193. if (newHash == actionFileHash)
  1194. {
  1195. return true;
  1196. }
  1197. actionFileHash = newHash;
  1198. }
  1199. actionFile = Valve.Newtonsoft.Json.JsonConvert.DeserializeObject<SteamVR_Input_ActionFile>(jsonText);
  1200. actionFile.InitializeHelperLists();
  1201. fileInitialized = true;
  1202. return true;
  1203. }
  1204. /// <summary>
  1205. /// Deletes the action manifest file and all the default bindings it had listed in the default bindings section
  1206. /// </summary>
  1207. /// <returns>True if we deleted an action file, false if not.</returns>
  1208. public static bool DeleteManifestAndBindings()
  1209. {
  1210. if (DoesActionsFileExist() == false)
  1211. return false;
  1212. InitializeFile();
  1213. string[] filesToDelete = actionFile.GetFilesToCopy();
  1214. foreach (string bindingFilePath in filesToDelete)
  1215. {
  1216. FileInfo bindingFileInfo = new FileInfo(bindingFilePath);
  1217. bindingFileInfo.IsReadOnly = false;
  1218. File.Delete(bindingFilePath);
  1219. }
  1220. if (File.Exists(actionsFilePath))
  1221. {
  1222. FileInfo actionFileInfo = new FileInfo(actionsFilePath);
  1223. actionFileInfo.IsReadOnly = false;
  1224. File.Delete(actionsFilePath);
  1225. actionFile = null;
  1226. fileInitialized = false;
  1227. return true;
  1228. }
  1229. return false;
  1230. }
  1231. #if UNITY_EDITOR
  1232. public static string GetResourcesFolderPath(bool fromAssetsDirectory = false)
  1233. {
  1234. string inputFolder = string.Format("Assets/{0}", SteamVR_Settings.instance.steamVRInputPath);
  1235. string path = Path.Combine(inputFolder, "Resources");
  1236. bool createdDirectory = false;
  1237. if (Directory.Exists(inputFolder) == false)
  1238. {
  1239. Directory.CreateDirectory(inputFolder);
  1240. createdDirectory = true;
  1241. }
  1242. if (Directory.Exists(path) == false)
  1243. {
  1244. Directory.CreateDirectory(path);
  1245. createdDirectory = true;
  1246. }
  1247. if (createdDirectory)
  1248. UnityEditor.AssetDatabase.Refresh();
  1249. if (fromAssetsDirectory == false)
  1250. return path.Replace("Assets/", "");
  1251. else
  1252. return path;
  1253. }
  1254. private static bool checkingSetup = false;
  1255. private static bool openingSetup = false;
  1256. public static bool IsOpeningSetup() { return openingSetup; }
  1257. private static void CheckSetup()
  1258. {
  1259. if (checkingSetup == false && openingSetup == false && (SteamVR_Input.actions == null || SteamVR_Input.actions.Length == 0))
  1260. {
  1261. checkingSetup = true;
  1262. Debug.Break();
  1263. bool open = UnityEditor.EditorUtility.DisplayDialog("[SteamVR]", "It looks like you haven't generated actions for SteamVR Input yet. Would you like to open the SteamVR Input window?", "Yes", "No");
  1264. if (open)
  1265. {
  1266. openingSetup = true;
  1267. UnityEditor.EditorApplication.isPlaying = false;
  1268. Type editorWindowType = FindType("Valve.VR.SteamVR_Input_EditorWindow");
  1269. if (editorWindowType != null)
  1270. {
  1271. var window = UnityEditor.EditorWindow.GetWindow(editorWindowType, false, "SteamVR Input", true);
  1272. if (window != null)
  1273. window.Show();
  1274. }
  1275. }
  1276. else
  1277. {
  1278. Debug.LogError("<b>[SteamVR]</b> This version of SteamVR will not work if you do not create and generate actions. Please open the SteamVR Input window or downgrade to version 1.2.3 (on github)");
  1279. }
  1280. checkingSetup = false;
  1281. }
  1282. }
  1283. private static Type FindType(string typeName)
  1284. {
  1285. var type = Type.GetType(typeName);
  1286. if (type != null) return type;
  1287. foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
  1288. {
  1289. type = a.GetType(typeName);
  1290. if (type != null)
  1291. return type;
  1292. }
  1293. return null;
  1294. }
  1295. #endif
  1296. }
  1297. }