@skewedaspect/sage 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/classes/bindings/toggle.d.ts +4 -4
  2. package/dist/classes/bindings/trigger.d.ts +4 -4
  3. package/dist/classes/bindings/value.d.ts +4 -4
  4. package/dist/classes/entity.d.ts +2 -2
  5. package/dist/classes/eventBus.d.ts +1 -1
  6. package/dist/classes/gameEngine.d.ts +33 -8
  7. package/dist/classes/input/gamepad.d.ts +3 -3
  8. package/dist/classes/input/keyboard.d.ts +3 -3
  9. package/dist/classes/input/mouse.d.ts +3 -3
  10. package/dist/classes/input/readers/gamepad.d.ts +1 -1
  11. package/dist/classes/input/readers/keyboard.d.ts +1 -1
  12. package/dist/classes/input/readers/mouse.d.ts +1 -1
  13. package/dist/classes/loggers/consoleBackend.d.ts +1 -1
  14. package/dist/classes/loggers/nullBackend.d.ts +1 -1
  15. package/dist/engines/scene.d.ts +6 -2
  16. package/dist/interfaces/binding.d.ts +4 -11
  17. package/dist/interfaces/entity.d.ts +9 -5
  18. package/dist/interfaces/game.d.ts +2 -2
  19. package/dist/managers/binding.d.ts +9 -5
  20. package/dist/managers/entity.d.ts +14 -9
  21. package/dist/managers/game.d.ts +11 -5
  22. package/dist/managers/input.d.ts +5 -5
  23. package/dist/managers/level.d.ts +5 -2
  24. package/dist/sage.d.ts +16 -14
  25. package/dist/sage.es.js +541 -356
  26. package/dist/sage.es.js.map +1 -1
  27. package/dist/sage.umd.js +1 -1
  28. package/dist/sage.umd.js.map +1 -1
  29. package/dist/utils/graphics.d.ts +1 -1
  30. package/dist/utils/logger.d.ts +3 -3
  31. package/package.json +13 -13
  32. package/src/classes/bindings/toggle.ts +0 -261
  33. package/src/classes/bindings/trigger.ts +0 -211
  34. package/src/classes/bindings/value.ts +0 -227
  35. package/src/classes/entity.ts +0 -256
  36. package/src/classes/eventBus.ts +0 -259
  37. package/src/classes/gameEngine.ts +0 -125
  38. package/src/classes/input/gamepad.ts +0 -388
  39. package/src/classes/input/keyboard.ts +0 -189
  40. package/src/classes/input/mouse.ts +0 -276
  41. package/src/classes/input/readers/gamepad.ts +0 -179
  42. package/src/classes/input/readers/keyboard.ts +0 -123
  43. package/src/classes/input/readers/mouse.ts +0 -133
  44. package/src/classes/loggers/consoleBackend.ts +0 -135
  45. package/src/classes/loggers/nullBackend.ts +0 -51
  46. package/src/engines/scene.ts +0 -112
  47. package/src/images/sage_logo.svg +0 -172
  48. package/src/images/sage_logo_shape.svg +0 -146
  49. package/src/interfaces/action.ts +0 -30
  50. package/src/interfaces/binding.ts +0 -191
  51. package/src/interfaces/entity.ts +0 -21
  52. package/src/interfaces/game.ts +0 -44
  53. package/src/interfaces/input.ts +0 -221
  54. package/src/interfaces/logger.ts +0 -118
  55. package/src/managers/binding.ts +0 -729
  56. package/src/managers/entity.ts +0 -252
  57. package/src/managers/game.ts +0 -111
  58. package/src/managers/input.ts +0 -233
  59. package/src/managers/level.ts +0 -261
  60. package/src/sage.ts +0 -122
  61. package/src/types/global.d.ts +0 -11
  62. package/src/utils/capabilities.ts +0 -16
  63. package/src/utils/graphics.ts +0 -148
  64. package/src/utils/logger.ts +0 -225
  65. package/src/utils/physics.ts +0 -16
  66. package/src/utils/version.ts +0 -11
package/dist/sage.es.js CHANGED
@@ -1,9 +1,9 @@
1
- var I = Object.defineProperty;
2
- var k = (a, e, t) => e in a ? I(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
3
- var n = (a, e, t) => k(a, typeof e != "symbol" ? e + "" : e, t);
4
- import { FreeCamera as V, Vector3 as b, HemisphericLight as G, MeshBuilder as D, PhysicsAggregate as E, PhysicsShapeType as C, Scene as L, NullEngine as B, WebGPUEngine as K, Engine as U, HavokPlugin as R } from "@babylonjs/core";
5
- import T from "@babylonjs/havok";
6
- const m = "0.5.0";
1
+ var A = Object.defineProperty;
2
+ var I = (r, e, t) => e in r ? A(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
+ var n = (r, e, t) => I(r, typeof e != "symbol" ? e + "" : e, t);
4
+ import { FreeCamera as G, Vector3 as b, HemisphericLight as V, MeshBuilder as E, PhysicsAggregate as C, PhysicsShapeType as D, Scene as B, NullEngine as L, WebGPUEngine as K, Engine as T, HavokPlugin as U } from "@babylonjs/core";
5
+ import R from "@babylonjs/havok";
6
+ const m = "0.6.0";
7
7
  class z {
8
8
  /**
9
9
  * Creates an instance of SkewedAspectGameEngine.
@@ -15,7 +15,7 @@ class z {
15
15
  * @param engines - The engines used in the game.
16
16
  * @param managers - The managers used in the game.
17
17
  */
18
- constructor(e, t, s, i, o, r, c) {
18
+ constructor(e, t, i, s, o, c, a) {
19
19
  n(this, "canvas");
20
20
  n(this, "renderEngine");
21
21
  n(this, "physics");
@@ -24,25 +24,91 @@ class z {
24
24
  n(this, "eventBus");
25
25
  n(this, "logger");
26
26
  n(this, "_log");
27
- this.canvas = e, this.renderEngine = t, this.physics = s, this.eventBus = i, this.logger = o, this.engines = r, this.managers = c, this._log = o.getLogger("GameEngine");
27
+ // Lifecycle hooks
28
+ n(this, "_beforeStartHook", null);
29
+ n(this, "_onStartHook", null);
30
+ n(this, "_onTeardownHook", null);
31
+ this.canvas = e, this.renderEngine = t, this.physics = i, this.eventBus = s, this.logger = o, this.engines = c, this.managers = a, this._log = o.getLogger("GameEngine");
28
32
  }
29
33
  //------------------------------------------------------------------------------------------------------------------
30
34
  // Public API
31
35
  //------------------------------------------------------------------------------------------------------------------
36
+ /**
37
+ * Register a function to be called before the game engine starts
38
+ * @param hook - Async function to be called before start
39
+ * @throws Error if a hook is already registered
40
+ */
41
+ onBeforeStart(e) {
42
+ if (this._beforeStartHook !== null)
43
+ throw new Error("A beforeStart hook is already registered. Only one hook is allowed per lifecycle event.");
44
+ this._beforeStartHook = e;
45
+ }
46
+ /**
47
+ * Register a function to be called after the game engine starts
48
+ * @param hook - Async function to be called after start
49
+ * @throws Error if a hook is already registered
50
+ */
51
+ onStart(e) {
52
+ if (this._onStartHook !== null)
53
+ throw new Error("An onStart hook is already registered. Only one hook is allowed per lifecycle event.");
54
+ this._onStartHook = e;
55
+ }
56
+ /**
57
+ * Register a function to be called when the game engine stops
58
+ * @param hook - Async function to be called during teardown
59
+ * @throws Error if a hook is already registered
60
+ */
61
+ onTeardown(e) {
62
+ if (this._onTeardownHook !== null)
63
+ throw new Error("An onTeardown hook is already registered. Only one hook is allowed per lifecycle event.");
64
+ this._onTeardownHook = e;
65
+ }
32
66
  /**
33
67
  * Starts the game engine.
34
68
  */
35
69
  async start() {
36
- this._log.info(`Starting SkewedAspect Game Engine (Version: ${m})...`), await this.managers.gameManager.start(this.canvas), this._log.info("Game engine started successfully");
70
+ this._log.info(`Starting SkewedAspect Game Engine (Version: ${m})...`), this._beforeStartHook && (this._log.debug("Executing beforeStart hook..."), await this._beforeStartHook(this)), await this.managers.gameManager.start(this.canvas), this._log.info("Game engine started successfully"), this._onStartHook && (this._log.debug("Executing onStart hook..."), await this._onStartHook(this));
37
71
  }
38
72
  /**
39
73
  * Stops the game engine.
40
74
  */
41
75
  async stop() {
42
- this._log.info(`Stopping SkewedAspect Game Engine (Version: ${m})...`), await this.managers.gameManager.stop(), this._log.info("Game engine stopped successfully");
76
+ this._log.info(`Stopping SkewedAspect Game Engine (Version: ${m})...`);
77
+ let e = null;
78
+ if (this._onTeardownHook)
79
+ try {
80
+ this._log.debug("Executing onTeardown hook..."), await this._onTeardownHook(this);
81
+ } catch (t) {
82
+ this._log.error(`Error in onTeardown hook: ${t}`), e = e || t;
83
+ }
84
+ for (const t of Object.keys(this.managers)) {
85
+ const i = this.managers[t];
86
+ if (typeof i.$teardown == "function")
87
+ try {
88
+ this._log.debug(`Tearing down manager: ${t}`), await i.$teardown();
89
+ } catch (s) {
90
+ this._log.error(`Error tearing down manager ${t}: ${s}`), e = e || s;
91
+ }
92
+ }
93
+ for (const t of Object.keys(this.engines)) {
94
+ const i = this.engines[t];
95
+ if (typeof i.$teardown == "function")
96
+ try {
97
+ this._log.debug(`Tearing down engine: ${t}`), await i.$teardown();
98
+ } catch (s) {
99
+ this._log.error(`Error tearing down engine ${t}: ${s}`), e = e || s;
100
+ }
101
+ }
102
+ try {
103
+ await this.managers.gameManager.stop();
104
+ } catch (t) {
105
+ this._log.error(`Error stopping game manager: ${t}`), e = e || t;
106
+ }
107
+ if (this._log.info("Game engine stopped successfully"), e)
108
+ throw e;
43
109
  }
44
110
  }
45
- class W {
111
+ class P {
46
112
  constructor() {
47
113
  n(this, "timers");
48
114
  this.timers = /* @__PURE__ */ new Map();
@@ -73,9 +139,9 @@ class W {
73
139
  * Format a log message with category, timestamp and log level
74
140
  */
75
141
  formatMessage(e, t) {
76
- const s = /* @__PURE__ */ new Date(), i = s.getHours() % 12 || 12, o = s.getMinutes().toString().padStart(2, "0"), r = s.getSeconds().toString().padStart(2, "0"), c = s.getHours() >= 12 ? "PM" : "AM", h = `[${i}:${o}:${r} ${c}]`, u = t.toUpperCase();
142
+ const i = /* @__PURE__ */ new Date(), s = i.getHours() % 12 || 12, o = i.getMinutes().toString().padStart(2, "0"), c = i.getSeconds().toString().padStart(2, "0"), a = i.getHours() >= 12 ? "PM" : "AM", h = `[${s}:${o}:${c} ${a}]`, d = t.toUpperCase();
77
143
  return [
78
- `${h} %c${u}%c (${e}): `,
144
+ `${h} %c${d}%c (${e}): `,
79
145
  // Format string with placeholders
80
146
  this.getStyleForLevel(t),
81
147
  // Level style
@@ -85,69 +151,74 @@ class W {
85
151
  // Reset style
86
152
  ];
87
153
  }
88
- trace(e, t, ...s) {
89
- const [i, o, r, c] = this.formatMessage(e, "trace");
90
- console.debug(i, o, r, c, t, ...s);
154
+ trace(e, t, ...i) {
155
+ const [s, o, c, a] = this.formatMessage(e, "trace");
156
+ console.debug(s, o, c, a, t, ...i);
91
157
  }
92
- debug(e, t, ...s) {
93
- const [i, o, r, c] = this.formatMessage(e, "debug");
94
- console.debug(i, o, r, c, t, ...s);
158
+ debug(e, t, ...i) {
159
+ const [s, o, c, a] = this.formatMessage(e, "debug");
160
+ console.debug(s, o, c, a, t, ...i);
95
161
  }
96
- info(e, t, ...s) {
97
- const [i, o, r, c] = this.formatMessage(e, "info");
98
- console.info(i, o, r, c, t, ...s);
162
+ info(e, t, ...i) {
163
+ const [s, o, c, a] = this.formatMessage(e, "info");
164
+ console.info(s, o, c, a, t, ...i);
99
165
  }
100
- warn(e, t, ...s) {
101
- const [i, o, r, c] = this.formatMessage(e, "warn");
102
- console.warn(i, o, r, c, t, ...s);
166
+ warn(e, t, ...i) {
167
+ const [s, o, c, a] = this.formatMessage(e, "warn");
168
+ console.warn(s, o, c, a, t, ...i);
103
169
  }
104
- error(e, t, ...s) {
105
- const [i, o, r, c] = this.formatMessage(e, "error");
106
- console.error(i, o, r, c, t, ...s);
170
+ error(e, t, ...i) {
171
+ const [s, o, c, a] = this.formatMessage(e, "error");
172
+ console.error(s, o, c, a, t, ...i);
107
173
  }
108
174
  /**
109
175
  * Start a timer with the specified label.
110
176
  */
111
177
  time(e, t) {
112
- const s = `${e}:${t}`;
113
- this.timers.set(s, performance.now());
178
+ const i = `${e}:${t}`;
179
+ this.timers.set(i, performance.now());
114
180
  }
115
181
  /**
116
182
  * End a timer and log the elapsed time.
117
183
  */
118
184
  timeEnd(e, t) {
119
- const s = `${e}:${t}`, i = this.timers.get(s);
120
- if (i !== void 0) {
121
- const o = performance.now() - i;
122
- this.timers.delete(s);
123
- const [r, c, h, u] = this.formatMessage(e, "timer");
124
- console.info(`${r} Timer '${t}' completed in ${o.toFixed(2)}ms`, c, h, u);
185
+ const i = `${e}:${t}`, s = this.timers.get(i);
186
+ if (s !== void 0) {
187
+ const o = performance.now() - s;
188
+ this.timers.delete(i);
189
+ const [c, a, h, d] = this.formatMessage(e, "timer");
190
+ console.info(
191
+ `${c} Timer '${t}' completed in ${o.toFixed(2)}ms`,
192
+ a,
193
+ h,
194
+ d
195
+ );
125
196
  } else
126
197
  console.warn(`[${e}]: Timer '${t}' does not exist`);
127
198
  }
128
199
  }
129
- class P {
130
- trace(e, t, ...s) {
200
+ class H {
201
+ trace(e, t, ...i) {
131
202
  }
132
- debug(e, t, ...s) {
203
+ debug(e, t, ...i) {
133
204
  }
134
- info(e, t, ...s) {
205
+ info(e, t, ...i) {
135
206
  }
136
- warn(e, t, ...s) {
207
+ warn(e, t, ...i) {
137
208
  }
138
- error(e, t, ...s) {
209
+ error(e, t, ...i) {
139
210
  }
140
211
  time(e, t) {
141
212
  }
142
213
  timeEnd(e, t) {
143
214
  }
144
215
  }
145
- class l {
146
- constructor(e, t = "none", s = new P()) {
216
+ class g {
217
+ constructor(e, t = "none", i = new H()) {
147
218
  n(this, "category");
148
219
  n(this, "backend");
149
220
  n(this, "minLevel");
150
- this.category = e, this.backend = s, this.minLevel = t;
221
+ this.category = e, this.backend = i, this.minLevel = t;
151
222
  }
152
223
  /**
153
224
  * Update the logger's backend and minimum level
@@ -198,14 +269,14 @@ class l {
198
269
  }
199
270
  }
200
271
  }
201
- class F {
272
+ class O {
202
273
  /**
203
274
  * Create a new LoggingUtility.
204
275
  *
205
276
  * @param level - The minimum logging level (defaults to INFO)
206
277
  * @param backend - The logging backend to use (defaults to ConsoleBackend)
207
278
  */
208
- constructor(e = "debug", t = new W()) {
279
+ constructor(e = "debug", t = new P()) {
209
280
  n(this, "backend");
210
281
  n(this, "level");
211
282
  n(this, "loggers");
@@ -218,7 +289,7 @@ class F {
218
289
  */
219
290
  setBackend(e) {
220
291
  this.backend = e, this.loggers.forEach((t) => {
221
- t instanceof l && t.updateSettings(this.backend, this.level);
292
+ t instanceof g && t.updateSettings(this.backend, this.level);
222
293
  });
223
294
  }
224
295
  /**
@@ -228,7 +299,7 @@ class F {
228
299
  */
229
300
  setLevel(e) {
230
301
  this.level = e, this.loggers.forEach((t) => {
231
- t instanceof l && t.updateSettings(this.backend, this.level);
302
+ t instanceof g && t.updateSettings(this.backend, this.level);
232
303
  });
233
304
  }
234
305
  /**
@@ -244,14 +315,14 @@ class F {
244
315
  * @returns A Logger instance for the specified category
245
316
  */
246
317
  getLogger(e) {
247
- this.loggers.has(e) || this.loggers.set(e, new l(e, this.level, this.backend));
318
+ this.loggers.has(e) || this.loggers.set(e, new g(e, this.level, this.backend));
248
319
  const t = this.loggers.get(e);
249
320
  if (t === void 0)
250
321
  throw new Error(`Failed to create logger for category: ${e}`);
251
322
  return t;
252
323
  }
253
324
  }
254
- class O {
325
+ class W {
255
326
  /**
256
327
  * Creates a new GameEventBus instance
257
328
  *
@@ -272,7 +343,7 @@ class O {
272
343
  * Logger instance
273
344
  */
274
345
  n(this, "_log");
275
- this._log = (e == null ? void 0 : e.getLogger("EventBus")) || new l("EventBus");
346
+ this._log = (e == null ? void 0 : e.getLogger("EventBus")) || new g("EventBus");
276
347
  }
277
348
  /**
278
349
  * Subscribe with automatic detection:
@@ -297,14 +368,14 @@ class O {
297
368
  */
298
369
  subscribeExact(e, t) {
299
370
  this._log.debug(`Adding exact subscription for: ${e}`);
300
- let s = this.directMap.get(e);
301
- s || (s = /* @__PURE__ */ new Set(), this.directMap.set(e, s));
302
- const i = {
371
+ let i = this.directMap.get(e);
372
+ i || (i = /* @__PURE__ */ new Set(), this.directMap.set(e, i));
373
+ const s = {
303
374
  callback: (o) => t(o)
304
375
  // runtime "type-lie" cast
305
376
  };
306
- return s.add(i), () => {
307
- this._log.debug(`Removing exact subscription for: ${e}`), s.delete(i), s.size === 0 && this.directMap.delete(e);
377
+ return i.add(s), () => {
378
+ this._log.debug(`Removing exact subscription for: ${e}`), i.delete(s), i.size === 0 && this.directMap.delete(e);
308
379
  };
309
380
  }
310
381
  /**
@@ -318,18 +389,20 @@ class O {
318
389
  * @returns {Unsubscribe} function that unsubscribes this pattern-based subscription.
319
390
  */
320
391
  subscribePattern(e, t) {
321
- let s;
392
+ let i;
322
393
  if (typeof e == "string") {
323
394
  const o = e.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&").replace(/\*/g, ".*");
324
- s = new RegExp(`^${o}$`), this._log.debug(`Adding pattern subscription for string: ${e}, regex: ${s.toString()}`);
395
+ i = new RegExp(`^${o}$`), this._log.debug(
396
+ `Adding pattern subscription for string: ${e}, regex: ${i.toString()}`
397
+ );
325
398
  } else
326
- s = e, this._log.debug(`Adding pattern subscription for regex: ${s.toString()}`);
327
- const i = {
328
- pattern: s,
399
+ i = e, this._log.debug(`Adding pattern subscription for regex: ${i.toString()}`);
400
+ const s = {
401
+ pattern: i,
329
402
  callback: (o) => t(o)
330
403
  };
331
- return this.patternSubs.add(i), () => {
332
- this._log.debug(`Removing pattern subscription: ${s.toString()}`), this.patternSubs.delete(i);
404
+ return this.patternSubs.add(s), () => {
405
+ this._log.debug(`Removing pattern subscription: ${i.toString()}`), this.patternSubs.delete(s);
333
406
  };
334
407
  }
335
408
  /**
@@ -342,48 +415,59 @@ class O {
342
415
  publish(e) {
343
416
  this._log.trace(`Publishing event: ${e.type}`, e);
344
417
  let t = 0;
345
- const s = this.directMap.get(e.type);
346
- if (s) {
347
- t += s.size;
348
- for (const i of s)
349
- Promise.resolve().then(() => i.callback(e));
418
+ const i = this.directMap.get(e.type);
419
+ if (i) {
420
+ t += i.size;
421
+ for (const s of i)
422
+ Promise.resolve().then(() => s.callback(e));
350
423
  }
351
- for (const i of this.patternSubs)
352
- i.pattern && i.pattern.test(e.type) && (t++, Promise.resolve().then(() => i.callback(e)));
424
+ for (const s of this.patternSubs)
425
+ s.pattern && s.pattern.test(e.type) && (t++, Promise.resolve().then(() => s.callback(e)));
353
426
  t === 0 ? this._log.debug(`No subscribers found for event: ${e.type}`) : this._log.trace(`Event ${e.type} dispatched to ${t} subscribers`);
354
427
  }
355
428
  }
356
- class N {
357
- constructor(e, t, s) {
429
+ class F {
430
+ constructor(e, t, i) {
358
431
  n(this, "_engine");
359
432
  n(this, "_physics");
360
433
  n(this, "_log");
361
- this._engine = e, this._physics = t, this._log = (s == null ? void 0 : s.getLogger("SceneEngine")) || new l("SceneEngine");
434
+ this._engine = e, this._physics = t, this._log = (i == null ? void 0 : i.getLogger("SceneEngine")) || new g("SceneEngine");
362
435
  }
363
436
  async _buildDemoScene(e, t) {
364
437
  this._log.debug("Building demo scene..."), this._log.trace("Creating camera...");
365
- const s = new V("camera1", new b(0, 5, -10), e);
366
- s.setTarget(b.Zero()), s.attachControl(t, !0), this._log.trace("Creating light...");
367
- const i = new G("light", new b(0, 1, 0), e);
368
- i.intensity = 0.7, this._log.trace("Creating sphere...");
369
- const o = D.CreateSphere("sphere", { diameter: 2, segments: 32 }, e);
438
+ const i = new G("camera1", new b(0, 5, -10), e);
439
+ i.setTarget(b.Zero()), i.attachControl(t, !0), this._log.trace("Creating light...");
440
+ const s = new V("light", new b(0, 1, 0), e);
441
+ s.intensity = 0.7, this._log.trace("Creating sphere...");
442
+ const o = E.CreateSphere("sphere", { diameter: 2, segments: 32 }, e);
370
443
  o.position.y = 4, this._log.trace("Creating ground...");
371
- const r = D.CreateGround("ground", { width: 10, height: 10 }, e);
372
- this._log.trace("Adding physics to sphere..."), new E(o, C.SPHERE, { mass: 1, restitution: 0.75 }, e), this._log.trace("Adding physics to ground..."), new E(r, C.BOX, { mass: 0 }, e), this._log.debug("Demo scene built successfully");
444
+ const c = E.CreateGround("ground", { width: 10, height: 10 }, e);
445
+ this._log.trace("Adding physics to sphere..."), new C(
446
+ o,
447
+ D.SPHERE,
448
+ { mass: 1, restitution: 0.75 },
449
+ e
450
+ ), this._log.trace("Adding physics to ground..."), new C(c, D.BOX, { mass: 0 }, e), this._log.debug("Demo scene built successfully");
373
451
  }
374
452
  // TODO: This needs more logic to handle different scenes
375
453
  async loadScene(e) {
376
454
  this._log.info("Loading scene..."), this._log.time("sceneLoad"), this._log.debug("Creating new scene...");
377
- const t = new L(this._engine);
455
+ const t = new B(this._engine);
378
456
  return this._log.debug("Enabling physics with gravity (0, -9.8, 0)..."), t.enablePhysics(new b(0, -9.8, 0), this._physics), await this._buildDemoScene(t, e), this._log.timeEnd("sceneLoad"), this._log.info("Scene loaded successfully"), t;
379
457
  }
458
+ /**
459
+ * Tears down the scene engine and cleans up any resources
460
+ */
461
+ async $teardown() {
462
+ return this._log.info("Tearing down SceneEngine"), this._log.info("SceneEngine torn down successfully"), Promise.resolve();
463
+ }
380
464
  }
381
- const J = [
465
+ const N = [
382
466
  "trigger",
383
467
  "toggle",
384
468
  "value"
385
469
  ];
386
- class Y {
470
+ class J {
387
471
  //------------------------------------------------------------------------------------------------------------------
388
472
  /**
389
473
  * Create a new trigger binding
@@ -393,7 +477,7 @@ class Y {
393
477
  * @param reader - Input reader to read values from
394
478
  * @param options - Binding configuration options
395
479
  */
396
- constructor(e, t, s, i = {}) {
480
+ constructor(e, t, i, s = {}) {
397
481
  n(this, "type", "trigger");
398
482
  n(this, "action");
399
483
  n(this, "context");
@@ -404,7 +488,7 @@ class Y {
404
488
  n(this, "_threshold");
405
489
  // State tracking
406
490
  n(this, "_lastDigitalState", !1);
407
- this.action = e, this.deviceID = t, this.reader = s, this.context = i.context, this._edgeMode = i.edgeMode ?? "rising", this._threshold = i.threshold ?? 0.5;
491
+ this.action = e, this.deviceID = t, this.reader = i, this.context = s.context, this._edgeMode = s.edgeMode ?? "rising", this._threshold = s.threshold ?? 0.5;
408
492
  }
409
493
  //------------------------------------------------------------------------------------------------------------------
410
494
  // Public Getters
@@ -431,39 +515,39 @@ class Y {
431
515
  * @returns True if an action was triggered, false otherwise
432
516
  */
433
517
  process(e, t) {
434
- const s = this.reader.getValue(e) ?? !1, i = typeof s == "boolean" ? s : s >= this._threshold;
518
+ const i = this.reader.getValue(e) ?? !1, s = typeof i == "boolean" ? i : i >= this._threshold;
435
519
  let o = !1;
436
520
  switch (this._edgeMode) {
437
521
  case "rising":
438
- o = i && !this._lastDigitalState;
522
+ o = s && !this._lastDigitalState;
439
523
  break;
440
524
  case "falling":
441
- o = !i && this._lastDigitalState;
525
+ o = !s && this._lastDigitalState;
442
526
  break;
443
527
  case "both":
444
- o = i !== this._lastDigitalState;
528
+ o = s !== this._lastDigitalState;
445
529
  break;
446
530
  }
447
- if (this._lastDigitalState = i, o) {
448
- let r;
531
+ if (this._lastDigitalState = s, o) {
532
+ let c;
449
533
  if (this.action.type === "analog") {
450
- let h = typeof s == "number" ? s : s ? 1 : 0;
534
+ let h = typeof i == "number" ? i : i ? 1 : 0;
451
535
  if (this.action.minValue !== void 0 || this.action.maxValue !== void 0) {
452
- const u = this.action.minValue ?? 0, g = this.action.maxValue ?? 1;
453
- h = u + h * (g - u);
536
+ const d = this.action.minValue ?? 0, _ = this.action.maxValue ?? 1;
537
+ h = d + h * (_ - d);
454
538
  }
455
- r = h;
539
+ c = h;
456
540
  } else
457
- r = !0;
458
- const c = {
541
+ c = !0;
542
+ const a = {
459
543
  type: `action:${this.action.name}`,
460
544
  payload: {
461
- value: r,
545
+ value: c,
462
546
  deviceId: this.deviceID,
463
547
  context: this.context
464
548
  }
465
549
  };
466
- t.publish(c);
550
+ t.publish(a);
467
551
  }
468
552
  }
469
553
  /**
@@ -484,7 +568,7 @@ class Y {
484
568
  };
485
569
  }
486
570
  }
487
- class H {
571
+ class Y {
488
572
  //------------------------------------------------------------------------------------------------------------------
489
573
  /**
490
574
  * Create a new toggle binding
@@ -494,7 +578,7 @@ class H {
494
578
  * @param reader - Input reader to read values from
495
579
  * @param options - Binding configuration options
496
580
  */
497
- constructor(e, t, s, i = {}) {
581
+ constructor(e, t, i, s = {}) {
498
582
  n(this, "type", "toggle");
499
583
  n(this, "action");
500
584
  n(this, "context");
@@ -509,7 +593,7 @@ class H {
509
593
  // State tracking
510
594
  n(this, "_lastDigitalState", !1);
511
595
  n(this, "_toggleState");
512
- this.action = e, this.deviceID = t, this.reader = s, this.context = i.context, this._invert = i.invert ?? !1, this._threshold = i.threshold ?? 0.5, this._initialState = i.initialState ?? !1, this._toggleState = this._initialState, this._onValue = i.onValue ?? !0, this._offValue = i.offValue ?? !1;
596
+ this.action = e, this.deviceID = t, this.reader = i, this.context = s.context, this._invert = s.invert ?? !1, this._threshold = s.threshold ?? 0.5, this._initialState = s.initialState ?? !1, this._toggleState = this._initialState, this._onValue = s.onValue ?? !0, this._offValue = s.offValue ?? !1;
513
597
  }
514
598
  //------------------------------------------------------------------------------------------------------------------
515
599
  // Public Getters
@@ -578,8 +662,8 @@ class H {
578
662
  * @param eventBus - Event bus to emit action events to
579
663
  */
580
664
  process(e, t) {
581
- const s = this.reader.getValue(e) ?? !1, i = typeof s == "boolean" ? s : s >= this._threshold, o = this._invert ? !i && this._lastDigitalState : i && !this._lastDigitalState;
582
- this._lastDigitalState = i, o && (this._toggleState = !this._toggleState, t.publish({
665
+ const i = this.reader.getValue(e) ?? !1, s = typeof i == "boolean" ? i : i >= this._threshold, o = this._invert ? !s && this._lastDigitalState : s && !this._lastDigitalState;
666
+ this._lastDigitalState = s, o && (this._toggleState = !this._toggleState, t.publish({
583
667
  type: `action:${this.action.name}`,
584
668
  payload: {
585
669
  value: this.value,
@@ -613,7 +697,7 @@ class H {
613
697
  };
614
698
  }
615
699
  }
616
- class X {
700
+ class j {
617
701
  //------------------------------------------------------------------------------------------------------------------
618
702
  /**
619
703
  * Create a new value binding
@@ -623,7 +707,7 @@ class X {
623
707
  * @param reader - Input reader to read values from
624
708
  * @param options - Binding configuration options
625
709
  */
626
- constructor(e, t, s, i = {}) {
710
+ constructor(e, t, i, s = {}) {
627
711
  n(this, "type", "value");
628
712
  n(this, "action");
629
713
  n(this, "context");
@@ -641,11 +725,11 @@ class X {
641
725
  n(this, "_max");
642
726
  // State tracking
643
727
  n(this, "_lastValue");
644
- this.action = e, this.deviceID = t, this.reader = s, this.context = i.context, this._scale = i.scale ?? 1, this._offset = i.offset ?? 0, this._invert = i.invert ?? !1, this._emitOnChange = i.emitOnChange ?? !0, this._deadzone = i.deadzone ?? 0, this._onValue = i.onValue ?? !0, this._offValue = i.offValue ?? !1;
728
+ this.action = e, this.deviceID = t, this.reader = i, this.context = s.context, this._scale = s.scale ?? 1, this._offset = s.offset ?? 0, this._invert = s.invert ?? !1, this._emitOnChange = s.emitOnChange ?? !0, this._deadzone = s.deadzone ?? 0, this._onValue = s.onValue ?? !0, this._offValue = s.offValue ?? !1;
645
729
  const o = this.action.type === "analog" ? this.action.minValue ?? Number.NEGATIVE_INFINITY : Number.NEGATIVE_INFINITY;
646
- this._min = i.min ?? o;
647
- const r = this.action.type === "analog" ? this.action.maxValue ?? Number.POSITIVE_INFINITY : Number.POSITIVE_INFINITY;
648
- this._max = i.max ?? r;
730
+ this._min = s.min ?? o;
731
+ const c = this.action.type === "analog" ? this.action.maxValue ?? Number.POSITIVE_INFINITY : Number.POSITIVE_INFINITY;
732
+ this._max = s.max ?? c;
649
733
  }
650
734
  //------------------------------------------------------------------------------------------------------------------
651
735
  /**
@@ -677,13 +761,13 @@ class X {
677
761
  * @returns True if a value was emitted, false otherwise
678
762
  */
679
763
  process(e, t) {
680
- const s = this.reader.getValue(e);
681
- if (s === void 0)
682
- return;
683
- const i = typeof s == "boolean" ? s ? 1 : 0 : s;
764
+ const i = this.reader.getValue(e);
684
765
  if (i === void 0)
685
766
  return;
686
- let o = this._deadzone > 0 && Math.abs(i) < this._deadzone ? 0 : i;
767
+ const s = typeof i == "boolean" ? i ? 1 : 0 : i;
768
+ if (s === void 0)
769
+ return;
770
+ let o = this._deadzone > 0 && Math.abs(s) < this._deadzone ? 0 : s;
687
771
  o = (this._invert ? -o : o) * this._scale + this._offset, o = Math.max(this._min, Math.min(this._max, o)), !(this._emitOnChange && this._lastValue === o) && (this._lastValue = o, t.publish({
688
772
  type: `action:${this.action.name}`,
689
773
  payload: {
@@ -711,7 +795,7 @@ class X {
711
795
  };
712
796
  }
713
797
  }
714
- class w {
798
+ class S {
715
799
  /**
716
800
  * Creates a new KeyboardValueReader
717
801
  *
@@ -753,7 +837,7 @@ class w {
753
837
  * @returns A new KeyboardValueReader instance
754
838
  */
755
839
  static fromString(e, t = {}) {
756
- return new w(e, t);
840
+ return new S(e, t);
757
841
  }
758
842
  /**
759
843
  * Returns a JSON-serializable representation of this keyboard value reader
@@ -803,8 +887,8 @@ class x {
803
887
  return t ? t.pressed : void 0;
804
888
  }
805
889
  case "position": {
806
- const [t, s] = this.sourceKey.split(":");
807
- return !t || !s || t !== "absolute" && t !== "relative" || s !== "x" && s !== "y" ? void 0 : e.position[t][s];
890
+ const [t, i] = this.sourceKey.split(":");
891
+ return !t || !i || t !== "absolute" && t !== "relative" || i !== "x" && i !== "y" ? void 0 : e.position[t][i];
808
892
  }
809
893
  case "wheel": {
810
894
  const t = this.sourceKey === "deltaX" || this.sourceKey === "deltaY" || this.sourceKey === "deltaZ";
@@ -821,10 +905,13 @@ class x {
821
905
  * @returns A new MouseValueReader instance
822
906
  */
823
907
  static fromString(e) {
824
- const [t, ...s] = e.split(":"), i = s.join(":");
825
- if (!t || !i)
908
+ const [t, ...i] = e.split(":"), s = i.join(":");
909
+ if (!t || !s)
826
910
  throw new Error(`Invalid mouse source format: ${e}`);
827
- return new x(t, i);
911
+ return new x(
912
+ t,
913
+ s
914
+ );
828
915
  }
829
916
  /**
830
917
  * Returns a JSON-serializable representation of this mouse value reader
@@ -839,7 +926,7 @@ class x {
839
926
  };
840
927
  }
841
928
  }
842
- class S {
929
+ class $ {
843
930
  /**
844
931
  * Creates a new GamepadValueReader
845
932
  *
@@ -847,7 +934,7 @@ class S {
847
934
  * @param sourceKey - The specific key for this input type
848
935
  * @param options - Configuration options
849
936
  */
850
- constructor(e, t, s = {}) {
937
+ constructor(e, t, i = {}) {
851
938
  /**
852
939
  * The type of gamepad input
853
940
  */
@@ -868,7 +955,7 @@ class S {
868
955
  * Whether to invert axis values
869
956
  */
870
957
  n(this, "invert");
871
- this.sourceType = e, this.sourceKey = t, this.useAnalogValue = s.useAnalogValue || !1, this.deadzone = s.deadzone || 0.1, this.invert = s.invert || !1;
958
+ this.sourceType = e, this.sourceKey = t, this.useAnalogValue = i.useAnalogValue || !1, this.deadzone = i.deadzone || 0.1, this.invert = i.invert || !1;
872
959
  }
873
960
  /**
874
961
  * Gets the value of the input source based on the current state
@@ -899,10 +986,14 @@ class S {
899
986
  * @returns A new GamepadValueReader instance
900
987
  */
901
988
  static fromString(e, t = {}) {
902
- const [s, i] = e.split(":");
903
- if (!s || !i)
989
+ const [i, s] = e.split(":");
990
+ if (!i || !s)
904
991
  throw new Error(`Invalid gamepad source format: ${e}`);
905
- return new S(s, i, t);
992
+ return new $(
993
+ i,
994
+ s,
995
+ t
996
+ );
906
997
  }
907
998
  /**
908
999
  * Returns a JSON-serializable representation of this gamepad value reader
@@ -922,7 +1013,7 @@ class S {
922
1013
  };
923
1014
  }
924
1015
  }
925
- class j {
1016
+ class X {
926
1017
  /**
927
1018
  * Creates an instance of BindingManager.
928
1019
  *
@@ -944,9 +1035,9 @@ class j {
944
1035
  n(this, "_eventBus");
945
1036
  /** Logger instance */
946
1037
  n(this, "_log");
947
- this._eventBus = e, this._eventBus.subscribe("input:changed", (s) => {
948
- s.payload && this.$handleInput(s.payload.device, s.payload.state);
949
- }), this._log = (t == null ? void 0 : t.getLogger("BindingManager")) || new l("BindingManager"), this._log.debug("BindingManager initialized");
1038
+ this._eventBus = e, this._eventBus.subscribe("input:changed", (i) => {
1039
+ i.payload && this.$handleInput(i.payload.device, i.payload.state);
1040
+ }), this._log = (t == null ? void 0 : t.getLogger("BindingManager")) || new g("BindingManager"), this._log.debug("BindingManager initialized");
950
1041
  }
951
1042
  //------------------------------------------------------------------------------------------------------------------
952
1043
  // Private Methods
@@ -968,11 +1059,11 @@ class j {
968
1059
  * @returns The context object
969
1060
  */
970
1061
  _getOrCreateContext(e, t = !0) {
971
- let s = this._contexts.get(e);
972
- return s || (s = {
1062
+ let i = this._contexts.get(e);
1063
+ return i || (i = {
973
1064
  name: e,
974
1065
  exclusive: t
975
- }, this._contexts.set(e, s), this._log.debug(`Auto-created context "${e}" (exclusive: ${t})`)), s;
1066
+ }, this._contexts.set(e, i), this._log.debug(`Auto-created context "${e}" (exclusive: ${t})`)), i;
976
1067
  }
977
1068
  /**
978
1069
  * Deactivate all exclusive contexts except the specified one
@@ -982,11 +1073,11 @@ class j {
982
1073
  */
983
1074
  _deactivateExclusiveContexts(e) {
984
1075
  const t = [];
985
- for (const s of this._activeContexts) {
986
- if (s === e)
1076
+ for (const i of this._activeContexts) {
1077
+ if (i === e)
987
1078
  continue;
988
- const i = this._contexts.get(s);
989
- i != null && i.exclusive && (this._activeContexts.delete(s), t.push(s));
1079
+ const s = this._contexts.get(i);
1080
+ s != null && s.exclusive && (this._activeContexts.delete(i), t.push(i));
990
1081
  }
991
1082
  return t;
992
1083
  }
@@ -1000,23 +1091,38 @@ class j {
1000
1091
  const t = this._actions.get(e.action);
1001
1092
  if (!t)
1002
1093
  return this._log.warn(`Cannot create binding: Action "${e.action}" not found.`), null;
1003
- const { deviceID: s, ...i } = e.input;
1094
+ const { deviceID: i, ...s } = e.input;
1004
1095
  switch (e.type) {
1005
1096
  case "trigger":
1006
- return new Y(t, s, this._createInputSourceFromDefinition(i), {
1007
- ...e.options || {},
1008
- context: e.context
1009
- });
1097
+ return new J(
1098
+ t,
1099
+ i,
1100
+ this._createInputSourceFromDefinition(s),
1101
+ {
1102
+ ...e.options || {},
1103
+ context: e.context
1104
+ }
1105
+ );
1010
1106
  case "toggle":
1011
- return new H(t, s, this._createInputSourceFromDefinition(i), {
1012
- ...e.options || {},
1013
- context: e.context
1014
- });
1107
+ return new Y(
1108
+ t,
1109
+ i,
1110
+ this._createInputSourceFromDefinition(s),
1111
+ {
1112
+ ...e.options || {},
1113
+ context: e.context
1114
+ }
1115
+ );
1015
1116
  case "value":
1016
- return new X(t, s, this._createInputSourceFromDefinition(i), {
1017
- ...e.options || {},
1018
- context: e.context
1019
- });
1117
+ return new j(
1118
+ t,
1119
+ i,
1120
+ this._createInputSourceFromDefinition(s),
1121
+ {
1122
+ ...e.options || {},
1123
+ context: e.context
1124
+ }
1125
+ );
1020
1126
  default:
1021
1127
  return this._log.error(`Binding type not implemented: ${e.type}`), null;
1022
1128
  }
@@ -1031,18 +1137,28 @@ class j {
1031
1137
  _createInputSourceFromDefinition(e) {
1032
1138
  switch (e.type) {
1033
1139
  case "keyboard":
1034
- return new w(e.sourceKey, e.options);
1140
+ return new S(
1141
+ e.sourceKey,
1142
+ e.options
1143
+ );
1035
1144
  case "mouse": {
1036
1145
  const t = e.sourceType;
1037
1146
  if (!(t === "button" || t === "position" || t === "wheel"))
1038
1147
  throw new Error(`Invalid mouse source type: ${t}`);
1039
- return new x(t, e.sourceKey);
1148
+ return new x(
1149
+ t,
1150
+ e.sourceKey
1151
+ );
1040
1152
  }
1041
1153
  case "gamepad": {
1042
1154
  const t = e.sourceType;
1043
1155
  if (!(t === "button" || t === "axis"))
1044
1156
  throw new Error(`Invalid gamepad source type: ${t}`);
1045
- return new S(t, e.sourceKey, e.options);
1157
+ return new $(
1158
+ t,
1159
+ e.sourceKey,
1160
+ e.options
1161
+ );
1046
1162
  }
1047
1163
  default:
1048
1164
  throw new Error(`Unsupported input source type: ${e.type}`);
@@ -1058,10 +1174,10 @@ class j {
1058
1174
  * @param state - Current input state
1059
1175
  */
1060
1176
  $handleInput(e, t) {
1061
- const s = this._bindings.get(e.id);
1062
- if (!(!s || s.length === 0) && !(this._activeContexts.size === 0 && s.some((i) => i.context)))
1063
- for (const i of s)
1064
- this._isBindingContextActive(i) && i.process(t, this._eventBus);
1177
+ const i = this._bindings.get(e.id);
1178
+ if (!(!i || i.length === 0) && !(this._activeContexts.size === 0 && i.some((s) => s.context)))
1179
+ for (const s of i)
1180
+ this._isBindingContextActive(s) && s.process(t, this._eventBus);
1065
1181
  }
1066
1182
  //------------------------------------------------------------------------------------------------------------------
1067
1183
  // Action Management API
@@ -1101,8 +1217,8 @@ class j {
1101
1217
  * @returns The registered context
1102
1218
  */
1103
1219
  registerContext(e, t = !0) {
1104
- const s = this._getOrCreateContext(e, t);
1105
- return s.exclusive !== t && (s.exclusive = t, this._log.info(`Updated context "${e}" exclusivity: ${t}`)), s;
1220
+ const i = this._getOrCreateContext(e, t);
1221
+ return i.exclusive !== t && (i.exclusive = t, this._log.info(`Updated context "${e}" exclusivity: ${t}`)), i;
1106
1222
  }
1107
1223
  /**
1108
1224
  * Activates a context, enabling all bindings associated with it.
@@ -1111,14 +1227,14 @@ class j {
1111
1227
  * @param contextName - The name of the context to activate
1112
1228
  */
1113
1229
  activateContext(e) {
1114
- const s = this._getOrCreateContext(e).exclusive;
1115
- this._log.debug(`Activating context "${e}" (exclusive: ${s})`);
1116
- const i = this._activeContexts.has(e);
1117
- if (s) {
1230
+ const i = this._getOrCreateContext(e).exclusive;
1231
+ this._log.debug(`Activating context "${e}" (exclusive: ${i})`);
1232
+ const s = this._activeContexts.has(e);
1233
+ if (i) {
1118
1234
  const o = this._deactivateExclusiveContexts(e);
1119
1235
  o.length > 0 && this._log.info(`Deactivated exclusive contexts: ${o.join(", ")}`);
1120
1236
  }
1121
- i || (this._activeContexts.add(e), this._log.info(`Context "${e}" activated${s ? " as exclusive" : ""}`));
1237
+ s || (this._activeContexts.add(e), this._log.info(`Context "${e}" activated${i ? " as exclusive" : ""}`));
1122
1238
  }
1123
1239
  /**
1124
1240
  * Deactivates a context, disabling all bindings associated with it
@@ -1165,7 +1281,7 @@ class j {
1165
1281
  */
1166
1282
  $registerBinding(e) {
1167
1283
  var t;
1168
- if (!J.includes(e.type))
1284
+ if (!N.includes(e.type))
1169
1285
  throw new Error(`Invalid binding type: ${e.type}`);
1170
1286
  e.context && !this._contexts.has(e.context) && this.registerContext(e.context), this._bindings.has(e.deviceID) || this._bindings.set(e.deviceID, []), (t = this._bindings.get(e.deviceID)) == null || t.push(e), this._log.debug(`Registered ${e.type} binding for "${e.action.name}" in context "${e.context || null}"`);
1171
1287
  }
@@ -1186,15 +1302,15 @@ class j {
1186
1302
  */
1187
1303
  unregisterBindings(e, t = null) {
1188
1304
  this._log.debug(`Unregistering all bindings for action "${e}" in context "${t}"`);
1189
- let s = 0;
1190
- for (const [i, o] of this._bindings.entries()) {
1191
- const r = o.filter((c) => {
1192
- const h = c.context || null, u = c.action.name !== e || h !== t;
1193
- return u || s++, u;
1305
+ let i = 0;
1306
+ for (const [s, o] of this._bindings.entries()) {
1307
+ const c = o.filter((a) => {
1308
+ const h = a.context || null, d = a.action.name !== e || h !== t;
1309
+ return d || i++, d;
1194
1310
  });
1195
- r.length !== o.length && this._bindings.set(i, r);
1311
+ c.length !== o.length && this._bindings.set(s, c);
1196
1312
  }
1197
- this._log.info(`Removed ${s} bindings for action "${e}" in context "${t}"`);
1313
+ this._log.info(`Removed ${i} bindings for action "${e}" in context "${t}"`);
1198
1314
  }
1199
1315
  /**
1200
1316
  * Gets all bindings for a specific action
@@ -1204,13 +1320,13 @@ class j {
1204
1320
  * @returns Array of bindings that match the criteria
1205
1321
  */
1206
1322
  getBindingsForAction(e, t) {
1207
- const s = [];
1208
- for (const i of this._bindings.values())
1209
- for (const o of i) {
1210
- const r = o.context || null;
1211
- o.action.name === e && (!t || r === t) && s.push(o);
1323
+ const i = [];
1324
+ for (const s of this._bindings.values())
1325
+ for (const o of s) {
1326
+ const c = o.context || null;
1327
+ o.action.name === e && (!t || c === t) && i.push(o);
1212
1328
  }
1213
- return s;
1329
+ return i;
1214
1330
  }
1215
1331
  //------------------------------------------------------------------------------------------------------------------
1216
1332
  // Configuration Management API
@@ -1222,24 +1338,24 @@ class j {
1222
1338
  */
1223
1339
  exportConfiguration() {
1224
1340
  this._log.debug("Exporting binding configuration");
1225
- const e = [...this._actions.values()].map((i) => i.type === "analog" ? {
1226
- name: i.name,
1227
- type: i.type,
1228
- minValue: i.minValue ?? 0,
1229
- maxValue: i.maxValue ?? 1
1230
- } : i), t = [];
1231
- for (const i of this._bindings.values())
1232
- for (const o of i)
1341
+ const e = [...this._actions.values()].map((s) => s.type === "analog" ? {
1342
+ name: s.name,
1343
+ type: s.type,
1344
+ minValue: s.minValue ?? 0,
1345
+ maxValue: s.maxValue ?? 1
1346
+ } : s), t = [];
1347
+ for (const s of this._bindings.values())
1348
+ for (const o of s)
1233
1349
  t.push(o.toJSON());
1234
- const s = [...this._contexts.values()].map((i) => ({
1235
- name: i.name,
1236
- exclusive: i.exclusive,
1237
- active: this._activeContexts.has(i.name)
1350
+ const i = [...this._contexts.values()].map((s) => ({
1351
+ name: s.name,
1352
+ exclusive: s.exclusive,
1353
+ active: this._activeContexts.has(s.name)
1238
1354
  }));
1239
- return this._log.info(`Configuration exported: ${e.length} actions, ${t.length} bindings, ${s.length} contexts`), {
1355
+ return this._log.info(`Configuration exported: ${e.length} actions, ${t.length} bindings, ${i.length} contexts`), {
1240
1356
  actions: e,
1241
1357
  bindings: t,
1242
- contexts: s
1358
+ contexts: i
1243
1359
  };
1244
1360
  }
1245
1361
  /**
@@ -1256,29 +1372,36 @@ class j {
1256
1372
  for (const t of e.bindings)
1257
1373
  try {
1258
1374
  this.registerBinding(t);
1259
- } catch (s) {
1260
- s instanceof Error && this._log.error(`Failed to import binding for action "${t.action}": ${s.message}`);
1375
+ } catch (i) {
1376
+ i instanceof Error && this._log.error(`Failed to import binding for action "${t.action}": ${i.message}`);
1261
1377
  }
1262
1378
  this._log.info(`Configuration imported: ${e.actions.length} actions, ${e.bindings.length} bindings, ${e.contexts.length} contexts`);
1263
1379
  }
1380
+ /**
1381
+ * Tears down the binding manager and cleans up any resources
1382
+ */
1383
+ async $teardown() {
1384
+ return this._log.info("Tearing down BindingManager"), this._bindings.clear(), this._actions.clear(), this._contexts.clear(), this._activeContexts.clear(), this._log.info("BindingManager torn down successfully"), Promise.resolve();
1385
+ }
1264
1386
  }
1265
- function A() {
1387
+ function w() {
1266
1388
  return typeof window < "u" && typeof window.document < "u";
1267
1389
  }
1268
- function $() {
1269
- return A() && !!window.navigator.gpu;
1390
+ function k() {
1391
+ return w() && !!window.navigator.gpu;
1270
1392
  }
1271
1393
  class Z {
1272
1394
  //------------------------------------------------------------------------------------------------------------------
1273
- constructor(e, t, s, i, o) {
1395
+ constructor(e, t, i, s, o) {
1274
1396
  n(this, "_engine");
1275
1397
  n(this, "_entityManager");
1276
1398
  n(this, "_inputManager");
1277
1399
  n(this, "_sceneEngine");
1278
1400
  n(this, "_currentScene", null);
1279
1401
  n(this, "_log");
1402
+ n(this, "_boundResizeHandler");
1280
1403
  n(this, "started", !1);
1281
- this._engine = e, this._sceneEngine = t, this._entityManager = s, this._inputManager = i, this._log = (o == null ? void 0 : o.getLogger("GameManager")) || new l("GameManager"), A() && window.addEventListener("resize", this._resizeHandler.bind(this));
1404
+ this._engine = e, this._sceneEngine = t, this._entityManager = i, this._inputManager = s, this._log = (o == null ? void 0 : o.getLogger("GameManager")) || new g("GameManager"), this._boundResizeHandler = this._resizeHandler.bind(this), w() && window.addEventListener("resize", this._boundResizeHandler);
1282
1405
  }
1283
1406
  _renderLoop() {
1284
1407
  const e = this._engine.getDeltaTime();
@@ -1296,8 +1419,15 @@ class Z {
1296
1419
  async stop() {
1297
1420
  this.started = !1, this._engine.stopRenderLoop(), this._log.info("SkewedAspect Game Engine stopped successfully");
1298
1421
  }
1422
+ /**
1423
+ * Tears down any resources held by the GameManager
1424
+ * This handles unregistering event listeners and any other cleanup
1425
+ */
1426
+ async $teardown() {
1427
+ this._log.info("Tearing down GameManager"), this.started && await this.stop(), w() && window.removeEventListener("resize", this._boundResizeHandler), this._log.info("GameManager torn down successfully");
1428
+ }
1299
1429
  }
1300
- class ue {
1430
+ class de {
1301
1431
  constructor() {
1302
1432
  n(this, "entity", null);
1303
1433
  }
@@ -1325,7 +1455,7 @@ class q {
1325
1455
  * @param behaviors - An array of behaviors to attach to the entity.
1326
1456
  * @param eventBus
1327
1457
  */
1328
- constructor(e, t, s, i) {
1458
+ constructor(e, t, i, s) {
1329
1459
  /** The unique identifier of the entity. */
1330
1460
  n(this, "id");
1331
1461
  /** The type of the entity. */
@@ -1338,8 +1468,8 @@ class q {
1338
1468
  n(this, "eventBus");
1339
1469
  /** The event subscriptions for the entity. */
1340
1470
  n(this, "subscriptions", /* @__PURE__ */ new Map());
1341
- this.id = crypto.randomUUID(), this.type = e, this.state = s, this.eventBus = t;
1342
- for (const o of i)
1471
+ this.id = crypto.randomUUID(), this.type = e, this.state = i, this.eventBus = t;
1472
+ for (const o of s)
1343
1473
  this.attachBehavior(new o());
1344
1474
  }
1345
1475
  //------------------------------------------------------------------------------------------------------------------
@@ -1361,8 +1491,8 @@ class q {
1361
1491
  */
1362
1492
  $update(e) {
1363
1493
  var t;
1364
- for (const s of this.behaviors.values())
1365
- (t = s.update) == null || t.call(s, e, this.state);
1494
+ for (const i of this.behaviors.values())
1495
+ (t = i.update) == null || t.call(i, e, this.state);
1366
1496
  }
1367
1497
  /**
1368
1498
  * Destroys the entity by calling the destroy method of its behaviors.
@@ -1388,12 +1518,12 @@ class q {
1388
1518
  if (this.behaviors.has(e.name))
1389
1519
  throw new Error(`Behavior ${e.name} is already attached to this entity.`);
1390
1520
  for (const t of e.eventSubscriptions) {
1391
- const s = this.subscriptions.get(t);
1392
- if (s)
1393
- s.count++;
1521
+ const i = this.subscriptions.get(t);
1522
+ if (i)
1523
+ i.count++;
1394
1524
  else {
1395
- const i = this.eventBus.subscribe(t, this.$processEvent.bind(this));
1396
- this.subscriptions.set(t, { count: 1, unsubscribe: i });
1525
+ const s = this.eventBus.subscribe(t, this.$processEvent.bind(this));
1526
+ this.subscriptions.set(t, { count: 1, unsubscribe: s });
1397
1527
  }
1398
1528
  }
1399
1529
  this.behaviors.set(e.name, e), e.$setEntity(this);
@@ -1405,9 +1535,9 @@ class q {
1405
1535
  detachBehavior(e) {
1406
1536
  const t = this.behaviors.get(e);
1407
1537
  if (t) {
1408
- for (const s of t.eventSubscriptions) {
1409
- const i = this.subscriptions.get(s);
1410
- i && (i.count--, i.count <= 0 && (i.unsubscribe(), this.subscriptions.delete(s)));
1538
+ for (const i of t.eventSubscriptions) {
1539
+ const s = this.subscriptions.get(i);
1540
+ s && (s.count--, s.count <= 0 && (s.unsubscribe(), this.subscriptions.delete(i)));
1411
1541
  }
1412
1542
  this.behaviors.delete(t.name), t.$setEntity(null);
1413
1543
  }
@@ -1420,7 +1550,7 @@ class Q {
1420
1550
  * @param logger - The logging utility to use
1421
1551
  * @param bindingManager - The binding manager for registering actions
1422
1552
  */
1423
- constructor(e, t, s) {
1553
+ constructor(e, t, i) {
1424
1554
  /** The event bus for the entity manager. */
1425
1555
  n(this, "eventBus");
1426
1556
  /** A map of entities managed by the entity manager. */
@@ -1431,7 +1561,7 @@ class Q {
1431
1561
  n(this, "bindingManager");
1432
1562
  /** Logger instance */
1433
1563
  n(this, "_log");
1434
- this.eventBus = e, this.bindingManager = s, this._log = (t == null ? void 0 : t.getLogger("EntityManager")) || new l("EntityManager"), this._log.info("EntityManager initialized");
1564
+ this.eventBus = e, this.bindingManager = i, this._log = (t == null ? void 0 : t.getLogger("EntityManager")) || new g("EntityManager"), this._log.info("EntityManager initialized");
1435
1565
  }
1436
1566
  //------------------------------------------------------------------------------------------------------------------
1437
1567
  // Private Methods
@@ -1442,21 +1572,25 @@ class Q {
1442
1572
  * @param newAction - The action being registered
1443
1573
  * @returns true if the actions are compatible, false if they have conflicting options
1444
1574
  */
1445
- areActionsCompatible(e, t) {
1575
+ _areActionsCompatible(e, t) {
1446
1576
  return !(e.type !== t.type || e.type === "analog" && t.type === "analog" && (t.minValue !== void 0 && e.minValue !== t.minValue || t.maxValue !== void 0 && e.maxValue !== t.maxValue));
1447
1577
  }
1448
1578
  /**
1449
1579
  * Registers actions defined in the entity definition with the binding manager
1450
1580
  * @param entityDef - The entity definition containing actions to register
1451
1581
  */
1452
- registerEntityActions(e) {
1582
+ _registerEntityActions(e) {
1453
1583
  if (e.actions)
1454
1584
  for (const t of e.actions)
1455
1585
  try {
1456
- const s = this.bindingManager.getAction(t.name);
1457
- s ? this.areActionsCompatible(s, t) ? this._log.trace(`Action "${t.name}" already registered with compatible options, skipping registration`) : this._log.warn(`Action "${t.name}" already registered with different options. Entity "${e.type}" requires: ${JSON.stringify(t)}, but found: ${JSON.stringify(s)}`) : (this._log.debug(`Registering action "${t.name}" from entity type "${e.type}"`), this.bindingManager.registerAction(t));
1458
- } catch (s) {
1459
- this._log.debug(`Failed to register action "${t.name}": ${s instanceof Error ? s.message : String(s)}`);
1586
+ const i = this.bindingManager.getAction(t.name);
1587
+ i ? this._areActionsCompatible(i, t) ? this._log.trace(
1588
+ `Action "${t.name}" already registered with compatible options, skipping registration`
1589
+ ) : this._log.warn(
1590
+ `Action "${t.name}" already registered with different options. Entity "${e.type}" requires: ${JSON.stringify(t)}, but found: ${JSON.stringify(i)}`
1591
+ ) : (this._log.debug(`Registering action "${t.name}" from entity type "${e.type}"`), this.bindingManager.registerAction(t));
1592
+ } catch (i) {
1593
+ this._log.debug(`Failed to register action "${t.name}": ${i instanceof Error ? i.message : String(i)}`);
1460
1594
  }
1461
1595
  }
1462
1596
  $frameUpdate(e) {
@@ -1472,7 +1606,7 @@ class Q {
1472
1606
  * @param entityDef - The definition of the entity.
1473
1607
  */
1474
1608
  registerEntityDefinition(e) {
1475
- this._log.debug(`Registering entity definition: ${e.type}`), this.registerEntityActions(e), this.entityDefinitions.set(e.type, e);
1609
+ this._log.debug(`Registering entity definition: ${e.type}`), this._registerEntityActions(e), this.entityDefinitions.set(e.type, e);
1476
1610
  }
1477
1611
  /**
1478
1612
  * Creates a new entity of the given type.
@@ -1480,26 +1614,51 @@ class Q {
1480
1614
  * @param initialState - The initial state of the entity.
1481
1615
  * @returns The created entity.
1482
1616
  */
1483
- createEntity(e, t = {}) {
1484
- var r;
1617
+ async createEntity(e, t = {}) {
1618
+ var c;
1485
1619
  this._log.debug(`Creating entity of type: ${e}`);
1486
- const s = this.entityDefinitions.get(e);
1487
- if (!s) {
1488
- const c = `Entity type ${e} is not registered.`;
1489
- throw this._log.error(c), new Error(c);
1620
+ const i = this.entityDefinitions.get(e);
1621
+ if (!i) {
1622
+ const a = `Entity type ${e} is not registered.`;
1623
+ throw this._log.error(a), new Error(a);
1490
1624
  }
1491
- this._log.trace(`Using entity definition with ${((r = s.behaviors) == null ? void 0 : r.length) || 0} behaviors`);
1492
- const i = { ...s.defaultState, ...t }, o = new q(s.type, this.eventBus, i, s.behaviors);
1493
- return this.entities.set(o.id, o), this._log.debug(`Entity created with ID: ${o.id}`), o;
1625
+ this._log.trace(`Using entity definition with ${((c = i.behaviors) == null ? void 0 : c.length) || 0} behaviors`);
1626
+ let s = { ...i.defaultState, ...t };
1627
+ if (i.onBeforeCreate) {
1628
+ this._log.trace(`Calling onBeforeCreate hook for entity type: ${e}`);
1629
+ const a = await i.onBeforeCreate(s);
1630
+ a !== void 0 && (s = a);
1631
+ }
1632
+ const o = new q(
1633
+ i.type,
1634
+ this.eventBus,
1635
+ s,
1636
+ i.behaviors
1637
+ );
1638
+ if (this.entities.set(o.id, o), this._log.debug(`Entity created with ID: ${o.id}`), i.onCreate) {
1639
+ this._log.trace(`Calling onCreate hook for entity type: ${e}`);
1640
+ const a = await i.onCreate(o.state);
1641
+ a !== void 0 && (o.state = a);
1642
+ }
1643
+ return o;
1494
1644
  }
1495
1645
  /**
1496
1646
  * Destroys the entity with the given ID.
1497
1647
  * @param entityID - The ID of the entity to destroy.
1498
1648
  */
1499
- destroyEntity(e) {
1649
+ async destroyEntity(e) {
1500
1650
  this._log.debug(`Destroying entity: ${e}`);
1501
1651
  const t = this.entities.get(e);
1502
- t ? (t.$destroy(), this.entities.delete(e), this._log.debug(`Entity ${e} destroyed`)) : this._log.warn(`Attempted to destroy non-existent entity: ${e}`);
1652
+ if (t) {
1653
+ const i = this.entityDefinitions.get(t.type);
1654
+ if (i != null && i.onBeforeDestroy) {
1655
+ this._log.trace(`Calling onBeforeDestroy hook for entity: ${e}`);
1656
+ const s = await i.onBeforeDestroy(t.state);
1657
+ s !== void 0 && (t.state = s);
1658
+ }
1659
+ await t.$destroy(), i != null && i.onDestroy && (this._log.trace(`Calling onDestroy hook for entity: ${e}`), await i.onDestroy(t.state)), this.entities.delete(e), this._log.debug(`Entity ${e} destroyed`);
1660
+ } else
1661
+ this._log.warn(`Attempted to destroy non-existent entity: ${e}`);
1503
1662
  }
1504
1663
  /**
1505
1664
  * Gets the entity with the given ID.
@@ -1523,6 +1682,21 @@ class Q {
1523
1682
  removeEntity(e) {
1524
1683
  this._log.debug(`Removing entity: ${e}`), this.entities.get(e) ? (this.entities.delete(e), this._log.debug(`Entity ${e} removed`)) : this._log.warn(`Attempted to remove non-existent entity: ${e}`);
1525
1684
  }
1685
+ /**
1686
+ * Tears down all entities and releases resources
1687
+ * @returns A promise that resolves when all entities have been destroyed
1688
+ */
1689
+ async $teardown() {
1690
+ this._log.info(`Tearing down EntityManager with ${this.entities.size} entities`);
1691
+ const e = [...this.entities.keys()];
1692
+ for (const t of e)
1693
+ try {
1694
+ await this.destroyEntity(t);
1695
+ } catch (i) {
1696
+ this._log.error(`Error destroying entity ${t}: ${i}`);
1697
+ }
1698
+ this.entityDefinitions.clear(), this._log.info("EntityManager torn down successfully");
1699
+ }
1526
1700
  }
1527
1701
  class ee {
1528
1702
  //------------------------------------------------------------------------------------------------------------------
@@ -1578,10 +1752,10 @@ class ee {
1578
1752
  return { ...this._keyboardDevice };
1579
1753
  }
1580
1754
  /**
1581
- * Destroy the keyboard resource access and clean up event listeners
1755
+ * Tears down the keyboard resource access and cleans up event listeners
1582
1756
  */
1583
- destroy() {
1584
- window.removeEventListener("keydown", this._handleKeyDown), window.removeEventListener("keyup", this._handleKeyUp);
1757
+ $teardown() {
1758
+ return window.removeEventListener("keydown", this._handleKeyDown), window.removeEventListener("keyup", this._handleKeyUp), Promise.resolve();
1585
1759
  }
1586
1760
  //------------------------------------------------------------------------------------------------------------------
1587
1761
  // Private Methods
@@ -1599,13 +1773,13 @@ class ee {
1599
1773
  this._keysState[e.code] = !0;
1600
1774
  const t = {};
1601
1775
  t[e.code] = !0;
1602
- const s = {
1776
+ const i = {
1603
1777
  type: "keyboard",
1604
1778
  keys: { ...this._keysState },
1605
1779
  delta: t,
1606
1780
  event: e
1607
1781
  };
1608
- this._notifyInputChanged(s);
1782
+ this._notifyInputChanged(i);
1609
1783
  }
1610
1784
  /**
1611
1785
  * Handle keyboard key up events
@@ -1614,13 +1788,13 @@ class ee {
1614
1788
  this._keysState[e.code] = !1;
1615
1789
  const t = {};
1616
1790
  t[e.code] = !1;
1617
- const s = {
1791
+ const i = {
1618
1792
  type: "keyboard",
1619
1793
  keys: { ...this._keysState },
1620
1794
  delta: t,
1621
1795
  event: e
1622
1796
  };
1623
- this._notifyInputChanged(s);
1797
+ this._notifyInputChanged(i);
1624
1798
  }
1625
1799
  /**
1626
1800
  * Notify subscribers of device connected event
@@ -1708,10 +1882,10 @@ class te {
1708
1882
  return { ...this._mouseDevice };
1709
1883
  }
1710
1884
  /**
1711
- * Destroy the mouse resource access and clean up event listeners
1885
+ * Tears down the mouse resource access and cleans up event listeners
1712
1886
  */
1713
- destroy() {
1714
- this._targetElement.removeEventListener("mousedown", this._handleMouseDown), this._targetElement.removeEventListener("mouseup", this._handleMouseUp), this._targetElement.removeEventListener("mousemove", this._handleMouseMove), this._targetElement.removeEventListener("wheel", this._handleMouseWheel);
1887
+ $teardown() {
1888
+ return this._targetElement.removeEventListener("mousedown", this._handleMouseDown), this._targetElement.removeEventListener("mouseup", this._handleMouseUp), this._targetElement.removeEventListener("mousemove", this._handleMouseMove), this._targetElement.removeEventListener("wheel", this._handleMouseWheel), Promise.resolve();
1715
1889
  }
1716
1890
  //------------------------------------------------------------------------------------------------------------------
1717
1891
  // Private Methods
@@ -1726,10 +1900,10 @@ class te {
1726
1900
  * Handle mouse button down events
1727
1901
  */
1728
1902
  _handleMouseDown(e) {
1729
- const t = `button-${e.button}`, s = {
1903
+ const t = `button-${e.button}`, i = {
1730
1904
  pressed: !0
1731
1905
  };
1732
- this._buttonState[t] = s, this._notifyInputChanged({
1906
+ this._buttonState[t] = i, this._notifyInputChanged({
1733
1907
  type: "mouse",
1734
1908
  event: e,
1735
1909
  buttons: { ...this._buttonState },
@@ -1741,10 +1915,10 @@ class te {
1741
1915
  * Handle mouse button up events
1742
1916
  */
1743
1917
  _handleMouseUp(e) {
1744
- const t = `button-${e.button}`, s = {
1918
+ const t = `button-${e.button}`, i = {
1745
1919
  pressed: !1
1746
1920
  };
1747
- this._buttonState[t] = s, this._notifyInputChanged({
1921
+ this._buttonState[t] = i, this._notifyInputChanged({
1748
1922
  type: "mouse",
1749
1923
  event: e,
1750
1924
  buttons: { ...this._buttonState },
@@ -1804,7 +1978,7 @@ class te {
1804
1978
  this._onInputChanged && this._onInputChanged(this._mouseDevice, e);
1805
1979
  }
1806
1980
  }
1807
- class se {
1981
+ class ie {
1808
1982
  //------------------------------------------------------------------------------------------------------------------
1809
1983
  /**
1810
1984
  * Create a new GamepadResourceAccess
@@ -1858,10 +2032,10 @@ class se {
1858
2032
  getStates() {
1859
2033
  const e = {};
1860
2034
  return Object.keys(this._buttonStates).forEach((t) => {
1861
- const s = Number(t), i = this._buttonStates[s] || {}, o = this._axesStates[s] || {};
1862
- e[s] = {
2035
+ const i = Number(t), s = this._buttonStates[i] || {}, o = this._axesStates[i] || {};
2036
+ e[i] = {
1863
2037
  type: "gamepad",
1864
- buttons: { ...i },
2038
+ buttons: { ...s },
1865
2039
  axes: { ...o }
1866
2040
  };
1867
2041
  }), e;
@@ -1881,11 +2055,11 @@ class se {
1881
2055
  * @param index - The index of the gamepad state to get
1882
2056
  */
1883
2057
  getState(e) {
1884
- const t = this._buttonStates[e], s = this._axesStates[e];
1885
- return !t && !s ? null : {
2058
+ const t = this._buttonStates[e], i = this._axesStates[e];
2059
+ return !t && !i ? null : {
1886
2060
  type: "gamepad",
1887
2061
  buttons: t ? { ...t } : {},
1888
- axes: s ? { ...s } : {}
2062
+ axes: i ? { ...i } : {}
1889
2063
  };
1890
2064
  }
1891
2065
  /**
@@ -1898,46 +2072,46 @@ class se {
1898
2072
  for (const t of e) {
1899
2073
  if (!t)
1900
2074
  continue;
1901
- const s = t.index;
1902
- if (!this._gamepadDevices[s]) {
2075
+ const i = t.index;
2076
+ if (!this._gamepadDevices[i]) {
1903
2077
  this._handleGamepadConnected(t);
1904
2078
  continue;
1905
2079
  }
1906
- const i = this._gamepadDevices[s];
1907
- if (!i)
2080
+ const s = this._gamepadDevices[i];
2081
+ if (!s)
1908
2082
  continue;
1909
- const o = this._buttonStates[s] || {}, r = this._axesStates[s] || {}, c = {};
2083
+ const o = this._buttonStates[i] || {}, c = this._axesStates[i] || {}, a = {};
1910
2084
  let h = !1;
1911
- t.buttons.forEach((d, _) => {
1912
- const p = `button-${_}`, f = {
1913
- pressed: d.pressed,
1914
- touched: d.touched,
1915
- value: d.value
2085
+ t.buttons.forEach((u, p) => {
2086
+ const l = `button-${p}`, f = {
2087
+ pressed: u.pressed,
2088
+ touched: u.touched,
2089
+ value: u.value
1916
2090
  };
1917
- c[p] = f;
1918
- const y = o[p];
2091
+ a[l] = f;
2092
+ const y = o[l];
1919
2093
  (!y || y.pressed !== f.pressed || y.touched !== f.touched || y.value !== f.value) && (h = !0);
1920
2094
  });
1921
- const u = {};
1922
- let g = !1;
1923
- if (t.axes.forEach((d, _) => {
1924
- const p = `axis-${_}`;
1925
- u[p] = d, r[p] !== d && (g = !0);
1926
- }), this._buttonStates[s] = c, this._axesStates[s] = u, h || g) {
1927
- const d = {
2095
+ const d = {};
2096
+ let _ = !1;
2097
+ if (t.axes.forEach((u, p) => {
2098
+ const l = `axis-${p}`;
2099
+ d[l] = u, c[l] !== u && (_ = !0);
2100
+ }), this._buttonStates[i] = a, this._axesStates[i] = d, h || _) {
2101
+ const u = {
1928
2102
  type: "gamepad",
1929
- buttons: { ...c },
1930
- axes: { ...u }
2103
+ buttons: { ...a },
2104
+ axes: { ...d }
1931
2105
  };
1932
- this._notifyInputChanged(i, d);
2106
+ this._notifyInputChanged(s, u);
1933
2107
  }
1934
2108
  }
1935
2109
  }
1936
2110
  /**
1937
- * Destroy the gamepad resource access and clean up event listeners
2111
+ * Tears down the gamepad resource access and cleans up event listeners
1938
2112
  */
1939
- destroy() {
1940
- window.removeEventListener("gamepadconnected", this._handleGamepadConnected), window.removeEventListener("gamepaddisconnected", this._handleGamepadDisconnected);
2113
+ $teardown() {
2114
+ return window.removeEventListener("gamepadconnected", this._handleGamepadConnected), window.removeEventListener("gamepaddisconnected", this._handleGamepadDisconnected), Promise.resolve();
1941
2115
  }
1942
2116
  //------------------------------------------------------------------------------------------------------------------
1943
2117
  // Private Methods
@@ -1956,32 +2130,32 @@ class se {
1956
2130
  * Handle gamepad connected event
1957
2131
  */
1958
2132
  _handleGamepadConnected(e) {
1959
- const t = e instanceof GamepadEvent ? e.gamepad : e, s = t.index, i = {
1960
- id: `gamepad-${s}`,
2133
+ const t = e instanceof GamepadEvent ? e.gamepad : e, i = t.index, s = {
2134
+ id: `gamepad-${i}`,
1961
2135
  name: t.id,
1962
2136
  type: "gamepad",
1963
2137
  connected: !0,
1964
- index: s,
2138
+ index: i,
1965
2139
  mapping: t.mapping,
1966
2140
  axes: Array.from(t.axes),
1967
2141
  buttons: Array.from(t.buttons)
1968
2142
  };
1969
- this._gamepadDevices[s] = i;
2143
+ this._gamepadDevices[i] = s;
1970
2144
  const o = {};
1971
- Array.from(t.buttons).forEach((c, h) => {
2145
+ Array.from(t.buttons).forEach((a, h) => {
1972
2146
  o[`button-${h}`] = {
1973
- pressed: c.pressed,
1974
- touched: c.touched,
1975
- value: c.value
2147
+ pressed: a.pressed,
2148
+ touched: a.touched,
2149
+ value: a.value
1976
2150
  };
1977
- }), this._buttonStates[s] = o;
1978
- const r = {};
1979
- Array.from(t.axes).forEach((c, h) => {
1980
- r[`axis-${h}`] = c;
1981
- }), this._axesStates[s] = r, this._notifyDeviceConnected(i), this._notifyInputChanged(i, {
2151
+ }), this._buttonStates[i] = o;
2152
+ const c = {};
2153
+ Array.from(t.axes).forEach((a, h) => {
2154
+ c[`axis-${h}`] = a;
2155
+ }), this._axesStates[i] = c, this._notifyDeviceConnected(s), this._notifyInputChanged(s, {
1982
2156
  type: "gamepad",
1983
2157
  buttons: { ...o },
1984
- axes: { ...r },
2158
+ axes: { ...c },
1985
2159
  event: e instanceof GamepadEvent ? e : void 0
1986
2160
  });
1987
2161
  }
@@ -1989,8 +2163,8 @@ class se {
1989
2163
  * Handle gamepad disconnected event
1990
2164
  */
1991
2165
  _handleGamepadDisconnected(e) {
1992
- const s = e.gamepad.index, i = this._gamepadDevices[s];
1993
- i && (i.connected = !1, this._notifyDeviceDisconnected(i), this._gamepadDevices[s] = void 0, this._buttonStates[s] = void 0, this._axesStates[s] = void 0);
2166
+ const i = e.gamepad.index, s = this._gamepadDevices[i];
2167
+ s && (s.connected = !1, this._notifyDeviceDisconnected(s), this._gamepadDevices[i] = void 0, this._buttonStates[i] = void 0, this._axesStates[i] = void 0);
1994
2168
  }
1995
2169
  /**
1996
2170
  * Notify subscribers of device connected event
@@ -2011,7 +2185,7 @@ class se {
2011
2185
  this._onInputChanged && this._onInputChanged(e, t);
2012
2186
  }
2013
2187
  }
2014
- class ie {
2188
+ class se {
2015
2189
  //------------------------------------------------------------------------------------------------------------------
2016
2190
  /**
2017
2191
  * Create a new UserInputManager
@@ -2020,14 +2194,14 @@ class ie {
2020
2194
  * @param canvas - The DOM element to attach input listeners to
2021
2195
  * @param logger - The logging utility to use
2022
2196
  */
2023
- constructor(e, t, s) {
2197
+ constructor(e, t, i) {
2024
2198
  n(this, "_eventBus");
2025
2199
  n(this, "_keyboardRA");
2026
2200
  n(this, "_mouseRA");
2027
2201
  n(this, "_gamepadRA");
2028
2202
  /** Logger instance */
2029
2203
  n(this, "_log");
2030
- this._eventBus = e, this._log = (s == null ? void 0 : s.getLogger("UserInputManager")) || new l("UserInputManager"), this._log.info("Initializing UserInputManager"), this._log.debug("Initializing input resource access classes"), this._keyboardRA = new ee(), this._mouseRA = new te(t), this._gamepadRA = new se(), this._log.debug("Registering input event callbacks"), this._keyboardRA.onDeviceConnected(this._publishDeviceConnected.bind(this)), this._keyboardRA.onInputChanged(this._publishInputChanged.bind(this)), this._mouseRA.onDeviceConnected(this._publishDeviceConnected.bind(this)), this._mouseRA.onInputChanged(this._publishInputChanged.bind(this)), this._gamepadRA.onDeviceConnected(this._publishDeviceConnected.bind(this)), this._gamepadRA.onDeviceDisconnected(this._publishDeviceDisconnected.bind(this)), this._gamepadRA.onInputChanged(this._publishInputChanged.bind(this)), this._log.info("UserInputManager initialized successfully");
2204
+ this._eventBus = e, this._log = (i == null ? void 0 : i.getLogger("UserInputManager")) || new g("UserInputManager"), this._log.info("Initializing UserInputManager"), this._log.debug("Initializing input resource access classes"), this._keyboardRA = new ee(), this._mouseRA = new te(t), this._gamepadRA = new ie(), this._log.debug("Registering input event callbacks"), this._keyboardRA.onDeviceConnected(this._publishDeviceConnected.bind(this)), this._keyboardRA.onInputChanged(this._publishInputChanged.bind(this)), this._mouseRA.onDeviceConnected(this._publishDeviceConnected.bind(this)), this._mouseRA.onInputChanged(this._publishInputChanged.bind(this)), this._gamepadRA.onDeviceConnected(this._publishDeviceConnected.bind(this)), this._gamepadRA.onDeviceDisconnected(this._publishDeviceDisconnected.bind(this)), this._gamepadRA.onInputChanged(this._publishInputChanged.bind(this)), this._log.info("UserInputManager initialized successfully");
2031
2205
  }
2032
2206
  //------------------------------------------------------------------------------------------------------------------
2033
2207
  // Private methods
@@ -2059,7 +2233,7 @@ class ie {
2059
2233
  */
2060
2234
  _publishInputChanged(e, t) {
2061
2235
  this._log.trace(`Input changed: ${e.id}`, t);
2062
- const s = {
2236
+ const i = {
2063
2237
  type: "input:changed",
2064
2238
  payload: {
2065
2239
  deviceId: e.id,
@@ -2067,16 +2241,22 @@ class ie {
2067
2241
  state: t
2068
2242
  }
2069
2243
  };
2070
- this._eventBus.publish(s);
2244
+ this._eventBus.publish(i);
2071
2245
  }
2072
2246
  //------------------------------------------------------------------------------------------------------------------
2073
2247
  // Internal methods
2074
2248
  //------------------------------------------------------------------------------------------------------------------
2075
2249
  /**
2076
- * Destroy the input manager and clean up event listeners
2250
+ * Tears down the input manager and clean up event listeners
2077
2251
  */
2078
- $destroy() {
2079
- this._log.info("Destroying UserInputManager"), this._log.debug("Cleaning up input resource access instances"), this._keyboardRA.destroy(), this._mouseRA.destroy(), this._gamepadRA.destroy(), this._log.info("UserInputManager destroyed");
2252
+ $teardown() {
2253
+ return this._log.info("Tearing down UserInputManager"), this._log.debug("Cleaning up input resource access instances"), Promise.all([
2254
+ this._keyboardRA.$teardown(),
2255
+ this._mouseRA.$teardown(),
2256
+ this._gamepadRA.$teardown()
2257
+ ]).then(() => {
2258
+ this._log.info("UserInputManager torn down successfully");
2259
+ });
2080
2260
  }
2081
2261
  //------------------------------------------------------------------------------------------------------------------
2082
2262
  // Public methods
@@ -2108,9 +2288,9 @@ class ie {
2108
2288
  return this._gamepadRA.getDevice(t);
2109
2289
  } else {
2110
2290
  const t = this.listDevices();
2111
- for (const s of t)
2112
- if (s.id === e)
2113
- return s;
2291
+ for (const i of t)
2292
+ if (i.id === e)
2293
+ return i;
2114
2294
  }
2115
2295
  return this._log.warn(`Device not found: ${e}`), null;
2116
2296
  }
@@ -2121,46 +2301,48 @@ class ie {
2121
2301
  this._gamepadRA.pollGamepads();
2122
2302
  }
2123
2303
  }
2124
- async function M(a, e) {
2125
- const t = new K(a, e);
2304
+ async function M(r, e) {
2305
+ const t = new K(r, e);
2126
2306
  return await t.initAsync(), t;
2127
2307
  }
2128
- function v(a, e) {
2129
- return new U(a, e.antialias, e.options, e.adaptToDeviceRatio);
2308
+ function v(r, e) {
2309
+ return new T(r, e.antialias, e.options, e.adaptToDeviceRatio);
2130
2310
  }
2131
- function ne(a) {
2132
- return new B(a);
2311
+ function ne(r) {
2312
+ return new L(r);
2133
2313
  }
2134
- async function oe(a, e) {
2135
- if (a === null)
2314
+ async function oe(r, e) {
2315
+ if (r === null)
2136
2316
  return console.debug("Using Null Engine"), ne(e);
2137
2317
  const t = e.engine || "auto";
2138
2318
  if (t === "webgpu")
2139
- if ($())
2319
+ if (k())
2140
2320
  try {
2141
- return console.debug("Using forced WebGPU engine"), await M(a, e);
2142
- } catch (s) {
2143
- throw console.error("Forced WebGPU initialization failed:", s), new Error("Forced WebGPU failed to initialize. If WebGPU is required, check browser compatibility.");
2321
+ return console.debug("Using forced WebGPU engine"), await M(r, e);
2322
+ } catch (i) {
2323
+ throw console.error("Forced WebGPU initialization failed:", i), new Error(
2324
+ "Forced WebGPU failed to initialize. If WebGPU is required, check browser compatibility."
2325
+ );
2144
2326
  }
2145
2327
  else
2146
2328
  throw new Error("WebGPU was forced but is not available in this browser.");
2147
2329
  if (t === "webgl")
2148
- return console.debug("Using forced WebGL engine"), v(a, e);
2149
- if ($())
2330
+ return console.debug("Using forced WebGL engine"), v(r, e);
2331
+ if (k())
2150
2332
  try {
2151
- return console.debug("Using WebGPU"), M(a, e).catch((s) => (console.warn("WebGPU initialization failed, falling back to WebGL:", s), v(a, e)));
2152
- } catch (s) {
2153
- console.warn("WebGPU initialization failed, falling back to WebGL:", s);
2333
+ return console.debug("Using WebGPU"), M(r, e).catch((i) => (console.warn("WebGPU initialization failed, falling back to WebGL:", i), v(r, e)));
2334
+ } catch (i) {
2335
+ console.warn("WebGPU initialization failed, falling back to WebGL:", i);
2154
2336
  }
2155
2337
  else
2156
2338
  console.warn("WebGPU not supported, falling back to WebGL.");
2157
- return console.debug("Using WebGL"), v(a, e);
2339
+ return console.debug("Using WebGL"), v(r, e);
2158
2340
  }
2159
2341
  async function ae() {
2160
- const a = await T();
2161
- return new R(!0, a);
2342
+ const r = await R();
2343
+ return new U(!0, r);
2162
2344
  }
2163
- const de = ["keyboard", "mouse", "gamepad"], le = [
2345
+ const ue = ["keyboard", "mouse", "gamepad"], le = [
2164
2346
  "trace",
2165
2347
  "debug",
2166
2348
  "info",
@@ -2168,53 +2350,56 @@ const de = ["keyboard", "mouse", "gamepad"], le = [
2168
2350
  "error",
2169
2351
  "none"
2170
2352
  ];
2171
- async function ge(a, e = {}) {
2172
- const t = new F(e.logLevel || "debug"), s = t.getLogger("SAGE");
2353
+ async function ge(r, e, t = {}) {
2354
+ const i = new O(t.logLevel || "debug"), s = i.getLogger("SAGE");
2173
2355
  s.info(`Initializing SAGE Game Engine v${m}...`), s.debug("Creating rendering engine...");
2174
- const i = await oe(a, e.renderOptions || {});
2356
+ const o = await oe(r, t.renderOptions || {});
2175
2357
  s.debug("Creating physics engine...");
2176
- const o = await ae();
2358
+ const c = await ae();
2177
2359
  s.debug("Creating event bus...");
2178
- const r = new O(t);
2360
+ const a = new W(i);
2179
2361
  s.debug("Creating scene engine...");
2180
- const c = new N(i, o, t);
2362
+ const h = new F(o, c, i);
2181
2363
  s.debug("Creating managers...");
2182
- const h = new ie(r, a, t), u = new j(r, t), g = new Q(r, t, u), d = new Z(i, c, g, h, t);
2183
- if (s.info(`SAGE Game Engine v${m} initialized successfully.`), s.debug("Registering default input bindings..."), e.bindings)
2184
- for (const _ of e.bindings)
2185
- u.registerBinding(_);
2364
+ const d = new se(a, r, i), _ = new X(a, i), u = new Q(a, i, _), p = new Z(o, h, u, d, i);
2365
+ s.info(`SAGE Game Engine v${m} initialized successfully.`), s.debug("Loading entities...");
2366
+ for (const l of e)
2367
+ u.registerEntityDefinition(l);
2368
+ if (s.debug("Registering default input bindings..."), t.bindings)
2369
+ for (const l of t.bindings)
2370
+ _.registerBinding(l);
2186
2371
  return new z(
2372
+ r,
2373
+ o,
2374
+ c,
2187
2375
  a,
2188
2376
  i,
2189
- o,
2190
- r,
2191
- t,
2192
2377
  // Engines
2193
2378
  {
2194
- sceneEngine: c
2379
+ sceneEngine: h
2195
2380
  },
2196
2381
  // Managers
2197
2382
  {
2198
- bindingManager: u,
2199
- entityManager: g,
2200
- gameManager: d,
2201
- inputManager: h
2383
+ bindingManager: _,
2384
+ entityManager: u,
2385
+ gameManager: p,
2386
+ inputManager: d
2202
2387
  }
2203
2388
  );
2204
2389
  }
2205
2390
  export {
2206
- W as ConsoleBackend,
2391
+ P as ConsoleBackend,
2207
2392
  q as GameEntity,
2208
- ue as GameEntityBehavior,
2209
- O as GameEventBus,
2393
+ de as GameEntityBehavior,
2394
+ W as GameEventBus,
2210
2395
  le as LogLevels,
2211
- F as LoggingUtility,
2212
- P as NullBackend,
2213
- l as SAGELogger,
2396
+ O as LoggingUtility,
2397
+ H as NullBackend,
2398
+ g as SAGELogger,
2214
2399
  z as SkewedAspectGameEngine,
2215
2400
  m as VERSION,
2216
- J as bindingTypes,
2401
+ N as bindingTypes,
2217
2402
  ge as createGameEngine,
2218
- de as validDeviceTypes
2403
+ ue as validDeviceTypes
2219
2404
  };
2220
2405
  //# sourceMappingURL=sage.es.js.map