SteamVR_ActionSet.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. using UnityEngine;
  3. using System.Collections;
  4. using System;
  5. using Valve.VR;
  6. using System.Runtime.InteropServices;
  7. using System.Collections.Generic;
  8. using System.Text;
  9. namespace Valve.VR
  10. {
  11. /// <summary>
  12. /// Action sets are logical groupings of actions. Multiple sets can be active at one time.
  13. /// </summary>
  14. [Serializable]
  15. public class SteamVR_ActionSet : IEquatable<SteamVR_ActionSet>, ISteamVR_ActionSet, ISerializationCallbackReceiver
  16. {
  17. public SteamVR_ActionSet() { }
  18. [SerializeField]
  19. private string actionSetPath;
  20. [NonSerialized]
  21. protected SteamVR_ActionSet_Data setData;
  22. /// <summary>All actions within this set (including out actions)</summary>
  23. public SteamVR_Action[] allActions
  24. {
  25. get
  26. {
  27. if (initialized == false)
  28. Initialize();
  29. return setData.allActions;
  30. }
  31. }
  32. /// <summary>All IN actions within this set that are NOT pose or skeleton actions</summary>
  33. public ISteamVR_Action_In[] nonVisualInActions
  34. {
  35. get
  36. {
  37. if (initialized == false)
  38. Initialize();
  39. return setData.nonVisualInActions;
  40. }
  41. }
  42. /// <summary>All pose and skeleton actions within this set</summary>
  43. public ISteamVR_Action_In[] visualActions
  44. {
  45. get
  46. {
  47. if (initialized == false)
  48. Initialize();
  49. return setData.visualActions;
  50. }
  51. }
  52. /// <summary>All pose actions within this set</summary>
  53. public SteamVR_Action_Pose[] poseActions
  54. {
  55. get
  56. {
  57. if (initialized == false)
  58. Initialize();
  59. return setData.poseActions;
  60. }
  61. }
  62. /// <summary>All skeleton actions within this set</summary>
  63. public SteamVR_Action_Skeleton[] skeletonActions
  64. {
  65. get
  66. {
  67. if (initialized == false)
  68. Initialize();
  69. return setData.skeletonActions;
  70. }
  71. }
  72. /// <summary>All out actions within this set</summary>
  73. public ISteamVR_Action_Out[] outActionArray
  74. {
  75. get
  76. {
  77. if (initialized == false)
  78. Initialize();
  79. return setData.outActionArray;
  80. }
  81. }
  82. /// <summary>The full path to this action set (ex: /actions/in/default)</summary>
  83. public string fullPath
  84. {
  85. get
  86. {
  87. if (initialized == false)
  88. Initialize();
  89. return setData.fullPath;
  90. }
  91. }
  92. public string usage
  93. {
  94. get
  95. {
  96. if (initialized == false)
  97. Initialize();
  98. return setData.usage;
  99. }
  100. }
  101. public ulong handle
  102. {
  103. get
  104. {
  105. if (initialized == false)
  106. Initialize();
  107. return setData.handle;
  108. }
  109. }
  110. [NonSerialized]
  111. protected bool initialized = false;
  112. public static CreateType Create<CreateType>(string newSetPath) where CreateType : SteamVR_ActionSet, new()
  113. {
  114. CreateType actionSet = new CreateType();
  115. actionSet.PreInitialize(newSetPath);
  116. return actionSet;
  117. }
  118. public static CreateType CreateFromName<CreateType>(string newSetName) where CreateType : SteamVR_ActionSet, new()
  119. {
  120. CreateType actionSet = new CreateType();
  121. actionSet.PreInitialize(SteamVR_Input_ActionFile_ActionSet.GetPathFromName(newSetName));
  122. return actionSet;
  123. }
  124. public void PreInitialize(string newActionPath)
  125. {
  126. actionSetPath = newActionPath;
  127. setData = new SteamVR_ActionSet_Data();
  128. setData.fullPath = actionSetPath;
  129. setData.PreInitialize();
  130. initialized = true;
  131. }
  132. public virtual void FinishPreInitialize()
  133. {
  134. setData.FinishPreInitialize();
  135. }
  136. /// <summary>
  137. /// Initializes the handle for the action
  138. /// </summary>
  139. public virtual void Initialize(bool createNew = false, bool throwErrors = true)
  140. {
  141. if (createNew)
  142. {
  143. setData.Initialize();
  144. }
  145. else
  146. {
  147. setData = SteamVR_Input.GetActionSetDataFromPath(actionSetPath);
  148. if (setData == null)
  149. {
  150. #if UNITY_EDITOR
  151. if (throwErrors)
  152. {
  153. if (string.IsNullOrEmpty(actionSetPath))
  154. {
  155. Debug.LogError("<b>[SteamVR]</b> Action has not been assigned.");
  156. }
  157. else
  158. {
  159. Debug.LogError("<b>[SteamVR]</b> Could not find action with path: " + actionSetPath);
  160. }
  161. }
  162. #endif
  163. }
  164. }
  165. initialized = true;
  166. }
  167. public string GetPath()
  168. {
  169. return actionSetPath;
  170. }
  171. /// <summary>
  172. /// Returns whether the set is currently active or not.
  173. /// </summary>
  174. /// <param name="source">The device to check. Any means all devices here (not left or right, but all)</param>
  175. public bool IsActive(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
  176. {
  177. return setData.IsActive(source);
  178. }
  179. /// <summary>
  180. /// Returns the last time this action set was changed (set to active or inactive)
  181. /// </summary>
  182. /// <param name="source">The device to check. Any means all devices here (not left or right, but all)</param>
  183. public float GetTimeLastChanged(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
  184. {
  185. return setData.GetTimeLastChanged(source);
  186. }
  187. /// <summary>
  188. /// Activate this set so its actions can be called
  189. /// </summary>
  190. /// <param name="disableAllOtherActionSets">Disable all other action sets at the same time</param>
  191. /// <param name="priority">The priority of this action set. If you have two actions bound to the same input (button) the higher priority set will override the lower priority. If they are the same priority both will execute.</param>
  192. /// <param name="activateForSource">Will activate this action set only for the specified source. Any if you want to activate for everything</param>
  193. public void Activate(SteamVR_Input_Sources activateForSource = SteamVR_Input_Sources.Any, int priority = 0, bool disableAllOtherActionSets = false)
  194. {
  195. setData.Activate(activateForSource, priority, disableAllOtherActionSets);
  196. }
  197. /// <summary>
  198. /// Deactivate the action set so its actions can no longer be called
  199. /// </summary>
  200. public void Deactivate(SteamVR_Input_Sources forSource = SteamVR_Input_Sources.Any)
  201. {
  202. setData.Deactivate(forSource);
  203. }
  204. /// <summary>Gets the last part of the path for this action. Removes "actions" and direction.</summary>
  205. public string GetShortName()
  206. {
  207. return setData.GetShortName();
  208. }
  209. public bool ReadRawSetActive(SteamVR_Input_Sources inputSource)
  210. {
  211. return setData.ReadRawSetActive(inputSource);
  212. }
  213. public float ReadRawSetLastChanged(SteamVR_Input_Sources inputSource)
  214. {
  215. return setData.ReadRawSetLastChanged(inputSource);
  216. }
  217. public int ReadRawSetPriority(SteamVR_Input_Sources inputSource)
  218. {
  219. return setData.ReadRawSetPriority(inputSource);
  220. }
  221. public SteamVR_ActionSet_Data GetActionSetData()
  222. {
  223. return setData;
  224. }
  225. public CreateType GetCopy<CreateType>() where CreateType : SteamVR_ActionSet, new()
  226. {
  227. CreateType actionSet = new CreateType();
  228. actionSet.actionSetPath = this.actionSetPath;
  229. actionSet.setData = this.setData;
  230. actionSet.initialized = true;
  231. return actionSet;
  232. //return (CreateType)this; //no need to make copies in builds - will reduce memory alloc //todo: having this enabled was not working. all sets were the same (maybe actions too)
  233. }
  234. public bool Equals(SteamVR_ActionSet other)
  235. {
  236. if (ReferenceEquals(null, other))
  237. return false;
  238. return this.actionSetPath == other.actionSetPath;
  239. }
  240. public override bool Equals(object other)
  241. {
  242. if (ReferenceEquals(null, other))
  243. {
  244. if (string.IsNullOrEmpty(this.actionSetPath)) //if we haven't set a path, say this action set is equal to null
  245. return true;
  246. return false;
  247. }
  248. if (ReferenceEquals(this, other))
  249. return true;
  250. if (other is SteamVR_ActionSet)
  251. return this.Equals((SteamVR_ActionSet)other);
  252. return false;
  253. }
  254. public override int GetHashCode()
  255. {
  256. if (actionSetPath == null)
  257. return 0;
  258. else
  259. return actionSetPath.GetHashCode();
  260. }
  261. public static bool operator !=(SteamVR_ActionSet set1, SteamVR_ActionSet set2)
  262. {
  263. return !(set1 == set2);
  264. }
  265. public static bool operator ==(SteamVR_ActionSet set1, SteamVR_ActionSet set2)
  266. {
  267. bool set1null = (ReferenceEquals(null, set1) || string.IsNullOrEmpty(set1.actionSetPath) || set1.GetActionSetData() == null);
  268. bool set2null = (ReferenceEquals(null, set2) || string.IsNullOrEmpty(set2.actionSetPath) || set2.GetActionSetData() == null);
  269. if (set1null && set2null)
  270. return true;
  271. else if (set1null != set2null)
  272. return false;
  273. return set1.Equals(set2);
  274. }
  275. void ISerializationCallbackReceiver.OnBeforeSerialize()
  276. {
  277. }
  278. void ISerializationCallbackReceiver.OnAfterDeserialize()
  279. {
  280. if (setData != null)
  281. {
  282. if (setData.fullPath != actionSetPath)
  283. {
  284. setData = SteamVR_Input.GetActionSetDataFromPath(actionSetPath);
  285. }
  286. }
  287. if (initialized == false)
  288. Initialize(false, false);
  289. }
  290. }
  291. /// <summary>
  292. /// Action sets are logical groupings of actions. Multiple sets can be active at one time.
  293. /// </summary>
  294. public class SteamVR_ActionSet_Data : ISteamVR_ActionSet
  295. {
  296. public SteamVR_ActionSet_Data() { }
  297. /// <summary>All actions within this set (including out actions)</summary>
  298. public SteamVR_Action[] allActions { get; set; }
  299. /// <summary>All IN actions within this set that are NOT pose or skeleton actions</summary>
  300. public ISteamVR_Action_In[] nonVisualInActions { get; set; }
  301. /// <summary>All pose and skeleton actions within this set</summary>
  302. public ISteamVR_Action_In[] visualActions { get; set; }
  303. /// <summary>All pose actions within this set</summary>
  304. public SteamVR_Action_Pose[] poseActions { get; set; }
  305. /// <summary>All skeleton actions within this set</summary>
  306. public SteamVR_Action_Skeleton[] skeletonActions { get; set; }
  307. /// <summary>All out actions within this set</summary>
  308. public ISteamVR_Action_Out[] outActionArray { get; set; }
  309. /// <summary>The full path to this action set (ex: /actions/in/default)</summary>
  310. public string fullPath { get; set; }
  311. public string usage { get; set; }
  312. public ulong handle { get; set; }
  313. protected Dictionary<SteamVR_Input_Sources, bool> rawSetActive = new Dictionary<SteamVR_Input_Sources, bool>(new SteamVR_Input_Sources_Comparer());
  314. protected Dictionary<SteamVR_Input_Sources, float> rawSetLastChanged = new Dictionary<SteamVR_Input_Sources, float>(new SteamVR_Input_Sources_Comparer());
  315. protected Dictionary<SteamVR_Input_Sources, int> rawSetPriority = new Dictionary<SteamVR_Input_Sources, int>(new SteamVR_Input_Sources_Comparer());
  316. protected bool initialized = false;
  317. public void PreInitialize()
  318. {
  319. SteamVR_Input_Sources[] sources = SteamVR_Input_Source.GetAllSources();
  320. for (int sourceIndex = 0; sourceIndex < sources.Length; sourceIndex++)
  321. {
  322. SteamVR_Input_Sources source = sources[sourceIndex];
  323. rawSetActive.Add(source, false);
  324. rawSetLastChanged.Add(source, 0);
  325. rawSetPriority.Add(source, 0);
  326. }
  327. }
  328. public void FinishPreInitialize()
  329. {
  330. List<SteamVR_Action> allActionsList = new List<SteamVR_Action>();
  331. List<ISteamVR_Action_In> nonVisualInActionsList = new List<ISteamVR_Action_In>();
  332. List<ISteamVR_Action_In> visualActionsList = new List<ISteamVR_Action_In>();
  333. List<SteamVR_Action_Pose> poseActionsList = new List<SteamVR_Action_Pose>();
  334. List<SteamVR_Action_Skeleton> skeletonActionsList = new List<SteamVR_Action_Skeleton>();
  335. List<ISteamVR_Action_Out> outActionList = new List<ISteamVR_Action_Out>();
  336. if (SteamVR_Input.actions == null)
  337. {
  338. Debug.LogError("<b>[SteamVR Input]</b> Actions not initialized!");
  339. return;
  340. }
  341. for (int actionIndex = 0; actionIndex < SteamVR_Input.actions.Length; actionIndex++)
  342. {
  343. SteamVR_Action action = SteamVR_Input.actions[actionIndex];
  344. if (action.actionSet.GetActionSetData() == this)
  345. {
  346. allActionsList.Add(action);
  347. if (action is ISteamVR_Action_Boolean || action is ISteamVR_Action_Single || action is ISteamVR_Action_Vector2 || action is ISteamVR_Action_Vector3)
  348. {
  349. nonVisualInActionsList.Add((ISteamVR_Action_In)action);
  350. }
  351. else if (action is SteamVR_Action_Pose)
  352. {
  353. visualActionsList.Add((ISteamVR_Action_In)action);
  354. poseActionsList.Add((SteamVR_Action_Pose)action);
  355. }
  356. else if (action is SteamVR_Action_Skeleton)
  357. {
  358. visualActionsList.Add((ISteamVR_Action_In)action);
  359. skeletonActionsList.Add((SteamVR_Action_Skeleton)action);
  360. }
  361. else if (action is ISteamVR_Action_Out)
  362. {
  363. outActionList.Add((ISteamVR_Action_Out)action);
  364. }
  365. else
  366. {
  367. Debug.LogError("<b>[SteamVR Input]</b> Action doesn't implement known interface: " + action.fullPath);
  368. }
  369. }
  370. }
  371. allActions = allActionsList.ToArray();
  372. nonVisualInActions = nonVisualInActionsList.ToArray();
  373. visualActions = visualActionsList.ToArray();
  374. poseActions = poseActionsList.ToArray();
  375. skeletonActions = skeletonActionsList.ToArray();
  376. outActionArray = outActionList.ToArray();
  377. }
  378. public void Initialize()
  379. {
  380. ulong newHandle = 0;
  381. EVRInputError err = OpenVR.Input.GetActionSetHandle(fullPath.ToLower(), ref newHandle);
  382. handle = newHandle;
  383. if (err != EVRInputError.None)
  384. Debug.LogError("<b>[SteamVR]</b> GetActionSetHandle (" + fullPath + ") error: " + err.ToString());
  385. initialized = true;
  386. }
  387. /// <summary>
  388. /// Returns whether the set is currently active or not.
  389. /// </summary>
  390. /// <param name="source">The device to check. Any means all devices here (not left or right, but all)</param>
  391. public bool IsActive(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
  392. {
  393. if (initialized)
  394. return rawSetActive[source] || rawSetActive[SteamVR_Input_Sources.Any];
  395. return false;
  396. }
  397. /// <summary>
  398. /// Returns the last time this action set was changed (set to active or inactive)
  399. /// </summary>
  400. /// <param name="source">The device to check. Any means all devices here (not left or right, but all)</param>
  401. public float GetTimeLastChanged(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
  402. {
  403. if (initialized)
  404. return rawSetLastChanged[source];
  405. return 0;
  406. }
  407. /// <summary>
  408. /// Activate this set so its actions can be called
  409. /// </summary>
  410. /// <param name="disableAllOtherActionSets">Disable all other action sets at the same time</param>
  411. /// <param name="priority">The priority of this action set. If you have two actions bound to the same input (button) the higher priority set will override the lower priority. If they are the same priority both will execute.</param>
  412. /// <param name="activateForSource">Will activate this action set only for the specified source. Any if you want to activate for everything</param>
  413. public void Activate(SteamVR_Input_Sources activateForSource = SteamVR_Input_Sources.Any, int priority = 0, bool disableAllOtherActionSets = false)
  414. {
  415. if (disableAllOtherActionSets)
  416. SteamVR_ActionSet_Manager.DisableAllActionSets();
  417. if (rawSetActive[activateForSource] == false)
  418. {
  419. rawSetActive[activateForSource] = true;
  420. SteamVR_ActionSet_Manager.SetChanged();
  421. rawSetLastChanged[activateForSource] = Time.realtimeSinceStartup;
  422. }
  423. if (rawSetPriority[activateForSource] != priority)
  424. {
  425. rawSetPriority[activateForSource] = priority;
  426. SteamVR_ActionSet_Manager.SetChanged();
  427. rawSetLastChanged[activateForSource] = Time.realtimeSinceStartup;
  428. }
  429. }
  430. /// <summary>
  431. /// Deactivate the action set so its actions can no longer be called
  432. /// </summary>
  433. public void Deactivate(SteamVR_Input_Sources forSource = SteamVR_Input_Sources.Any)
  434. {
  435. if (rawSetActive[forSource] != false)
  436. {
  437. rawSetLastChanged[forSource] = Time.realtimeSinceStartup;
  438. SteamVR_ActionSet_Manager.SetChanged();
  439. }
  440. rawSetActive[forSource] = false;
  441. rawSetPriority[forSource] = 0;
  442. }
  443. private string cachedShortName;
  444. /// <summary>Gets the last part of the path for this action. Removes "actions" and direction.</summary>
  445. public string GetShortName()
  446. {
  447. if (cachedShortName == null)
  448. {
  449. cachedShortName = SteamVR_Input_ActionFile.GetShortName(fullPath);
  450. }
  451. return cachedShortName;
  452. }
  453. public bool ReadRawSetActive(SteamVR_Input_Sources inputSource)
  454. {
  455. return rawSetActive[inputSource];
  456. }
  457. public float ReadRawSetLastChanged(SteamVR_Input_Sources inputSource)
  458. {
  459. return rawSetLastChanged[inputSource];
  460. }
  461. public int ReadRawSetPriority(SteamVR_Input_Sources inputSource)
  462. {
  463. return rawSetPriority[inputSource];
  464. }
  465. }
  466. /// <summary>
  467. /// Action sets are logical groupings of actions. Multiple sets can be active at one time.
  468. /// </summary>
  469. public interface ISteamVR_ActionSet
  470. {
  471. /// <summary>All actions within this set (including out actions)</summary>
  472. SteamVR_Action[] allActions { get; }
  473. /// <summary>All IN actions within this set that are NOT pose or skeleton actions</summary>
  474. ISteamVR_Action_In[] nonVisualInActions { get; }
  475. /// <summary>All pose and skeleton actions within this set</summary>
  476. ISteamVR_Action_In[] visualActions { get; }
  477. /// <summary>All pose actions within this set</summary>
  478. SteamVR_Action_Pose[] poseActions { get; }
  479. /// <summary>All skeleton actions within this set</summary>
  480. SteamVR_Action_Skeleton[] skeletonActions { get; }
  481. /// <summary>All out actions within this set</summary>
  482. ISteamVR_Action_Out[] outActionArray { get; }
  483. /// <summary>The full path to this action set (ex: /actions/in/default)</summary>
  484. string fullPath { get; }
  485. /// <summary>How the binding UI should display this set</summary>
  486. string usage { get; }
  487. ulong handle { get; }
  488. bool ReadRawSetActive(SteamVR_Input_Sources inputSource);
  489. float ReadRawSetLastChanged(SteamVR_Input_Sources inputSource);
  490. int ReadRawSetPriority(SteamVR_Input_Sources inputSource);
  491. /// <summary>
  492. /// Returns whether the set is currently active or not.
  493. /// </summary>
  494. /// <param name="source">The device to check. Any means all devices here (not left or right, but all)</param>
  495. bool IsActive(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any);
  496. /// <summary>
  497. /// Returns the last time this action set was changed (set to active or inactive)
  498. /// </summary>
  499. /// <param name="source">The device to check. Any means all devices here (not left or right, but all)</param>
  500. float GetTimeLastChanged(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any);
  501. /// <summary>
  502. /// Activate this set so its actions can be called
  503. /// </summary>
  504. /// <param name="disableAllOtherActionSets">Disable all other action sets at the same time</param>
  505. /// <param name="priority">The priority of this action set. If you have two actions bound to the same input (button) the higher priority set will override the lower priority. If they are the same priority both will execute.</param>
  506. /// <param name="activateForSource">Will activate this action set only for the specified source. Any if you want to activate for everything</param>
  507. void Activate(SteamVR_Input_Sources activateForSource = SteamVR_Input_Sources.Any, int priority = 0, bool disableAllOtherActionSets = false);
  508. /// <summary>Deactivate the action set so its actions can no longer be called</summary>
  509. void Deactivate(SteamVR_Input_Sources forSource = SteamVR_Input_Sources.Any);
  510. /// <summary>Gets the last part of the path for this action. Removes "actions" and direction.</summary>
  511. string GetShortName();
  512. }
  513. }