WebXRAbstractFeature.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { IWebXRFeature } from '../webXRFeaturesManager';
  2. import { Observer, Observable, EventState } from '../../../Misc/observable';
  3. import { Nullable } from '../../../types';
  4. import { WebXRSessionManager } from '../webXRSessionManager';
  5. /**
  6. * This is the base class for all WebXR features.
  7. * Since most features require almost the same resources and callbacks, this class can be used to simplify the development
  8. * Note that since the features manager is using the `IWebXRFeature` you are in no way obligated to use this class
  9. */
  10. export abstract class WebXRAbstractFeature implements IWebXRFeature {
  11. /**
  12. * Construct a new (abstract) webxr feature
  13. * @param _xrSessionManager the xr session manager for this feature
  14. */
  15. constructor(protected _xrSessionManager: WebXRSessionManager) {
  16. }
  17. private _attached: boolean = false;
  18. private _removeOnDetach: {
  19. observer: Nullable<Observer<any>>;
  20. observable: Observable<any>;
  21. }[] = [];
  22. /**
  23. * Is this feature attached
  24. */
  25. public get attached() {
  26. return this._attached;
  27. }
  28. /**
  29. * Should auto-attach be disabled?
  30. */
  31. public disableAutoAttach: boolean = false;
  32. /**
  33. * attach this feature
  34. *
  35. * @returns true if successful, false is failed or already attached
  36. */
  37. public attach(force?: boolean): boolean {
  38. if (!force) {
  39. if (this.attached) {
  40. return false;
  41. }
  42. } else {
  43. if (this.attached) {
  44. // detach first, to be sure
  45. this.detach();
  46. }
  47. }
  48. this._attached = true;
  49. this._addNewAttachObserver(this._xrSessionManager.onXRFrameObservable, (frame) => this._onXRFrame(frame));
  50. return true;
  51. }
  52. /**
  53. * detach this feature.
  54. *
  55. * @returns true if successful, false if failed or already detached
  56. */
  57. public detach(): boolean {
  58. if (!this._attached) {
  59. this.disableAutoAttach = true;
  60. return false;
  61. }
  62. this._attached = false;
  63. this._removeOnDetach.forEach((toRemove) => {
  64. toRemove.observable.remove(toRemove.observer);
  65. });
  66. return true;
  67. }
  68. /**
  69. * Dispose this feature and all of the resources attached
  70. */
  71. public dispose(): void {
  72. this.detach();
  73. }
  74. /**
  75. * Code in this function will be executed on each xrFrame received from the browser.
  76. * This function will not execute after the feature is detached.
  77. * @param _xrFrame the current frame
  78. */
  79. protected abstract _onXRFrame(_xrFrame: XRFrame): void;
  80. /**
  81. * This is used to register callbacks that will automatically be removed when detach is called.
  82. * @param observable the observable to which the observer will be attached
  83. * @param callback the callback to register
  84. */
  85. protected _addNewAttachObserver<T>(observable: Observable<T>, callback: (eventData: T, eventState: EventState) => void) {
  86. this._removeOnDetach.push({
  87. observable,
  88. observer: observable.add(callback)
  89. });
  90. }
  91. }