deviceSourceManager.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { DeviceType } from "./deviceEnums.js";
  2. import { Observable } from "../../Misc/observable.js";
  3. import { InternalDeviceSourceManager } from "../internalDeviceSourceManager.js";
  4. /**
  5. * Class to keep track of devices
  6. */
  7. export class DeviceSourceManager {
  8. // Public Functions
  9. /**
  10. * Gets a DeviceSource, given a type and slot
  11. * @param deviceType - Type of Device
  12. * @param deviceSlot - Slot or ID of device
  13. * @returns DeviceSource
  14. */
  15. getDeviceSource(deviceType, deviceSlot) {
  16. if (deviceSlot === undefined) {
  17. if (this._firstDevice[deviceType] === undefined) {
  18. return null;
  19. }
  20. deviceSlot = this._firstDevice[deviceType];
  21. }
  22. if (!this._devices[deviceType] || this._devices[deviceType][deviceSlot] === undefined) {
  23. return null;
  24. }
  25. return this._devices[deviceType][deviceSlot];
  26. }
  27. /**
  28. * Gets an array of DeviceSource objects for a given device type
  29. * @param deviceType - Type of Device
  30. * @returns All available DeviceSources of a given type
  31. */
  32. getDeviceSources(deviceType) {
  33. // If device type hasn't had any devices connected yet, return empty array.
  34. if (!this._devices[deviceType]) {
  35. return [];
  36. }
  37. return this._devices[deviceType].filter((source) => {
  38. return !!source;
  39. });
  40. }
  41. /**
  42. * Default constructor
  43. * @param engine - Used to get canvas (if applicable)
  44. */
  45. constructor(engine) {
  46. const numberOfDeviceTypes = Object.keys(DeviceType).length / 2;
  47. this._devices = new Array(numberOfDeviceTypes);
  48. this._firstDevice = new Array(numberOfDeviceTypes);
  49. this._engine = engine;
  50. if (!this._engine._deviceSourceManager) {
  51. this._engine._deviceSourceManager = new InternalDeviceSourceManager(engine);
  52. }
  53. this._engine._deviceSourceManager._refCount++;
  54. // Observables
  55. this.onDeviceConnectedObservable = new Observable((observer) => {
  56. for (const devices of this._devices) {
  57. if (devices) {
  58. for (const device of devices) {
  59. if (device) {
  60. this.onDeviceConnectedObservable.notifyObserver(observer, device);
  61. }
  62. }
  63. }
  64. }
  65. });
  66. this.onDeviceDisconnectedObservable = new Observable();
  67. this._engine._deviceSourceManager.registerManager(this);
  68. this._onDisposeObserver = engine.onDisposeObservable.add(() => {
  69. this.dispose();
  70. });
  71. }
  72. /**
  73. * Dispose of DeviceSourceManager
  74. */
  75. dispose() {
  76. // Null out observable refs
  77. this.onDeviceConnectedObservable.clear();
  78. this.onDeviceDisconnectedObservable.clear();
  79. if (this._engine._deviceSourceManager) {
  80. this._engine._deviceSourceManager.unregisterManager(this);
  81. if (--this._engine._deviceSourceManager._refCount < 1) {
  82. this._engine._deviceSourceManager.dispose();
  83. delete this._engine._deviceSourceManager;
  84. }
  85. }
  86. this._engine.onDisposeObservable.remove(this._onDisposeObserver);
  87. }
  88. // Hidden Functions
  89. /**
  90. * @param deviceSource - Source to add
  91. * @internal
  92. */
  93. _addDevice(deviceSource) {
  94. if (!this._devices[deviceSource.deviceType]) {
  95. this._devices[deviceSource.deviceType] = new Array();
  96. }
  97. if (!this._devices[deviceSource.deviceType][deviceSource.deviceSlot]) {
  98. this._devices[deviceSource.deviceType][deviceSource.deviceSlot] = deviceSource;
  99. this._updateFirstDevices(deviceSource.deviceType);
  100. }
  101. this.onDeviceConnectedObservable.notifyObservers(deviceSource);
  102. }
  103. /**
  104. * @param deviceType - DeviceType
  105. * @param deviceSlot - DeviceSlot
  106. * @internal
  107. */
  108. _removeDevice(deviceType, deviceSlot) {
  109. const deviceSource = this._devices[deviceType]?.[deviceSlot]; // Grab local reference to use before removing from devices
  110. this.onDeviceDisconnectedObservable.notifyObservers(deviceSource);
  111. if (this._devices[deviceType]?.[deviceSlot]) {
  112. delete this._devices[deviceType][deviceSlot];
  113. }
  114. // Even if we don't delete a device, we should still check for the first device as things may have gotten out of sync.
  115. this._updateFirstDevices(deviceType);
  116. }
  117. /**
  118. * @param deviceType - DeviceType
  119. * @param deviceSlot - DeviceSlot
  120. * @param eventData - Event
  121. * @internal
  122. */
  123. _onInputChanged(deviceType, deviceSlot, eventData) {
  124. this._devices[deviceType]?.[deviceSlot]?.onInputChangedObservable.notifyObservers(eventData);
  125. }
  126. // Private Functions
  127. _updateFirstDevices(type) {
  128. switch (type) {
  129. case DeviceType.Keyboard:
  130. case DeviceType.Mouse:
  131. this._firstDevice[type] = 0;
  132. break;
  133. case DeviceType.Touch:
  134. case DeviceType.DualSense:
  135. case DeviceType.DualShock:
  136. case DeviceType.Xbox:
  137. case DeviceType.Switch:
  138. case DeviceType.Generic: {
  139. delete this._firstDevice[type];
  140. // eslint-disable-next-line no-case-declarations
  141. const devices = this._devices[type];
  142. if (devices) {
  143. for (let i = 0; i < devices.length; i++) {
  144. if (devices[i]) {
  145. this._firstDevice[type] = i;
  146. break;
  147. }
  148. }
  149. }
  150. break;
  151. }
  152. }
  153. }
  154. }
  155. //# sourceMappingURL=deviceSourceManager.js.map