SDKInputBindingSetup.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. using UnityEditor.PackageManager.Requests;
  6. using UnityEditor.PackageManager;
  7. using System;
  8. using System.IO;
  9. namespace Ximmerse.XR
  10. {
  11. /// <summary>
  12. /// Ximmerse SDK XR Setup binding.
  13. /// </summary>
  14. public static class SDKInputBindingSetup
  15. {
  16. [InitializeOnLoadMethod]
  17. static void AutoSetup()
  18. {
  19. GenerateXimmerseXRControllerInputBinding();
  20. }
  21. #region Internal Process
  22. /// <summary>
  23. /// The default input binding required to access ximmerse ring controller event.
  24. /// </summary>
  25. static List<InputAxis> axisList = new List<InputAxis>
  26. {
  27. #region Default Unity bindings
  28. new InputAxis()
  29. {
  30. name = "Horizontal",
  31. descriptiveName = "Horizontal",
  32. dead = 0.19f,
  33. axis = 4,
  34. type = 0,
  35. },
  36. new InputAxis()
  37. {
  38. name = "Vertical",
  39. descriptiveName = "Vertical",
  40. dead = 0.19f,
  41. axis = 5,
  42. type = 0,
  43. },
  44. new InputAxis()
  45. {
  46. name = "Fire1",
  47. positiveButton = "left ctrl",
  48. altPositiveButton = "mouse 0",
  49. dead = 0.19f,
  50. axis = 5,
  51. type = 0,
  52. },
  53. new InputAxis()
  54. {
  55. name = "Fire2",
  56. positiveButton = "left alt",
  57. altPositiveButton = "mouse 1",
  58. dead = 0.19f,
  59. axis = 5,
  60. type = 0,
  61. },
  62. new InputAxis()
  63. {
  64. name = "Fire3",
  65. positiveButton = "left shift",
  66. altPositiveButton = "mouse 2",
  67. dead = 0.19f,
  68. axis = 5,
  69. type = 0,
  70. },
  71. new InputAxis()
  72. {
  73. name = "Jump",
  74. positiveButton = "space",
  75. dead = 0.19f,
  76. axis = 5,
  77. type = 0,
  78. },
  79. new InputAxis()
  80. {
  81. name = "Mouse X",
  82. dead = 0,
  83. sensitivity = 0.1f,
  84. axis = 1,
  85. type = 1,
  86. },
  87. new InputAxis()
  88. {
  89. name = "Mouse Y",
  90. dead = 0,
  91. sensitivity = 0.1f,
  92. axis = 2,
  93. type = 1,
  94. },
  95. new InputAxis()
  96. {
  97. name = "Mouse ScrollWheel",
  98. dead = 0,
  99. sensitivity = 0.1f,
  100. axis = 3,
  101. type = 1,
  102. },
  103. new InputAxis()
  104. {
  105. name = "Submit",
  106. descriptiveName = "Submit",
  107. positiveButton = "joystick button 0",
  108. gravity = 0.0f,
  109. dead = 0.0f,
  110. sensitivity = 0.1f,
  111. type = 0,
  112. },
  113. new InputAxis()
  114. {
  115. name = "Cancel",
  116. descriptiveName = "Cancel",
  117. positiveButton = "joystick button 1",
  118. gravity = 0.0f,
  119. dead = 0.0f,
  120. sensitivity = 0.1f,
  121. type = 0,
  122. },
  123. #endregion
  124. #region LeftHand
  125. new InputAxis()
  126. {
  127. name = "XRI_Left_Primary2DAxis_Vertical",
  128. descriptiveName = "Device joystick/touchpad horizontal motion",
  129. dead = 0.19f,
  130. axis = 2,
  131. type = 2,
  132. },
  133. new InputAxis()
  134. {
  135. name = "XRI_Left_Primary2DAxis_Horizontal",
  136. descriptiveName = "Device joystick/touchpad horizontal motion",
  137. dead = 0.19f,
  138. axis = 1,
  139. type = 2,
  140. },
  141. new InputAxis()
  142. {
  143. name = "XRI_Left_Trigger",
  144. descriptiveName = "Device trigger axis",
  145. axis = 9,
  146. type = 2,
  147. },
  148. new InputAxis()
  149. {
  150. name = "XRI_Left_Grip",
  151. descriptiveName = "Device grip axis",
  152. axis = 11,
  153. type = 2,
  154. },
  155. new InputAxis()
  156. {
  157. name = "XRI_Left_IndexTouch",
  158. descriptiveName = "Device index finger proximity touch axis.",
  159. dead = 0.19f,
  160. axis = 13,
  161. type = 2,
  162. },
  163. // Button Data
  164. new InputAxis()
  165. {
  166. name = "XRI_Left_PrimaryButton",
  167. descriptiveName = "Device primary button",
  168. positiveButton = "joystick button 2",
  169. gravity = 1000.0f,
  170. sensitivity = 1000.0f,
  171. type = 0,
  172. },
  173. new InputAxis()
  174. {
  175. name = "XRI_Left_SecondaryButton",
  176. descriptiveName = "Device secondary button",
  177. positiveButton = "joystick button 3",
  178. gravity = 1000.0f,
  179. sensitivity = 1000.0f,
  180. type = 0,
  181. },
  182. new InputAxis()
  183. {
  184. name = "XRI_Left_GripButton",
  185. descriptiveName = "Device grip button",
  186. positiveButton = "joystick button 4",
  187. gravity = 0.0f,
  188. dead = 0.0f,
  189. sensitivity = 0.1f,
  190. type = 0,
  191. },
  192. new InputAxis()
  193. {
  194. name = "XRI_Left_TriggerButton",
  195. descriptiveName = "Device trigger button",
  196. positiveButton = "joystick button 14",
  197. gravity = 0.0f,
  198. dead = 0.0f,
  199. sensitivity = 0.1f,
  200. type = 0,
  201. },
  202. new InputAxis()
  203. {
  204. name = "XRI_Left_MenuButton",
  205. descriptiveName = "Device menu button",
  206. positiveButton = "joystick button 6",
  207. gravity = 1000.0f,
  208. sensitivity = 1000.0f,
  209. type = 0,
  210. },
  211. new InputAxis()
  212. {
  213. name = "XRI_Left_Primary2DAxisClick",
  214. descriptiveName = "Device stick/touchpad click",
  215. positiveButton = "joystick button 8",
  216. gravity = 0.0f,
  217. dead = 0.0f,
  218. sensitivity = 0.1f,
  219. type = 0,
  220. },
  221. new InputAxis()
  222. {
  223. name = "XRI_Left_Primary2DAxisTouch",
  224. descriptiveName = "Device stick/touchpad touch",
  225. positiveButton = "joystick button 16",
  226. gravity = 0.0f,
  227. dead = 0.0f,
  228. sensitivity = 0.1f,
  229. type = 0,
  230. },
  231. new InputAxis()
  232. {
  233. name = "XRI_Left_Thumbrest",
  234. descriptiveName = "Device thumbrest",
  235. positiveButton = "joystick button 18",
  236. gravity = 0.0f,
  237. dead = 0.0f,
  238. sensitivity = 0.1f,
  239. type = 0,
  240. },
  241. #endregion
  242. #region RightHand
  243. //######################################################################################################################################
  244. // Right Hand
  245. //######################################################################################################################################
  246. new InputAxis()
  247. {
  248. name = "XRI_Right_Primary2DAxis_Vertical",
  249. descriptiveName = "Device joystick/touchpad horizontal motion",
  250. dead = 0.19f,
  251. axis = 5,
  252. type = 2,
  253. },
  254. new InputAxis()
  255. {
  256. name = "XRI_Right_Primary2DAxis_Horizontal",
  257. descriptiveName = "Device joystick/touchpad horizontal motion",
  258. dead = 0.19f,
  259. axis = 4,
  260. type = 2,
  261. },
  262. new InputAxis()
  263. {
  264. name = "XRI_Right_Trigger",
  265. descriptiveName = "Device trigger axis",
  266. axis = 10,
  267. type = 2,
  268. },
  269. new InputAxis()
  270. {
  271. name = "XRI_Right_Grip",
  272. descriptiveName = "Device grip axis",
  273. axis = 12,
  274. type = 2,
  275. },
  276. new InputAxis()
  277. {
  278. name = "XRI_Right_IndexTouch",
  279. descriptiveName = "Device index finger proximity touch axis.",
  280. dead = 0.19f,
  281. axis = 14,
  282. type = 2,
  283. },
  284. // Button Data
  285. new InputAxis()
  286. {
  287. name = "XRI_Right_PrimaryButton",
  288. descriptiveName = "Device primary button",
  289. positiveButton = "joystick button 0",
  290. gravity = 1000.0f,
  291. sensitivity = 1000.0f,
  292. type = 0,
  293. },
  294. new InputAxis()
  295. {
  296. name = "XRI_Right_SecondaryButton",
  297. descriptiveName = "Device secondary button",
  298. positiveButton = "joystick button 1",
  299. gravity = 1000.0f,
  300. sensitivity = 1000.0f,
  301. type = 0,
  302. },
  303. new InputAxis()
  304. {
  305. name = "XRI_Right_GripButton",
  306. descriptiveName = "Device grip button",
  307. positiveButton = "joystick button 5",
  308. gravity = 0.0f,
  309. dead = 0.0f,
  310. sensitivity = 0.1f,
  311. type = 0,
  312. },
  313. new InputAxis()
  314. {
  315. name = "XRI_Right_TriggerButton",
  316. descriptiveName = "Device trigger button",
  317. positiveButton = "joystick button 15",
  318. gravity = 0.0f,
  319. dead = 0.0f,
  320. sensitivity = 0.1f,
  321. type = 0,
  322. },
  323. new InputAxis()
  324. {
  325. name = "XRI_Right_MenuButton",
  326. descriptiveName = "Device menu button",
  327. positiveButton = "joystick button 7",
  328. gravity = 1000.0f,
  329. sensitivity = 1000.0f,
  330. type = 0,
  331. },
  332. new InputAxis()
  333. {
  334. name = "XRI_Right_Primary2DAxisClick",
  335. descriptiveName = "Device stick/touchpad click",
  336. positiveButton = "joystick button 9",
  337. gravity = 0.0f,
  338. dead = 0.0f,
  339. sensitivity = 0.1f,
  340. type = 0,
  341. },
  342. new InputAxis()
  343. {
  344. name = "XRI_Right_Primary2DAxisTouch",
  345. descriptiveName = "Device stick/touchpad touch",
  346. positiveButton = "joystick button 17",
  347. gravity = 0.0f,
  348. dead = 0.0f,
  349. sensitivity = 0.1f,
  350. type = 0,
  351. },
  352. new InputAxis()
  353. {
  354. name = "XRI_Right_Thumbrest",
  355. descriptiveName = "Device thumbrest",
  356. positiveButton = "joystick button 19",
  357. gravity = 0.0f,
  358. dead = 0.0f,
  359. sensitivity = 0.1f,
  360. type = 0,
  361. },
  362. #endregion
  363. };
  364. // Same as InputAxis.h
  365. internal class InputAxis
  366. {
  367. public string name = "";
  368. public string descriptiveName = "";
  369. public string descriptiveNegativeName = "";
  370. public string negativeButton = "";
  371. public string positiveButton = "";
  372. public string altNegativeButton = "";
  373. public string altPositiveButton = "";
  374. public float gravity = 0.0f;
  375. public float dead = 0.001f;
  376. public float sensitivity = 1.0f;
  377. public bool snap = false;
  378. public bool invert = false;
  379. public int type = 0;
  380. public int axis = 0;
  381. public int joyNum = 0;
  382. }
  383. internal struct BindingData
  384. {
  385. public int newDataIndex;
  386. public int inputManagerIndex;
  387. public bool exists;
  388. }
  389. /// <summary>
  390. /// Main entrypoint for generating the XR Bindings and adding them to the Input Asset. The Custom uGUI editor calls this function when the user wishes to
  391. /// seed the Input Asset with XR bindings.
  392. /// </summary>
  393. static void GenerateXimmerseXRControllerInputBinding()
  394. {
  395. // seed map of axis data so we can whitewash against existing.
  396. Dictionary<string, BindingData> axisMap = new Dictionary<string, BindingData>();
  397. for (int i = 0; i < axisList.Count; ++i)
  398. {
  399. axisMap.Add(axisList[i].name, new BindingData() { newDataIndex = i, exists = false, inputManagerIndex = -1 });
  400. if (axisList[i].axis > 0)
  401. {
  402. axisList[i].axis--;
  403. }
  404. }
  405. // load the input asset
  406. var inputManagerAsset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/InputManager.asset")[0];
  407. if (inputManagerAsset != null)
  408. {
  409. var serializedObject = new SerializedObject(inputManagerAsset);
  410. var inputManagerCurrentData = serializedObject.FindProperty("m_Axes");
  411. if (inputManagerCurrentData != null)
  412. {
  413. List<InputAxis> currentInputData = new List<InputAxis>();
  414. LoadExistingDataAndCheckAgainstNewData(inputManagerCurrentData, ref axisMap, ref currentInputData);
  415. serializedObject.ApplyModifiedProperties();
  416. ApplyDataToInputManager(currentInputData, axisList, axisMap, ref inputManagerCurrentData);
  417. serializedObject.ApplyModifiedProperties();
  418. AssetDatabase.Refresh();
  419. }
  420. }
  421. }
  422. static void ApplyDataToInputManager(List<InputAxis> inputManagerData, List<InputAxis> newData, Dictionary<string, BindingData> newDataMap, ref SerializedProperty arrayRoot)
  423. {
  424. // likely will be larger than we need, but that's ok. it'll be big enough for all the data which is worst case
  425. arrayRoot.arraySize = inputManagerData.Count + newData.Count;
  426. int arrayIndex = inputManagerData.Count;
  427. // write everything that doesn't clash from our new data
  428. for (int i = 0; i < newData.Count; ++i)
  429. {
  430. BindingData bindingData;
  431. if (newDataMap.TryGetValue(newData[i].name, out bindingData))
  432. {
  433. if (bindingData.exists == true)
  434. {
  435. continue;
  436. }
  437. }
  438. var axisEntry = arrayRoot.GetArrayElementAtIndex(arrayIndex);
  439. WriteDataToInputAxis(newData[i], ref axisEntry);
  440. arrayIndex++;
  441. }
  442. arrayRoot.arraySize = arrayIndex;
  443. }
  444. static void WriteDataToInputAxis(InputAxis sourceData, ref SerializedProperty serializedProperty)
  445. {
  446. var iteratorProperty = serializedProperty.Copy();
  447. iteratorProperty.Next(true);
  448. do
  449. {
  450. switch (iteratorProperty.name)
  451. {
  452. case "m_Name":
  453. iteratorProperty.stringValue = sourceData.name;
  454. break;
  455. case "descriptiveName":
  456. iteratorProperty.stringValue = sourceData.descriptiveName;
  457. break;
  458. case "descriptiveNegativeName":
  459. iteratorProperty.stringValue = sourceData.descriptiveNegativeName;
  460. break;
  461. case "negativeButton":
  462. iteratorProperty.stringValue = sourceData.negativeButton;
  463. break;
  464. case "positiveButton":
  465. iteratorProperty.stringValue = sourceData.positiveButton;
  466. break;
  467. case "altNegativeButton":
  468. iteratorProperty.stringValue = sourceData.altNegativeButton;
  469. break;
  470. case "altPositiveButton":
  471. iteratorProperty.stringValue = sourceData.altPositiveButton;
  472. break;
  473. case "gravity":
  474. iteratorProperty.floatValue = sourceData.gravity;
  475. break;
  476. case "dead":
  477. iteratorProperty.floatValue = sourceData.dead;
  478. break;
  479. case "sensitivity":
  480. iteratorProperty.floatValue = sourceData.sensitivity;
  481. break;
  482. case "snap":
  483. iteratorProperty.boolValue = sourceData.snap;
  484. break;
  485. case "invert":
  486. iteratorProperty.boolValue = sourceData.invert;
  487. break;
  488. case "type":
  489. iteratorProperty.intValue = sourceData.type;
  490. break;
  491. case "axis":
  492. iteratorProperty.intValue = sourceData.axis;
  493. break;
  494. case "joyNum":
  495. iteratorProperty.intValue = sourceData.joyNum;
  496. break;
  497. }
  498. } while (iteratorProperty.Next(false));
  499. }
  500. static void LoadExistingDataAndCheckAgainstNewData(SerializedProperty arrayRoot, ref Dictionary<string, BindingData> newDataMap, ref List<InputAxis> existingData)
  501. {
  502. existingData.Clear();
  503. for (int i = 0; i < arrayRoot.arraySize; ++i)
  504. {
  505. InputAxis readData = new InputAxis();
  506. var axisEntry = arrayRoot.GetArrayElementAtIndex(i);
  507. var iteratorProperty = axisEntry.Copy();
  508. iteratorProperty.Next(true);
  509. do
  510. {
  511. switch (iteratorProperty.name)
  512. {
  513. case "m_Name":
  514. readData.name = iteratorProperty.stringValue;
  515. BindingData bindingData;
  516. if (newDataMap.TryGetValue(readData.name, out bindingData))
  517. {
  518. // using TryGetElement returns a copy, not very useful.
  519. bindingData.exists = true;
  520. bindingData.inputManagerIndex = i;
  521. newDataMap[readData.name] = bindingData;
  522. }
  523. break;
  524. case "descriptiveName":
  525. readData.descriptiveName = iteratorProperty.stringValue;
  526. break;
  527. case "descriptiveNegativeName":
  528. readData.descriptiveNegativeName = iteratorProperty.stringValue;
  529. break;
  530. case "negativeButton":
  531. readData.negativeButton = iteratorProperty.stringValue;
  532. break;
  533. case "positiveButton":
  534. readData.positiveButton = iteratorProperty.stringValue;
  535. break;
  536. case "altNegativeButton":
  537. readData.altNegativeButton = iteratorProperty.stringValue;
  538. break;
  539. case "altPositiveButton":
  540. readData.altPositiveButton = iteratorProperty.stringValue;
  541. break;
  542. case "gravity":
  543. readData.gravity = iteratorProperty.floatValue;
  544. break;
  545. case "dead":
  546. readData.dead = iteratorProperty.floatValue;
  547. break;
  548. case "sensitivity":
  549. readData.sensitivity = iteratorProperty.floatValue;
  550. break;
  551. case "snap":
  552. readData.snap = iteratorProperty.boolValue;
  553. break;
  554. case "invert":
  555. readData.invert = iteratorProperty.boolValue;
  556. break;
  557. case "type":
  558. readData.type = iteratorProperty.intValue;
  559. break;
  560. case "axis":
  561. readData.axis = iteratorProperty.intValue;
  562. break;
  563. case "joyNum":
  564. readData.joyNum = iteratorProperty.intValue;
  565. break;
  566. }
  567. } while (iteratorProperty.Next(false));
  568. existingData.Add(readData);
  569. }
  570. }
  571. #endregion
  572. }
  573. }