@skewedaspect/sage 0.6.1 → 0.7.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.
package/dist/sage.es.js CHANGED
@@ -1,10 +1,10 @@
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
- class z {
1
+ var k = Object.defineProperty;
2
+ var L = (r, e, t) => e in r ? k(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
+ var n = (r, e, t) => L(r, typeof e != "symbol" ? e + "" : e, t);
4
+ import { Scene as A, Vector3 as C, FreeCamera as I, HemisphericLight as B, DirectionalLight as G, PointLight as V, SpotLight as K, MeshBuilder as v, PhysicsAggregate as T, Sound as U, SceneLoader as E, NullEngine as R, WebGPUEngine as z, Engine as P, HavokPlugin as O } from "@babylonjs/core";
5
+ import H from "@babylonjs/havok";
6
+ const b = "0.6.2";
7
+ class W {
8
8
  /**
9
9
  * Creates an instance of SkewedAspectGameEngine.
10
10
  * @param canvas - The game canvas.
@@ -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, i, s, o, c, a) {
18
+ constructor(e, t, s, i, o, c, a) {
19
19
  n(this, "canvas");
20
20
  n(this, "renderEngine");
21
21
  n(this, "physics");
@@ -29,7 +29,7 @@ class z {
29
29
  n(this, "_beforeStartHook", null);
30
30
  n(this, "_onStartHook", null);
31
31
  n(this, "_onTeardownHook", null);
32
- 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");
32
+ this.canvas = e, this.renderEngine = t, this.physics = s, this.eventBus = i, this.logger = o, this.engines = c, this.managers = a, this._log = o.getLogger("GameEngine");
33
33
  }
34
34
  //------------------------------------------------------------------------------------------------------------------
35
35
  // Public API
@@ -68,14 +68,14 @@ class z {
68
68
  * Starts the game engine.
69
69
  */
70
70
  async start() {
71
- this.started ? this._log.warn("Game engine is already started. Skipping start.") : (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)), this.started = !0);
71
+ this.started ? this._log.warn("Game engine is already started. Skipping start.") : (this._log.info(`Starting SkewedAspect Game Engine (Version: ${b})...`), this._beforeStartHook && (this._log.debug("Executing beforeStart hook..."), await this._beforeStartHook(this)), await this.managers.gameManager.start(), this._log.info("Game engine started successfully"), this._onStartHook && (this._log.debug("Executing onStart hook..."), await this._onStartHook(this)), this.started = !0);
72
72
  }
73
73
  /**
74
74
  * Stops the game engine.
75
75
  */
76
76
  async stop() {
77
77
  if (this.started) {
78
- this._log.info(`Stopping SkewedAspect Game Engine (Version: ${m})...`);
78
+ this._log.info(`Stopping SkewedAspect Game Engine (Version: ${b})...`);
79
79
  let e = null;
80
80
  if (this._onTeardownHook)
81
81
  try {
@@ -84,21 +84,21 @@ class z {
84
84
  this._log.error(`Error in onTeardown hook: ${t}`), e = e || t;
85
85
  }
86
86
  for (const t of Object.keys(this.managers)) {
87
- const i = this.managers[t];
88
- if (typeof i.$teardown == "function")
87
+ const s = this.managers[t];
88
+ if (typeof s.$teardown == "function")
89
89
  try {
90
- this._log.debug(`Tearing down manager: ${t}`), await i.$teardown();
91
- } catch (s) {
92
- this._log.error(`Error tearing down manager ${t}: ${s}`), e = e || s;
90
+ this._log.debug(`Tearing down manager: ${t}`), await s.$teardown();
91
+ } catch (i) {
92
+ this._log.error(`Error tearing down manager ${t}: ${i}`), e = e || i;
93
93
  }
94
94
  }
95
95
  for (const t of Object.keys(this.engines)) {
96
- const i = this.engines[t];
97
- if (typeof i.$teardown == "function")
96
+ const s = this.engines[t];
97
+ if (typeof s.$teardown == "function")
98
98
  try {
99
- this._log.debug(`Tearing down engine: ${t}`), await i.$teardown();
100
- } catch (s) {
101
- this._log.error(`Error tearing down engine ${t}: ${s}`), e = e || s;
99
+ this._log.debug(`Tearing down engine: ${t}`), await s.$teardown();
100
+ } catch (i) {
101
+ this._log.error(`Error tearing down engine ${t}: ${i}`), e = e || i;
102
102
  }
103
103
  }
104
104
  try {
@@ -112,7 +112,7 @@ class z {
112
112
  this._log.warn("Game engine is not started. Skipping stop.");
113
113
  }
114
114
  }
115
- class P {
115
+ class F {
116
116
  constructor() {
117
117
  n(this, "timers");
118
118
  this.timers = /* @__PURE__ */ new Map();
@@ -143,9 +143,9 @@ class P {
143
143
  * Format a log message with category, timestamp and log level
144
144
  */
145
145
  formatMessage(e, t) {
146
- 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();
146
+ const s = /* @__PURE__ */ new Date(), i = s.getHours() % 12 || 12, o = s.getMinutes().toString().padStart(2, "0"), c = s.getSeconds().toString().padStart(2, "0"), a = s.getHours() >= 12 ? "PM" : "AM", h = `[${i}:${o}:${c} ${a}]`, l = t.toUpperCase();
147
147
  return [
148
- `${h} %c${d}%c (${e}): `,
148
+ `${h} %c${l}%c (${e}): `,
149
149
  // Format string with placeholders
150
150
  this.getStyleForLevel(t),
151
151
  // Level style
@@ -155,74 +155,74 @@ class P {
155
155
  // Reset style
156
156
  ];
157
157
  }
158
- trace(e, t, ...i) {
159
- const [s, o, c, a] = this.formatMessage(e, "trace");
160
- console.debug(s, o, c, a, t, ...i);
158
+ trace(e, t, ...s) {
159
+ const [i, o, c, a] = this.formatMessage(e, "trace");
160
+ console.debug(i, o, c, a, t, ...s);
161
161
  }
162
- debug(e, t, ...i) {
163
- const [s, o, c, a] = this.formatMessage(e, "debug");
164
- console.debug(s, o, c, a, t, ...i);
162
+ debug(e, t, ...s) {
163
+ const [i, o, c, a] = this.formatMessage(e, "debug");
164
+ console.debug(i, o, c, a, t, ...s);
165
165
  }
166
- info(e, t, ...i) {
167
- const [s, o, c, a] = this.formatMessage(e, "info");
168
- console.info(s, o, c, a, t, ...i);
166
+ info(e, t, ...s) {
167
+ const [i, o, c, a] = this.formatMessage(e, "info");
168
+ console.info(i, o, c, a, t, ...s);
169
169
  }
170
- warn(e, t, ...i) {
171
- const [s, o, c, a] = this.formatMessage(e, "warn");
172
- console.warn(s, o, c, a, t, ...i);
170
+ warn(e, t, ...s) {
171
+ const [i, o, c, a] = this.formatMessage(e, "warn");
172
+ console.warn(i, o, c, a, t, ...s);
173
173
  }
174
- error(e, t, ...i) {
175
- const [s, o, c, a] = this.formatMessage(e, "error");
176
- console.error(s, o, c, a, t, ...i);
174
+ error(e, t, ...s) {
175
+ const [i, o, c, a] = this.formatMessage(e, "error");
176
+ console.error(i, o, c, a, t, ...s);
177
177
  }
178
178
  /**
179
179
  * Start a timer with the specified label.
180
180
  */
181
181
  time(e, t) {
182
- const i = `${e}:${t}`;
183
- this.timers.set(i, performance.now());
182
+ const s = `${e}:${t}`;
183
+ this.timers.set(s, performance.now());
184
184
  }
185
185
  /**
186
186
  * End a timer and log the elapsed time.
187
187
  */
188
188
  timeEnd(e, t) {
189
- const i = `${e}:${t}`, s = this.timers.get(i);
190
- if (s !== void 0) {
191
- const o = performance.now() - s;
192
- this.timers.delete(i);
193
- const [c, a, h, d] = this.formatMessage(e, "timer");
189
+ const s = `${e}:${t}`, i = this.timers.get(s);
190
+ if (i !== void 0) {
191
+ const o = performance.now() - i;
192
+ this.timers.delete(s);
193
+ const [c, a, h, l] = this.formatMessage(e, "timer");
194
194
  console.info(
195
195
  `${c} Timer '${t}' completed in ${o.toFixed(2)}ms`,
196
196
  a,
197
197
  h,
198
- d
198
+ l
199
199
  );
200
200
  } else
201
201
  console.warn(`[${e}]: Timer '${t}' does not exist`);
202
202
  }
203
203
  }
204
- class H {
205
- trace(e, t, ...i) {
204
+ class N {
205
+ trace(e, t, ...s) {
206
206
  }
207
- debug(e, t, ...i) {
207
+ debug(e, t, ...s) {
208
208
  }
209
- info(e, t, ...i) {
209
+ info(e, t, ...s) {
210
210
  }
211
- warn(e, t, ...i) {
211
+ warn(e, t, ...s) {
212
212
  }
213
- error(e, t, ...i) {
213
+ error(e, t, ...s) {
214
214
  }
215
215
  time(e, t) {
216
216
  }
217
217
  timeEnd(e, t) {
218
218
  }
219
219
  }
220
- class g {
221
- constructor(e, t = "none", i = new H()) {
220
+ class u {
221
+ constructor(e, t = "none", s = new N()) {
222
222
  n(this, "category");
223
223
  n(this, "backend");
224
224
  n(this, "minLevel");
225
- this.category = e, this.backend = i, this.minLevel = t;
225
+ this.category = e, this.backend = s, this.minLevel = t;
226
226
  }
227
227
  /**
228
228
  * Update the logger's backend and minimum level
@@ -273,14 +273,14 @@ class g {
273
273
  }
274
274
  }
275
275
  }
276
- class O {
276
+ class J {
277
277
  /**
278
278
  * Create a new LoggingUtility.
279
279
  *
280
280
  * @param level - The minimum logging level (defaults to INFO)
281
281
  * @param backend - The logging backend to use (defaults to ConsoleBackend)
282
282
  */
283
- constructor(e = "debug", t = new P()) {
283
+ constructor(e = "debug", t = new F()) {
284
284
  n(this, "backend");
285
285
  n(this, "level");
286
286
  n(this, "loggers");
@@ -293,7 +293,7 @@ class O {
293
293
  */
294
294
  setBackend(e) {
295
295
  this.backend = e, this.loggers.forEach((t) => {
296
- t instanceof g && t.updateSettings(this.backend, this.level);
296
+ t instanceof u && t.updateSettings(this.backend, this.level);
297
297
  });
298
298
  }
299
299
  /**
@@ -303,7 +303,7 @@ class O {
303
303
  */
304
304
  setLevel(e) {
305
305
  this.level = e, this.loggers.forEach((t) => {
306
- t instanceof g && t.updateSettings(this.backend, this.level);
306
+ t instanceof u && t.updateSettings(this.backend, this.level);
307
307
  });
308
308
  }
309
309
  /**
@@ -319,14 +319,14 @@ class O {
319
319
  * @returns A Logger instance for the specified category
320
320
  */
321
321
  getLogger(e) {
322
- this.loggers.has(e) || this.loggers.set(e, new g(e, this.level, this.backend));
322
+ this.loggers.has(e) || this.loggers.set(e, new u(e, this.level, this.backend));
323
323
  const t = this.loggers.get(e);
324
324
  if (t === void 0)
325
325
  throw new Error(`Failed to create logger for category: ${e}`);
326
326
  return t;
327
327
  }
328
328
  }
329
- class W {
329
+ class Y {
330
330
  /**
331
331
  * Creates a new GameEventBus instance
332
332
  *
@@ -347,7 +347,7 @@ class W {
347
347
  * Logger instance
348
348
  */
349
349
  n(this, "_log");
350
- this._log = (e == null ? void 0 : e.getLogger("EventBus")) || new g("EventBus");
350
+ this._log = (e == null ? void 0 : e.getLogger("EventBus")) || new u("EventBus");
351
351
  }
352
352
  /**
353
353
  * Subscribe with automatic detection:
@@ -372,14 +372,14 @@ class W {
372
372
  */
373
373
  subscribeExact(e, t) {
374
374
  this._log.debug(`Adding exact subscription for: ${e}`);
375
- let i = this.directMap.get(e);
376
- i || (i = /* @__PURE__ */ new Set(), this.directMap.set(e, i));
377
- const s = {
375
+ let s = this.directMap.get(e);
376
+ s || (s = /* @__PURE__ */ new Set(), this.directMap.set(e, s));
377
+ const i = {
378
378
  callback: (o) => t(o)
379
379
  // runtime "type-lie" cast
380
380
  };
381
- return i.add(s), () => {
382
- this._log.debug(`Removing exact subscription for: ${e}`), i.delete(s), i.size === 0 && this.directMap.delete(e);
381
+ return s.add(i), () => {
382
+ this._log.debug(`Removing exact subscription for: ${e}`), s.delete(i), s.size === 0 && this.directMap.delete(e);
383
383
  };
384
384
  }
385
385
  /**
@@ -393,20 +393,20 @@ class W {
393
393
  * @returns {Unsubscribe} function that unsubscribes this pattern-based subscription.
394
394
  */
395
395
  subscribePattern(e, t) {
396
- let i;
396
+ let s;
397
397
  if (typeof e == "string") {
398
398
  const o = e.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&").replace(/\*/g, ".*");
399
- i = new RegExp(`^${o}$`), this._log.debug(
400
- `Adding pattern subscription for string: ${e}, regex: ${i.toString()}`
399
+ s = new RegExp(`^${o}$`), this._log.debug(
400
+ `Adding pattern subscription for string: ${e}, regex: ${s.toString()}`
401
401
  );
402
402
  } else
403
- i = e, this._log.debug(`Adding pattern subscription for regex: ${i.toString()}`);
404
- const s = {
405
- pattern: i,
403
+ s = e, this._log.debug(`Adding pattern subscription for regex: ${s.toString()}`);
404
+ const i = {
405
+ pattern: s,
406
406
  callback: (o) => t(o)
407
407
  };
408
- return this.patternSubs.add(s), () => {
409
- this._log.debug(`Removing pattern subscription: ${i.toString()}`), this.patternSubs.delete(s);
408
+ return this.patternSubs.add(i), () => {
409
+ this._log.debug(`Removing pattern subscription: ${s.toString()}`), this.patternSubs.delete(i);
410
410
  };
411
411
  }
412
412
  /**
@@ -419,45 +419,224 @@ class W {
419
419
  publish(e) {
420
420
  this._log.trace(`Publishing event: ${e.type}`, e);
421
421
  let t = 0;
422
- const i = this.directMap.get(e.type);
423
- if (i) {
424
- t += i.size;
425
- for (const s of i)
426
- Promise.resolve().then(() => s.callback(e));
422
+ const s = this.directMap.get(e.type);
423
+ if (s) {
424
+ t += s.size;
425
+ for (const i of s)
426
+ Promise.resolve().then(() => i.callback(e));
427
427
  }
428
- for (const s of this.patternSubs)
429
- s.pattern && s.pattern.test(e.type) && (t++, Promise.resolve().then(() => s.callback(e)));
428
+ for (const i of this.patternSubs)
429
+ i.pattern && i.pattern.test(e.type) && (t++, Promise.resolve().then(() => i.callback(e)));
430
430
  t === 0 ? this._log.debug(`No subscribers found for event: ${e.type}`) : this._log.trace(`Event ${e.type} dispatched to ${t} subscribers`);
431
431
  }
432
432
  }
433
- class F {
434
- constructor(e, t, i) {
433
+ class j {
434
+ constructor(e, t, s, i) {
435
+ n(this, "_canvas");
435
436
  n(this, "_engine");
436
437
  n(this, "_physics");
437
438
  n(this, "_log");
438
- this._engine = e, this._physics = t, this._log = (i == null ? void 0 : i.getLogger("SceneEngine")) || new g("SceneEngine");
439
- }
440
- async _buildDemoScene(e, t) {
441
- this._log.debug("Building demo scene..."), this._log.trace("Creating camera...");
442
- const i = new G("camera1", new b(0, 5, -10), e);
443
- i.setTarget(b.Zero()), i.attachControl(t, !0), this._log.trace("Creating light...");
444
- const s = new V("light", new b(0, 1, 0), e);
445
- s.intensity = 0.7, this._log.trace("Creating sphere...");
446
- const o = E.CreateSphere("sphere", { diameter: 2, segments: 32 }, e);
447
- o.position.y = 4, this._log.trace("Creating ground...");
448
- const c = E.CreateGround("ground", { width: 10, height: 10 }, e);
449
- this._log.trace("Adding physics to sphere..."), new C(
450
- o,
451
- D.SPHERE,
452
- { mass: 1, restitution: 0.75 },
453
- e
454
- ), this._log.trace("Adding physics to ground..."), new C(c, D.BOX, { mass: 0 }, e), this._log.debug("Demo scene built successfully");
455
- }
456
- // TODO: This needs more logic to handle different scenes
457
- async loadScene(e) {
458
- this._log.info("Loading scene..."), this._log.time("sceneLoad"), this._log.debug("Creating new scene...");
459
- const t = new B(this._engine);
460
- 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;
439
+ this._canvas = e, this._engine = t, this._physics = s, this._log = (i == null ? void 0 : i.getLogger("SceneEngine")) || new u("SceneEngine");
440
+ }
441
+ /**
442
+ * Creates a new scene with physics enabled
443
+ * @returns A new Scene instance with physics enabled
444
+ */
445
+ createScene() {
446
+ return this._log.debug("Creating new scene..."), new A(this._engine);
447
+ }
448
+ enablePhysics(e, t = new C(0, -9.8, 0)) {
449
+ this._log.debug(
450
+ `Enabling physics with gravity (${t.x}, ${t.y}, ${t.z})...`
451
+ ), e.enablePhysics(t, this._physics);
452
+ }
453
+ // Camera Utilities
454
+ /**
455
+ * Creates a free camera at the specified position
456
+ * @param name - The name for the camera
457
+ * @param position - The position of the camera
458
+ * @param scene - The scene to add the camera to
459
+ * @param canvas - The canvas to attach the camera controls to
460
+ * @returns A new FreeCamera instance
461
+ */
462
+ createFreeCamera(e, t, s, i) {
463
+ this._log.debug(`Creating free camera: ${e}`);
464
+ const o = new I(e, t, s);
465
+ return o.setTarget(C.Zero()), i = i ?? this._canvas, i && o.attachControl(i, !0), o;
466
+ }
467
+ // Lighting Utilities
468
+ /**
469
+ * Creates a hemispheric light (ambient lighting)
470
+ * @param name - The name for the light
471
+ * @param direction - The direction of the light
472
+ * @param scene - The scene to add the light to
473
+ * @param intensity - The intensity of the light (default: 0.7)
474
+ * @returns A new HemisphericLight instance
475
+ */
476
+ createHemisphericLight(e, t, s, i = 0.7) {
477
+ this._log.debug(`Creating hemispheric light: ${e}`);
478
+ const o = new B(e, t, s);
479
+ return o.intensity = i, o;
480
+ }
481
+ /**
482
+ * Creates a directional light (sun-like lighting)
483
+ * @param name - The name for the light
484
+ * @param direction - The direction of the light
485
+ * @param scene - The scene to add the light to
486
+ * @param intensity - The intensity of the light (default: 1.0)
487
+ * @returns A new DirectionalLight instance
488
+ */
489
+ createDirectionalLight(e, t, s, i = 1) {
490
+ this._log.debug(`Creating directional light: ${e}`);
491
+ const o = new G(e, t, s);
492
+ return o.intensity = i, o;
493
+ }
494
+ /**
495
+ * Creates a point light (bulb-like lighting)
496
+ * @param name - The name for the light
497
+ * @param position - The position of the light
498
+ * @param scene - The scene to add the light to
499
+ * @param intensity - The intensity of the light (default: 1.0)
500
+ * @returns A new PointLight instance
501
+ */
502
+ createPointLight(e, t, s, i = 1) {
503
+ this._log.debug(`Creating point light: ${e}`);
504
+ const o = new V(e, t, s);
505
+ return o.intensity = i, o;
506
+ }
507
+ /**
508
+ * Creates a spot light (flashlight-like lighting)
509
+ * @param name - The name for the light
510
+ * @param position - The position of the light
511
+ * @param direction - The direction of the light
512
+ * @param angle - The angle of the light cone
513
+ * @param exponent - The exponent of the light falloff
514
+ * @param scene - The scene to add the light to
515
+ * @param intensity - The intensity of the light (default: 1.0)
516
+ * @returns A new SpotLight instance
517
+ */
518
+ createSpotLight(e, t, s, i, o, c, a = 1) {
519
+ this._log.debug(`Creating spot light: ${e}`);
520
+ const h = new K(e, t, s, i, o, c);
521
+ return h.intensity = a, h;
522
+ }
523
+ // Mesh Creation Utilities
524
+ /**
525
+ * Creates a sphere mesh
526
+ * @param name - The name for the mesh
527
+ * @param options - Options for creating the sphere
528
+ * @param scene - The scene to add the mesh to
529
+ * @returns A new sphere Mesh instance
530
+ */
531
+ createSphere(e, t = {}, s) {
532
+ this._log.debug(`Creating sphere: ${e}`);
533
+ const i = { diameter: 1, segments: 32 };
534
+ return v.CreateSphere(e, { ...i, ...t }, s);
535
+ }
536
+ /**
537
+ * Creates a box mesh
538
+ * @param name - The name for the mesh
539
+ * @param options - Options for creating the box
540
+ * @param scene - The scene to add the mesh to
541
+ * @returns A new box Mesh instance
542
+ */
543
+ createBox(e, t = {}, s) {
544
+ this._log.debug(`Creating box: ${e}`);
545
+ const i = { size: 1 };
546
+ return v.CreateBox(e, { ...i, ...t }, s);
547
+ }
548
+ /**
549
+ * Creates a ground mesh
550
+ * @param name - The name for the mesh
551
+ * @param options - Options for creating the ground
552
+ * @param scene - The scene to add the mesh to
553
+ * @returns A new ground Mesh instance
554
+ */
555
+ createGround(e, t = {}, s) {
556
+ this._log.debug(`Creating ground: ${e}`);
557
+ const i = { width: 6, height: 6, subdivisions: 2 };
558
+ return v.CreateGround(e, { ...i, ...t }, s);
559
+ }
560
+ /**
561
+ * Creates a cylinder mesh
562
+ * @param name - The name for the mesh
563
+ * @param options - Options for creating the cylinder
564
+ * @param scene - The scene to add the mesh to
565
+ * @returns A new cylinder Mesh instance
566
+ */
567
+ createCylinder(e, t = {}, s) {
568
+ this._log.debug(`Creating cylinder: ${e}`);
569
+ const i = { height: 2, diameterTop: 1, diameterBottom: 1 };
570
+ return v.CreateCylinder(e, { ...i, ...t }, s);
571
+ }
572
+ // Physics Utilities
573
+ /**
574
+ * Adds physics to a mesh
575
+ * @param mesh - The mesh to add physics to
576
+ * @param shapeType - The physics shape type
577
+ * @param physicsProps - The physics properties (mass, restitution, etc.)
578
+ * @param scene - The scene the mesh belongs to
579
+ * @returns A new PhysicsAggregate instance
580
+ */
581
+ addPhysics(e, t, s = {}, i) {
582
+ this._log.debug(`Adding physics to mesh: ${e.name}`);
583
+ const o = { mass: 1, restitution: 0.75, friction: 0.5 };
584
+ return new T(e, t, { ...o, ...s }, i);
585
+ }
586
+ // Audio Utilities
587
+ /**
588
+ * Creates and loads a sound
589
+ * @param name - The name for the sound
590
+ * @param url - The URL or file path of the sound
591
+ * @param scene - The scene to add the sound to
592
+ * @param options - Additional sound options
593
+ * @returns A new Sound instance
594
+ */
595
+ createSound(e, t, s, i = {}) {
596
+ this._log.debug(`Creating sound: ${e}`);
597
+ const c = { ...{ loop: !1, autoplay: !1, volume: 1, playbackRate: 1 }, ...i };
598
+ return new U(
599
+ e,
600
+ t,
601
+ s,
602
+ void 0,
603
+ // readyToPlayCallback
604
+ c
605
+ );
606
+ }
607
+ // Model Loading Utilities
608
+ /**
609
+ * Loads a 3D model/asset from a file
610
+ * @param rootUrl - The root URL where the file is located
611
+ * @param sceneFilename - The filename of the scene file
612
+ * @param scene - The scene to load the model into
613
+ * @returns Promise that resolves with the loaded AssetContainer
614
+ */
615
+ async loadModel(e, t, s) {
616
+ this._log.debug(`Loading model: ${e}${t}`);
617
+ try {
618
+ const i = await E.LoadAssetContainerAsync(e, t, s);
619
+ return this._log.debug(`Model loaded successfully: ${t}`), i;
620
+ } catch (i) {
621
+ throw this._log.error(`Failed to load model: ${t}`, i), i;
622
+ }
623
+ }
624
+ /**
625
+ * Imports meshes from a file
626
+ * @param meshNames - Array of mesh names to import (empty array imports all)
627
+ * @param rootUrl - The root URL where the file is located
628
+ * @param sceneFilename - The filename of the scene file
629
+ * @param scene - The scene to import the meshes into
630
+ * @returns Promise that resolves with the import result
631
+ */
632
+ async importMeshes(e, t, s, i) {
633
+ this._log.debug(`Importing meshes from: ${t}${s}`);
634
+ try {
635
+ const o = await E.ImportMeshAsync(e, t, s, i);
636
+ return this._log.debug(`Meshes imported successfully: ${e.length > 0 ? e.join(", ") : "all"}`), o;
637
+ } catch (o) {
638
+ throw this._log.error(`Failed to import meshes from: ${s}`, o), o;
639
+ }
461
640
  }
462
641
  /**
463
642
  * Tears down the scene engine and cleans up any resources
@@ -466,12 +645,12 @@ class F {
466
645
  return this._log.info("Tearing down SceneEngine"), this._log.info("SceneEngine torn down successfully"), Promise.resolve();
467
646
  }
468
647
  }
469
- const N = [
648
+ const X = [
470
649
  "trigger",
471
650
  "toggle",
472
651
  "value"
473
652
  ];
474
- class J {
653
+ class Z {
475
654
  //------------------------------------------------------------------------------------------------------------------
476
655
  /**
477
656
  * Create a new trigger binding
@@ -481,7 +660,7 @@ class J {
481
660
  * @param reader - Input reader to read values from
482
661
  * @param options - Binding configuration options
483
662
  */
484
- constructor(e, t, i, s = {}) {
663
+ constructor(e, t, s, i = {}) {
485
664
  n(this, "type", "trigger");
486
665
  n(this, "action");
487
666
  n(this, "context");
@@ -492,7 +671,7 @@ class J {
492
671
  n(this, "_threshold");
493
672
  // State tracking
494
673
  n(this, "_lastDigitalState", !1);
495
- this.action = e, this.deviceID = t, this.reader = i, this.context = s.context, this._edgeMode = s.edgeMode ?? "rising", this._threshold = s.threshold ?? 0.5;
674
+ this.action = e, this.deviceID = t, this.reader = s, this.context = i.context, this._edgeMode = i.edgeMode ?? "rising", this._threshold = i.threshold ?? 0.5;
496
675
  }
497
676
  //------------------------------------------------------------------------------------------------------------------
498
677
  // Public Getters
@@ -519,26 +698,26 @@ class J {
519
698
  * @returns True if an action was triggered, false otherwise
520
699
  */
521
700
  process(e, t) {
522
- const i = this.reader.getValue(e) ?? !1, s = typeof i == "boolean" ? i : i >= this._threshold;
701
+ const s = this.reader.getValue(e) ?? !1, i = typeof s == "boolean" ? s : s >= this._threshold;
523
702
  let o = !1;
524
703
  switch (this._edgeMode) {
525
704
  case "rising":
526
- o = s && !this._lastDigitalState;
705
+ o = i && !this._lastDigitalState;
527
706
  break;
528
707
  case "falling":
529
- o = !s && this._lastDigitalState;
708
+ o = !i && this._lastDigitalState;
530
709
  break;
531
710
  case "both":
532
- o = s !== this._lastDigitalState;
711
+ o = i !== this._lastDigitalState;
533
712
  break;
534
713
  }
535
- if (this._lastDigitalState = s, o) {
714
+ if (this._lastDigitalState = i, o) {
536
715
  let c;
537
716
  if (this.action.type === "analog") {
538
- let h = typeof i == "number" ? i : i ? 1 : 0;
717
+ let h = typeof s == "number" ? s : s ? 1 : 0;
539
718
  if (this.action.minValue !== void 0 || this.action.maxValue !== void 0) {
540
- const d = this.action.minValue ?? 0, _ = this.action.maxValue ?? 1;
541
- h = d + h * (_ - d);
719
+ const l = this.action.minValue ?? 0, _ = this.action.maxValue ?? 1;
720
+ h = l + h * (_ - l);
542
721
  }
543
722
  c = h;
544
723
  } else
@@ -572,7 +751,7 @@ class J {
572
751
  };
573
752
  }
574
753
  }
575
- class Y {
754
+ class q {
576
755
  //------------------------------------------------------------------------------------------------------------------
577
756
  /**
578
757
  * Create a new toggle binding
@@ -582,7 +761,7 @@ class Y {
582
761
  * @param reader - Input reader to read values from
583
762
  * @param options - Binding configuration options
584
763
  */
585
- constructor(e, t, i, s = {}) {
764
+ constructor(e, t, s, i = {}) {
586
765
  n(this, "type", "toggle");
587
766
  n(this, "action");
588
767
  n(this, "context");
@@ -597,7 +776,7 @@ class Y {
597
776
  // State tracking
598
777
  n(this, "_lastDigitalState", !1);
599
778
  n(this, "_toggleState");
600
- 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;
779
+ 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;
601
780
  }
602
781
  //------------------------------------------------------------------------------------------------------------------
603
782
  // Public Getters
@@ -666,8 +845,8 @@ class Y {
666
845
  * @param eventBus - Event bus to emit action events to
667
846
  */
668
847
  process(e, t) {
669
- const i = this.reader.getValue(e) ?? !1, s = typeof i == "boolean" ? i : i >= this._threshold, o = this._invert ? !s && this._lastDigitalState : s && !this._lastDigitalState;
670
- this._lastDigitalState = s, o && (this._toggleState = !this._toggleState, t.publish({
848
+ const s = this.reader.getValue(e) ?? !1, i = typeof s == "boolean" ? s : s >= this._threshold, o = this._invert ? !i && this._lastDigitalState : i && !this._lastDigitalState;
849
+ this._lastDigitalState = i, o && (this._toggleState = !this._toggleState, t.publish({
671
850
  type: `action:${this.action.name}`,
672
851
  payload: {
673
852
  value: this.value,
@@ -701,7 +880,7 @@ class Y {
701
880
  };
702
881
  }
703
882
  }
704
- class j {
883
+ class Q {
705
884
  //------------------------------------------------------------------------------------------------------------------
706
885
  /**
707
886
  * Create a new value binding
@@ -711,7 +890,7 @@ class j {
711
890
  * @param reader - Input reader to read values from
712
891
  * @param options - Binding configuration options
713
892
  */
714
- constructor(e, t, i, s = {}) {
893
+ constructor(e, t, s, i = {}) {
715
894
  n(this, "type", "value");
716
895
  n(this, "action");
717
896
  n(this, "context");
@@ -729,11 +908,11 @@ class j {
729
908
  n(this, "_max");
730
909
  // State tracking
731
910
  n(this, "_lastValue");
732
- 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;
911
+ 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;
733
912
  const o = this.action.type === "analog" ? this.action.minValue ?? Number.NEGATIVE_INFINITY : Number.NEGATIVE_INFINITY;
734
- this._min = s.min ?? o;
913
+ this._min = i.min ?? o;
735
914
  const c = this.action.type === "analog" ? this.action.maxValue ?? Number.POSITIVE_INFINITY : Number.POSITIVE_INFINITY;
736
- this._max = s.max ?? c;
915
+ this._max = i.max ?? c;
737
916
  }
738
917
  //------------------------------------------------------------------------------------------------------------------
739
918
  /**
@@ -765,13 +944,13 @@ class j {
765
944
  * @returns True if a value was emitted, false otherwise
766
945
  */
767
946
  process(e, t) {
768
- const i = this.reader.getValue(e);
769
- if (i === void 0)
770
- return;
771
- const s = typeof i == "boolean" ? i ? 1 : 0 : i;
947
+ const s = this.reader.getValue(e);
772
948
  if (s === void 0)
773
949
  return;
774
- let o = this._deadzone > 0 && Math.abs(s) < this._deadzone ? 0 : s;
950
+ const i = typeof s == "boolean" ? s ? 1 : 0 : s;
951
+ if (i === void 0)
952
+ return;
953
+ let o = this._deadzone > 0 && Math.abs(i) < this._deadzone ? 0 : i;
775
954
  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({
776
955
  type: `action:${this.action.name}`,
777
956
  payload: {
@@ -799,7 +978,7 @@ class j {
799
978
  };
800
979
  }
801
980
  }
802
- class S {
981
+ class $ {
803
982
  /**
804
983
  * Creates a new KeyboardValueReader
805
984
  *
@@ -841,7 +1020,7 @@ class S {
841
1020
  * @returns A new KeyboardValueReader instance
842
1021
  */
843
1022
  static fromString(e, t = {}) {
844
- return new S(e, t);
1023
+ return new $(e, t);
845
1024
  }
846
1025
  /**
847
1026
  * Returns a JSON-serializable representation of this keyboard value reader
@@ -859,7 +1038,7 @@ class S {
859
1038
  };
860
1039
  }
861
1040
  }
862
- class x {
1041
+ class S {
863
1042
  /**
864
1043
  * Creates a new MouseValueReader
865
1044
  *
@@ -891,8 +1070,8 @@ class x {
891
1070
  return t ? t.pressed : void 0;
892
1071
  }
893
1072
  case "position": {
894
- const [t, i] = this.sourceKey.split(":");
895
- return !t || !i || t !== "absolute" && t !== "relative" || i !== "x" && i !== "y" ? void 0 : e.position[t][i];
1073
+ const [t, s] = this.sourceKey.split(":");
1074
+ return !t || !s || t !== "absolute" && t !== "relative" || s !== "x" && s !== "y" ? void 0 : e.position[t][s];
896
1075
  }
897
1076
  case "wheel": {
898
1077
  const t = this.sourceKey === "deltaX" || this.sourceKey === "deltaY" || this.sourceKey === "deltaZ";
@@ -909,12 +1088,12 @@ class x {
909
1088
  * @returns A new MouseValueReader instance
910
1089
  */
911
1090
  static fromString(e) {
912
- const [t, ...i] = e.split(":"), s = i.join(":");
913
- if (!t || !s)
1091
+ const [t, ...s] = e.split(":"), i = s.join(":");
1092
+ if (!t || !i)
914
1093
  throw new Error(`Invalid mouse source format: ${e}`);
915
- return new x(
1094
+ return new S(
916
1095
  t,
917
- s
1096
+ i
918
1097
  );
919
1098
  }
920
1099
  /**
@@ -930,7 +1109,7 @@ class x {
930
1109
  };
931
1110
  }
932
1111
  }
933
- class $ {
1112
+ class x {
934
1113
  /**
935
1114
  * Creates a new GamepadValueReader
936
1115
  *
@@ -938,7 +1117,7 @@ class $ {
938
1117
  * @param sourceKey - The specific key for this input type
939
1118
  * @param options - Configuration options
940
1119
  */
941
- constructor(e, t, i = {}) {
1120
+ constructor(e, t, s = {}) {
942
1121
  /**
943
1122
  * The type of gamepad input
944
1123
  */
@@ -959,7 +1138,7 @@ class $ {
959
1138
  * Whether to invert axis values
960
1139
  */
961
1140
  n(this, "invert");
962
- this.sourceType = e, this.sourceKey = t, this.useAnalogValue = i.useAnalogValue || !1, this.deadzone = i.deadzone || 0.1, this.invert = i.invert || !1;
1141
+ this.sourceType = e, this.sourceKey = t, this.useAnalogValue = s.useAnalogValue || !1, this.deadzone = s.deadzone || 0.1, this.invert = s.invert || !1;
963
1142
  }
964
1143
  /**
965
1144
  * Gets the value of the input source based on the current state
@@ -990,12 +1169,12 @@ class $ {
990
1169
  * @returns A new GamepadValueReader instance
991
1170
  */
992
1171
  static fromString(e, t = {}) {
993
- const [i, s] = e.split(":");
994
- if (!i || !s)
1172
+ const [s, i] = e.split(":");
1173
+ if (!s || !i)
995
1174
  throw new Error(`Invalid gamepad source format: ${e}`);
996
- return new $(
997
- i,
1175
+ return new x(
998
1176
  s,
1177
+ i,
999
1178
  t
1000
1179
  );
1001
1180
  }
@@ -1017,7 +1196,7 @@ class $ {
1017
1196
  };
1018
1197
  }
1019
1198
  }
1020
- class X {
1199
+ class ee {
1021
1200
  /**
1022
1201
  * Creates an instance of BindingManager.
1023
1202
  *
@@ -1039,9 +1218,9 @@ class X {
1039
1218
  n(this, "_eventBus");
1040
1219
  /** Logger instance */
1041
1220
  n(this, "_log");
1042
- this._eventBus = e, this._eventBus.subscribe("input:changed", (i) => {
1043
- i.payload && this.$handleInput(i.payload.device, i.payload.state);
1044
- }), this._log = (t == null ? void 0 : t.getLogger("BindingManager")) || new g("BindingManager"), this._log.debug("BindingManager initialized");
1221
+ this._eventBus = e, this._eventBus.subscribe("input:changed", (s) => {
1222
+ s.payload && this.$handleInput(s.payload.device, s.payload.state);
1223
+ }), this._log = (t == null ? void 0 : t.getLogger("BindingManager")) || new u("BindingManager"), this._log.debug("BindingManager initialized");
1045
1224
  }
1046
1225
  //------------------------------------------------------------------------------------------------------------------
1047
1226
  // Private Methods
@@ -1063,11 +1242,11 @@ class X {
1063
1242
  * @returns The context object
1064
1243
  */
1065
1244
  _getOrCreateContext(e, t = !0) {
1066
- let i = this._contexts.get(e);
1067
- return i || (i = {
1245
+ let s = this._contexts.get(e);
1246
+ return s || (s = {
1068
1247
  name: e,
1069
1248
  exclusive: t
1070
- }, this._contexts.set(e, i), this._log.debug(`Auto-created context "${e}" (exclusive: ${t})`)), i;
1249
+ }, this._contexts.set(e, s), this._log.debug(`Auto-created context "${e}" (exclusive: ${t})`)), s;
1071
1250
  }
1072
1251
  /**
1073
1252
  * Deactivate all exclusive contexts except the specified one
@@ -1077,11 +1256,11 @@ class X {
1077
1256
  */
1078
1257
  _deactivateExclusiveContexts(e) {
1079
1258
  const t = [];
1080
- for (const i of this._activeContexts) {
1081
- if (i === e)
1259
+ for (const s of this._activeContexts) {
1260
+ if (s === e)
1082
1261
  continue;
1083
- const s = this._contexts.get(i);
1084
- s != null && s.exclusive && (this._activeContexts.delete(i), t.push(i));
1262
+ const i = this._contexts.get(s);
1263
+ i != null && i.exclusive && (this._activeContexts.delete(s), t.push(s));
1085
1264
  }
1086
1265
  return t;
1087
1266
  }
@@ -1095,33 +1274,33 @@ class X {
1095
1274
  const t = this._actions.get(e.action);
1096
1275
  if (!t)
1097
1276
  return this._log.warn(`Cannot create binding: Action "${e.action}" not found.`), null;
1098
- const { deviceID: i, ...s } = e.input;
1277
+ const { deviceID: s, ...i } = e.input;
1099
1278
  switch (e.type) {
1100
1279
  case "trigger":
1101
- return new J(
1280
+ return new Z(
1102
1281
  t,
1103
- i,
1104
- this._createInputSourceFromDefinition(s),
1282
+ s,
1283
+ this._createInputSourceFromDefinition(i),
1105
1284
  {
1106
1285
  ...e.options || {},
1107
1286
  context: e.context
1108
1287
  }
1109
1288
  );
1110
1289
  case "toggle":
1111
- return new Y(
1290
+ return new q(
1112
1291
  t,
1113
- i,
1114
- this._createInputSourceFromDefinition(s),
1292
+ s,
1293
+ this._createInputSourceFromDefinition(i),
1115
1294
  {
1116
1295
  ...e.options || {},
1117
1296
  context: e.context
1118
1297
  }
1119
1298
  );
1120
1299
  case "value":
1121
- return new j(
1300
+ return new Q(
1122
1301
  t,
1123
- i,
1124
- this._createInputSourceFromDefinition(s),
1302
+ s,
1303
+ this._createInputSourceFromDefinition(i),
1125
1304
  {
1126
1305
  ...e.options || {},
1127
1306
  context: e.context
@@ -1141,7 +1320,7 @@ class X {
1141
1320
  _createInputSourceFromDefinition(e) {
1142
1321
  switch (e.type) {
1143
1322
  case "keyboard":
1144
- return new S(
1323
+ return new $(
1145
1324
  e.sourceKey,
1146
1325
  e.options
1147
1326
  );
@@ -1149,7 +1328,7 @@ class X {
1149
1328
  const t = e.sourceType;
1150
1329
  if (!(t === "button" || t === "position" || t === "wheel"))
1151
1330
  throw new Error(`Invalid mouse source type: ${t}`);
1152
- return new x(
1331
+ return new S(
1153
1332
  t,
1154
1333
  e.sourceKey
1155
1334
  );
@@ -1158,7 +1337,7 @@ class X {
1158
1337
  const t = e.sourceType;
1159
1338
  if (!(t === "button" || t === "axis"))
1160
1339
  throw new Error(`Invalid gamepad source type: ${t}`);
1161
- return new $(
1340
+ return new x(
1162
1341
  t,
1163
1342
  e.sourceKey,
1164
1343
  e.options
@@ -1178,10 +1357,10 @@ class X {
1178
1357
  * @param state - Current input state
1179
1358
  */
1180
1359
  $handleInput(e, t) {
1181
- const i = this._bindings.get(e.id);
1182
- if (!(!i || i.length === 0) && !(this._activeContexts.size === 0 && i.some((s) => s.context)))
1183
- for (const s of i)
1184
- this._isBindingContextActive(s) && s.process(t, this._eventBus);
1360
+ const s = this._bindings.get(e.id);
1361
+ if (!(!s || s.length === 0) && !(this._activeContexts.size === 0 && s.some((i) => i.context)))
1362
+ for (const i of s)
1363
+ this._isBindingContextActive(i) && i.process(t, this._eventBus);
1185
1364
  }
1186
1365
  //------------------------------------------------------------------------------------------------------------------
1187
1366
  // Action Management API
@@ -1221,8 +1400,8 @@ class X {
1221
1400
  * @returns The registered context
1222
1401
  */
1223
1402
  registerContext(e, t = !0) {
1224
- const i = this._getOrCreateContext(e, t);
1225
- return i.exclusive !== t && (i.exclusive = t, this._log.info(`Updated context "${e}" exclusivity: ${t}`)), i;
1403
+ const s = this._getOrCreateContext(e, t);
1404
+ return s.exclusive !== t && (s.exclusive = t, this._log.info(`Updated context "${e}" exclusivity: ${t}`)), s;
1226
1405
  }
1227
1406
  /**
1228
1407
  * Activates a context, enabling all bindings associated with it.
@@ -1231,14 +1410,14 @@ class X {
1231
1410
  * @param contextName - The name of the context to activate
1232
1411
  */
1233
1412
  activateContext(e) {
1234
- const i = this._getOrCreateContext(e).exclusive;
1235
- this._log.debug(`Activating context "${e}" (exclusive: ${i})`);
1236
- const s = this._activeContexts.has(e);
1237
- if (i) {
1413
+ const s = this._getOrCreateContext(e).exclusive;
1414
+ this._log.debug(`Activating context "${e}" (exclusive: ${s})`);
1415
+ const i = this._activeContexts.has(e);
1416
+ if (s) {
1238
1417
  const o = this._deactivateExclusiveContexts(e);
1239
1418
  o.length > 0 && this._log.info(`Deactivated exclusive contexts: ${o.join(", ")}`);
1240
1419
  }
1241
- s || (this._activeContexts.add(e), this._log.info(`Context "${e}" activated${i ? " as exclusive" : ""}`));
1420
+ i || (this._activeContexts.add(e), this._log.info(`Context "${e}" activated${s ? " as exclusive" : ""}`));
1242
1421
  }
1243
1422
  /**
1244
1423
  * Deactivates a context, disabling all bindings associated with it
@@ -1285,7 +1464,7 @@ class X {
1285
1464
  */
1286
1465
  $registerBinding(e) {
1287
1466
  var t;
1288
- if (!N.includes(e.type))
1467
+ if (!X.includes(e.type))
1289
1468
  throw new Error(`Invalid binding type: ${e.type}`);
1290
1469
  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}"`);
1291
1470
  }
@@ -1306,15 +1485,15 @@ class X {
1306
1485
  */
1307
1486
  unregisterBindings(e, t = null) {
1308
1487
  this._log.debug(`Unregistering all bindings for action "${e}" in context "${t}"`);
1309
- let i = 0;
1310
- for (const [s, o] of this._bindings.entries()) {
1488
+ let s = 0;
1489
+ for (const [i, o] of this._bindings.entries()) {
1311
1490
  const c = o.filter((a) => {
1312
- const h = a.context || null, d = a.action.name !== e || h !== t;
1313
- return d || i++, d;
1491
+ const h = a.context || null, l = a.action.name !== e || h !== t;
1492
+ return l || s++, l;
1314
1493
  });
1315
- c.length !== o.length && this._bindings.set(s, c);
1494
+ c.length !== o.length && this._bindings.set(i, c);
1316
1495
  }
1317
- this._log.info(`Removed ${i} bindings for action "${e}" in context "${t}"`);
1496
+ this._log.info(`Removed ${s} bindings for action "${e}" in context "${t}"`);
1318
1497
  }
1319
1498
  /**
1320
1499
  * Gets all bindings for a specific action
@@ -1324,13 +1503,13 @@ class X {
1324
1503
  * @returns Array of bindings that match the criteria
1325
1504
  */
1326
1505
  getBindingsForAction(e, t) {
1327
- const i = [];
1328
- for (const s of this._bindings.values())
1329
- for (const o of s) {
1506
+ const s = [];
1507
+ for (const i of this._bindings.values())
1508
+ for (const o of i) {
1330
1509
  const c = o.context || null;
1331
- o.action.name === e && (!t || c === t) && i.push(o);
1510
+ o.action.name === e && (!t || c === t) && s.push(o);
1332
1511
  }
1333
- return i;
1512
+ return s;
1334
1513
  }
1335
1514
  //------------------------------------------------------------------------------------------------------------------
1336
1515
  // Configuration Management API
@@ -1342,24 +1521,24 @@ class X {
1342
1521
  */
1343
1522
  exportConfiguration() {
1344
1523
  this._log.debug("Exporting binding configuration");
1345
- const e = [...this._actions.values()].map((s) => s.type === "analog" ? {
1346
- name: s.name,
1347
- type: s.type,
1348
- minValue: s.minValue ?? 0,
1349
- maxValue: s.maxValue ?? 1
1350
- } : s), t = [];
1351
- for (const s of this._bindings.values())
1352
- for (const o of s)
1524
+ const e = [...this._actions.values()].map((i) => i.type === "analog" ? {
1525
+ name: i.name,
1526
+ type: i.type,
1527
+ minValue: i.minValue ?? 0,
1528
+ maxValue: i.maxValue ?? 1
1529
+ } : i), t = [];
1530
+ for (const i of this._bindings.values())
1531
+ for (const o of i)
1353
1532
  t.push(o.toJSON());
1354
- const i = [...this._contexts.values()].map((s) => ({
1355
- name: s.name,
1356
- exclusive: s.exclusive,
1357
- active: this._activeContexts.has(s.name)
1533
+ const s = [...this._contexts.values()].map((i) => ({
1534
+ name: i.name,
1535
+ exclusive: i.exclusive,
1536
+ active: this._activeContexts.has(i.name)
1358
1537
  }));
1359
- return this._log.info(`Configuration exported: ${e.length} actions, ${t.length} bindings, ${i.length} contexts`), {
1538
+ return this._log.info(`Configuration exported: ${e.length} actions, ${t.length} bindings, ${s.length} contexts`), {
1360
1539
  actions: e,
1361
1540
  bindings: t,
1362
- contexts: i
1541
+ contexts: s
1363
1542
  };
1364
1543
  }
1365
1544
  /**
@@ -1376,8 +1555,8 @@ class X {
1376
1555
  for (const t of e.bindings)
1377
1556
  try {
1378
1557
  this.registerBinding(t);
1379
- } catch (i) {
1380
- i instanceof Error && this._log.error(`Failed to import binding for action "${t.action}": ${i.message}`);
1558
+ } catch (s) {
1559
+ s instanceof Error && this._log.error(`Failed to import binding for action "${t.action}": ${s.message}`);
1381
1560
  }
1382
1561
  this._log.info(`Configuration imported: ${e.actions.length} actions, ${e.bindings.length} bindings, ${e.contexts.length} contexts`);
1383
1562
  }
@@ -1391,25 +1570,28 @@ class X {
1391
1570
  function w() {
1392
1571
  return typeof window < "u" && typeof window.document < "u";
1393
1572
  }
1394
- function k() {
1573
+ function D() {
1395
1574
  return w() && !!window.navigator.gpu;
1396
1575
  }
1397
- class Z {
1576
+ class te {
1398
1577
  //------------------------------------------------------------------------------------------------------------------
1399
- constructor(e, t, i, s, o) {
1578
+ constructor(e, t, s, i, o) {
1400
1579
  n(this, "_engine");
1401
1580
  n(this, "_entityManager");
1402
1581
  n(this, "_inputManager");
1403
- n(this, "_sceneEngine");
1404
- n(this, "_currentScene", null);
1582
+ n(this, "_levelManager");
1405
1583
  n(this, "_log");
1406
1584
  n(this, "_boundResizeHandler");
1407
1585
  n(this, "started", !1);
1408
- 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);
1586
+ this._engine = e, this._entityManager = t, this._inputManager = s, this._levelManager = i, this._log = (o == null ? void 0 : o.getLogger("GameManager")) || new u("GameManager"), this._boundResizeHandler = this._resizeHandler.bind(this), w() && window.addEventListener("resize", this._boundResizeHandler);
1587
+ }
1588
+ get currentScene() {
1589
+ var e;
1590
+ return ((e = this._levelManager.currentLevel) == null ? void 0 : e.scene) ?? null;
1409
1591
  }
1410
1592
  _renderLoop() {
1411
1593
  const e = this._engine.getDeltaTime();
1412
- this._entityManager.$frameUpdate(e), this._inputManager && this._inputManager.pollGamepads(), this._currentScene && this._currentScene.render();
1594
+ this._entityManager.$frameUpdate(e), this._inputManager && this._inputManager.pollGamepads(), this.currentScene && this.currentScene.render();
1413
1595
  }
1414
1596
  _resizeHandler() {
1415
1597
  this.started && this._engine.resize();
@@ -1417,8 +1599,8 @@ class Z {
1417
1599
  //------------------------------------------------------------------------------------------------------------------
1418
1600
  // Public API
1419
1601
  //------------------------------------------------------------------------------------------------------------------
1420
- async start(e) {
1421
- this._currentScene = await this._sceneEngine.loadScene(e), this._engine.runRenderLoop(this._renderLoop.bind(this)), this.started = !0, this._log.info("SkewedAspect Game Engine started successfully");
1602
+ async start() {
1603
+ this._engine.runRenderLoop(this._renderLoop.bind(this)), this.started = !0, this._log.info("SkewedAspect Game Engine started successfully");
1422
1604
  }
1423
1605
  async stop() {
1424
1606
  this.started = !1, this._engine.stopRenderLoop(), this._log.info("SkewedAspect Game Engine stopped successfully");
@@ -1431,7 +1613,7 @@ class Z {
1431
1613
  this._log.info("Tearing down GameManager"), this.started && await this.stop(), w() && window.removeEventListener("resize", this._boundResizeHandler), this._log.info("GameManager torn down successfully");
1432
1614
  }
1433
1615
  }
1434
- class de {
1616
+ class pe {
1435
1617
  constructor() {
1436
1618
  n(this, "entity", null);
1437
1619
  }
@@ -1451,7 +1633,7 @@ class de {
1451
1633
  this.entity = e;
1452
1634
  }
1453
1635
  }
1454
- class q {
1636
+ class se {
1455
1637
  /**
1456
1638
  * Creates an instance of GameEntityBase.
1457
1639
  * @param type - The type of the entity.
@@ -1459,7 +1641,7 @@ class q {
1459
1641
  * @param behaviors - An array of behaviors to attach to the entity.
1460
1642
  * @param eventBus
1461
1643
  */
1462
- constructor(e, t, i, s) {
1644
+ constructor(e, t, s, i) {
1463
1645
  /** The unique identifier of the entity. */
1464
1646
  n(this, "id");
1465
1647
  /** The type of the entity. */
@@ -1472,8 +1654,8 @@ class q {
1472
1654
  n(this, "eventBus");
1473
1655
  /** The event subscriptions for the entity. */
1474
1656
  n(this, "subscriptions", /* @__PURE__ */ new Map());
1475
- this.id = crypto.randomUUID(), this.type = e, this.state = i, this.eventBus = t;
1476
- for (const o of s)
1657
+ this.id = crypto.randomUUID(), this.type = e, this.state = s, this.eventBus = t;
1658
+ for (const o of i)
1477
1659
  this.attachBehavior(new o());
1478
1660
  }
1479
1661
  //------------------------------------------------------------------------------------------------------------------
@@ -1495,8 +1677,8 @@ class q {
1495
1677
  */
1496
1678
  $update(e) {
1497
1679
  var t;
1498
- for (const i of this.behaviors.values())
1499
- (t = i.update) == null || t.call(i, e, this.state);
1680
+ for (const s of this.behaviors.values())
1681
+ (t = s.update) == null || t.call(s, e, this.state);
1500
1682
  }
1501
1683
  /**
1502
1684
  * Destroys the entity by calling the destroy method of its behaviors.
@@ -1522,12 +1704,12 @@ class q {
1522
1704
  if (this.behaviors.has(e.name))
1523
1705
  throw new Error(`Behavior ${e.name} is already attached to this entity.`);
1524
1706
  for (const t of e.eventSubscriptions) {
1525
- const i = this.subscriptions.get(t);
1526
- if (i)
1527
- i.count++;
1707
+ const s = this.subscriptions.get(t);
1708
+ if (s)
1709
+ s.count++;
1528
1710
  else {
1529
- const s = this.eventBus.subscribe(t, this.$processEvent.bind(this));
1530
- this.subscriptions.set(t, { count: 1, unsubscribe: s });
1711
+ const i = this.eventBus.subscribe(t, this.$processEvent.bind(this));
1712
+ this.subscriptions.set(t, { count: 1, unsubscribe: i });
1531
1713
  }
1532
1714
  }
1533
1715
  this.behaviors.set(e.name, e), e.$setEntity(this);
@@ -1539,22 +1721,22 @@ class q {
1539
1721
  detachBehavior(e) {
1540
1722
  const t = this.behaviors.get(e);
1541
1723
  if (t) {
1542
- for (const i of t.eventSubscriptions) {
1543
- const s = this.subscriptions.get(i);
1544
- s && (s.count--, s.count <= 0 && (s.unsubscribe(), this.subscriptions.delete(i)));
1724
+ for (const s of t.eventSubscriptions) {
1725
+ const i = this.subscriptions.get(s);
1726
+ i && (i.count--, i.count <= 0 && (i.unsubscribe(), this.subscriptions.delete(s)));
1545
1727
  }
1546
1728
  this.behaviors.delete(t.name), t.$setEntity(null);
1547
1729
  }
1548
1730
  }
1549
1731
  }
1550
- class Q {
1732
+ class ie {
1551
1733
  /**
1552
1734
  * Creates an instance of EntityManager.
1553
1735
  * @param eventBus - The event bus for the entity manager.
1554
1736
  * @param logger - The logging utility to use
1555
1737
  * @param bindingManager - The binding manager for registering actions
1556
1738
  */
1557
- constructor(e, t, i) {
1739
+ constructor(e, t, s) {
1558
1740
  /** The event bus for the entity manager. */
1559
1741
  n(this, "eventBus");
1560
1742
  /** A map of entities managed by the entity manager. */
@@ -1565,7 +1747,7 @@ class Q {
1565
1747
  n(this, "bindingManager");
1566
1748
  /** Logger instance */
1567
1749
  n(this, "_log");
1568
- this.eventBus = e, this.bindingManager = i, this._log = (t == null ? void 0 : t.getLogger("EntityManager")) || new g("EntityManager"), this._log.info("EntityManager initialized");
1750
+ this.eventBus = e, this.bindingManager = s, this._log = (t == null ? void 0 : t.getLogger("EntityManager")) || new u("EntityManager"), this._log.info("EntityManager initialized");
1569
1751
  }
1570
1752
  //------------------------------------------------------------------------------------------------------------------
1571
1753
  // Private Methods
@@ -1587,14 +1769,14 @@ class Q {
1587
1769
  if (e.actions)
1588
1770
  for (const t of e.actions)
1589
1771
  try {
1590
- const i = this.bindingManager.getAction(t.name);
1591
- i ? this._areActionsCompatible(i, t) ? this._log.trace(
1772
+ const s = this.bindingManager.getAction(t.name);
1773
+ s ? this._areActionsCompatible(s, t) ? this._log.trace(
1592
1774
  `Action "${t.name}" already registered with compatible options, skipping registration`
1593
1775
  ) : this._log.warn(
1594
- `Action "${t.name}" already registered with different options. Entity "${e.type}" requires: ${JSON.stringify(t)}, but found: ${JSON.stringify(i)}`
1776
+ `Action "${t.name}" already registered with different options. Entity "${e.type}" requires: ${JSON.stringify(t)}, but found: ${JSON.stringify(s)}`
1595
1777
  ) : (this._log.debug(`Registering action "${t.name}" from entity type "${e.type}"`), this.bindingManager.registerAction(t));
1596
- } catch (i) {
1597
- this._log.debug(`Failed to register action "${t.name}": ${i instanceof Error ? i.message : String(i)}`);
1778
+ } catch (s) {
1779
+ this._log.debug(`Failed to register action "${t.name}": ${s instanceof Error ? s.message : String(s)}`);
1598
1780
  }
1599
1781
  }
1600
1782
  $frameUpdate(e) {
@@ -1621,27 +1803,27 @@ class Q {
1621
1803
  async createEntity(e, t = {}) {
1622
1804
  var c;
1623
1805
  this._log.debug(`Creating entity of type: ${e}`);
1624
- const i = this.entityDefinitions.get(e);
1625
- if (!i) {
1806
+ const s = this.entityDefinitions.get(e);
1807
+ if (!s) {
1626
1808
  const a = `Entity type ${e} is not registered.`;
1627
1809
  throw this._log.error(a), new Error(a);
1628
1810
  }
1629
- this._log.trace(`Using entity definition with ${((c = i.behaviors) == null ? void 0 : c.length) || 0} behaviors`);
1630
- let s = { ...i.defaultState, ...t };
1631
- if (i.onBeforeCreate) {
1811
+ this._log.trace(`Using entity definition with ${((c = s.behaviors) == null ? void 0 : c.length) || 0} behaviors`);
1812
+ let i = { ...s.defaultState, ...t };
1813
+ if (s.onBeforeCreate) {
1632
1814
  this._log.trace(`Calling onBeforeCreate hook for entity type: ${e}`);
1633
- const a = await i.onBeforeCreate(s);
1634
- a !== void 0 && (s = a);
1815
+ const a = await s.onBeforeCreate(i);
1816
+ a !== void 0 && (i = a);
1635
1817
  }
1636
- const o = new q(
1637
- i.type,
1818
+ const o = new se(
1819
+ s.type,
1638
1820
  this.eventBus,
1639
- s,
1640
- i.behaviors
1821
+ i,
1822
+ s.behaviors
1641
1823
  );
1642
- if (this.entities.set(o.id, o), this._log.debug(`Entity created with ID: ${o.id}`), i.onCreate) {
1824
+ if (this.entities.set(o.id, o), this._log.debug(`Entity created with ID: ${o.id}`), s.onCreate) {
1643
1825
  this._log.trace(`Calling onCreate hook for entity type: ${e}`);
1644
- const a = await i.onCreate(o.state);
1826
+ const a = await s.onCreate(o.state);
1645
1827
  a !== void 0 && (o.state = a);
1646
1828
  }
1647
1829
  return o;
@@ -1654,13 +1836,13 @@ class Q {
1654
1836
  this._log.debug(`Destroying entity: ${e}`);
1655
1837
  const t = this.entities.get(e);
1656
1838
  if (t) {
1657
- const i = this.entityDefinitions.get(t.type);
1658
- if (i != null && i.onBeforeDestroy) {
1839
+ const s = this.entityDefinitions.get(t.type);
1840
+ if (s != null && s.onBeforeDestroy) {
1659
1841
  this._log.trace(`Calling onBeforeDestroy hook for entity: ${e}`);
1660
- const s = await i.onBeforeDestroy(t.state);
1661
- s !== void 0 && (t.state = s);
1842
+ const i = await s.onBeforeDestroy(t.state);
1843
+ i !== void 0 && (t.state = i);
1662
1844
  }
1663
- 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`);
1845
+ await t.$destroy(), s != null && s.onDestroy && (this._log.trace(`Calling onDestroy hook for entity: ${e}`), await s.onDestroy(t.state)), this.entities.delete(e), this._log.debug(`Entity ${e} destroyed`);
1664
1846
  } else
1665
1847
  this._log.warn(`Attempted to destroy non-existent entity: ${e}`);
1666
1848
  }
@@ -1696,13 +1878,96 @@ class Q {
1696
1878
  for (const t of e)
1697
1879
  try {
1698
1880
  await this.destroyEntity(t);
1699
- } catch (i) {
1700
- this._log.error(`Error destroying entity ${t}: ${i}`);
1881
+ } catch (s) {
1882
+ this._log.error(`Error destroying entity ${t}: ${s}`);
1701
1883
  }
1702
1884
  this.entityDefinitions.clear(), this._log.info("EntityManager torn down successfully");
1703
1885
  }
1704
1886
  }
1705
- class ee {
1887
+ class ne {
1888
+ constructor(e, t, s) {
1889
+ n(this, "_eventBus");
1890
+ n(this, "_sceneEngine");
1891
+ n(this, "_log");
1892
+ /** Map of registered levels by name */
1893
+ n(this, "_registeredLevels", /* @__PURE__ */ new Map());
1894
+ /** The currently active level */
1895
+ n(this, "_currentLevel", null);
1896
+ this._eventBus = e, this._sceneEngine = t, this._log = (s == null ? void 0 : s.getLogger("LevelManager")) || new u("LevelManager"), this._eventBus.subscribe("level:*", (i) => {
1897
+ i.payload && this._handleLevelEvent(i.payload);
1898
+ }), this._log.info("LevelManager initialized");
1899
+ }
1900
+ /**
1901
+ * Handles level events from the event bus
1902
+ */
1903
+ _handleLevelEvent(e) {
1904
+ switch (e.type) {
1905
+ case "level:progress":
1906
+ this._log.debug(`Level ${e.levelName} progress: ${e.progress}%`);
1907
+ break;
1908
+ case "level:complete":
1909
+ this._log.info(`Level ${e.levelName} loaded successfully`);
1910
+ break;
1911
+ case "level:error":
1912
+ this._log.error(`Level ${e.levelName} error: ${e.message}`);
1913
+ break;
1914
+ }
1915
+ }
1916
+ /**
1917
+ * Registers a level class that can be instantiated later
1918
+ * @param name - The name to register the level under
1919
+ * @param level - The level class instance
1920
+ */
1921
+ registerLevel(e, t) {
1922
+ this._registeredLevels.has(e) && this._log.warn(`Level '${e}' is already registered. Overwriting.`), this._registeredLevels.set(e, t), this._log.info(`Registered level: ${e}`);
1923
+ }
1924
+ /**
1925
+ * Loads and activates a level by name
1926
+ * @param levelName - The name of the level to load
1927
+ * @returns Promise that resolves when the level is loaded
1928
+ */
1929
+ async loadLevel(e) {
1930
+ const t = this._registeredLevels.get(e);
1931
+ if (!t)
1932
+ throw new Error(`Level '${e}' is not registered.`);
1933
+ t.isLoaded || (this._log.debug(`Loading level: ${e}`), await t.loadScene(this._eventBus, this._sceneEngine)), this._currentLevel = t, this._log.info(`Activated level: ${e}`);
1934
+ }
1935
+ /**
1936
+ * Gets the currently active level
1937
+ */
1938
+ get currentLevel() {
1939
+ return this._currentLevel;
1940
+ }
1941
+ /**
1942
+ * Gets a loaded level by name
1943
+ */
1944
+ getLevel(e) {
1945
+ return this._registeredLevels.get(e) || null;
1946
+ }
1947
+ /**
1948
+ * Unloads a level and disposes its resources
1949
+ */
1950
+ unloadLevel(e) {
1951
+ const t = this._registeredLevels.get(e);
1952
+ t && (this._currentLevel === t && (this._currentLevel = null), t.dispose(), this._log.info(`Unloaded level: ${e}`));
1953
+ }
1954
+ /**
1955
+ * Unloads the current level and disposes its resources
1956
+ */
1957
+ unloadCurrentLevel() {
1958
+ this._currentLevel ? this.unloadLevel(this._currentLevel.name) : this._log.warn("No current level to unload");
1959
+ }
1960
+ //------------------------------------------------------------------------------------------------------------------
1961
+ /**
1962
+ * Tears down the level manager and cleans up any resources
1963
+ */
1964
+ async $teardown() {
1965
+ for (const e of this._registeredLevels.values())
1966
+ e.dispose();
1967
+ return this._registeredLevels.clear(), this._currentLevel = null, Promise.resolve();
1968
+ }
1969
+ }
1970
+ class oe {
1706
1971
  //------------------------------------------------------------------------------------------------------------------
1707
1972
  /**
1708
1973
  * Create a new KeyboardResourceAccess
@@ -1777,13 +2042,13 @@ class ee {
1777
2042
  this._keysState[e.code] = !0;
1778
2043
  const t = {};
1779
2044
  t[e.code] = !0;
1780
- const i = {
2045
+ const s = {
1781
2046
  type: "keyboard",
1782
2047
  keys: { ...this._keysState },
1783
2048
  delta: t,
1784
2049
  event: e
1785
2050
  };
1786
- this._notifyInputChanged(i);
2051
+ this._notifyInputChanged(s);
1787
2052
  }
1788
2053
  /**
1789
2054
  * Handle keyboard key up events
@@ -1792,13 +2057,13 @@ class ee {
1792
2057
  this._keysState[e.code] = !1;
1793
2058
  const t = {};
1794
2059
  t[e.code] = !1;
1795
- const i = {
2060
+ const s = {
1796
2061
  type: "keyboard",
1797
2062
  keys: { ...this._keysState },
1798
2063
  delta: t,
1799
2064
  event: e
1800
2065
  };
1801
- this._notifyInputChanged(i);
2066
+ this._notifyInputChanged(s);
1802
2067
  }
1803
2068
  /**
1804
2069
  * Notify subscribers of device connected event
@@ -1813,7 +2078,7 @@ class ee {
1813
2078
  this._onInputChanged && this._onInputChanged(this._keyboardDevice, e);
1814
2079
  }
1815
2080
  }
1816
- class te {
2081
+ class ae {
1817
2082
  //------------------------------------------------------------------------------------------------------------------
1818
2083
  /**
1819
2084
  * Create a new MouseResourceAccess
@@ -1904,10 +2169,10 @@ class te {
1904
2169
  * Handle mouse button down events
1905
2170
  */
1906
2171
  _handleMouseDown(e) {
1907
- const t = `button-${e.button}`, i = {
2172
+ const t = `button-${e.button}`, s = {
1908
2173
  pressed: !0
1909
2174
  };
1910
- this._buttonState[t] = i, this._notifyInputChanged({
2175
+ this._buttonState[t] = s, this._notifyInputChanged({
1911
2176
  type: "mouse",
1912
2177
  event: e,
1913
2178
  buttons: { ...this._buttonState },
@@ -1919,10 +2184,10 @@ class te {
1919
2184
  * Handle mouse button up events
1920
2185
  */
1921
2186
  _handleMouseUp(e) {
1922
- const t = `button-${e.button}`, i = {
2187
+ const t = `button-${e.button}`, s = {
1923
2188
  pressed: !1
1924
2189
  };
1925
- this._buttonState[t] = i, this._notifyInputChanged({
2190
+ this._buttonState[t] = s, this._notifyInputChanged({
1926
2191
  type: "mouse",
1927
2192
  event: e,
1928
2193
  buttons: { ...this._buttonState },
@@ -1982,7 +2247,7 @@ class te {
1982
2247
  this._onInputChanged && this._onInputChanged(this._mouseDevice, e);
1983
2248
  }
1984
2249
  }
1985
- class ie {
2250
+ class re {
1986
2251
  //------------------------------------------------------------------------------------------------------------------
1987
2252
  /**
1988
2253
  * Create a new GamepadResourceAccess
@@ -2036,10 +2301,10 @@ class ie {
2036
2301
  getStates() {
2037
2302
  const e = {};
2038
2303
  return Object.keys(this._buttonStates).forEach((t) => {
2039
- const i = Number(t), s = this._buttonStates[i] || {}, o = this._axesStates[i] || {};
2040
- e[i] = {
2304
+ const s = Number(t), i = this._buttonStates[s] || {}, o = this._axesStates[s] || {};
2305
+ e[s] = {
2041
2306
  type: "gamepad",
2042
- buttons: { ...s },
2307
+ buttons: { ...i },
2043
2308
  axes: { ...o }
2044
2309
  };
2045
2310
  }), e;
@@ -2059,11 +2324,11 @@ class ie {
2059
2324
  * @param index - The index of the gamepad state to get
2060
2325
  */
2061
2326
  getState(e) {
2062
- const t = this._buttonStates[e], i = this._axesStates[e];
2063
- return !t && !i ? null : {
2327
+ const t = this._buttonStates[e], s = this._axesStates[e];
2328
+ return !t && !s ? null : {
2064
2329
  type: "gamepad",
2065
2330
  buttons: t ? { ...t } : {},
2066
- axes: i ? { ...i } : {}
2331
+ axes: s ? { ...s } : {}
2067
2332
  };
2068
2333
  }
2069
2334
  /**
@@ -2076,38 +2341,38 @@ class ie {
2076
2341
  for (const t of e) {
2077
2342
  if (!t)
2078
2343
  continue;
2079
- const i = t.index;
2080
- if (!this._gamepadDevices[i]) {
2344
+ const s = t.index;
2345
+ if (!this._gamepadDevices[s]) {
2081
2346
  this._handleGamepadConnected(t);
2082
2347
  continue;
2083
2348
  }
2084
- const s = this._gamepadDevices[i];
2085
- if (!s)
2349
+ const i = this._gamepadDevices[s];
2350
+ if (!i)
2086
2351
  continue;
2087
- const o = this._buttonStates[i] || {}, c = this._axesStates[i] || {}, a = {};
2352
+ const o = this._buttonStates[s] || {}, c = this._axesStates[s] || {}, a = {};
2088
2353
  let h = !1;
2089
- t.buttons.forEach((u, p) => {
2090
- const l = `button-${p}`, f = {
2091
- pressed: u.pressed,
2092
- touched: u.touched,
2093
- value: u.value
2354
+ t.buttons.forEach((d, f) => {
2355
+ const p = `button-${f}`, g = {
2356
+ pressed: d.pressed,
2357
+ touched: d.touched,
2358
+ value: d.value
2094
2359
  };
2095
- a[l] = f;
2096
- const y = o[l];
2097
- (!y || y.pressed !== f.pressed || y.touched !== f.touched || y.value !== f.value) && (h = !0);
2360
+ a[p] = g;
2361
+ const y = o[p];
2362
+ (!y || y.pressed !== g.pressed || y.touched !== g.touched || y.value !== g.value) && (h = !0);
2098
2363
  });
2099
- const d = {};
2364
+ const l = {};
2100
2365
  let _ = !1;
2101
- if (t.axes.forEach((u, p) => {
2102
- const l = `axis-${p}`;
2103
- d[l] = u, c[l] !== u && (_ = !0);
2104
- }), this._buttonStates[i] = a, this._axesStates[i] = d, h || _) {
2105
- const u = {
2366
+ if (t.axes.forEach((d, f) => {
2367
+ const p = `axis-${f}`;
2368
+ l[p] = d, c[p] !== d && (_ = !0);
2369
+ }), this._buttonStates[s] = a, this._axesStates[s] = l, h || _) {
2370
+ const d = {
2106
2371
  type: "gamepad",
2107
2372
  buttons: { ...a },
2108
- axes: { ...d }
2373
+ axes: { ...l }
2109
2374
  };
2110
- this._notifyInputChanged(s, u);
2375
+ this._notifyInputChanged(i, d);
2111
2376
  }
2112
2377
  }
2113
2378
  }
@@ -2134,17 +2399,17 @@ class ie {
2134
2399
  * Handle gamepad connected event
2135
2400
  */
2136
2401
  _handleGamepadConnected(e) {
2137
- const t = e instanceof GamepadEvent ? e.gamepad : e, i = t.index, s = {
2138
- id: `gamepad-${i}`,
2402
+ const t = e instanceof GamepadEvent ? e.gamepad : e, s = t.index, i = {
2403
+ id: `gamepad-${s}`,
2139
2404
  name: t.id,
2140
2405
  type: "gamepad",
2141
2406
  connected: !0,
2142
- index: i,
2407
+ index: s,
2143
2408
  mapping: t.mapping,
2144
2409
  axes: Array.from(t.axes),
2145
2410
  buttons: Array.from(t.buttons)
2146
2411
  };
2147
- this._gamepadDevices[i] = s;
2412
+ this._gamepadDevices[s] = i;
2148
2413
  const o = {};
2149
2414
  Array.from(t.buttons).forEach((a, h) => {
2150
2415
  o[`button-${h}`] = {
@@ -2152,11 +2417,11 @@ class ie {
2152
2417
  touched: a.touched,
2153
2418
  value: a.value
2154
2419
  };
2155
- }), this._buttonStates[i] = o;
2420
+ }), this._buttonStates[s] = o;
2156
2421
  const c = {};
2157
2422
  Array.from(t.axes).forEach((a, h) => {
2158
2423
  c[`axis-${h}`] = a;
2159
- }), this._axesStates[i] = c, this._notifyDeviceConnected(s), this._notifyInputChanged(s, {
2424
+ }), this._axesStates[s] = c, this._notifyDeviceConnected(i), this._notifyInputChanged(i, {
2160
2425
  type: "gamepad",
2161
2426
  buttons: { ...o },
2162
2427
  axes: { ...c },
@@ -2167,8 +2432,8 @@ class ie {
2167
2432
  * Handle gamepad disconnected event
2168
2433
  */
2169
2434
  _handleGamepadDisconnected(e) {
2170
- const i = e.gamepad.index, s = this._gamepadDevices[i];
2171
- s && (s.connected = !1, this._notifyDeviceDisconnected(s), this._gamepadDevices[i] = void 0, this._buttonStates[i] = void 0, this._axesStates[i] = void 0);
2435
+ const s = e.gamepad.index, i = this._gamepadDevices[s];
2436
+ i && (i.connected = !1, this._notifyDeviceDisconnected(i), this._gamepadDevices[s] = void 0, this._buttonStates[s] = void 0, this._axesStates[s] = void 0);
2172
2437
  }
2173
2438
  /**
2174
2439
  * Notify subscribers of device connected event
@@ -2189,7 +2454,7 @@ class ie {
2189
2454
  this._onInputChanged && this._onInputChanged(e, t);
2190
2455
  }
2191
2456
  }
2192
- class se {
2457
+ class ce {
2193
2458
  //------------------------------------------------------------------------------------------------------------------
2194
2459
  /**
2195
2460
  * Create a new UserInputManager
@@ -2198,14 +2463,14 @@ class se {
2198
2463
  * @param canvas - The DOM element to attach input listeners to
2199
2464
  * @param logger - The logging utility to use
2200
2465
  */
2201
- constructor(e, t, i) {
2466
+ constructor(e, t, s) {
2202
2467
  n(this, "_eventBus");
2203
2468
  n(this, "_keyboardRA");
2204
2469
  n(this, "_mouseRA");
2205
2470
  n(this, "_gamepadRA");
2206
2471
  /** Logger instance */
2207
2472
  n(this, "_log");
2208
- 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");
2473
+ this._eventBus = e, this._log = (s == null ? void 0 : s.getLogger("UserInputManager")) || new u("UserInputManager"), this._log.info("Initializing UserInputManager"), this._log.debug("Initializing input resource access classes"), this._keyboardRA = new oe(), this._mouseRA = new ae(t), this._gamepadRA = new re(), 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");
2209
2474
  }
2210
2475
  //------------------------------------------------------------------------------------------------------------------
2211
2476
  // Private methods
@@ -2237,7 +2502,7 @@ class se {
2237
2502
  */
2238
2503
  _publishInputChanged(e, t) {
2239
2504
  this._log.trace(`Input changed: ${e.id}`, t);
2240
- const i = {
2505
+ const s = {
2241
2506
  type: "input:changed",
2242
2507
  payload: {
2243
2508
  deviceId: e.id,
@@ -2245,7 +2510,7 @@ class se {
2245
2510
  state: t
2246
2511
  }
2247
2512
  };
2248
- this._eventBus.publish(i);
2513
+ this._eventBus.publish(s);
2249
2514
  }
2250
2515
  //------------------------------------------------------------------------------------------------------------------
2251
2516
  // Internal methods
@@ -2292,9 +2557,9 @@ class se {
2292
2557
  return this._gamepadRA.getDevice(t);
2293
2558
  } else {
2294
2559
  const t = this.listDevices();
2295
- for (const i of t)
2296
- if (i.id === e)
2297
- return i;
2560
+ for (const s of t)
2561
+ if (s.id === e)
2562
+ return s;
2298
2563
  }
2299
2564
  return this._log.warn(`Device not found: ${e}`), null;
2300
2565
  }
@@ -2306,47 +2571,47 @@ class se {
2306
2571
  }
2307
2572
  }
2308
2573
  async function M(r, e) {
2309
- const t = new K(r, e);
2574
+ const t = new z(r, e);
2310
2575
  return await t.initAsync(), t;
2311
2576
  }
2312
- function v(r, e) {
2313
- return new T(r, e.antialias, e.options, e.adaptToDeviceRatio);
2577
+ function m(r, e) {
2578
+ return new P(r, e.antialias, e.options, e.adaptToDeviceRatio);
2314
2579
  }
2315
- function ne(r) {
2316
- return new L(r);
2580
+ function he(r) {
2581
+ return new R(r);
2317
2582
  }
2318
- async function oe(r, e) {
2583
+ async function le(r, e) {
2319
2584
  if (r === null)
2320
- return console.debug("Using Null Engine"), ne(e);
2585
+ return console.debug("Using Null Engine"), he(e);
2321
2586
  const t = e.engine || "auto";
2322
2587
  if (t === "webgpu")
2323
- if (k())
2588
+ if (D())
2324
2589
  try {
2325
2590
  return console.debug("Using forced WebGPU engine"), await M(r, e);
2326
- } catch (i) {
2327
- throw console.error("Forced WebGPU initialization failed:", i), new Error(
2591
+ } catch (s) {
2592
+ throw console.error("Forced WebGPU initialization failed:", s), new Error(
2328
2593
  "Forced WebGPU failed to initialize. If WebGPU is required, check browser compatibility."
2329
2594
  );
2330
2595
  }
2331
2596
  else
2332
2597
  throw new Error("WebGPU was forced but is not available in this browser.");
2333
2598
  if (t === "webgl")
2334
- return console.debug("Using forced WebGL engine"), v(r, e);
2335
- if (k())
2599
+ return console.debug("Using forced WebGL engine"), m(r, e);
2600
+ if (D())
2336
2601
  try {
2337
- return console.debug("Using WebGPU"), M(r, e).catch((i) => (console.warn("WebGPU initialization failed, falling back to WebGL:", i), v(r, e)));
2338
- } catch (i) {
2339
- console.warn("WebGPU initialization failed, falling back to WebGL:", i);
2602
+ return console.debug("Using WebGPU"), M(r, e).catch((s) => (console.warn("WebGPU initialization failed, falling back to WebGL:", s), m(r, e)));
2603
+ } catch (s) {
2604
+ console.warn("WebGPU initialization failed, falling back to WebGL:", s);
2340
2605
  }
2341
2606
  else
2342
2607
  console.warn("WebGPU not supported, falling back to WebGL.");
2343
- return console.debug("Using WebGL"), v(r, e);
2608
+ return console.debug("Using WebGL"), m(r, e);
2344
2609
  }
2345
- async function ae() {
2346
- const r = await R();
2347
- return new U(!0, r);
2610
+ async function de() {
2611
+ const r = await H();
2612
+ return new O(!0, r);
2348
2613
  }
2349
- const ue = ["keyboard", "mouse", "gamepad"], le = [
2614
+ const fe = ["keyboard", "mouse", "gamepad"], ye = [
2350
2615
  "trace",
2351
2616
  "debug",
2352
2617
  "info",
@@ -2354,30 +2619,109 @@ const ue = ["keyboard", "mouse", "gamepad"], le = [
2354
2619
  "error",
2355
2620
  "none"
2356
2621
  ];
2357
- async function ge(r, e, t = {}) {
2358
- const i = new O(t.logLevel || "debug"), s = i.getLogger("SAGE");
2359
- s.info(`Initializing SAGE Game Engine v${m}...`), s.debug("Creating rendering engine...");
2360
- const o = await oe(r, t.renderOptions || {});
2361
- s.debug("Creating physics engine...");
2362
- const c = await ae();
2363
- s.debug("Creating event bus...");
2364
- const a = new W(i);
2365
- s.debug("Creating scene engine...");
2366
- const h = new F(o, c, i);
2367
- s.debug("Creating managers...");
2368
- const d = new se(a, r, i), _ = new X(a, i), u = new Q(a, i, _), p = new Z(o, h, u, d, i);
2369
- s.info(`SAGE Game Engine v${m} initialized successfully.`), s.debug("Loading entities...");
2370
- for (const l of e)
2371
- u.registerEntityDefinition(l);
2372
- if (s.debug("Registering default input bindings..."), t.bindings)
2373
- for (const l of t.bindings)
2374
- _.registerBinding(l);
2375
- return new z(
2622
+ class ve {
2623
+ //------------------------------------------------------------------------------------------------------------------
2624
+ constructor(e) {
2625
+ n(this, "_name");
2626
+ n(this, "_sceneEngine");
2627
+ n(this, "_eventBus");
2628
+ n(this, "_scene", null);
2629
+ n(this, "_log");
2630
+ this._name = e, this._log = new u(`Level:${e}`, "info");
2631
+ }
2632
+ /**
2633
+ * The name of this level
2634
+ */
2635
+ get name() {
2636
+ return this._name;
2637
+ }
2638
+ /**
2639
+ * The current scene for this level (null if not loaded)
2640
+ */
2641
+ get scene() {
2642
+ return this._scene;
2643
+ }
2644
+ /**
2645
+ * Whether this level has been loaded
2646
+ */
2647
+ get isLoaded() {
2648
+ return this._scene !== null;
2649
+ }
2650
+ //------------------------------------------------------------------------------------------------------------------
2651
+ /**
2652
+ * Emit a progress event during loading
2653
+ */
2654
+ _emitProgress(e, t) {
2655
+ if (!this._eventBus)
2656
+ throw new Error("Event bus is not initialized. Call loadScene() first.");
2657
+ this._eventBus.publish({
2658
+ type: "level:progress",
2659
+ levelName: this._name,
2660
+ progress: e,
2661
+ message: t
2662
+ });
2663
+ }
2664
+ //------------------------------------------------------------------------------------------------------------------
2665
+ /**
2666
+ * Load and create the scene for this level.
2667
+ * Progress events will be emitted during loading.
2668
+ *
2669
+ * @param eventBus - The game event bus for publishing events
2670
+ * @param sceneEngine - The scene engine used to create the scene
2671
+ *
2672
+ * @returns Promise that resolves to the loaded scene
2673
+ */
2674
+ async loadScene(e, t) {
2675
+ if (this._scene)
2676
+ return this._log.warn(`Level ${this._name} is already loaded`), this._scene;
2677
+ this._eventBus = e, this._sceneEngine = t, this._log.info(`Loading level: ${this._name}`), this._log.time(`level-${this._name}-load`);
2678
+ try {
2679
+ return this._emitProgress(0, "Starting level load..."), this._scene = await this.buildScene(), this._emitProgress(100, "Level loaded successfully"), this._eventBus.publish({
2680
+ type: "level:complete",
2681
+ levelName: this._name,
2682
+ message: "Level loaded successfully"
2683
+ }), this._log.timeEnd(`level-${this._name}-load`), this._log.info(`Level ${this._name} loaded successfully`), this._scene;
2684
+ } catch (s) {
2685
+ throw this._log.error(`Failed to load level ${this._name}:`, s), this._eventBus.publish({
2686
+ type: "level:error",
2687
+ levelName: this._name,
2688
+ message: "Failed to load level",
2689
+ error: s
2690
+ }), s;
2691
+ }
2692
+ }
2693
+ //------------------------------------------------------------------------------------------------------------------
2694
+ /**
2695
+ * Dispose of this level's resources
2696
+ */
2697
+ dispose() {
2698
+ this._scene && (this._log.info(`Disposing level: ${this._name}`), this._scene.dispose(), this._scene = null);
2699
+ }
2700
+ }
2701
+ async function be(r, e, t = {}) {
2702
+ const s = new J(t.logLevel || "debug"), i = s.getLogger("SAGE");
2703
+ i.info(`Initializing SAGE Game Engine v${b}...`), i.debug("Creating rendering engine...");
2704
+ const o = await le(r, t.renderOptions || {});
2705
+ i.debug("Creating physics engine...");
2706
+ const c = await de();
2707
+ i.debug("Creating event bus...");
2708
+ const a = new Y(s);
2709
+ i.debug("Creating scene engine...");
2710
+ const h = new j(r, o, c, s);
2711
+ i.debug("Creating managers...");
2712
+ const l = new ce(a, r, s), _ = new ee(a, s), d = new ie(a, s, _), f = new ne(a, h, s), p = new te(o, d, l, f, s);
2713
+ i.info(`SAGE Game Engine v${b} initialized successfully.`), i.debug("Loading entities...");
2714
+ for (const g of e)
2715
+ d.registerEntityDefinition(g);
2716
+ if (i.debug("Registering default input bindings..."), t.bindings)
2717
+ for (const g of t.bindings)
2718
+ _.registerBinding(g);
2719
+ return new W(
2376
2720
  r,
2377
2721
  o,
2378
2722
  c,
2379
2723
  a,
2380
- i,
2724
+ s,
2381
2725
  // Engines
2382
2726
  {
2383
2727
  sceneEngine: h
@@ -2385,25 +2729,27 @@ async function ge(r, e, t = {}) {
2385
2729
  // Managers
2386
2730
  {
2387
2731
  bindingManager: _,
2388
- entityManager: u,
2732
+ entityManager: d,
2389
2733
  gameManager: p,
2390
- inputManager: d
2734
+ inputManager: l,
2735
+ levelManager: f
2391
2736
  }
2392
2737
  );
2393
2738
  }
2394
2739
  export {
2395
- P as ConsoleBackend,
2396
- q as GameEntity,
2397
- de as GameEntityBehavior,
2398
- W as GameEventBus,
2399
- le as LogLevels,
2400
- O as LoggingUtility,
2401
- H as NullBackend,
2402
- g as SAGELogger,
2403
- z as SkewedAspectGameEngine,
2404
- m as VERSION,
2405
- N as bindingTypes,
2406
- ge as createGameEngine,
2407
- ue as validDeviceTypes
2740
+ F as ConsoleBackend,
2741
+ se as GameEntity,
2742
+ pe as GameEntityBehavior,
2743
+ Y as GameEventBus,
2744
+ ve as Level,
2745
+ ye as LogLevels,
2746
+ J as LoggingUtility,
2747
+ N as NullBackend,
2748
+ u as SAGELogger,
2749
+ W as SkewedAspectGameEngine,
2750
+ b as VERSION,
2751
+ X as bindingTypes,
2752
+ be as createGameEngine,
2753
+ fe as validDeviceTypes
2408
2754
  };
2409
2755
  //# sourceMappingURL=sage.es.js.map