2021년 4학년 1학기 기업연계프로젝트2 컴퓨터소프트웨어공학과 <원광투어팀> 팀장 : 송유진 팀원 : 김나영, 이경희, 한유진
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

750 lines
30 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. using HTC.UnityPlugin.Utility;
  3. using HTC.UnityPlugin.VRModuleManagement;
  4. using System;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using UnityEngine.Events;
  8. namespace HTC.UnityPlugin.Vive
  9. {
  10. public static partial class ViveRole
  11. {
  12. public struct MappingChangedEventArg
  13. {
  14. public int roleValue;
  15. public uint previousDeviceIndex;
  16. public uint currentDeviceIndex;
  17. }
  18. public struct MappingChangedEventArg<TRole>
  19. {
  20. public TRole role;
  21. public uint previousDeviceIndex;
  22. public uint currentDeviceIndex;
  23. }
  24. public interface IMap
  25. {
  26. ViveRoleEnum.IInfo RoleValueInfo { get; }
  27. IMapHandler Handler { get; }
  28. int BindingCount { get; }
  29. IIndexedTableReadOnly<string, int> BindingTable { get; }
  30. bool IsRoleValueMapped(int roleValue);
  31. bool IsDeviceMapped(uint deviceIndex);
  32. uint GetMappedDeviceByRoleValue(int roleValue);
  33. int GetMappedRoleValueByDevice(uint deviceIndex);
  34. [Obsolete("Use BindDeviceToRoleValue instead")]
  35. void BindRoleValue(int roleValue, string deviceSN);
  36. void BindDeviceToRoleValue(string deviceSN, int roleValue);
  37. void BindAll();
  38. bool UnbindRoleValue(int roleValue); // return true if role is ready for bind
  39. bool UnbindDevice(string deviceSN); // return true if device is ready for bind
  40. bool UnbindConnectedDevice(uint deviceIndex); // return true if device is ready for bind
  41. void UnbindAll();
  42. bool IsRoleValueBound(int roleValue);
  43. bool IsDeviceBound(string deviceSN);
  44. bool IsDeviceConnectedAndBound(uint deviceIndex);
  45. string GetBoundDeviceByRoleValue(int roleValue);
  46. /// <summary>
  47. /// Should use IsDeviceBound to validate deviceSN before calling this function
  48. /// </summary>
  49. int GetBoundRoleValueByDevice(string deviceSN);
  50. /// <summary>
  51. /// Should use IsDeviceConnectedAndBound to validate deviceIndex before calling this function
  52. /// </summary>
  53. int GetBoundRoleValueByConnectedDevice(uint deviceIndex);
  54. event UnityAction<IMap, MappingChangedEventArg> onRoleValueMappingChanged;
  55. }
  56. private sealed class Map : IMap
  57. {
  58. private readonly ViveRoleEnum.IInfo m_info;
  59. private IMapHandler m_handler;
  60. private bool m_lockInternalMapping;
  61. // mapping table
  62. private readonly uint[] m_role2index;
  63. private readonly int[] m_index2role;
  64. // binding table
  65. private readonly IndexedSet<uint>[] m_roleBoundDevices; // connected devices only
  66. private readonly IndexedTable<string, int> m_sn2role;
  67. public Map(Type roleType)
  68. {
  69. m_info = ViveRoleEnum.GetInfo(roleType);
  70. m_role2index = new uint[m_info.ValidRoleLength];
  71. m_index2role = new int[VRModule.MAX_DEVICE_COUNT];
  72. m_roleBoundDevices = new IndexedSet<uint>[m_info.ValidRoleLength];
  73. m_sn2role = new IndexedTable<string, int>(Mathf.Min(m_info.ValidRoleLength, (int)VRModule.MAX_DEVICE_COUNT));
  74. for (int i = 0; i < m_role2index.Length; ++i)
  75. {
  76. m_role2index[i] = VRModule.INVALID_DEVICE_INDEX;
  77. }
  78. for (int i = 0; i < m_index2role.Length; ++i)
  79. {
  80. m_index2role[i] = m_info.InvalidRoleValue;
  81. }
  82. }
  83. public ViveRoleEnum.IInfo RoleValueInfo { get { return m_info; } }
  84. public int BindingCount { get { return m_sn2role.Count; } }
  85. public IIndexedTableReadOnly<string, int> BindingTable { get { return m_sn2role.ReadOnly; } }
  86. public IMapHandler Handler
  87. {
  88. get { return m_handler; }
  89. set
  90. {
  91. if (m_handler == value) { return; }
  92. if (m_handler != null)
  93. {
  94. m_handler.OnDivestedOfCurrentMapHandler();
  95. m_handler = null;
  96. }
  97. if (value != null)
  98. {
  99. if (value.BlockBindings)
  100. {
  101. UnbindAll();
  102. }
  103. m_handler = value;
  104. m_handler.OnAssignedAsCurrentMapHandler();
  105. }
  106. }
  107. }
  108. public event UnityAction<IMap, MappingChangedEventArg> onRoleValueMappingChanged;
  109. private string DeviceSN(uint deviceIndex) { return VRModule.GetCurrentDeviceState(deviceIndex).serialNumber; }
  110. public void OnConnectedDeviceChanged(uint deviceIndex, VRModuleDeviceClass deviceClass, string deviceSN, bool connected)
  111. {
  112. if (connected)
  113. {
  114. if (IsDeviceBound(deviceSN))
  115. {
  116. InternalInsertRoleBoundDevice(deviceSN, deviceIndex, GetBoundRoleValueByDevice(deviceSN));
  117. }
  118. }
  119. else
  120. {
  121. if (IsDeviceMapped(deviceIndex))
  122. {
  123. if (IsDeviceBound(deviceSN))
  124. {
  125. InternalRemoveRoleBoundDevice(deviceSN, deviceIndex, GetBoundRoleValueByDevice(deviceSN));
  126. }
  127. if (IsDeviceMapped(deviceIndex))
  128. {
  129. InternalUnmapping(GetMappedRoleValueByDevice(deviceIndex), deviceIndex);
  130. }
  131. }
  132. }
  133. if (m_handler != null)
  134. {
  135. m_handler.OnConnectedDeviceChanged(deviceIndex, deviceClass, deviceSN, connected);
  136. }
  137. }
  138. public void OnTrackedDeviceRoleChanged()
  139. {
  140. if (m_handler != null)
  141. {
  142. m_handler.OnTrackedDeviceRoleChanged();
  143. }
  144. }
  145. #region retrieve state
  146. public bool IsRoleValueMapped(int roleValue)
  147. {
  148. if (!m_info.IsValidRoleValue(roleValue)) { return false; }
  149. return IsRoleOffsetMapped(m_info.RoleValueToRoleOffset(roleValue));
  150. }
  151. public bool IsRoleOffsetMapped(int roleOffset)
  152. {
  153. return VRModule.IsValidDeviceIndex(m_role2index[roleOffset]);
  154. }
  155. public bool IsDeviceMapped(uint deviceIndex)
  156. {
  157. return VRModule.IsValidDeviceIndex(deviceIndex) && m_info.IsValidRoleValue(m_index2role[deviceIndex]);
  158. }
  159. public bool IsRoleValueBound(int roleValue)
  160. {
  161. if (!m_info.IsValidRoleValue(roleValue)) { return false; }
  162. var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
  163. return m_roleBoundDevices[roleOffset] != null && m_roleBoundDevices[roleOffset].Count > 0;
  164. }
  165. public bool IsDeviceBound(string deviceSN)
  166. {
  167. return string.IsNullOrEmpty(deviceSN) ? false : m_sn2role.ContainsKey(deviceSN);
  168. }
  169. public bool IsDeviceConnectedAndBound(uint deviceIndex)
  170. {
  171. return IsDeviceBound(DeviceSN(deviceIndex));
  172. }
  173. public uint GetMappedDeviceByRoleValue(int roleValue)
  174. {
  175. if (m_info.IsValidRoleValue(roleValue))
  176. {
  177. return m_role2index[m_info.RoleValueToRoleOffset(roleValue)];
  178. }
  179. else
  180. {
  181. return VRModule.INVALID_DEVICE_INDEX;
  182. }
  183. }
  184. public int GetMappedRoleValueByDevice(uint deviceIndex)
  185. {
  186. if (VRModule.IsValidDeviceIndex(deviceIndex))
  187. {
  188. return m_index2role[deviceIndex];
  189. }
  190. else
  191. {
  192. return m_info.InvalidRoleValue;
  193. }
  194. }
  195. public string GetBoundDeviceByRoleValue(int roleValue)
  196. {
  197. if (!IsRoleValueBound(roleValue)) { return string.Empty; }
  198. return DeviceSN(GetMappedDeviceByRoleValue(roleValue));
  199. }
  200. public int GetBoundRoleValueByDevice(string deviceSN)
  201. {
  202. return m_sn2role[deviceSN];
  203. }
  204. public int GetBoundRoleValueByConnectedDevice(uint deviceIndex)
  205. {
  206. return GetBoundRoleValueByDevice(DeviceSN(deviceIndex));
  207. }
  208. #endregion retrieve state
  209. #region internal operation
  210. // both roleValue and deviceIndex must be valid
  211. // ignore binding state
  212. private void InternalMapping(int roleValue, uint deviceIndex)
  213. {
  214. if (m_lockInternalMapping) { throw new Exception("Recursive calling InternalMapping"); }
  215. m_lockInternalMapping = true;
  216. var previousRoleValue = m_index2role[deviceIndex];
  217. if (roleValue == previousRoleValue)
  218. {
  219. m_lockInternalMapping = false;
  220. return;
  221. }
  222. if (m_info.IsValidRoleValue(previousRoleValue))
  223. {
  224. m_lockInternalMapping = false;
  225. InternalUnmapping(previousRoleValue, deviceIndex);
  226. m_lockInternalMapping = true;
  227. }
  228. var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
  229. var previousDeviceIndex = m_role2index[roleOffset];
  230. var eventArg = new MappingChangedEventArg()
  231. {
  232. roleValue = roleValue,
  233. previousDeviceIndex = previousDeviceIndex,
  234. currentDeviceIndex = deviceIndex,
  235. };
  236. m_role2index[roleOffset] = deviceIndex;
  237. m_index2role[deviceIndex] = roleValue;
  238. if (VRModule.IsValidDeviceIndex(previousDeviceIndex))
  239. {
  240. m_index2role[previousDeviceIndex] = m_info.InvalidRoleValue;
  241. }
  242. if (onRoleValueMappingChanged != null)
  243. {
  244. onRoleValueMappingChanged(this, eventArg);
  245. }
  246. m_lockInternalMapping = false;
  247. }
  248. // both roleValue and deviceIndex must be valid
  249. // ignore binding state
  250. private void InternalUnmapping(int roleValue, uint deviceIndex)
  251. {
  252. if (m_lockInternalMapping) { throw new Exception("Recursive calling InternalMapping"); }
  253. m_lockInternalMapping = true;
  254. var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
  255. var eventArg = new MappingChangedEventArg()
  256. {
  257. roleValue = roleValue,
  258. previousDeviceIndex = deviceIndex,
  259. currentDeviceIndex = VRModule.INVALID_DEVICE_INDEX,
  260. };
  261. m_role2index[roleOffset] = VRModule.INVALID_DEVICE_INDEX;
  262. m_index2role[deviceIndex] = m_info.InvalidRoleValue;
  263. if (onRoleValueMappingChanged != null)
  264. {
  265. onRoleValueMappingChanged(this, eventArg);
  266. }
  267. m_lockInternalMapping = false;
  268. }
  269. // device must be valid and connected and have bound role value
  270. // device must not exist in role bound devices
  271. // boundRoleValue can be whether valid or not
  272. private void InternalInsertRoleBoundDevice(string deviceSN, uint deviceIndex, int boundRoleValue)
  273. {
  274. if (m_info.IsValidRoleValue(boundRoleValue))
  275. {
  276. var roleBoundDevices = InternalGetRoleBoundDevices(boundRoleValue);
  277. roleBoundDevices.Add(deviceIndex); // if key already added here, means that this device already in role bound devices
  278. InternalMapping(boundRoleValue, deviceIndex);
  279. }
  280. }
  281. // device must be valid and connected and have bound role value
  282. // device must already exist in role bound devices
  283. // boundRoleValue can be whether valid or not
  284. private void InternalRemoveRoleBoundDevice(string deviceSN, uint deviceIndex, int boundRoleValue)
  285. {
  286. if (m_info.IsValidRoleValue(boundRoleValue))
  287. {
  288. var roleBoundDevices = InternalGetRoleBoundDevices(boundRoleValue);
  289. if (!roleBoundDevices.Remove(deviceIndex))
  290. {
  291. throw new Exception("device([" + deviceIndex + "]" + deviceSN + ") has not been InternalMappingRoleBoundDevice");
  292. }
  293. if (roleBoundDevices.Count > 0)
  294. {
  295. InternalMapping(boundRoleValue, roleBoundDevices[0]);
  296. }
  297. }
  298. }
  299. // deviceSN must be valid
  300. // device can be whether bound or not
  301. // device can be whether connected or not
  302. private void InternalBind(string deviceSN, int roleValue)
  303. {
  304. var deviceIndex = VRModule.GetConnectedDeviceIndex(deviceSN);
  305. bool previousIsBound = false;
  306. int previousBoundRoleValue = m_info.InvalidRoleValue;
  307. if (m_sn2role.TryGetValue(deviceSN, out previousBoundRoleValue))
  308. {
  309. if (previousBoundRoleValue == roleValue) { return; }
  310. previousIsBound = true;
  311. m_sn2role.Remove(deviceSN);
  312. if (VRModule.IsValidDeviceIndex(deviceIndex))
  313. {
  314. InternalRemoveRoleBoundDevice(deviceSN, deviceIndex, previousBoundRoleValue);
  315. }
  316. }
  317. m_sn2role[deviceSN] = roleValue;
  318. if (VRModule.IsValidDeviceIndex(deviceIndex))
  319. {
  320. InternalInsertRoleBoundDevice(deviceSN, deviceIndex, roleValue);
  321. }
  322. if (m_handler != null)
  323. {
  324. m_handler.OnBindingRoleValueChanged(deviceSN, previousIsBound, previousBoundRoleValue, true, roleValue);
  325. }
  326. }
  327. // deviceSN must be valid
  328. // device must be bound
  329. // device can be whether connected or not
  330. private void InternalUnbind(string deviceSN, int boundRoleValue)
  331. {
  332. var deviceIndex = VRModule.GetConnectedDeviceIndex(deviceSN);
  333. if (!m_sn2role.Remove(deviceSN))
  334. {
  335. throw new Exception("device([" + deviceIndex + "]" + deviceSN + ") already unbound");
  336. }
  337. if (VRModule.IsValidDeviceIndex(deviceIndex))
  338. {
  339. InternalRemoveRoleBoundDevice(deviceSN, deviceIndex, boundRoleValue);
  340. }
  341. if (m_handler != null)
  342. {
  343. m_handler.OnBindingRoleValueChanged(deviceSN, true, boundRoleValue, false, m_info.InvalidRoleValue);
  344. }
  345. }
  346. #endregion internal operation
  347. #region mapping
  348. public void MappingRoleValue(int roleValue, uint deviceIndex)
  349. {
  350. if (!m_info.IsValidRoleValue(roleValue))
  351. {
  352. throw new ArgumentException("Cannot mapping invalid roleValue(" + m_info.RoleEnumType.Name + "[" + roleValue + "])");
  353. }
  354. if (!VRModule.IsValidDeviceIndex(deviceIndex))
  355. {
  356. throw new ArgumentException("Cannot mapping invalid deviceIndex(" + deviceIndex + ")");
  357. }
  358. if (IsRoleValueBound(roleValue))
  359. {
  360. throw new ArgumentException("roleValue(" + m_info.RoleEnumType.Name + "[" + roleValue + "]) is already bound, unbind first.");
  361. }
  362. if (IsDeviceConnectedAndBound(deviceIndex))
  363. {
  364. throw new ArgumentException("deviceIndex(" + deviceIndex + ") is already bound, unbind first");
  365. }
  366. InternalMapping(roleValue, deviceIndex);
  367. }
  368. // return true if role is ready for mapping
  369. public bool UnmappingRoleValue(int roleValue)
  370. {
  371. // is mapped?
  372. if (!IsRoleValueMapped(roleValue)) { return false; }
  373. // is bound?
  374. if (IsRoleValueBound(roleValue)) { return false; }
  375. InternalUnmapping(roleValue, GetMappedDeviceByRoleValue(roleValue));
  376. return true;
  377. }
  378. // return true if device is ready for mapping
  379. public bool UnmappingDevice(uint deviceIndex)
  380. {
  381. // is mapped?
  382. if (!IsDeviceMapped(deviceIndex)) { return false; }
  383. // is bound?
  384. if (IsDeviceConnectedAndBound(deviceIndex)) { return false; }
  385. InternalUnmapping(GetMappedRoleValueByDevice(deviceIndex), deviceIndex);
  386. return true;
  387. }
  388. public void UnmappingAll()
  389. {
  390. for (int roleValue = m_info.MinValidRoleValue; roleValue <= m_info.MaxValidRoleValue; ++roleValue)
  391. {
  392. if (!m_info.IsValidRoleValue(roleValue)) { continue; }
  393. UnmappingRoleValue(roleValue);
  394. }
  395. }
  396. #endregion mapping
  397. #region bind
  398. [Obsolete("Use BindDeviceToRoleValue instead")]
  399. public void BindRoleValue(int roleValue, string deviceSN)
  400. {
  401. BindDeviceToRoleValue(deviceSN, roleValue);
  402. }
  403. public void BindDeviceToRoleValue(string deviceSN, int roleValue)
  404. {
  405. if (string.IsNullOrEmpty(deviceSN))
  406. {
  407. throw new ArgumentException("deviceSN cannot be null or empty.");
  408. }
  409. if (m_handler != null && m_handler.BlockBindings) { return; }
  410. InternalBind(deviceSN, roleValue);
  411. }
  412. // bind all mapped roles & devices
  413. public void BindAll()
  414. {
  415. if (m_handler != null && m_handler.BlockBindings) { return; }
  416. for (int roleValue = m_info.MinValidRoleValue; roleValue <= m_info.MaxValidRoleValue; ++roleValue)
  417. {
  418. if (!m_info.IsValidRoleValue(roleValue)) { continue; }
  419. if (IsRoleValueMapped(roleValue) && !IsRoleValueBound(roleValue))
  420. {
  421. InternalBind(DeviceSN(GetMappedDeviceByRoleValue(roleValue)), roleValue);
  422. }
  423. }
  424. }
  425. public bool UnbindRoleValue(int roleValue)
  426. {
  427. if (!IsRoleValueBound(roleValue)) { return false; }
  428. var roleBoundDevices = InternalGetRoleBoundDevices(roleValue);
  429. var boundDeviceIndex = GetMappedDeviceByRoleValue(roleValue);
  430. // unbind other bound device first, to avoid redundent mapping changes event
  431. while (roleBoundDevices.Count > 1)
  432. {
  433. for (int i = roleBoundDevices.Count - 1; i >= 0; --i)
  434. {
  435. if (roleBoundDevices[i] != boundDeviceIndex)
  436. {
  437. InternalUnbind(DeviceSN(roleBoundDevices[i]), roleValue);
  438. break;
  439. }
  440. }
  441. };
  442. if (roleBoundDevices.Count == 1)
  443. {
  444. InternalUnbind(DeviceSN(boundDeviceIndex), roleValue);
  445. }
  446. return true;
  447. }
  448. public bool UnbindDevice(string deviceSN)
  449. {
  450. if (!IsDeviceBound(deviceSN)) { return false; }
  451. InternalUnbind(deviceSN, GetBoundRoleValueByDevice(deviceSN));
  452. return true;
  453. }
  454. public bool UnbindConnectedDevice(uint deviceIndex)
  455. {
  456. return UnbindDevice(DeviceSN(deviceIndex));
  457. }
  458. public void UnbindAll()
  459. {
  460. for (int i = m_sn2role.Count - 1; i >= 0; --i)
  461. {
  462. UnbindDevice(m_sn2role.GetKeyByIndex(i));
  463. }
  464. }
  465. // roleValue must be valid
  466. private IndexedSet<uint> InternalGetRoleBoundDevices(int roleValue)
  467. {
  468. var roleOffset = m_info.RoleValueToRoleOffset(roleValue);
  469. if (m_roleBoundDevices[roleOffset] == null)
  470. {
  471. m_roleBoundDevices[roleOffset] = new IndexedSet<uint>();
  472. }
  473. return m_roleBoundDevices[roleOffset];
  474. }
  475. #endregion bind
  476. }
  477. public interface IMap<TRole> : IMap
  478. {
  479. ViveRoleEnum.IInfo<TRole> RoleInfo { get; }
  480. bool IsRoleMapped(TRole role);
  481. uint GetMappedDeviceByRole(TRole role);
  482. TRole GetMappedRoleByDevice(uint deviceIndex);
  483. [Obsolete("Use BindDeviceToRole instead")]
  484. void BindRole(TRole role, string deviceSN);
  485. void BindDeviceToRole(string deviceSN, TRole role);
  486. bool UnbindRole(TRole role); // return true if role is ready for bind
  487. bool IsRoleBound(TRole role);
  488. string GetBoundDeviceByRole(TRole role);
  489. TRole GetBoundRoleByDevice(string deviceSN);
  490. TRole GetBoundRoleByConnectedDevice(uint deviceIndex);
  491. event UnityAction<IMap<TRole>, MappingChangedEventArg<TRole>> onRoleMappingChanged;
  492. }
  493. private sealed class GenericMap<TRole> : IMap<TRole>
  494. {
  495. public static GenericMap<TRole> s_instance;
  496. private readonly ViveRoleEnum.IInfo<TRole> m_info;
  497. private readonly Map m_map;
  498. public GenericMap()
  499. {
  500. m_info = ViveRoleEnum.GetInfo<TRole>();
  501. m_map = GetInternalMap(typeof(TRole));
  502. if (s_instance == null)
  503. {
  504. s_instance = this;
  505. }
  506. else
  507. {
  508. Debug.LogWarning("duplicated instance for RoleInfo<" + typeof(TRole).Name + ">");
  509. }
  510. m_map.onRoleValueMappingChanged += OnMappingChanged;
  511. }
  512. public ViveRoleEnum.IInfo RoleValueInfo { get { return m_map.RoleValueInfo; } }
  513. public ViveRoleEnum.IInfo<TRole> RoleInfo { get { return m_info; } }
  514. public IMapHandler Handler { get { return m_map.Handler; } }
  515. public int BindingCount { get { return m_map.BindingCount; } }
  516. public IIndexedTableReadOnly<string, int> BindingTable { get { return m_map.BindingTable; } }
  517. public event UnityAction<IMap, MappingChangedEventArg> onRoleValueMappingChanged { add { m_map.onRoleValueMappingChanged += value; } remove { m_map.onRoleValueMappingChanged -= value; } }
  518. public event UnityAction<IMap<TRole>, MappingChangedEventArg<TRole>> onRoleMappingChanged;
  519. private void OnMappingChanged(IMap map, MappingChangedEventArg arg)
  520. {
  521. if (onRoleMappingChanged != null)
  522. {
  523. onRoleMappingChanged(this, new MappingChangedEventArg<TRole>()
  524. {
  525. role = m_info.ToRole(arg.roleValue),
  526. previousDeviceIndex = arg.previousDeviceIndex,
  527. currentDeviceIndex = arg.currentDeviceIndex,
  528. });
  529. }
  530. }
  531. public void MappingRole(TRole role, uint deviceIndex) { m_map.MappingRoleValue(m_info.ToRoleValue(role), deviceIndex); }
  532. public void MappingRoleValue(int roleValue, uint deviceIndex) { m_map.MappingRoleValue(roleValue, deviceIndex); }
  533. public bool UnmappingRole(TRole role) { return m_map.UnmappingRoleValue(m_info.ToRoleValue(role)); }
  534. public bool UnmappingRoleValue(int roleValue) { return m_map.UnmappingRoleValue(roleValue); }
  535. public bool UnmappingDevice(uint deviceIndex) { return m_map.UnmappingDevice(deviceIndex); }
  536. public void UnmappingAll() { m_map.UnmappingAll(); }
  537. public bool IsRoleMapped(TRole role) { return m_map.IsRoleValueMapped(m_info.ToRoleValue(role)); }
  538. public bool IsRoleValueMapped(int roleValue) { return m_map.IsRoleValueMapped(roleValue); }
  539. public bool IsDeviceMapped(uint deviceIndex) { return m_map.IsDeviceMapped(deviceIndex); }
  540. public uint GetMappedDeviceByRole(TRole role) { return m_map.GetMappedDeviceByRoleValue(m_info.ToRoleValue(role)); }
  541. public TRole GetMappedRoleByDevice(uint deviceIndex) { return m_info.ToRole(m_map.GetMappedRoleValueByDevice(deviceIndex)); }
  542. public uint GetMappedDeviceByRoleValue(int roleValue) { return m_map.GetMappedDeviceByRoleValue(roleValue); }
  543. public int GetMappedRoleValueByDevice(uint deviceIndex) { return m_map.GetMappedRoleValueByDevice(deviceIndex); }
  544. [Obsolete("Use BindDeviceToRole instead")]
  545. public void BindRole(TRole role, string deviceSN) { m_map.BindDeviceToRoleValue(deviceSN, m_info.ToRoleValue(role)); }
  546. [Obsolete("Use BindDeviceToRoleValue instead")]
  547. public void BindRoleValue(int roleValue, string deviceSN) { m_map.BindDeviceToRoleValue(deviceSN, roleValue); }
  548. public void BindDeviceToRole(string deviceSN, TRole role) { m_map.BindDeviceToRoleValue(deviceSN, m_info.ToRoleValue(role)); }
  549. public void BindDeviceToRoleValue(string deviceSN, int roleValue) { m_map.BindDeviceToRoleValue(deviceSN, roleValue); }
  550. public void BindAll() { m_map.BindAll(); }
  551. public bool UnbindRole(TRole role) { return m_map.UnbindRoleValue(m_info.ToRoleValue(role)); }
  552. public bool UnbindRoleValue(int roleValue) { return m_map.UnbindRoleValue(roleValue); }
  553. public bool UnbindDevice(string deviceSN) { return m_map.UnbindDevice(deviceSN); }
  554. public bool UnbindConnectedDevice(uint deviceIndex) { return UnbindConnectedDevice(deviceIndex); }
  555. public void UnbindAll() { m_map.UnbindAll(); }
  556. public bool IsRoleBound(TRole role) { return m_map.IsRoleValueBound(m_info.ToRoleValue(role)); }
  557. public bool IsRoleValueBound(int roleValue) { return m_map.IsRoleValueBound(roleValue); }
  558. public bool IsDeviceBound(string deviceSN) { return m_map.IsDeviceBound(deviceSN); }
  559. public bool IsDeviceConnectedAndBound(uint deviceIndex) { return m_map.IsDeviceConnectedAndBound(deviceIndex); }
  560. public TRole GetBoundRoleByDevice(string deviceSN) { return m_info.ToRole(m_map.GetBoundRoleValueByDevice(deviceSN)); }
  561. public TRole GetBoundRoleByConnectedDevice(uint deviceIndex) { return m_info.ToRole(m_map.GetBoundRoleValueByConnectedDevice(deviceIndex)); }
  562. public string GetBoundDeviceByRole(TRole role) { return m_map.GetBoundDeviceByRoleValue(m_info.ToRoleValue(role)); }
  563. public string GetBoundDeviceByRoleValue(int roleValue) { return m_map.GetBoundDeviceByRoleValue(roleValue); }
  564. public int GetBoundRoleValueByDevice(string deviceSN) { return m_map.GetBoundRoleValueByDevice(deviceSN); }
  565. public int GetBoundRoleValueByConnectedDevice(uint deviceIndex) { return m_map.GetBoundRoleValueByConnectedDevice(deviceIndex); }
  566. }
  567. private static IndexedTable<Type, Map> s_mapTable;
  568. private static Map GetInternalMap(Type roleType)
  569. {
  570. if (s_mapTable == null)
  571. {
  572. s_mapTable = new IndexedTable<Type, Map>();
  573. }
  574. Map map;
  575. if (!s_mapTable.TryGetValue(roleType, out map))
  576. {
  577. var validateResult = ViveRoleEnum.ValidateViveRoleEnum(roleType);
  578. if (validateResult != ViveRoleEnumValidateResult.Valid)
  579. {
  580. Debug.LogWarning(roleType.Name + " is not valid ViveRole type. " + validateResult);
  581. return null;
  582. }
  583. map = new Map(roleType);
  584. s_mapTable.Add(roleType, map);
  585. }
  586. return map;
  587. }
  588. public static IMap GetMap(Type roleType)
  589. {
  590. return GetInternalMap(roleType);
  591. }
  592. private static GenericMap<TRole> GetInternalMap<TRole>()
  593. {
  594. var roleEnumType = typeof(TRole);
  595. if (GenericMap<TRole>.s_instance == null)
  596. {
  597. var validateResult = ViveRoleEnum.ValidateViveRoleEnum(roleEnumType);
  598. if (validateResult != ViveRoleEnumValidateResult.Valid)
  599. {
  600. Debug.LogWarning(roleEnumType.Name + " is not valid ViveRole type. " + validateResult);
  601. return null;
  602. }
  603. new GenericMap<TRole>();
  604. }
  605. return GenericMap<TRole>.s_instance;
  606. }
  607. public static IMap<TRole> GetMap<TRole>()
  608. {
  609. return GetInternalMap<TRole>();
  610. }
  611. public static void AssignMapHandler<TRole>(MapHandler<TRole> mapHandler)
  612. {
  613. Initialize();
  614. GetInternalMap(typeof(TRole)).Handler = mapHandler;
  615. }
  616. }
  617. }