webXRInput.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { Observable } from "../Misc/observable.js";
  2. import { WebXRInputSource } from "./webXRInputSource.js";
  3. import { WebXRMotionControllerManager } from "./motionController/webXRMotionControllerManager.js";
  4. /**
  5. * XR input used to track XR inputs such as controllers/rays
  6. */
  7. export class WebXRInput {
  8. /**
  9. * Initializes the WebXRInput
  10. * @param xrSessionManager the xr session manager for this session
  11. * @param xrCamera the WebXR camera for this session. Mainly used for teleportation
  12. * @param _options = initialization options for this xr input
  13. */
  14. constructor(
  15. /**
  16. * the xr session manager for this session
  17. */
  18. xrSessionManager,
  19. /**
  20. * the WebXR camera for this session. Mainly used for teleportation
  21. */
  22. xrCamera, _options = {}) {
  23. this.xrSessionManager = xrSessionManager;
  24. this.xrCamera = xrCamera;
  25. this._options = _options;
  26. /**
  27. * XR controllers being tracked
  28. */
  29. this.controllers = [];
  30. /**
  31. * Event when a controller has been connected/added
  32. */
  33. this.onControllerAddedObservable = new Observable();
  34. /**
  35. * Event when a controller has been removed/disconnected
  36. */
  37. this.onControllerRemovedObservable = new Observable();
  38. this._onInputSourcesChange = (event) => {
  39. this._addAndRemoveControllers(event.added, event.removed);
  40. };
  41. // Remove controllers when exiting XR
  42. this._sessionEndedObserver = this.xrSessionManager.onXRSessionEnded.add(() => {
  43. this._addAndRemoveControllers([], this.controllers.map((c) => {
  44. return c.inputSource;
  45. }));
  46. });
  47. this._sessionInitObserver = this.xrSessionManager.onXRSessionInit.add((session) => {
  48. session.addEventListener("inputsourceschange", this._onInputSourcesChange);
  49. });
  50. this._frameObserver = this.xrSessionManager.onXRFrameObservable.add((frame) => {
  51. // Update controller pose info
  52. this.controllers.forEach((controller) => {
  53. controller.updateFromXRFrame(frame, this.xrSessionManager.referenceSpace, this.xrCamera, this.xrSessionManager);
  54. });
  55. });
  56. if (this._options.customControllersRepositoryURL) {
  57. WebXRMotionControllerManager.BaseRepositoryUrl = this._options.customControllersRepositoryURL;
  58. }
  59. WebXRMotionControllerManager.UseOnlineRepository = !this._options.disableOnlineControllerRepository;
  60. if (WebXRMotionControllerManager.UseOnlineRepository) {
  61. // pre-load the profiles list to load the controllers quicker afterwards
  62. try {
  63. WebXRMotionControllerManager.UpdateProfilesList().catch(() => {
  64. WebXRMotionControllerManager.UseOnlineRepository = false;
  65. });
  66. }
  67. catch (e) {
  68. WebXRMotionControllerManager.UseOnlineRepository = false;
  69. }
  70. }
  71. }
  72. _addAndRemoveControllers(addInputs, removeInputs) {
  73. // Add controllers if they don't already exist
  74. const sources = this.controllers.map((c) => {
  75. return c.inputSource;
  76. });
  77. for (const input of addInputs) {
  78. if (sources.indexOf(input) === -1) {
  79. const controller = new WebXRInputSource(this.xrSessionManager.scene, input, {
  80. ...(this._options.controllerOptions || {}),
  81. forceControllerProfile: this._options.forceInputProfile,
  82. doNotLoadControllerMesh: this._options.doNotLoadControllerMeshes,
  83. disableMotionControllerAnimation: this._options.disableControllerAnimation,
  84. });
  85. this.controllers.push(controller);
  86. this.onControllerAddedObservable.notifyObservers(controller);
  87. }
  88. }
  89. // Remove and dispose of controllers to be disposed
  90. const keepControllers = [];
  91. const removedControllers = [];
  92. this.controllers.forEach((c) => {
  93. if (removeInputs.indexOf(c.inputSource) === -1) {
  94. keepControllers.push(c);
  95. }
  96. else {
  97. removedControllers.push(c);
  98. }
  99. });
  100. this.controllers = keepControllers;
  101. removedControllers.forEach((c) => {
  102. this.onControllerRemovedObservable.notifyObservers(c);
  103. c.dispose();
  104. });
  105. }
  106. /**
  107. * Disposes of the object
  108. */
  109. dispose() {
  110. this.controllers.forEach((c) => {
  111. c.dispose();
  112. });
  113. this.xrSessionManager.onXRFrameObservable.remove(this._frameObserver);
  114. this.xrSessionManager.onXRSessionInit.remove(this._sessionInitObserver);
  115. this.xrSessionManager.onXRSessionEnded.remove(this._sessionEndedObserver);
  116. this.onControllerAddedObservable.clear();
  117. this.onControllerRemovedObservable.clear();
  118. // clear the controller cache
  119. WebXRMotionControllerManager.ClearControllerCache();
  120. }
  121. }
  122. //# sourceMappingURL=webXRInput.js.map