SteamVR_Input.cs 76 KB

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