@yagejs/debug 0.1.0 → 0.2.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/index.cjs CHANGED
@@ -28,14 +28,15 @@ __export(index_exports, {
28
28
  module.exports = __toCommonJS(index_exports);
29
29
 
30
30
  // src/DebugPlugin.ts
31
- var import_core3 = require("@yagejs/core");
31
+ var import_core4 = require("@yagejs/core");
32
32
 
33
33
  // src/types.ts
34
34
  var import_core = require("@yagejs/core");
35
35
  var DebugRegistryKey = new import_core.ServiceKey("debugRegistry");
36
36
 
37
37
  // src/DebugPlugin.ts
38
- var import_renderer = require("@yagejs/renderer");
38
+ var import_renderer2 = require("@yagejs/renderer");
39
+ var import_renderer3 = require("@yagejs/renderer");
39
40
 
40
41
  // src/DebugClock.ts
41
42
  var DebugClock = class {
@@ -131,6 +132,44 @@ var DebugRegistryImpl = class {
131
132
  }
132
133
  };
133
134
 
135
+ // src/DebugScene.ts
136
+ var import_core2 = require("@yagejs/core");
137
+ var import_renderer = require("@yagejs/renderer");
138
+ var DebugScene = class extends import_core2.Scene {
139
+ static {
140
+ __name(this, "DebugScene");
141
+ }
142
+ name = "__debug__";
143
+ pauseBelow = false;
144
+ transparentBelow = true;
145
+ layers = [
146
+ { name: "debug-world", order: 999999 },
147
+ { name: "debug-hud", order: 999999 }
148
+ ];
149
+ /** Called after `_mountDetached` has materialized the render tree. */
150
+ onReady;
151
+ /** Called by the plugin when the scene is unmounted. */
152
+ onTearDown;
153
+ onEnter() {
154
+ const tree = this._resolveScoped(import_renderer.SceneRenderTreeKey);
155
+ if (!tree) {
156
+ const logger = this.context.tryResolve(import_core2.LoggerKey);
157
+ const msg = "DebugScene.onEnter: SceneRenderTreeKey missing \u2014 debug overlay will not render. Is RendererPlugin registered?";
158
+ if (logger) logger.warn("debug", msg);
159
+ else console.warn(`[yage] ${msg}`);
160
+ return;
161
+ }
162
+ const worldContainer = tree.get("debug-world").container;
163
+ const hudContainer = tree.get("debug-hud").container;
164
+ worldContainer.eventMode = "none";
165
+ hudContainer.eventMode = "none";
166
+ this.onReady?.(worldContainer, hudContainer);
167
+ }
168
+ onExit() {
169
+ this.onTearDown?.();
170
+ }
171
+ };
172
+
134
173
  // src/StatsStore.ts
135
174
  var WINDOW_SIZE = 120;
136
175
  var StatsStore = class {
@@ -365,9 +404,9 @@ var HudDebugApiImpl = class {
365
404
  };
366
405
 
367
406
  // src/DebugRenderSystem.ts
368
- var import_core2 = require("@yagejs/core");
369
- var DebugRenderSystem = class extends import_core2.System {
370
- constructor(registry, graphicsPool, textPool, worldApi, hudApi, stats, worldContainer, hudContainer) {
407
+ var import_core3 = require("@yagejs/core");
408
+ var DebugRenderSystem = class extends import_core3.System {
409
+ constructor(registry, graphicsPool, textPool, worldApi, hudApi, stats, worldContainer, hudContainer, cameraAccessor) {
371
410
  super();
372
411
  this.registry = registry;
373
412
  this.graphicsPool = graphicsPool;
@@ -377,6 +416,7 @@ var DebugRenderSystem = class extends import_core2.System {
377
416
  this.stats = stats;
378
417
  this.worldContainer = worldContainer;
379
418
  this.hudContainer = hudContainer;
419
+ this.cameraAccessor = cameraAccessor;
380
420
  }
381
421
  registry;
382
422
  graphicsPool;
@@ -386,10 +426,11 @@ var DebugRenderSystem = class extends import_core2.System {
386
426
  stats;
387
427
  worldContainer;
388
428
  hudContainer;
429
+ cameraAccessor;
389
430
  static {
390
431
  __name(this, "DebugRenderSystem");
391
432
  }
392
- phase = import_core2.Phase.Render;
433
+ phase = import_core3.Phase.Render;
393
434
  priority = 9999;
394
435
  update(dt) {
395
436
  if (!this.registry.enabled) {
@@ -399,6 +440,7 @@ var DebugRenderSystem = class extends import_core2.System {
399
440
  }
400
441
  this.worldContainer.visible = true;
401
442
  this.hudContainer.visible = true;
443
+ this.syncWorldCamera();
402
444
  this.graphicsPool.resetFrame();
403
445
  this.textPool.resetFrame();
404
446
  for (const [name, contributor] of this.registry.contributors) {
@@ -413,6 +455,22 @@ var DebugRenderSystem = class extends import_core2.System {
413
455
  }
414
456
  }
415
457
  }
458
+ syncWorldCamera() {
459
+ const cam = this.cameraAccessor.findCamera();
460
+ if (!cam) {
461
+ this.worldContainer.position.set(0, 0);
462
+ this.worldContainer.scale.set(1, 1);
463
+ this.worldContainer.rotation = 0;
464
+ return;
465
+ }
466
+ const vw = this.cameraAccessor.viewportWidth;
467
+ const vh = this.cameraAccessor.viewportHeight;
468
+ const rotatedPos = cam.effectivePosition.scale(cam.zoom).rotate(-cam.rotation);
469
+ this.worldContainer.position.x = vw / 2 - rotatedPos.x;
470
+ this.worldContainer.position.y = vh / 2 - rotatedPos.y;
471
+ this.worldContainer.scale.set(cam.zoom);
472
+ this.worldContainer.rotation = -cam.rotation;
473
+ }
416
474
  };
417
475
 
418
476
  // src/contributors/FpsContributor.ts
@@ -493,42 +551,33 @@ var DebugPlugin = class {
493
551
  __name(this, "DebugPlugin");
494
552
  }
495
553
  name = "debug";
496
- version = "2.0.0";
554
+ version = "3.0.0";
497
555
  dependencies = ["renderer"];
498
556
  config;
499
557
  registry;
500
558
  stats;
501
- graphicsPool;
502
- textPool;
503
- worldContainer;
504
- hudContainer;
505
- worldApi;
506
- hudApi;
559
+ graphicsPool = null;
560
+ textPool = null;
561
+ worldApi = null;
562
+ hudApi = null;
563
+ renderSystem = null;
507
564
  systemTimings = /* @__PURE__ */ new Map();
508
565
  originalUpdates = /* @__PURE__ */ new Map();
509
566
  keyListener = null;
510
567
  context;
511
568
  renderer;
569
+ scheduler;
570
+ sceneManager;
571
+ debugScene = null;
572
+ provider = null;
573
+ eventUnsubs = [];
512
574
  clock = null;
513
575
  constructor(config) {
514
576
  this.config = config ?? {};
515
577
  }
516
578
  install(context) {
517
579
  this.context = context;
518
- this.renderer = context.resolve(import_renderer.RendererKey);
519
- const camera = context.resolve(import_renderer.CameraKey);
520
- const worldLayers = context.resolve(import_renderer.RenderLayerManagerKey);
521
- const debugLayer = worldLayers.getOrCreate("debug", 999999);
522
- this.worldContainer = debugLayer.container;
523
- this.worldContainer.eventMode = "none";
524
- const hudLayers = this.renderer.createScreenContainer("debug-hud");
525
- this.hudContainer = hudLayers.defaultLayer.container;
526
- this.hudContainer.eventMode = "none";
527
- this.graphicsPool = new GraphicsPool(
528
- this.worldContainer,
529
- this.config.maxGraphics
530
- );
531
- this.textPool = new TextPool(this.hudContainer, this.config.maxHudLines);
580
+ this.renderer = context.resolve(import_renderer2.RendererKey);
532
581
  this.registry = new DebugRegistryImpl();
533
582
  this.registry.enabled = this.config.startEnabled ?? false;
534
583
  if (this.config.flags) {
@@ -540,34 +589,14 @@ var DebugPlugin = class {
540
589
  }
541
590
  }
542
591
  this.stats = new StatsStore();
543
- this.worldApi = new WorldDebugApiImpl(
544
- this.graphicsPool,
545
- this.registry,
546
- camera
547
- );
548
- this.hudApi = new HudDebugApiImpl(
549
- this.textPool,
550
- this.registry,
551
- camera.viewportWidth,
552
- camera.viewportHeight
553
- );
554
592
  context.register(DebugRegistryKey, this.registry);
555
593
  }
556
594
  registerSystems(scheduler) {
557
- scheduler.add(
558
- new DebugRenderSystem(
559
- this.registry,
560
- this.graphicsPool,
561
- this.textPool,
562
- this.worldApi,
563
- this.hudApi,
564
- this.stats,
565
- this.worldContainer,
566
- this.hudContainer
567
- )
568
- );
595
+ this.scheduler = scheduler;
569
596
  }
570
- onStart() {
597
+ async onStart() {
598
+ this.sceneManager = this.context.resolve(import_core4.SceneManagerKey);
599
+ const bus = this.context.resolve(import_core4.EventBusKey);
571
600
  const toggleKey = this.config.toggleKey ?? "Backquote";
572
601
  const stepKey = this.config.stepKey ?? "Period";
573
602
  this.keyListener = (e) => {
@@ -583,8 +612,7 @@ var DebugPlugin = class {
583
612
  if (typeof window !== "undefined") {
584
613
  window.addEventListener("keydown", this.keyListener);
585
614
  }
586
- const scheduler = this.context.resolve(import_core3.SystemSchedulerKey);
587
- for (const system of scheduler.getAllSystems()) {
615
+ for (const system of this.scheduler.getAllSystems()) {
588
616
  if (system instanceof DebugRenderSystem) continue;
589
617
  const name = system.constructor.name;
590
618
  const original = system.update.bind(system);
@@ -595,11 +623,11 @@ var DebugPlugin = class {
595
623
  this.systemTimings.set(name, performance.now() - t0);
596
624
  };
597
625
  }
598
- const inspector = this.context.resolve(import_core3.InspectorKey);
626
+ const inspector = this.context.resolve(import_core4.InspectorKey);
599
627
  this.registry.register(new FpsContributor());
600
628
  this.registry.register(new EntityCountContributor(inspector));
601
629
  this.registry.register(new SystemTimingContributor(this.systemTimings));
602
- const gameLoop = this.context.resolve(import_core3.GameLoopKey);
630
+ const gameLoop = this.context.resolve(import_core4.GameLoopKey);
603
631
  const app = this.renderer.application;
604
632
  this.clock = new DebugClock(
605
633
  gameLoop,
@@ -611,8 +639,21 @@ var DebugPlugin = class {
611
639
  this.clock.setManual(true);
612
640
  }
613
641
  this.attachToGlobal(this.clock);
642
+ this.provider = this.context.tryResolve(import_renderer3.SceneRenderTreeProviderKey) ?? null;
643
+ this.attachInspectorDiagnostics(inspector);
644
+ await this.materializeDebugScene();
645
+ const bringToFront = /* @__PURE__ */ __name(() => {
646
+ if (this.debugScene && this.provider?.bringSceneToFront) {
647
+ this.provider.bringSceneToFront(this.debugScene);
648
+ }
649
+ }, "bringToFront");
650
+ this.eventUnsubs.push(bus.on("scene:pushed", bringToFront));
651
+ this.eventUnsubs.push(bus.on("scene:popped", bringToFront));
652
+ this.eventUnsubs.push(bus.on("scene:replaced", bringToFront));
614
653
  }
615
654
  onDestroy() {
655
+ for (const unsub of this.eventUnsubs) unsub();
656
+ this.eventUnsubs.length = 0;
616
657
  for (const [system, original] of this.originalUpdates) {
617
658
  system.update = original;
618
659
  }
@@ -629,9 +670,112 @@ var DebugPlugin = class {
629
670
  contributor.dispose?.();
630
671
  }
631
672
  this.registry.contributors.clear();
632
- this.graphicsPool.destroy();
633
- this.textPool.destroy();
634
- this.renderer.destroyScreenContainer("debug-hud");
673
+ this.tearDownDebugInfra();
674
+ this.teardownDebugScene();
675
+ }
676
+ async materializeDebugScene() {
677
+ const scene = new DebugScene();
678
+ scene.onReady = (worldContainer, hudContainer) => this.setUpDebugInfra(worldContainer, hudContainer);
679
+ scene.onTearDown = () => this.tearDownDebugInfra();
680
+ await this.sceneManager._mountDetached(scene);
681
+ this.debugScene = scene;
682
+ }
683
+ teardownDebugScene() {
684
+ if (!this.debugScene) return;
685
+ this.sceneManager._unmountDetached(this.debugScene);
686
+ this.debugScene = null;
687
+ this.provider = null;
688
+ }
689
+ findActiveCamera() {
690
+ return findTopmostCamera(this.sceneManager);
691
+ }
692
+ setUpDebugInfra(worldContainer, hudContainer) {
693
+ const vw = this.renderer.virtualSize.width;
694
+ const vh = this.renderer.virtualSize.height;
695
+ const self = this;
696
+ const cameraProxy = {
697
+ get zoom() {
698
+ return self.findActiveCamera()?.zoom ?? 1;
699
+ }
700
+ };
701
+ this.graphicsPool = new GraphicsPool(
702
+ worldContainer,
703
+ this.config.maxGraphics
704
+ );
705
+ this.textPool = new TextPool(hudContainer, this.config.maxHudLines);
706
+ this.worldApi = new WorldDebugApiImpl(
707
+ this.graphicsPool,
708
+ this.registry,
709
+ cameraProxy
710
+ );
711
+ this.hudApi = new HudDebugApiImpl(this.textPool, this.registry, vw, vh);
712
+ this.renderSystem = new DebugRenderSystem(
713
+ this.registry,
714
+ this.graphicsPool,
715
+ this.textPool,
716
+ this.worldApi,
717
+ this.hudApi,
718
+ this.stats,
719
+ worldContainer,
720
+ hudContainer,
721
+ {
722
+ findCamera: /* @__PURE__ */ __name(() => self.findActiveCamera(), "findCamera"),
723
+ viewportWidth: vw,
724
+ viewportHeight: vh
725
+ }
726
+ );
727
+ this.scheduler.add(this.renderSystem);
728
+ }
729
+ tearDownDebugInfra() {
730
+ if (this.renderSystem) {
731
+ this.scheduler.remove(this.renderSystem);
732
+ this.renderSystem = null;
733
+ }
734
+ this.graphicsPool?.destroy();
735
+ this.textPool?.destroy();
736
+ this.graphicsPool = null;
737
+ this.textPool = null;
738
+ this.worldApi = null;
739
+ this.hudApi = null;
740
+ }
741
+ attachInspectorDiagnostics(inspector) {
742
+ const g = globalThis["__yage__"];
743
+ if (!g || typeof g !== "object") return;
744
+ const debugSurface = g;
745
+ const diagnostics = inspector;
746
+ debugSurface["inspector"] = inspector;
747
+ diagnostics.getLayerTransform = (sceneName, layerName) => {
748
+ const scene = this.sceneManager.all.find(
749
+ (candidate) => candidate.name === sceneName
750
+ );
751
+ if (!scene) return void 0;
752
+ const layer = this.provider?.getTree(scene)?.tryGet(layerName);
753
+ if (!layer) return void 0;
754
+ const container = layer.container;
755
+ return {
756
+ x: container.position.x,
757
+ y: container.position.y,
758
+ scaleX: container.scale.x,
759
+ scaleY: container.scale.y,
760
+ rotation: container.rotation
761
+ };
762
+ };
763
+ diagnostics.getCameraStack = () => {
764
+ const cameras = [];
765
+ for (const scene of this.sceneManager.all) {
766
+ for (const entity of scene.getEntities()) {
767
+ const cam = entity.tryGet(import_renderer2.CameraComponent);
768
+ if (!cam) continue;
769
+ cameras.push({
770
+ scene: scene.name,
771
+ name: cam.cameraName,
772
+ priority: cam.priority,
773
+ enabled: cam.enabled
774
+ });
775
+ }
776
+ }
777
+ return cameras;
778
+ };
635
779
  }
636
780
  attachToGlobal(clock) {
637
781
  const g = globalThis["__yage__"];
@@ -646,6 +790,23 @@ var DebugPlugin = class {
646
790
  }
647
791
  }
648
792
  };
793
+ function findTopmostCamera(sceneManager) {
794
+ const stack = sceneManager.all;
795
+ for (let i = stack.length - 1; i >= 0; i--) {
796
+ const scene = stack[i];
797
+ if (!scene) continue;
798
+ let highestPriorityCamera;
799
+ for (const entity of scene.getEntities()) {
800
+ const cam = entity.tryGet(import_renderer2.CameraComponent);
801
+ if (cam && cam.enabled && (!highestPriorityCamera || cam.priority > highestPriorityCamera.priority)) {
802
+ highestPriorityCamera = cam;
803
+ }
804
+ }
805
+ if (highestPriorityCamera) return highestPriorityCamera;
806
+ }
807
+ return void 0;
808
+ }
809
+ __name(findTopmostCamera, "findTopmostCamera");
649
810
  // Annotate the CommonJS export names for ESM import in node:
650
811
  0 && (module.exports = {
651
812
  DebugPlugin,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/DebugPlugin.ts","../src/types.ts","../src/DebugClock.ts","../src/DebugRegistryImpl.ts","../src/StatsStore.ts","../src/GraphicsPool.ts","../src/TextPool.ts","../src/WorldDebugApiImpl.ts","../src/HudDebugApiImpl.ts","../src/DebugRenderSystem.ts","../src/contributors/FpsContributor.ts","../src/contributors/EntityCountContributor.ts","../src/contributors/SystemTimingContributor.ts"],"sourcesContent":["export { DebugPlugin } from \"./DebugPlugin.js\";\nexport type { DebugConfig } from \"./DebugPlugin.js\";\nexport type { IDebugClock } from \"./DebugClock.js\";\nexport { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nexport { StatsStore } from \"./StatsStore.js\";\n","import { SystemSchedulerKey, InspectorKey, GameLoopKey } from \"@yagejs/core\";\nimport type {\n EngineContext,\n Plugin,\n SystemScheduler,\n System,\n} from \"@yagejs/core\";\nimport { DebugRegistryKey } from \"./types.js\";\nimport { RendererKey, RenderLayerManagerKey, CameraKey } from \"@yagejs/renderer\";\nimport type { RendererPlugin } from \"@yagejs/renderer\";\nimport { Container } from \"pixi.js\";\nimport { DebugClock } from \"./DebugClock.js\";\nimport type { IDebugClock } from \"./DebugClock.js\";\nimport { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport { StatsStore } from \"./StatsStore.js\";\nimport { GraphicsPool } from \"./GraphicsPool.js\";\nimport { TextPool } from \"./TextPool.js\";\nimport { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport { DebugRenderSystem } from \"./DebugRenderSystem.js\";\nimport { FpsContributor } from \"./contributors/FpsContributor.js\";\nimport { EntityCountContributor } from \"./contributors/EntityCountContributor.js\";\nimport { SystemTimingContributor } from \"./contributors/SystemTimingContributor.js\";\n\n/** Configuration for the DebugPlugin. */\nexport interface DebugConfig {\n /** Key code to toggle debug overlay. Default: \"Backquote\" */\n toggleKey?: string;\n /** When true, stop the renderer ticker and advance simulation manually via `window.__yage__.clock`. */\n manualClock?: boolean;\n /** Key code to advance one fixed-timestep frame while manual clock mode is active. Default: \"Period\" */\n stepKey?: string;\n /** Max pooled Graphics objects. Default: 256 */\n maxGraphics?: number;\n /** Max HUD text lines. Default: 32 */\n maxHudLines?: number;\n /** Whether the overlay starts enabled. Default: false */\n startEnabled?: boolean;\n /** Initial flag overrides, keyed by \"contributorName.flagName\". */\n flags?: Record<string, boolean>;\n}\n\n/** Debug overlay plugin. Depends on the renderer plugin. */\nexport class DebugPlugin implements Plugin {\n readonly name = \"debug\";\n readonly version = \"2.0.0\";\n readonly dependencies = [\"renderer\"] as const;\n\n private readonly config: DebugConfig;\n private registry!: DebugRegistryImpl;\n private stats!: StatsStore;\n private graphicsPool!: GraphicsPool;\n private textPool!: TextPool;\n private worldContainer!: Container;\n private hudContainer!: Container;\n private worldApi!: WorldDebugApiImpl;\n private hudApi!: HudDebugApiImpl;\n private systemTimings = new Map<string, number>();\n private originalUpdates = new Map<System, (dt: number) => void>();\n private keyListener: ((e: KeyboardEvent) => void) | null = null;\n private context!: EngineContext;\n private renderer!: RendererPlugin;\n private clock: DebugClock | null = null;\n\n constructor(config?: DebugConfig) {\n this.config = config ?? {};\n }\n\n install(context: EngineContext): void {\n this.context = context;\n\n this.renderer = context.resolve(RendererKey);\n const camera = context.resolve(CameraKey);\n\n // World-space debug layer (child of world container, drawn on top)\n const worldLayers = context.resolve(RenderLayerManagerKey);\n const debugLayer = worldLayers.getOrCreate(\"debug\", 999999);\n this.worldContainer = debugLayer.container;\n this.worldContainer.eventMode = \"none\";\n\n // Screen-space HUD container (sibling of world container, unaffected by camera)\n const hudLayers = this.renderer.createScreenContainer(\"debug-hud\");\n this.hudContainer = hudLayers.defaultLayer.container;\n this.hudContainer.eventMode = \"none\";\n\n this.graphicsPool = new GraphicsPool(\n this.worldContainer,\n this.config.maxGraphics,\n );\n this.textPool = new TextPool(this.hudContainer, this.config.maxHudLines);\n\n this.registry = new DebugRegistryImpl();\n this.registry.enabled = this.config.startEnabled ?? false;\n\n if (this.config.flags) {\n for (const [key, value] of Object.entries(this.config.flags)) {\n const dot = key.indexOf(\".\");\n if (dot > 0) {\n this.registry.setFlag(key.slice(0, dot), key.slice(dot + 1), value);\n }\n }\n }\n\n this.stats = new StatsStore();\n\n this.worldApi = new WorldDebugApiImpl(\n this.graphicsPool,\n this.registry,\n camera,\n );\n this.hudApi = new HudDebugApiImpl(\n this.textPool,\n this.registry,\n camera.viewportWidth,\n camera.viewportHeight,\n );\n\n context.register(DebugRegistryKey, this.registry);\n }\n\n registerSystems(scheduler: SystemScheduler): void {\n scheduler.add(\n new DebugRenderSystem(\n this.registry,\n this.graphicsPool,\n this.textPool,\n this.worldApi,\n this.hudApi,\n this.stats,\n this.worldContainer,\n this.hudContainer,\n ),\n );\n }\n\n onStart(): void {\n // Toggle / step key listener\n const toggleKey = this.config.toggleKey ?? \"Backquote\";\n const stepKey = this.config.stepKey ?? \"Period\";\n this.keyListener = (e: KeyboardEvent) => {\n if (e.code === toggleKey) {\n this.registry.toggle();\n return;\n }\n if (e.code === stepKey && this.clock?.isManual) {\n e.preventDefault();\n this.clock.step();\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", this.keyListener);\n }\n\n // Instrument system timings\n const scheduler = this.context.resolve(SystemSchedulerKey);\n for (const system of scheduler.getAllSystems()) {\n if (system instanceof DebugRenderSystem) continue;\n const name = system.constructor.name;\n const original = system.update.bind(system);\n this.originalUpdates.set(system, original);\n system.update = (dt: number) => {\n const t0 = performance.now();\n original(dt);\n this.systemTimings.set(name, performance.now() - t0);\n };\n }\n\n // Built-in contributors\n const inspector = this.context.resolve(InspectorKey);\n this.registry.register(new FpsContributor());\n this.registry.register(new EntityCountContributor(inspector));\n this.registry.register(new SystemTimingContributor(this.systemTimings));\n\n // Manual clock for deterministic stepping\n const gameLoop = this.context.resolve(GameLoopKey);\n const app = this.renderer.application;\n\n this.clock = new DebugClock(\n gameLoop,\n () => app.stop(),\n () => app.start(),\n () => app.render(),\n );\n\n if (this.config.manualClock) {\n this.clock.setManual(true);\n }\n\n this.attachToGlobal(this.clock);\n }\n\n onDestroy(): void {\n // Restore original system.update methods\n for (const [system, original] of this.originalUpdates) {\n system.update = original;\n }\n this.originalUpdates.clear();\n\n if (this.keyListener) {\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"keydown\", this.keyListener);\n }\n this.keyListener = null;\n }\n\n this.detachFromGlobal();\n this.clock = null;\n\n for (const contributor of this.registry.contributors.values()) {\n contributor.dispose?.();\n }\n this.registry.contributors.clear();\n\n this.graphicsPool.destroy();\n this.textPool.destroy();\n // worldContainer is owned by the world RenderLayerManager — don't destroy it\n this.renderer.destroyScreenContainer(\"debug-hud\");\n }\n\n private attachToGlobal(clock: IDebugClock): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (g && typeof g === \"object\") {\n (g as Record<string, unknown>)[\"clock\"] = clock;\n }\n }\n\n private detachFromGlobal(): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (\n g &&\n typeof g === \"object\" &&\n (g as Record<string, unknown>)[\"clock\"] === this.clock\n ) {\n delete (g as Record<string, unknown>)[\"clock\"];\n }\n }\n}\n","import { ServiceKey } from \"@yagejs/core\";\n\n/**\n * Minimal subset of PixiJS Graphics used by debug drawing.\n * Avoids a runtime pixi.js dependency in the ./api subpath.\n */\nexport interface DebugGraphics {\n position: { x: number; y: number };\n rotation: number;\n visible: boolean;\n clear(): DebugGraphics;\n rect(x: number, y: number, width: number, height: number): DebugGraphics;\n circle(x: number, y: number, radius: number): DebugGraphics;\n moveTo(x: number, y: number): DebugGraphics;\n lineTo(x: number, y: number): DebugGraphics;\n stroke(style: { width: number; color: number; alpha?: number }): DebugGraphics;\n fill(style: { color: number; alpha?: number }): DebugGraphics;\n}\n\n/** Camera-space drawing API passed to contributors. */\nexport interface WorldDebugApi {\n acquireGraphics(): DebugGraphics | undefined;\n isFlagEnabled(flag: string): boolean;\n readonly cameraZoom: number;\n}\n\n/** Screen-space HUD API passed to contributors. */\nexport interface HudDebugApi {\n addLine(text: string): void;\n isFlagEnabled(flag: string): boolean;\n readonly screenWidth: number;\n readonly screenHeight: number;\n}\n\n/** Rolling-window statistics collector. */\nexport interface StatsApi {\n push(key: string, value: number): void;\n average(key: string): number;\n latest(key: string): number;\n min(key: string): number;\n max(key: string): number;\n}\n\n/** A debug contributor that registers drawing/sampling callbacks. */\nexport interface DebugContributor {\n readonly name: string;\n readonly flags: readonly string[];\n drawWorld?(api: WorldDebugApi): void;\n drawHud?(api: HudDebugApi): void;\n sample?(stats: StatsApi, dt: number): void;\n dispose?(): void;\n}\n\n/** Service interface for the debug registry. */\nexport interface DebugRegistry {\n register(contributor: DebugContributor): void;\n isEnabled(): boolean;\n isFlagEnabled(contributorName: string, flag: string): boolean;\n}\n\n/** Service key for resolving the DebugRegistry via DI. */\nexport const DebugRegistryKey = new ServiceKey<DebugRegistry>(\"debugRegistry\");\n","/** Public interface for the manual debug clock, accessible via `window.__yage__.clock`. */\nexport interface IDebugClock {\n readonly isManual: boolean;\n startAuto(): void;\n stopAuto(): void;\n step(dtMs?: number): void;\n stepFrames(count: number, dtMs?: number): void;\n}\n\n/** Minimal view of a game loop needed by the debug clock. */\ninterface GameLoopLike {\n tick(dtMs: number): void;\n readonly fixedTimestep: number;\n}\n\n/**\n * Controls engine time-stepping for deterministic E2E tests.\n *\n * When manual mode is active the renderer ticker is paused and frames\n * advance only via explicit `step()` / `stepFrames()` calls.\n */\nexport class DebugClock implements IDebugClock {\n private _isManual = false;\n\n constructor(\n private readonly gameLoop: GameLoopLike,\n private readonly stopTicker: () => void,\n private readonly startTicker: () => void,\n private readonly render: () => void,\n ) {}\n\n get isManual(): boolean {\n return this._isManual;\n }\n\n startAuto(): void {\n if (!this._isManual) return;\n this.startTicker();\n this._isManual = false;\n }\n\n stopAuto(): void {\n if (this._isManual) return;\n this.stopTicker();\n this._isManual = true;\n }\n\n step(dtMs?: number): void {\n if (!this._isManual) {\n throw new Error(\n \"Manual clock is not active. Call clock.stopAuto() first.\",\n );\n }\n const dt = dtMs ?? this.gameLoop.fixedTimestep;\n this.gameLoop.tick(dt);\n this.render();\n }\n\n stepFrames(count: number, dtMs?: number): void {\n if (!Number.isInteger(count) || count < 0) {\n throw new Error(\n \"stepFrames(count) requires a non-negative integer count.\",\n );\n }\n for (let i = 0; i < count; i++) {\n this.step(dtMs);\n }\n }\n\n /** Enter or exit manual mode. Used by DebugPlugin for config-driven init. */\n setManual(enabled: boolean): void {\n if (enabled === this._isManual) return;\n if (enabled) {\n this.stopTicker();\n } else {\n this.startTicker();\n }\n this._isManual = enabled;\n }\n}\n","import type { DebugContributor, DebugRegistry } from \"./types.js\";\n\n/** Concrete implementation of the DebugRegistry interface. */\nexport class DebugRegistryImpl implements DebugRegistry {\n readonly contributors = new Map<string, DebugContributor>();\n enabled = false;\n private flags = new Map<string, boolean>();\n\n register(contributor: DebugContributor): void {\n if (this.contributors.has(contributor.name)) return;\n this.contributors.set(contributor.name, contributor);\n for (const flag of contributor.flags) {\n this.flags.set(`${contributor.name}.${flag}`, true);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n isFlagEnabled(contributorName: string, flag: string): boolean {\n return this.flags.get(`${contributorName}.${flag}`) ?? true;\n }\n\n toggle(): void {\n this.enabled = !this.enabled;\n }\n\n toggleFlag(contributorName: string, flag: string): void {\n const key = `${contributorName}.${flag}`;\n this.flags.set(key, !(this.flags.get(key) ?? true));\n }\n\n setFlag(contributorName: string, flag: string, value: boolean): void {\n this.flags.set(`${contributorName}.${flag}`, value);\n }\n}\n","import type { StatsApi } from \"./types.js\";\n\nconst WINDOW_SIZE = 120;\n\ninterface RingBuffer {\n data: Float64Array;\n count: number;\n index: number;\n}\n\n/** Rolling-window statistics store backed by Float64Array ring buffers. */\nexport class StatsStore implements StatsApi {\n private rings = new Map<string, RingBuffer>();\n\n push(key: string, value: number): void {\n let ring = this.rings.get(key);\n if (!ring) {\n ring = { data: new Float64Array(WINDOW_SIZE), count: 0, index: 0 };\n this.rings.set(key, ring);\n }\n ring.data[ring.index] = value;\n ring.index = (ring.index + 1) % WINDOW_SIZE;\n if (ring.count < WINDOW_SIZE) ring.count++;\n }\n\n average(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let sum = 0;\n for (let i = 0; i < count; i++) sum += data[i] ?? 0;\n return sum / count;\n }\n\n latest(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n return ring.data[(ring.index - 1 + WINDOW_SIZE) % WINDOW_SIZE] ?? 0;\n }\n\n min(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v < m) m = v;\n }\n return m;\n }\n\n max(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = -Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v > m) m = v;\n }\n return m;\n }\n}\n","import { Graphics, Container } from \"pixi.js\";\n\n/** Allocation-free pool of PixiJS Graphics objects for debug drawing. */\nexport class GraphicsPool {\n private pool: Graphics[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxSize: number;\n\n constructor(container: Container, maxSize = 256) {\n this.container = container;\n this.maxSize = maxSize;\n }\n\n /** Lazily create Graphics objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Graphics[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxSize; i++) {\n const g = new Graphics();\n g.visible = false;\n g.eventMode = \"none\";\n this.container.addChild(g);\n this.pool.push(g);\n }\n return this.pool;\n }\n\n /** Return the next available Graphics, or undefined if the pool is exhausted. */\n acquire(): Graphics | undefined {\n const pool = this.ensure();\n if (this.index >= pool.length) return undefined;\n const g = pool[this.index]!;\n g.visible = true;\n this.index++;\n return g;\n }\n\n /** Clear and hide all previously acquired graphics, reset index. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n const g = this.pool[i]!;\n g.clear();\n g.visible = false;\n g.position.set(0, 0);\n g.rotation = 0;\n g.scale.set(1, 1);\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const g of this.pool) {\n g.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import { Text, Container } from \"pixi.js\";\n\nconst LINE_HEIGHT = 16;\nconst FONT_SIZE = 14;\nconst PADDING = 4;\n\n/** Allocation-free pool of PixiJS Text objects for HUD debug lines. */\nexport class TextPool {\n private pool: Text[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxLines: number;\n\n constructor(container: Container, maxLines = 32) {\n this.container = container;\n this.maxLines = maxLines;\n }\n\n /** Lazily create Text objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Text[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxLines; i++) {\n const t = new Text({\n text: \"\",\n style: {\n fontFamily: \"monospace\",\n fontSize: FONT_SIZE,\n fill: 0xffffff,\n },\n });\n t.visible = false;\n t.eventMode = \"none\";\n this.container.addChild(t);\n this.pool.push(t);\n }\n return this.pool;\n }\n\n /** Show a text line at the next available slot. */\n addLine(text: string): void {\n const pool = this.ensure();\n if (this.index >= pool.length) return;\n const t = pool[this.index]!;\n t.text = text;\n t.visible = true;\n t.position.set(PADDING, PADDING + this.index * LINE_HEIGHT);\n this.index++;\n }\n\n /** Hide all lines and reset for the next frame. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n this.pool[i]!.visible = false;\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const t of this.pool) {\n t.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import type { WorldDebugApi, DebugGraphics } from \"./types.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** WorldDebugApi backed by a GraphicsPool. Contributor name is swapped per iteration. */\nexport class WorldDebugApiImpl implements WorldDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly pool: GraphicsPool,\n private readonly registry: DebugRegistryImpl,\n private readonly _camera: { zoom: number },\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawWorld). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n acquireGraphics(): DebugGraphics | undefined {\n return this.pool.acquire() as unknown as DebugGraphics | undefined;\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n\n get cameraZoom(): number {\n return this._camera.zoom;\n }\n}\n","import type { HudDebugApi } from \"./types.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** HudDebugApi backed by a TextPool. Contributor name is swapped per iteration. */\nexport class HudDebugApiImpl implements HudDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly textPool: TextPool,\n private readonly registry: DebugRegistryImpl,\n public readonly screenWidth: number,\n public readonly screenHeight: number,\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawHud). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n addLine(text: string): void {\n this.textPool.addLine(text);\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport type { Container } from \"pixi.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport type { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport type { StatsStore } from \"./StatsStore.js\";\n\n/** Renders all debug contributors. Runs after DisplaySystem in the Render phase. */\nexport class DebugRenderSystem extends System {\n readonly phase = Phase.Render;\n readonly priority = 9999;\n\n constructor(\n private readonly registry: DebugRegistryImpl,\n private readonly graphicsPool: GraphicsPool,\n private readonly textPool: TextPool,\n private readonly worldApi: WorldDebugApiImpl,\n private readonly hudApi: HudDebugApiImpl,\n private readonly stats: StatsStore,\n private readonly worldContainer: Container,\n private readonly hudContainer: Container,\n ) {\n super();\n }\n\n update(dt: number): void {\n if (!this.registry.enabled) {\n this.worldContainer.visible = false;\n this.hudContainer.visible = false;\n return;\n }\n\n this.worldContainer.visible = true;\n this.hudContainer.visible = true;\n this.graphicsPool.resetFrame();\n this.textPool.resetFrame();\n\n for (const [name, contributor] of this.registry.contributors) {\n contributor.sample?.(this.stats, dt);\n\n if (contributor.drawWorld) {\n this.worldApi.setContributor(name);\n contributor.drawWorld(this.worldApi);\n }\n\n if (contributor.drawHud) {\n this.hudApi.setContributor(name);\n contributor.drawHud(this.hudApi);\n }\n }\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class FpsContributor implements DebugContributor {\n readonly name = \"fps\";\n readonly flags: readonly string[] = [];\n private stats: StatsApi | null = null;\n\n sample(stats: StatsApi, dt: number): void {\n this.stats = stats;\n if (dt > 0) stats.push(\"fps\", 1000 / dt);\n }\n\n drawHud(api: HudDebugApi): void {\n const avg = this.stats?.average(\"fps\") ?? 0;\n api.addLine(`FPS: ${Math.round(avg)}`);\n }\n}\n","import type { DebugContributor, HudDebugApi } from \"../types.js\";\nimport type { Inspector } from \"@yagejs/core\";\n\nexport class EntityCountContributor implements DebugContributor {\n readonly name = \"entities\";\n readonly flags: readonly string[] = [];\n\n constructor(private readonly inspector: Inspector) {}\n\n drawHud(api: HudDebugApi): void {\n const count = this.inspector.snapshot().entityCount;\n api.addLine(`Entities: ${count}`);\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class SystemTimingContributor implements DebugContributor {\n readonly name = \"timing\";\n readonly flags = [\"breakdown\"] as const;\n private stats: StatsApi | null = null;\n\n constructor(private readonly timings: Map<string, number>) {}\n\n sample(stats: StatsApi): void {\n this.stats = stats;\n for (const [name, ms] of this.timings) {\n stats.push(`system.${name}`, ms);\n }\n }\n\n drawHud(api: HudDebugApi): void {\n if (!this.stats) return;\n\n let total = 0;\n const entries: Array<[string, number]> = [];\n for (const name of this.timings.keys()) {\n const avg = this.stats.average(`system.${name}`);\n total += avg;\n entries.push([name, avg]);\n }\n\n api.addLine(`Systems: ${total.toFixed(2)}ms`);\n\n if (api.isFlagEnabled(\"breakdown\")) {\n entries.sort((a, b) => b[1] - a[1]);\n for (const [name, avg] of entries) {\n api.addLine(` ${name}: ${avg.toFixed(2)}ms`);\n }\n }\n }\n}\n"],"mappings":"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","names":["import_core","import_pixi","import_core"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/DebugPlugin.ts","../src/types.ts","../src/DebugClock.ts","../src/DebugRegistryImpl.ts","../src/DebugScene.ts","../src/StatsStore.ts","../src/GraphicsPool.ts","../src/TextPool.ts","../src/WorldDebugApiImpl.ts","../src/HudDebugApiImpl.ts","../src/DebugRenderSystem.ts","../src/contributors/FpsContributor.ts","../src/contributors/EntityCountContributor.ts","../src/contributors/SystemTimingContributor.ts"],"sourcesContent":["export { DebugPlugin } from \"./DebugPlugin.js\";\nexport type { DebugConfig } from \"./DebugPlugin.js\";\nexport type { IDebugClock } from \"./DebugClock.js\";\nexport { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nexport { StatsStore } from \"./StatsStore.js\";\n","import {\n EventBusKey,\n GameLoopKey,\n InspectorKey,\n SceneManagerKey,\n} from \"@yagejs/core\";\nimport type {\n EngineContext,\n EventBus,\n EngineEvents,\n Inspector,\n Plugin,\n SceneManager,\n System,\n SystemScheduler,\n} from \"@yagejs/core\";\nimport { DebugRegistryKey } from \"./types.js\";\nimport { CameraComponent, RendererKey } from \"@yagejs/renderer\";\nimport type { RendererPlugin, SceneRenderTreeProvider } from \"@yagejs/renderer\";\nimport { SceneRenderTreeProviderKey } from \"@yagejs/renderer\";\nimport type { Container } from \"pixi.js\";\nimport { DebugClock } from \"./DebugClock.js\";\nimport type { IDebugClock } from \"./DebugClock.js\";\nimport { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport { DebugScene } from \"./DebugScene.js\";\nimport { StatsStore } from \"./StatsStore.js\";\nimport { GraphicsPool } from \"./GraphicsPool.js\";\nimport { TextPool } from \"./TextPool.js\";\nimport { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport { DebugRenderSystem } from \"./DebugRenderSystem.js\";\nimport { FpsContributor } from \"./contributors/FpsContributor.js\";\nimport { EntityCountContributor } from \"./contributors/EntityCountContributor.js\";\nimport { SystemTimingContributor } from \"./contributors/SystemTimingContributor.js\";\n\n/** Configuration for the DebugPlugin. */\nexport interface DebugConfig {\n /** Key code to toggle debug overlay. Default: \"Backquote\" */\n toggleKey?: string;\n /** When true, stop the renderer ticker and advance simulation manually via `window.__yage__.clock`. */\n manualClock?: boolean;\n /** Key code to advance one fixed-timestep frame while manual clock mode is active. Default: \"Period\" */\n stepKey?: string;\n /** Max pooled Graphics objects. Default: 256 */\n maxGraphics?: number;\n /** Max HUD text lines. Default: 32 */\n maxHudLines?: number;\n /** Whether the overlay starts enabled. Default: false */\n startEnabled?: boolean;\n /** Initial flag overrides, keyed by \"contributorName.flagName\". */\n flags?: Record<string, boolean>;\n}\n\ninterface LayerTransformSnapshot {\n x: number;\n y: number;\n scaleX: number;\n scaleY: number;\n rotation: number;\n}\n\ninterface CameraStackSnapshot {\n scene: string;\n name: string | undefined;\n priority: number;\n enabled: boolean;\n}\n\ninterface InspectorDiagnostics {\n getLayerTransform(\n sceneName: string,\n layerName: string,\n ): LayerTransformSnapshot | undefined;\n getCameraStack(): CameraStackSnapshot[];\n}\n\n/**\n * Debug overlay plugin. Mounts a private `DebugScene` through\n * `SceneManager._mountDetached` so it goes through the same scoped-DI\n * lifecycle as stacked scenes (the renderer's `beforeEnter` hook creates\n * its render tree) while staying off the user-visible scene stack.\n */\nexport class DebugPlugin implements Plugin {\n readonly name = \"debug\";\n readonly version = \"3.0.0\";\n readonly dependencies = [\"renderer\"] as const;\n\n private readonly config: DebugConfig;\n private registry!: DebugRegistryImpl;\n private stats!: StatsStore;\n private graphicsPool: GraphicsPool | null = null;\n private textPool: TextPool | null = null;\n private worldApi: WorldDebugApiImpl | null = null;\n private hudApi: HudDebugApiImpl | null = null;\n private renderSystem: DebugRenderSystem | null = null;\n private systemTimings = new Map<string, number>();\n private originalUpdates = new Map<System, (dt: number) => void>();\n private keyListener: ((e: KeyboardEvent) => void) | null = null;\n private context!: EngineContext;\n private renderer!: RendererPlugin;\n private scheduler!: SystemScheduler;\n private sceneManager!: SceneManager;\n private debugScene: DebugScene | null = null;\n private provider: SceneRenderTreeProvider | null = null;\n private eventUnsubs: Array<() => void> = [];\n private clock: DebugClock | null = null;\n\n constructor(config?: DebugConfig) {\n this.config = config ?? {};\n }\n\n install(context: EngineContext): void {\n this.context = context;\n this.renderer = context.resolve(RendererKey);\n\n this.registry = new DebugRegistryImpl();\n this.registry.enabled = this.config.startEnabled ?? false;\n\n if (this.config.flags) {\n for (const [key, value] of Object.entries(this.config.flags)) {\n const dot = key.indexOf(\".\");\n if (dot > 0) {\n this.registry.setFlag(key.slice(0, dot), key.slice(dot + 1), value);\n }\n }\n }\n\n this.stats = new StatsStore();\n\n context.register(DebugRegistryKey, this.registry);\n }\n\n registerSystems(scheduler: SystemScheduler): void {\n // DebugRenderSystem is registered lazily once the debug scene is ready —\n // its constructor needs the scene's layer containers.\n this.scheduler = scheduler;\n }\n\n async onStart(): Promise<void> {\n this.sceneManager = this.context.resolve(SceneManagerKey);\n const bus = this.context.resolve(EventBusKey) as EventBus<EngineEvents>;\n\n // Key listeners (toggle, manual-clock step)\n const toggleKey = this.config.toggleKey ?? \"Backquote\";\n const stepKey = this.config.stepKey ?? \"Period\";\n this.keyListener = (e: KeyboardEvent) => {\n if (e.code === toggleKey) {\n this.registry.toggle();\n return;\n }\n if (e.code === stepKey && this.clock?.isManual) {\n e.preventDefault();\n this.clock.step();\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", this.keyListener);\n }\n\n // Instrument system timings — reuse the scheduler captured in\n // `registerSystems`, which ran before `onStart`.\n for (const system of this.scheduler.getAllSystems()) {\n if (system instanceof DebugRenderSystem) continue;\n const name = system.constructor.name;\n const original = system.update.bind(system);\n this.originalUpdates.set(system, original);\n system.update = (dt: number) => {\n const t0 = performance.now();\n original(dt);\n this.systemTimings.set(name, performance.now() - t0);\n };\n }\n\n // Built-in contributors\n const inspector = this.context.resolve(InspectorKey);\n this.registry.register(new FpsContributor());\n this.registry.register(new EntityCountContributor(inspector));\n this.registry.register(new SystemTimingContributor(this.systemTimings));\n\n // Manual clock for deterministic stepping\n const gameLoop = this.context.resolve(GameLoopKey);\n const app = this.renderer.application;\n this.clock = new DebugClock(\n gameLoop,\n () => app.stop(),\n () => app.start(),\n () => app.render(),\n );\n if (this.config.manualClock) {\n this.clock.setManual(true);\n }\n this.attachToGlobal(this.clock);\n\n // Materialize the debug scene off-stack. `_mountDetached` routes through\n // the same beforeEnter hooks as `push`, so the renderer materializes the\n // debug scene's tree and registers SceneRenderTreeKey on its scope.\n this.provider = this.context.tryResolve(SceneRenderTreeProviderKey) ?? null;\n this.attachInspectorDiagnostics(inspector);\n await this.materializeDebugScene();\n\n // Keep the debug scene visually on top of the user stack after any\n // push/pop/replace by reordering its root containers.\n const bringToFront = () => {\n if (this.debugScene && this.provider?.bringSceneToFront) {\n this.provider.bringSceneToFront(this.debugScene);\n }\n };\n this.eventUnsubs.push(bus.on(\"scene:pushed\", bringToFront));\n this.eventUnsubs.push(bus.on(\"scene:popped\", bringToFront));\n this.eventUnsubs.push(bus.on(\"scene:replaced\", bringToFront));\n }\n\n onDestroy(): void {\n for (const unsub of this.eventUnsubs) unsub();\n this.eventUnsubs.length = 0;\n\n for (const [system, original] of this.originalUpdates) {\n system.update = original;\n }\n this.originalUpdates.clear();\n\n if (this.keyListener) {\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"keydown\", this.keyListener);\n }\n this.keyListener = null;\n }\n\n this.detachFromGlobal();\n this.clock = null;\n\n for (const contributor of this.registry.contributors.values()) {\n contributor.dispose?.();\n }\n this.registry.contributors.clear();\n\n this.tearDownDebugInfra();\n this.teardownDebugScene();\n }\n\n private async materializeDebugScene(): Promise<void> {\n const scene = new DebugScene();\n scene.onReady = (worldContainer, hudContainer) =>\n this.setUpDebugInfra(worldContainer, hudContainer);\n scene.onTearDown = () => this.tearDownDebugInfra();\n await this.sceneManager._mountDetached(scene);\n this.debugScene = scene;\n }\n\n private teardownDebugScene(): void {\n // If destroy is called while `_mountDetached` is still pending, we don't\n // yet hold a reference to the partially-mounted scene. Skipping unmount\n // here is safe: onDestroy still runs `tearDownDebugInfra` below, and the\n // engine teardown tears down the renderer next which destroys any\n // half-created provider entries.\n if (!this.debugScene) return;\n this.sceneManager._unmountDetached(this.debugScene);\n this.debugScene = null;\n this.provider = null;\n }\n\n private findActiveCamera(): CameraComponent | undefined {\n return findTopmostCamera(this.sceneManager);\n }\n\n private setUpDebugInfra(\n worldContainer: Container,\n hudContainer: Container,\n ): void {\n const vw = this.renderer.virtualSize.width;\n const vh = this.renderer.virtualSize.height;\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n // Lazy camera accessor — reads from whichever stacked scene has a camera\n const cameraProxy = {\n get zoom() {\n return self.findActiveCamera()?.zoom ?? 1;\n },\n };\n\n this.graphicsPool = new GraphicsPool(\n worldContainer,\n this.config.maxGraphics,\n );\n this.textPool = new TextPool(hudContainer, this.config.maxHudLines);\n\n this.worldApi = new WorldDebugApiImpl(\n this.graphicsPool,\n this.registry,\n cameraProxy,\n );\n this.hudApi = new HudDebugApiImpl(this.textPool, this.registry, vw, vh);\n\n this.renderSystem = new DebugRenderSystem(\n this.registry,\n this.graphicsPool,\n this.textPool,\n this.worldApi,\n this.hudApi,\n this.stats,\n worldContainer,\n hudContainer,\n {\n findCamera: () => self.findActiveCamera(),\n viewportWidth: vw,\n viewportHeight: vh,\n },\n );\n this.scheduler.add(this.renderSystem);\n }\n\n private tearDownDebugInfra(): void {\n if (this.renderSystem) {\n this.scheduler.remove(this.renderSystem);\n this.renderSystem = null;\n }\n this.graphicsPool?.destroy();\n this.textPool?.destroy();\n this.graphicsPool = null;\n this.textPool = null;\n this.worldApi = null;\n this.hudApi = null;\n }\n\n private attachInspectorDiagnostics(inspector: Inspector): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (!g || typeof g !== \"object\") return;\n\n const debugSurface = g as Record<string, unknown>;\n const diagnostics = inspector as Inspector & InspectorDiagnostics;\n debugSurface[\"inspector\"] = inspector;\n\n diagnostics.getLayerTransform = (sceneName, layerName) => {\n const scene = this.sceneManager.all.find(\n (candidate) => candidate.name === sceneName,\n );\n if (!scene) return undefined;\n\n const layer = this.provider?.getTree(scene)?.tryGet(layerName);\n if (!layer) return undefined;\n\n const container = layer.container;\n return {\n x: container.position.x,\n y: container.position.y,\n scaleX: container.scale.x,\n scaleY: container.scale.y,\n rotation: container.rotation,\n };\n };\n\n diagnostics.getCameraStack = () => {\n const cameras: CameraStackSnapshot[] = [];\n for (const scene of this.sceneManager.all) {\n for (const entity of scene.getEntities()) {\n const cam = entity.tryGet(CameraComponent);\n if (!cam) continue;\n cameras.push({\n scene: scene.name,\n name: cam.cameraName,\n priority: cam.priority,\n enabled: cam.enabled,\n });\n }\n }\n return cameras;\n };\n }\n\n private attachToGlobal(clock: IDebugClock): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (g && typeof g === \"object\") {\n (g as Record<string, unknown>)[\"clock\"] = clock;\n }\n }\n\n private detachFromGlobal(): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (\n g &&\n typeof g === \"object\" &&\n (g as Record<string, unknown>)[\"clock\"] === this.clock\n ) {\n delete (g as Record<string, unknown>)[\"clock\"];\n }\n }\n}\n\n/**\n * Find the highest-priority enabled camera on the topmost scene that has one.\n * `sceneManager.all` is bottom→top, so we walk in reverse — a pause/HUD\n * scene's camera wins over a frozen scene beneath it.\n */\nexport function findTopmostCamera(\n sceneManager: SceneManager,\n): CameraComponent | undefined {\n const stack = sceneManager.all;\n for (let i = stack.length - 1; i >= 0; i--) {\n const scene = stack[i];\n if (!scene) continue;\n let highestPriorityCamera: CameraComponent | undefined;\n for (const entity of scene.getEntities()) {\n const cam = entity.tryGet(CameraComponent);\n if (\n cam &&\n cam.enabled &&\n (!highestPriorityCamera ||\n cam.priority > highestPriorityCamera.priority)\n ) {\n highestPriorityCamera = cam;\n }\n }\n if (highestPriorityCamera) return highestPriorityCamera;\n }\n return undefined;\n}\n","import { ServiceKey } from \"@yagejs/core\";\n\n/**\n * Minimal subset of PixiJS Graphics used by debug drawing.\n * Avoids a runtime pixi.js dependency in the ./api subpath.\n */\nexport interface DebugGraphics {\n position: { x: number; y: number };\n rotation: number;\n visible: boolean;\n clear(): DebugGraphics;\n rect(x: number, y: number, width: number, height: number): DebugGraphics;\n circle(x: number, y: number, radius: number): DebugGraphics;\n moveTo(x: number, y: number): DebugGraphics;\n lineTo(x: number, y: number): DebugGraphics;\n stroke(style: { width: number; color: number; alpha?: number }): DebugGraphics;\n fill(style: { color: number; alpha?: number }): DebugGraphics;\n}\n\n/** Camera-space drawing API passed to contributors. */\nexport interface WorldDebugApi {\n acquireGraphics(): DebugGraphics | undefined;\n isFlagEnabled(flag: string): boolean;\n readonly cameraZoom: number;\n}\n\n/** Screen-space HUD API passed to contributors. */\nexport interface HudDebugApi {\n addLine(text: string): void;\n isFlagEnabled(flag: string): boolean;\n readonly screenWidth: number;\n readonly screenHeight: number;\n}\n\n/** Rolling-window statistics collector. */\nexport interface StatsApi {\n push(key: string, value: number): void;\n average(key: string): number;\n latest(key: string): number;\n min(key: string): number;\n max(key: string): number;\n}\n\n/** A debug contributor that registers drawing/sampling callbacks. */\nexport interface DebugContributor {\n readonly name: string;\n readonly flags: readonly string[];\n drawWorld?(api: WorldDebugApi): void;\n drawHud?(api: HudDebugApi): void;\n sample?(stats: StatsApi, dt: number): void;\n dispose?(): void;\n}\n\n/** Service interface for the debug registry. */\nexport interface DebugRegistry {\n register(contributor: DebugContributor): void;\n isEnabled(): boolean;\n isFlagEnabled(contributorName: string, flag: string): boolean;\n}\n\n/** Service key for resolving the DebugRegistry via DI. */\nexport const DebugRegistryKey = new ServiceKey<DebugRegistry>(\"debugRegistry\");\n","/** Public interface for the manual debug clock, accessible via `window.__yage__.clock`. */\nexport interface IDebugClock {\n readonly isManual: boolean;\n startAuto(): void;\n stopAuto(): void;\n step(dtMs?: number): void;\n stepFrames(count: number, dtMs?: number): void;\n}\n\n/** Minimal view of a game loop needed by the debug clock. */\ninterface GameLoopLike {\n tick(dtMs: number): void;\n readonly fixedTimestep: number;\n}\n\n/**\n * Controls engine time-stepping for deterministic E2E tests.\n *\n * When manual mode is active the renderer ticker is paused and frames\n * advance only via explicit `step()` / `stepFrames()` calls.\n */\nexport class DebugClock implements IDebugClock {\n private _isManual = false;\n\n constructor(\n private readonly gameLoop: GameLoopLike,\n private readonly stopTicker: () => void,\n private readonly startTicker: () => void,\n private readonly render: () => void,\n ) {}\n\n get isManual(): boolean {\n return this._isManual;\n }\n\n startAuto(): void {\n if (!this._isManual) return;\n this.startTicker();\n this._isManual = false;\n }\n\n stopAuto(): void {\n if (this._isManual) return;\n this.stopTicker();\n this._isManual = true;\n }\n\n step(dtMs?: number): void {\n if (!this._isManual) {\n throw new Error(\n \"Manual clock is not active. Call clock.stopAuto() first.\",\n );\n }\n const dt = dtMs ?? this.gameLoop.fixedTimestep;\n this.gameLoop.tick(dt);\n this.render();\n }\n\n stepFrames(count: number, dtMs?: number): void {\n if (!Number.isInteger(count) || count < 0) {\n throw new Error(\n \"stepFrames(count) requires a non-negative integer count.\",\n );\n }\n for (let i = 0; i < count; i++) {\n this.step(dtMs);\n }\n }\n\n /** Enter or exit manual mode. Used by DebugPlugin for config-driven init. */\n setManual(enabled: boolean): void {\n if (enabled === this._isManual) return;\n if (enabled) {\n this.stopTicker();\n } else {\n this.startTicker();\n }\n this._isManual = enabled;\n }\n}\n","import type { DebugContributor, DebugRegistry } from \"./types.js\";\n\n/** Concrete implementation of the DebugRegistry interface. */\nexport class DebugRegistryImpl implements DebugRegistry {\n readonly contributors = new Map<string, DebugContributor>();\n enabled = false;\n private flags = new Map<string, boolean>();\n\n register(contributor: DebugContributor): void {\n if (this.contributors.has(contributor.name)) return;\n this.contributors.set(contributor.name, contributor);\n for (const flag of contributor.flags) {\n this.flags.set(`${contributor.name}.${flag}`, true);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n isFlagEnabled(contributorName: string, flag: string): boolean {\n return this.flags.get(`${contributorName}.${flag}`) ?? true;\n }\n\n toggle(): void {\n this.enabled = !this.enabled;\n }\n\n toggleFlag(contributorName: string, flag: string): void {\n const key = `${contributorName}.${flag}`;\n this.flags.set(key, !(this.flags.get(key) ?? true));\n }\n\n setFlag(contributorName: string, flag: string, value: boolean): void {\n this.flags.set(`${contributorName}.${flag}`, value);\n }\n}\n","import { LoggerKey, Scene } from \"@yagejs/core\";\nimport type { Logger } from \"@yagejs/core\";\nimport type { LayerDef } from \"@yagejs/renderer\";\nimport { SceneRenderTreeKey } from \"@yagejs/renderer\";\nimport type { Container } from \"pixi.js\";\n\n/**\n * Scene mounted by the debug plugin via `SceneManager._mountDetached`.\n * Declares two layers:\n * - `\"debug-world\"` — world-space, rides the camera (for collision shapes).\n * - `\"debug-hud\"` — screen-space, fixed overlay (text readouts).\n *\n * `pauseBelow: false` / `transparentBelow: true` so the underlying game\n * keeps running and rendering behind the overlay.\n */\nexport class DebugScene extends Scene {\n readonly name = \"__debug__\";\n override readonly pauseBelow = false;\n override readonly transparentBelow = true;\n readonly layers: readonly LayerDef[] = [\n { name: \"debug-world\", order: 999999 },\n { name: \"debug-hud\", order: 999999 },\n ];\n\n /** Called after `_mountDetached` has materialized the render tree. */\n onReady?: (worldContainer: Container, hudContainer: Container) => void;\n\n /** Called by the plugin when the scene is unmounted. */\n onTearDown?: () => void;\n\n onEnter(): void {\n const tree = this._resolveScoped(SceneRenderTreeKey);\n if (!tree) {\n // Shouldn't happen — DebugPlugin declares `renderer` as a dependency\n // so the renderer's `beforeEnter` hook should have materialized a\n // tree before this runs. Surface it rather than silently skipping\n // the overlay wiring.\n const logger = this.context.tryResolve(LoggerKey) as Logger | undefined;\n const msg =\n \"DebugScene.onEnter: SceneRenderTreeKey missing — debug overlay will not render. Is RendererPlugin registered?\";\n if (logger) logger.warn(\"debug\", msg);\n else console.warn(`[yage] ${msg}`);\n return;\n }\n const worldContainer = tree.get(\"debug-world\").container;\n const hudContainer = tree.get(\"debug-hud\").container;\n worldContainer.eventMode = \"none\";\n hudContainer.eventMode = \"none\";\n this.onReady?.(worldContainer, hudContainer);\n }\n\n onExit(): void {\n this.onTearDown?.();\n }\n}\n","import type { StatsApi } from \"./types.js\";\n\nconst WINDOW_SIZE = 120;\n\ninterface RingBuffer {\n data: Float64Array;\n count: number;\n index: number;\n}\n\n/** Rolling-window statistics store backed by Float64Array ring buffers. */\nexport class StatsStore implements StatsApi {\n private rings = new Map<string, RingBuffer>();\n\n push(key: string, value: number): void {\n let ring = this.rings.get(key);\n if (!ring) {\n ring = { data: new Float64Array(WINDOW_SIZE), count: 0, index: 0 };\n this.rings.set(key, ring);\n }\n ring.data[ring.index] = value;\n ring.index = (ring.index + 1) % WINDOW_SIZE;\n if (ring.count < WINDOW_SIZE) ring.count++;\n }\n\n average(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let sum = 0;\n for (let i = 0; i < count; i++) sum += data[i] ?? 0;\n return sum / count;\n }\n\n latest(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n return ring.data[(ring.index - 1 + WINDOW_SIZE) % WINDOW_SIZE] ?? 0;\n }\n\n min(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v < m) m = v;\n }\n return m;\n }\n\n max(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = -Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v > m) m = v;\n }\n return m;\n }\n}\n","import { Graphics, Container } from \"pixi.js\";\n\n/** Allocation-free pool of PixiJS Graphics objects for debug drawing. */\nexport class GraphicsPool {\n private pool: Graphics[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxSize: number;\n\n constructor(container: Container, maxSize = 256) {\n this.container = container;\n this.maxSize = maxSize;\n }\n\n /** Lazily create Graphics objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Graphics[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxSize; i++) {\n const g = new Graphics();\n g.visible = false;\n g.eventMode = \"none\";\n this.container.addChild(g);\n this.pool.push(g);\n }\n return this.pool;\n }\n\n /** Return the next available Graphics, or undefined if the pool is exhausted. */\n acquire(): Graphics | undefined {\n const pool = this.ensure();\n if (this.index >= pool.length) return undefined;\n const g = pool[this.index]!;\n g.visible = true;\n this.index++;\n return g;\n }\n\n /** Clear and hide all previously acquired graphics, reset index. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n const g = this.pool[i]!;\n g.clear();\n g.visible = false;\n g.position.set(0, 0);\n g.rotation = 0;\n g.scale.set(1, 1);\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const g of this.pool) {\n g.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import { Text, Container } from \"pixi.js\";\n\nconst LINE_HEIGHT = 16;\nconst FONT_SIZE = 14;\nconst PADDING = 4;\n\n/** Allocation-free pool of PixiJS Text objects for HUD debug lines. */\nexport class TextPool {\n private pool: Text[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxLines: number;\n\n constructor(container: Container, maxLines = 32) {\n this.container = container;\n this.maxLines = maxLines;\n }\n\n /** Lazily create Text objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Text[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxLines; i++) {\n const t = new Text({\n text: \"\",\n style: {\n fontFamily: \"monospace\",\n fontSize: FONT_SIZE,\n fill: 0xffffff,\n },\n });\n t.visible = false;\n t.eventMode = \"none\";\n this.container.addChild(t);\n this.pool.push(t);\n }\n return this.pool;\n }\n\n /** Show a text line at the next available slot. */\n addLine(text: string): void {\n const pool = this.ensure();\n if (this.index >= pool.length) return;\n const t = pool[this.index]!;\n t.text = text;\n t.visible = true;\n t.position.set(PADDING, PADDING + this.index * LINE_HEIGHT);\n this.index++;\n }\n\n /** Hide all lines and reset for the next frame. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n this.pool[i]!.visible = false;\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const t of this.pool) {\n t.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import type { WorldDebugApi, DebugGraphics } from \"./types.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** WorldDebugApi backed by a GraphicsPool. Contributor name is swapped per iteration. */\nexport class WorldDebugApiImpl implements WorldDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly pool: GraphicsPool,\n private readonly registry: DebugRegistryImpl,\n private readonly _camera: { zoom: number },\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawWorld). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n acquireGraphics(): DebugGraphics | undefined {\n return this.pool.acquire() as unknown as DebugGraphics | undefined;\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n\n get cameraZoom(): number {\n return this._camera.zoom;\n }\n}\n","import type { HudDebugApi } from \"./types.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** HudDebugApi backed by a TextPool. Contributor name is swapped per iteration. */\nexport class HudDebugApiImpl implements HudDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly textPool: TextPool,\n private readonly registry: DebugRegistryImpl,\n public readonly screenWidth: number,\n public readonly screenHeight: number,\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawHud). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n addLine(text: string): void {\n this.textPool.addLine(text);\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport type { Container } from \"pixi.js\";\nimport type { CameraComponent } from \"@yagejs/renderer\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport type { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport type { StatsStore } from \"./StatsStore.js\";\n\nexport interface DebugCameraAccessor {\n findCamera(): CameraComponent | undefined;\n viewportWidth: number;\n viewportHeight: number;\n}\n\n/** Renders all debug contributors. Runs after DisplaySystem in the Render phase. */\nexport class DebugRenderSystem extends System {\n readonly phase = Phase.Render;\n readonly priority = 9999;\n\n constructor(\n private readonly registry: DebugRegistryImpl,\n private readonly graphicsPool: GraphicsPool,\n private readonly textPool: TextPool,\n private readonly worldApi: WorldDebugApiImpl,\n private readonly hudApi: HudDebugApiImpl,\n private readonly stats: StatsStore,\n private readonly worldContainer: Container,\n private readonly hudContainer: Container,\n private readonly cameraAccessor: DebugCameraAccessor,\n ) {\n super();\n }\n\n update(dt: number): void {\n if (!this.registry.enabled) {\n this.worldContainer.visible = false;\n this.hudContainer.visible = false;\n return;\n }\n\n this.worldContainer.visible = true;\n this.hudContainer.visible = true;\n\n // Apply camera transform to the debug world container so that\n // world-space debug drawing (collision shapes, etc.) aligns with\n // the active scene's camera.\n this.syncWorldCamera();\n\n this.graphicsPool.resetFrame();\n this.textPool.resetFrame();\n\n for (const [name, contributor] of this.registry.contributors) {\n contributor.sample?.(this.stats, dt);\n\n if (contributor.drawWorld) {\n this.worldApi.setContributor(name);\n contributor.drawWorld(this.worldApi);\n }\n\n if (contributor.drawHud) {\n this.hudApi.setContributor(name);\n contributor.drawHud(this.hudApi);\n }\n }\n }\n\n private syncWorldCamera(): void {\n const cam = this.cameraAccessor.findCamera();\n if (!cam) {\n this.worldContainer.position.set(0, 0);\n this.worldContainer.scale.set(1, 1);\n this.worldContainer.rotation = 0;\n return;\n }\n\n const vw = this.cameraAccessor.viewportWidth;\n const vh = this.cameraAccessor.viewportHeight;\n const rotatedPos = cam.effectivePosition\n .scale(cam.zoom)\n .rotate(-cam.rotation);\n this.worldContainer.position.x = vw / 2 - rotatedPos.x;\n this.worldContainer.position.y = vh / 2 - rotatedPos.y;\n this.worldContainer.scale.set(cam.zoom);\n this.worldContainer.rotation = -cam.rotation;\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class FpsContributor implements DebugContributor {\n readonly name = \"fps\";\n readonly flags: readonly string[] = [];\n private stats: StatsApi | null = null;\n\n sample(stats: StatsApi, dt: number): void {\n this.stats = stats;\n if (dt > 0) stats.push(\"fps\", 1000 / dt);\n }\n\n drawHud(api: HudDebugApi): void {\n const avg = this.stats?.average(\"fps\") ?? 0;\n api.addLine(`FPS: ${Math.round(avg)}`);\n }\n}\n","import type { DebugContributor, HudDebugApi } from \"../types.js\";\nimport type { Inspector } from \"@yagejs/core\";\n\nexport class EntityCountContributor implements DebugContributor {\n readonly name = \"entities\";\n readonly flags: readonly string[] = [];\n\n constructor(private readonly inspector: Inspector) {}\n\n drawHud(api: HudDebugApi): void {\n const count = this.inspector.snapshot().entityCount;\n api.addLine(`Entities: ${count}`);\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class SystemTimingContributor implements DebugContributor {\n readonly name = \"timing\";\n readonly flags = [\"breakdown\"] as const;\n private stats: StatsApi | null = null;\n\n constructor(private readonly timings: Map<string, number>) {}\n\n sample(stats: StatsApi): void {\n this.stats = stats;\n for (const [name, ms] of this.timings) {\n stats.push(`system.${name}`, ms);\n }\n }\n\n drawHud(api: HudDebugApi): void {\n if (!this.stats) return;\n\n let total = 0;\n const entries: Array<[string, number]> = [];\n for (const name of this.timings.keys()) {\n const avg = this.stats.average(`system.${name}`);\n total += avg;\n entries.push([name, avg]);\n }\n\n api.addLine(`Systems: ${total.toFixed(2)}ms`);\n\n if (api.isFlagEnabled(\"breakdown\")) {\n entries.sort((a, b) => b[1] - a[1]);\n for (const [name, avg] of entries) {\n api.addLine(` ${name}: ${avg.toFixed(2)}ms`);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,eAKO;;;ACLP,kBAA2B;AA6DpB,IAAM,mBAAmB,IAAI,uBAA0B,eAAe;;;AD5C7E,IAAAC,mBAA6C;AAE7C,IAAAA,mBAA2C;;;AEEpC,IAAM,aAAN,MAAwC;AAAA,EAG7C,YACmB,UACA,YACA,aACA,QACjB;AAJiB;AACA;AACA;AACA;AAAA,EAChB;AAAA,EAJgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EA5BrB,OAqB+C;AAAA;AAAA;AAAA,EACrC,YAAY;AAAA,EASpB,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAkB;AAChB,QAAI,CAAC,KAAK,UAAW;AACrB,SAAK,YAAY;AACjB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,WAAiB;AACf,QAAI,KAAK,UAAW;AACpB,SAAK,WAAW;AAChB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,KAAK,MAAqB;AACxB,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,QAAQ,KAAK,SAAS;AACjC,SAAK,SAAS,KAAK,EAAE;AACrB,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,WAAW,OAAe,MAAqB;AAC7C,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,WAAK,KAAK,IAAI;AAAA,IAChB;AAAA,EACF;AAAA;AAAA,EAGA,UAAU,SAAwB;AAChC,QAAI,YAAY,KAAK,UAAW;AAChC,QAAI,SAAS;AACX,WAAK,WAAW;AAAA,IAClB,OAAO;AACL,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,YAAY;AAAA,EACnB;AACF;;;AC5EO,IAAM,oBAAN,MAAiD;AAAA,EAHxD,OAGwD;AAAA;AAAA;AAAA,EAC7C,eAAe,oBAAI,IAA8B;AAAA,EAC1D,UAAU;AAAA,EACF,QAAQ,oBAAI,IAAqB;AAAA,EAEzC,SAAS,aAAqC;AAC5C,QAAI,KAAK,aAAa,IAAI,YAAY,IAAI,EAAG;AAC7C,SAAK,aAAa,IAAI,YAAY,MAAM,WAAW;AACnD,eAAW,QAAQ,YAAY,OAAO;AACpC,WAAK,MAAM,IAAI,GAAG,YAAY,IAAI,IAAI,IAAI,IAAI,IAAI;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,YAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAc,iBAAyB,MAAuB;AAC5D,WAAO,KAAK,MAAM,IAAI,GAAG,eAAe,IAAI,IAAI,EAAE,KAAK;AAAA,EACzD;AAAA,EAEA,SAAe;AACb,SAAK,UAAU,CAAC,KAAK;AAAA,EACvB;AAAA,EAEA,WAAW,iBAAyB,MAAoB;AACtD,UAAM,MAAM,GAAG,eAAe,IAAI,IAAI;AACtC,SAAK,MAAM,IAAI,KAAK,EAAE,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK;AAAA,EACpD;AAAA,EAEA,QAAQ,iBAAyB,MAAc,OAAsB;AACnE,SAAK,MAAM,IAAI,GAAG,eAAe,IAAI,IAAI,IAAI,KAAK;AAAA,EACpD;AACF;;;ACpCA,IAAAC,eAAiC;AAGjC,sBAAmC;AAY5B,IAAM,aAAN,cAAyB,mBAAM;AAAA,EAftC,OAesC;AAAA;AAAA;AAAA,EAC3B,OAAO;AAAA,EACE,aAAa;AAAA,EACb,mBAAmB;AAAA,EAC5B,SAA8B;AAAA,IACrC,EAAE,MAAM,eAAe,OAAO,OAAO;AAAA,IACrC,EAAE,MAAM,aAAa,OAAO,OAAO;AAAA,EACrC;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EAEA,UAAgB;AACd,UAAM,OAAO,KAAK,eAAe,kCAAkB;AACnD,QAAI,CAAC,MAAM;AAKT,YAAM,SAAS,KAAK,QAAQ,WAAW,sBAAS;AAChD,YAAM,MACJ;AACF,UAAI,OAAQ,QAAO,KAAK,SAAS,GAAG;AAAA,UAC/B,SAAQ,KAAK,UAAU,GAAG,EAAE;AACjC;AAAA,IACF;AACA,UAAM,iBAAiB,KAAK,IAAI,aAAa,EAAE;AAC/C,UAAM,eAAe,KAAK,IAAI,WAAW,EAAE;AAC3C,mBAAe,YAAY;AAC3B,iBAAa,YAAY;AACzB,SAAK,UAAU,gBAAgB,YAAY;AAAA,EAC7C;AAAA,EAEA,SAAe;AACb,SAAK,aAAa;AAAA,EACpB;AACF;;;ACpDA,IAAM,cAAc;AASb,IAAM,aAAN,MAAqC;AAAA,EAX5C,OAW4C;AAAA;AAAA;AAAA,EAClC,QAAQ,oBAAI,IAAwB;AAAA,EAE5C,KAAK,KAAa,OAAqB;AACrC,QAAI,OAAO,KAAK,MAAM,IAAI,GAAG;AAC7B,QAAI,CAAC,MAAM;AACT,aAAO,EAAE,MAAM,IAAI,aAAa,WAAW,GAAG,OAAO,GAAG,OAAO,EAAE;AACjE,WAAK,MAAM,IAAI,KAAK,IAAI;AAAA,IAC1B;AACA,SAAK,KAAK,KAAK,KAAK,IAAI;AACxB,SAAK,SAAS,KAAK,QAAQ,KAAK;AAChC,QAAI,KAAK,QAAQ,YAAa,MAAK;AAAA,EACrC;AAAA,EAEA,QAAQ,KAAqB;AAC3B,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,QAAI,CAAC,QAAQ,KAAK,UAAU,EAAG,QAAO;AACtC,UAAM,EAAE,MAAM,MAAM,IAAI;AACxB,QAAI,MAAM;AACV,aAAS,IAAI,GAAG,IAAI,OAAO,IAAK,QAAO,KAAK,CAAC,KAAK;AAClD,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,OAAO,KAAqB;AAC1B,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,QAAI,CAAC,QAAQ,KAAK,UAAU,EAAG,QAAO;AACtC,WAAO,KAAK,MAAM,KAAK,QAAQ,IAAI,eAAe,WAAW,KAAK;AAAA,EACpE;AAAA,EAEA,IAAI,KAAqB;AACvB,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,QAAI,CAAC,QAAQ,KAAK,UAAU,EAAG,QAAO;AACtC,UAAM,EAAE,MAAM,MAAM,IAAI;AACxB,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,IAAI,KAAK,CAAC,KAAK;AACrB,UAAI,IAAI,EAAG,KAAI;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAqB;AACvB,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,QAAI,CAAC,QAAQ,KAAK,UAAU,EAAG,QAAO;AACtC,UAAM,EAAE,MAAM,MAAM,IAAI;AACxB,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,IAAI,KAAK,CAAC,KAAK;AACrB,UAAI,IAAI,EAAG,KAAI;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AACF;;;AC/DA,kBAAoC;AAG7B,IAAM,eAAN,MAAmB;AAAA,EAH1B,OAG0B;AAAA;AAAA;AAAA,EAChB,OAA0B;AAAA,EAC1B,QAAQ;AAAA,EACC;AAAA,EACA;AAAA,EAEjB,YAAY,WAAsB,UAAU,KAAK;AAC/C,SAAK,YAAY;AACjB,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA,EAGQ,SAAqB;AAC3B,QAAI,KAAK,KAAM,QAAO,KAAK;AAC3B,SAAK,OAAO,CAAC;AACb,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,KAAK;AACrC,YAAM,IAAI,IAAI,qBAAS;AACvB,QAAE,UAAU;AACZ,QAAE,YAAY;AACd,WAAK,UAAU,SAAS,CAAC;AACzB,WAAK,KAAK,KAAK,CAAC;AAAA,IAClB;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,UAAgC;AAC9B,UAAM,OAAO,KAAK,OAAO;AACzB,QAAI,KAAK,SAAS,KAAK,OAAQ,QAAO;AACtC,UAAM,IAAI,KAAK,KAAK,KAAK;AACzB,MAAE,UAAU;AACZ,SAAK;AACL,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAmB;AACjB,QAAI,CAAC,KAAK,KAAM;AAChB,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,KAAK;AACnC,YAAM,IAAI,KAAK,KAAK,CAAC;AACrB,QAAE,MAAM;AACR,QAAE,UAAU;AACZ,QAAE,SAAS,IAAI,GAAG,CAAC;AACnB,QAAE,WAAW;AACb,QAAE,MAAM,IAAI,GAAG,CAAC;AAAA,IAClB;AACA,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,KAAM;AAChB,eAAW,KAAK,KAAK,MAAM;AACzB,QAAE,QAAQ;AAAA,IACZ;AACA,SAAK,KAAK,SAAS;AAAA,EACrB;AACF;;;AC3DA,IAAAC,eAAgC;AAEhC,IAAM,cAAc;AACpB,IAAM,YAAY;AAClB,IAAM,UAAU;AAGT,IAAM,WAAN,MAAe;AAAA,EAPtB,OAOsB;AAAA;AAAA;AAAA,EACZ,OAAsB;AAAA,EACtB,QAAQ;AAAA,EACC;AAAA,EACA;AAAA,EAEjB,YAAY,WAAsB,WAAW,IAAI;AAC/C,SAAK,YAAY;AACjB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGQ,SAAiB;AACvB,QAAI,KAAK,KAAM,QAAO,KAAK;AAC3B,SAAK,OAAO,CAAC;AACb,aAAS,IAAI,GAAG,IAAI,KAAK,UAAU,KAAK;AACtC,YAAM,IAAI,IAAI,kBAAK;AAAA,QACjB,MAAM;AAAA,QACN,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AACD,QAAE,UAAU;AACZ,QAAE,YAAY;AACd,WAAK,UAAU,SAAS,CAAC;AACzB,WAAK,KAAK,KAAK,CAAC;AAAA,IAClB;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,QAAQ,MAAoB;AAC1B,UAAM,OAAO,KAAK,OAAO;AACzB,QAAI,KAAK,SAAS,KAAK,OAAQ;AAC/B,UAAM,IAAI,KAAK,KAAK,KAAK;AACzB,MAAE,OAAO;AACT,MAAE,UAAU;AACZ,MAAE,SAAS,IAAI,SAAS,UAAU,KAAK,QAAQ,WAAW;AAC1D,SAAK;AAAA,EACP;AAAA;AAAA,EAGA,aAAmB;AACjB,QAAI,CAAC,KAAK,KAAM;AAChB,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,KAAK;AACnC,WAAK,KAAK,CAAC,EAAG,UAAU;AAAA,IAC1B;AACA,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,KAAM;AAChB,eAAW,KAAK,KAAK,MAAM;AACzB,QAAE,QAAQ;AAAA,IACZ;AACA,SAAK,KAAK,SAAS;AAAA,EACrB;AACF;;;AC7DO,IAAM,oBAAN,MAAiD;AAAA,EAGtD,YACmB,MACA,UACA,SACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EAXrB,OAKwD;AAAA;AAAA;AAAA,EAC9C,mBAAmB;AAAA;AAAA,EAS3B,eAAe,MAAoB;AACjC,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,kBAA6C;AAC3C,WAAO,KAAK,KAAK,QAAQ;AAAA,EAC3B;AAAA,EAEA,cAAc,MAAuB;AACnC,WAAO,KAAK,SAAS,cAAc,KAAK,kBAAkB,IAAI;AAAA,EAChE;AAAA,EAEA,IAAI,aAAqB;AACvB,WAAO,KAAK,QAAQ;AAAA,EACtB;AACF;;;ACzBO,IAAM,kBAAN,MAA6C;AAAA,EAGlD,YACmB,UACA,UACD,aACA,cAChB;AAJiB;AACA;AACD;AACA;AAAA,EACf;AAAA,EAJgB;AAAA,EACA;AAAA,EACD;AAAA,EACA;AAAA,EAZpB,OAKoD;AAAA;AAAA;AAAA,EAC1C,mBAAmB;AAAA;AAAA,EAU3B,eAAe,MAAoB;AACjC,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,QAAQ,MAAoB;AAC1B,SAAK,SAAS,QAAQ,IAAI;AAAA,EAC5B;AAAA,EAEA,cAAc,MAAuB;AACnC,WAAO,KAAK,SAAS,cAAc,KAAK,kBAAkB,IAAI;AAAA,EAChE;AACF;;;AC3BA,IAAAC,eAA8B;AAiBvB,IAAM,oBAAN,cAAgC,oBAAO;AAAA,EAI5C,YACmB,UACA,cACA,UACA,UACA,QACA,OACA,gBACA,cACA,gBACjB;AACA,UAAM;AAVW;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA,EAGnB;AAAA,EAXmB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EA9BrB,OAiB8C;AAAA;AAAA;AAAA,EACnC,QAAQ,mBAAM;AAAA,EACd,WAAW;AAAA,EAgBpB,OAAO,IAAkB;AACvB,QAAI,CAAC,KAAK,SAAS,SAAS;AAC1B,WAAK,eAAe,UAAU;AAC9B,WAAK,aAAa,UAAU;AAC5B;AAAA,IACF;AAEA,SAAK,eAAe,UAAU;AAC9B,SAAK,aAAa,UAAU;AAK5B,SAAK,gBAAgB;AAErB,SAAK,aAAa,WAAW;AAC7B,SAAK,SAAS,WAAW;AAEzB,eAAW,CAAC,MAAM,WAAW,KAAK,KAAK,SAAS,cAAc;AAC5D,kBAAY,SAAS,KAAK,OAAO,EAAE;AAEnC,UAAI,YAAY,WAAW;AACzB,aAAK,SAAS,eAAe,IAAI;AACjC,oBAAY,UAAU,KAAK,QAAQ;AAAA,MACrC;AAEA,UAAI,YAAY,SAAS;AACvB,aAAK,OAAO,eAAe,IAAI;AAC/B,oBAAY,QAAQ,KAAK,MAAM;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,MAAM,KAAK,eAAe,WAAW;AAC3C,QAAI,CAAC,KAAK;AACR,WAAK,eAAe,SAAS,IAAI,GAAG,CAAC;AACrC,WAAK,eAAe,MAAM,IAAI,GAAG,CAAC;AAClC,WAAK,eAAe,WAAW;AAC/B;AAAA,IACF;AAEA,UAAM,KAAK,KAAK,eAAe;AAC/B,UAAM,KAAK,KAAK,eAAe;AAC/B,UAAM,aAAa,IAAI,kBACpB,MAAM,IAAI,IAAI,EACd,OAAO,CAAC,IAAI,QAAQ;AACvB,SAAK,eAAe,SAAS,IAAI,KAAK,IAAI,WAAW;AACrD,SAAK,eAAe,SAAS,IAAI,KAAK,IAAI,WAAW;AACrD,SAAK,eAAe,MAAM,IAAI,IAAI,IAAI;AACtC,SAAK,eAAe,WAAW,CAAC,IAAI;AAAA,EACtC;AACF;;;ACrFO,IAAM,iBAAN,MAAiD;AAAA,EAFxD,OAEwD;AAAA;AAAA;AAAA,EAC7C,OAAO;AAAA,EACP,QAA2B,CAAC;AAAA,EAC7B,QAAyB;AAAA,EAEjC,OAAO,OAAiB,IAAkB;AACxC,SAAK,QAAQ;AACb,QAAI,KAAK,EAAG,OAAM,KAAK,OAAO,MAAO,EAAE;AAAA,EACzC;AAAA,EAEA,QAAQ,KAAwB;AAC9B,UAAM,MAAM,KAAK,OAAO,QAAQ,KAAK,KAAK;AAC1C,QAAI,QAAQ,QAAQ,KAAK,MAAM,GAAG,CAAC,EAAE;AAAA,EACvC;AACF;;;ACbO,IAAM,yBAAN,MAAyD;AAAA,EAI9D,YAA6B,WAAsB;AAAtB;AAAA,EAAuB;AAAA,EAAvB;AAAA,EAP/B,OAGgE;AAAA;AAAA;AAAA,EACrD,OAAO;AAAA,EACP,QAA2B,CAAC;AAAA,EAIrC,QAAQ,KAAwB;AAC9B,UAAM,QAAQ,KAAK,UAAU,SAAS,EAAE;AACxC,QAAI,QAAQ,aAAa,KAAK,EAAE;AAAA,EAClC;AACF;;;ACXO,IAAM,0BAAN,MAA0D;AAAA,EAK/D,YAA6B,SAA8B;AAA9B;AAAA,EAA+B;AAAA,EAA/B;AAAA,EAP/B,OAEiE;AAAA;AAAA;AAAA,EACtD,OAAO;AAAA,EACP,QAAQ,CAAC,WAAW;AAAA,EACrB,QAAyB;AAAA,EAIjC,OAAO,OAAuB;AAC5B,SAAK,QAAQ;AACb,eAAW,CAAC,MAAM,EAAE,KAAK,KAAK,SAAS;AACrC,YAAM,KAAK,UAAU,IAAI,IAAI,EAAE;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,QAAQ,KAAwB;AAC9B,QAAI,CAAC,KAAK,MAAO;AAEjB,QAAI,QAAQ;AACZ,UAAM,UAAmC,CAAC;AAC1C,eAAW,QAAQ,KAAK,QAAQ,KAAK,GAAG;AACtC,YAAM,MAAM,KAAK,MAAM,QAAQ,UAAU,IAAI,EAAE;AAC/C,eAAS;AACT,cAAQ,KAAK,CAAC,MAAM,GAAG,CAAC;AAAA,IAC1B;AAEA,QAAI,QAAQ,YAAY,MAAM,QAAQ,CAAC,CAAC,IAAI;AAE5C,QAAI,IAAI,cAAc,WAAW,GAAG;AAClC,cAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAClC,iBAAW,CAAC,MAAM,GAAG,KAAK,SAAS;AACjC,YAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,CAAC,CAAC,IAAI;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;;;Ab8CO,IAAM,cAAN,MAAoC;AAAA,EAlF3C,OAkF2C;AAAA;AAAA;AAAA,EAChC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,eAAe,CAAC,UAAU;AAAA,EAElB;AAAA,EACT;AAAA,EACA;AAAA,EACA,eAAoC;AAAA,EACpC,WAA4B;AAAA,EAC5B,WAAqC;AAAA,EACrC,SAAiC;AAAA,EACjC,eAAyC;AAAA,EACzC,gBAAgB,oBAAI,IAAoB;AAAA,EACxC,kBAAkB,oBAAI,IAAkC;AAAA,EACxD,cAAmD;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAgC;AAAA,EAChC,WAA2C;AAAA,EAC3C,cAAiC,CAAC;AAAA,EAClC,QAA2B;AAAA,EAEnC,YAAY,QAAsB;AAChC,SAAK,SAAS,UAAU,CAAC;AAAA,EAC3B;AAAA,EAEA,QAAQ,SAA8B;AACpC,SAAK,UAAU;AACf,SAAK,WAAW,QAAQ,QAAQ,4BAAW;AAE3C,SAAK,WAAW,IAAI,kBAAkB;AACtC,SAAK,SAAS,UAAU,KAAK,OAAO,gBAAgB;AAEpD,QAAI,KAAK,OAAO,OAAO;AACrB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,KAAK,GAAG;AAC5D,cAAM,MAAM,IAAI,QAAQ,GAAG;AAC3B,YAAI,MAAM,GAAG;AACX,eAAK,SAAS,QAAQ,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,MAAM,CAAC,GAAG,KAAK;AAAA,QACpE;AAAA,MACF;AAAA,IACF;AAEA,SAAK,QAAQ,IAAI,WAAW;AAE5B,YAAQ,SAAS,kBAAkB,KAAK,QAAQ;AAAA,EAClD;AAAA,EAEA,gBAAgB,WAAkC;AAGhD,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,eAAe,KAAK,QAAQ,QAAQ,4BAAe;AACxD,UAAM,MAAM,KAAK,QAAQ,QAAQ,wBAAW;AAG5C,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,UAAM,UAAU,KAAK,OAAO,WAAW;AACvC,SAAK,cAAc,CAAC,MAAqB;AACvC,UAAI,EAAE,SAAS,WAAW;AACxB,aAAK,SAAS,OAAO;AACrB;AAAA,MACF;AACA,UAAI,EAAE,SAAS,WAAW,KAAK,OAAO,UAAU;AAC9C,UAAE,eAAe;AACjB,aAAK,MAAM,KAAK;AAAA,MAClB;AAAA,IACF;AACA,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,iBAAiB,WAAW,KAAK,WAAW;AAAA,IACrD;AAIA,eAAW,UAAU,KAAK,UAAU,cAAc,GAAG;AACnD,UAAI,kBAAkB,kBAAmB;AACzC,YAAM,OAAO,OAAO,YAAY;AAChC,YAAM,WAAW,OAAO,OAAO,KAAK,MAAM;AAC1C,WAAK,gBAAgB,IAAI,QAAQ,QAAQ;AACzC,aAAO,SAAS,CAAC,OAAe;AAC9B,cAAM,KAAK,YAAY,IAAI;AAC3B,iBAAS,EAAE;AACX,aAAK,cAAc,IAAI,MAAM,YAAY,IAAI,IAAI,EAAE;AAAA,MACrD;AAAA,IACF;AAGA,UAAM,YAAY,KAAK,QAAQ,QAAQ,yBAAY;AACnD,SAAK,SAAS,SAAS,IAAI,eAAe,CAAC;AAC3C,SAAK,SAAS,SAAS,IAAI,uBAAuB,SAAS,CAAC;AAC5D,SAAK,SAAS,SAAS,IAAI,wBAAwB,KAAK,aAAa,CAAC;AAGtE,UAAM,WAAW,KAAK,QAAQ,QAAQ,wBAAW;AACjD,UAAM,MAAM,KAAK,SAAS;AAC1B,SAAK,QAAQ,IAAI;AAAA,MACf;AAAA,MACA,MAAM,IAAI,KAAK;AAAA,MACf,MAAM,IAAI,MAAM;AAAA,MAChB,MAAM,IAAI,OAAO;AAAA,IACnB;AACA,QAAI,KAAK,OAAO,aAAa;AAC3B,WAAK,MAAM,UAAU,IAAI;AAAA,IAC3B;AACA,SAAK,eAAe,KAAK,KAAK;AAK9B,SAAK,WAAW,KAAK,QAAQ,WAAW,2CAA0B,KAAK;AACvE,SAAK,2BAA2B,SAAS;AACzC,UAAM,KAAK,sBAAsB;AAIjC,UAAM,eAAe,6BAAM;AACzB,UAAI,KAAK,cAAc,KAAK,UAAU,mBAAmB;AACvD,aAAK,SAAS,kBAAkB,KAAK,UAAU;AAAA,MACjD;AAAA,IACF,GAJqB;AAKrB,SAAK,YAAY,KAAK,IAAI,GAAG,gBAAgB,YAAY,CAAC;AAC1D,SAAK,YAAY,KAAK,IAAI,GAAG,gBAAgB,YAAY,CAAC;AAC1D,SAAK,YAAY,KAAK,IAAI,GAAG,kBAAkB,YAAY,CAAC;AAAA,EAC9D;AAAA,EAEA,YAAkB;AAChB,eAAW,SAAS,KAAK,YAAa,OAAM;AAC5C,SAAK,YAAY,SAAS;AAE1B,eAAW,CAAC,QAAQ,QAAQ,KAAK,KAAK,iBAAiB;AACrD,aAAO,SAAS;AAAA,IAClB;AACA,SAAK,gBAAgB,MAAM;AAE3B,QAAI,KAAK,aAAa;AACpB,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO,oBAAoB,WAAW,KAAK,WAAW;AAAA,MACxD;AACA,WAAK,cAAc;AAAA,IACrB;AAEA,SAAK,iBAAiB;AACtB,SAAK,QAAQ;AAEb,eAAW,eAAe,KAAK,SAAS,aAAa,OAAO,GAAG;AAC7D,kBAAY,UAAU;AAAA,IACxB;AACA,SAAK,SAAS,aAAa,MAAM;AAEjC,SAAK,mBAAmB;AACxB,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAc,wBAAuC;AACnD,UAAM,QAAQ,IAAI,WAAW;AAC7B,UAAM,UAAU,CAAC,gBAAgB,iBAC/B,KAAK,gBAAgB,gBAAgB,YAAY;AACnD,UAAM,aAAa,MAAM,KAAK,mBAAmB;AACjD,UAAM,KAAK,aAAa,eAAe,KAAK;AAC5C,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,qBAA2B;AAMjC,QAAI,CAAC,KAAK,WAAY;AACtB,SAAK,aAAa,iBAAiB,KAAK,UAAU;AAClD,SAAK,aAAa;AAClB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEQ,mBAAgD;AACtD,WAAO,kBAAkB,KAAK,YAAY;AAAA,EAC5C;AAAA,EAEQ,gBACN,gBACA,cACM;AACN,UAAM,KAAK,KAAK,SAAS,YAAY;AACrC,UAAM,KAAK,KAAK,SAAS,YAAY;AAGrC,UAAM,OAAO;AAEb,UAAM,cAAc;AAAA,MAClB,IAAI,OAAO;AACT,eAAO,KAAK,iBAAiB,GAAG,QAAQ;AAAA,MAC1C;AAAA,IACF;AAEA,SAAK,eAAe,IAAI;AAAA,MACtB;AAAA,MACA,KAAK,OAAO;AAAA,IACd;AACA,SAAK,WAAW,IAAI,SAAS,cAAc,KAAK,OAAO,WAAW;AAElE,SAAK,WAAW,IAAI;AAAA,MAClB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IACF;AACA,SAAK,SAAS,IAAI,gBAAgB,KAAK,UAAU,KAAK,UAAU,IAAI,EAAE;AAEtE,SAAK,eAAe,IAAI;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,QACE,YAAY,6BAAM,KAAK,iBAAiB,GAA5B;AAAA,QACZ,eAAe;AAAA,QACf,gBAAgB;AAAA,MAClB;AAAA,IACF;AACA,SAAK,UAAU,IAAI,KAAK,YAAY;AAAA,EACtC;AAAA,EAEQ,qBAA2B;AACjC,QAAI,KAAK,cAAc;AACrB,WAAK,UAAU,OAAO,KAAK,YAAY;AACvC,WAAK,eAAe;AAAA,IACtB;AACA,SAAK,cAAc,QAAQ;AAC3B,SAAK,UAAU,QAAQ;AACvB,SAAK,eAAe;AACpB,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,2BAA2B,WAA4B;AAC7D,UAAM,IAAK,WAAuC,UAAU;AAC5D,QAAI,CAAC,KAAK,OAAO,MAAM,SAAU;AAEjC,UAAM,eAAe;AACrB,UAAM,cAAc;AACpB,iBAAa,WAAW,IAAI;AAE5B,gBAAY,oBAAoB,CAAC,WAAW,cAAc;AACxD,YAAM,QAAQ,KAAK,aAAa,IAAI;AAAA,QAClC,CAAC,cAAc,UAAU,SAAS;AAAA,MACpC;AACA,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,QAAQ,KAAK,UAAU,QAAQ,KAAK,GAAG,OAAO,SAAS;AAC7D,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,YAAY,MAAM;AACxB,aAAO;AAAA,QACL,GAAG,UAAU,SAAS;AAAA,QACtB,GAAG,UAAU,SAAS;AAAA,QACtB,QAAQ,UAAU,MAAM;AAAA,QACxB,QAAQ,UAAU,MAAM;AAAA,QACxB,UAAU,UAAU;AAAA,MACtB;AAAA,IACF;AAEA,gBAAY,iBAAiB,MAAM;AACjC,YAAM,UAAiC,CAAC;AACxC,iBAAW,SAAS,KAAK,aAAa,KAAK;AACzC,mBAAW,UAAU,MAAM,YAAY,GAAG;AACxC,gBAAM,MAAM,OAAO,OAAO,gCAAe;AACzC,cAAI,CAAC,IAAK;AACV,kBAAQ,KAAK;AAAA,YACX,OAAO,MAAM;AAAA,YACb,MAAM,IAAI;AAAA,YACV,UAAU,IAAI;AAAA,YACd,SAAS,IAAI;AAAA,UACf,CAAC;AAAA,QACH;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,eAAe,OAA0B;AAC/C,UAAM,IAAK,WAAuC,UAAU;AAC5D,QAAI,KAAK,OAAO,MAAM,UAAU;AAC9B,MAAC,EAA8B,OAAO,IAAI;AAAA,IAC5C;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,UAAM,IAAK,WAAuC,UAAU;AAC5D,QACE,KACA,OAAO,MAAM,YACZ,EAA8B,OAAO,MAAM,KAAK,OACjD;AACA,aAAQ,EAA8B,OAAO;AAAA,IAC/C;AAAA,EACF;AACF;AAOO,SAAS,kBACd,cAC6B;AAC7B,QAAM,QAAQ,aAAa;AAC3B,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;AAC1C,UAAM,QAAQ,MAAM,CAAC;AACrB,QAAI,CAAC,MAAO;AACZ,QAAI;AACJ,eAAW,UAAU,MAAM,YAAY,GAAG;AACxC,YAAM,MAAM,OAAO,OAAO,gCAAe;AACzC,UACE,OACA,IAAI,YACH,CAAC,yBACA,IAAI,WAAW,sBAAsB,WACvC;AACA,gCAAwB;AAAA,MAC1B;AAAA,IACF;AACA,QAAI,sBAAuB,QAAO;AAAA,EACpC;AACA,SAAO;AACT;AAtBgB;","names":["import_core","import_renderer","import_core","import_pixi","import_core"]}
package/dist/index.d.cts CHANGED
@@ -18,31 +18,46 @@ interface DebugConfig {
18
18
  /** Initial flag overrides, keyed by "contributorName.flagName". */
19
19
  flags?: Record<string, boolean>;
20
20
  }
21
- /** Debug overlay plugin. Depends on the renderer plugin. */
21
+ /**
22
+ * Debug overlay plugin. Mounts a private `DebugScene` through
23
+ * `SceneManager._mountDetached` so it goes through the same scoped-DI
24
+ * lifecycle as stacked scenes (the renderer's `beforeEnter` hook creates
25
+ * its render tree) while staying off the user-visible scene stack.
26
+ */
22
27
  declare class DebugPlugin implements Plugin {
23
28
  readonly name = "debug";
24
- readonly version = "2.0.0";
29
+ readonly version = "3.0.0";
25
30
  readonly dependencies: readonly ["renderer"];
26
31
  private readonly config;
27
32
  private registry;
28
33
  private stats;
29
34
  private graphicsPool;
30
35
  private textPool;
31
- private worldContainer;
32
- private hudContainer;
33
36
  private worldApi;
34
37
  private hudApi;
38
+ private renderSystem;
35
39
  private systemTimings;
36
40
  private originalUpdates;
37
41
  private keyListener;
38
42
  private context;
39
43
  private renderer;
44
+ private scheduler;
45
+ private sceneManager;
46
+ private debugScene;
47
+ private provider;
48
+ private eventUnsubs;
40
49
  private clock;
41
50
  constructor(config?: DebugConfig);
42
51
  install(context: EngineContext): void;
43
52
  registerSystems(scheduler: SystemScheduler): void;
44
- onStart(): void;
53
+ onStart(): Promise<void>;
45
54
  onDestroy(): void;
55
+ private materializeDebugScene;
56
+ private teardownDebugScene;
57
+ private findActiveCamera;
58
+ private setUpDebugInfra;
59
+ private tearDownDebugInfra;
60
+ private attachInspectorDiagnostics;
46
61
  private attachToGlobal;
47
62
  private detachFromGlobal;
48
63
  }
package/dist/index.d.ts CHANGED
@@ -18,31 +18,46 @@ interface DebugConfig {
18
18
  /** Initial flag overrides, keyed by "contributorName.flagName". */
19
19
  flags?: Record<string, boolean>;
20
20
  }
21
- /** Debug overlay plugin. Depends on the renderer plugin. */
21
+ /**
22
+ * Debug overlay plugin. Mounts a private `DebugScene` through
23
+ * `SceneManager._mountDetached` so it goes through the same scoped-DI
24
+ * lifecycle as stacked scenes (the renderer's `beforeEnter` hook creates
25
+ * its render tree) while staying off the user-visible scene stack.
26
+ */
22
27
  declare class DebugPlugin implements Plugin {
23
28
  readonly name = "debug";
24
- readonly version = "2.0.0";
29
+ readonly version = "3.0.0";
25
30
  readonly dependencies: readonly ["renderer"];
26
31
  private readonly config;
27
32
  private registry;
28
33
  private stats;
29
34
  private graphicsPool;
30
35
  private textPool;
31
- private worldContainer;
32
- private hudContainer;
33
36
  private worldApi;
34
37
  private hudApi;
38
+ private renderSystem;
35
39
  private systemTimings;
36
40
  private originalUpdates;
37
41
  private keyListener;
38
42
  private context;
39
43
  private renderer;
44
+ private scheduler;
45
+ private sceneManager;
46
+ private debugScene;
47
+ private provider;
48
+ private eventUnsubs;
40
49
  private clock;
41
50
  constructor(config?: DebugConfig);
42
51
  install(context: EngineContext): void;
43
52
  registerSystems(scheduler: SystemScheduler): void;
44
- onStart(): void;
53
+ onStart(): Promise<void>;
45
54
  onDestroy(): void;
55
+ private materializeDebugScene;
56
+ private teardownDebugScene;
57
+ private findActiveCamera;
58
+ private setUpDebugInfra;
59
+ private tearDownDebugInfra;
60
+ private attachInspectorDiagnostics;
46
61
  private attachToGlobal;
47
62
  private detachFromGlobal;
48
63
  }
package/dist/index.js CHANGED
@@ -4,8 +4,14 @@ import {
4
4
  } from "./chunk-QSE3OVXA.js";
5
5
 
6
6
  // src/DebugPlugin.ts
7
- import { SystemSchedulerKey, InspectorKey, GameLoopKey } from "@yagejs/core";
8
- import { RendererKey, RenderLayerManagerKey, CameraKey } from "@yagejs/renderer";
7
+ import {
8
+ EventBusKey,
9
+ GameLoopKey,
10
+ InspectorKey,
11
+ SceneManagerKey
12
+ } from "@yagejs/core";
13
+ import { CameraComponent, RendererKey } from "@yagejs/renderer";
14
+ import { SceneRenderTreeProviderKey } from "@yagejs/renderer";
9
15
 
10
16
  // src/DebugClock.ts
11
17
  var DebugClock = class {
@@ -101,6 +107,44 @@ var DebugRegistryImpl = class {
101
107
  }
102
108
  };
103
109
 
110
+ // src/DebugScene.ts
111
+ import { LoggerKey, Scene } from "@yagejs/core";
112
+ import { SceneRenderTreeKey } from "@yagejs/renderer";
113
+ var DebugScene = class extends Scene {
114
+ static {
115
+ __name(this, "DebugScene");
116
+ }
117
+ name = "__debug__";
118
+ pauseBelow = false;
119
+ transparentBelow = true;
120
+ layers = [
121
+ { name: "debug-world", order: 999999 },
122
+ { name: "debug-hud", order: 999999 }
123
+ ];
124
+ /** Called after `_mountDetached` has materialized the render tree. */
125
+ onReady;
126
+ /** Called by the plugin when the scene is unmounted. */
127
+ onTearDown;
128
+ onEnter() {
129
+ const tree = this._resolveScoped(SceneRenderTreeKey);
130
+ if (!tree) {
131
+ const logger = this.context.tryResolve(LoggerKey);
132
+ const msg = "DebugScene.onEnter: SceneRenderTreeKey missing \u2014 debug overlay will not render. Is RendererPlugin registered?";
133
+ if (logger) logger.warn("debug", msg);
134
+ else console.warn(`[yage] ${msg}`);
135
+ return;
136
+ }
137
+ const worldContainer = tree.get("debug-world").container;
138
+ const hudContainer = tree.get("debug-hud").container;
139
+ worldContainer.eventMode = "none";
140
+ hudContainer.eventMode = "none";
141
+ this.onReady?.(worldContainer, hudContainer);
142
+ }
143
+ onExit() {
144
+ this.onTearDown?.();
145
+ }
146
+ };
147
+
104
148
  // src/StatsStore.ts
105
149
  var WINDOW_SIZE = 120;
106
150
  var StatsStore = class {
@@ -337,7 +381,7 @@ var HudDebugApiImpl = class {
337
381
  // src/DebugRenderSystem.ts
338
382
  import { System, Phase } from "@yagejs/core";
339
383
  var DebugRenderSystem = class extends System {
340
- constructor(registry, graphicsPool, textPool, worldApi, hudApi, stats, worldContainer, hudContainer) {
384
+ constructor(registry, graphicsPool, textPool, worldApi, hudApi, stats, worldContainer, hudContainer, cameraAccessor) {
341
385
  super();
342
386
  this.registry = registry;
343
387
  this.graphicsPool = graphicsPool;
@@ -347,6 +391,7 @@ var DebugRenderSystem = class extends System {
347
391
  this.stats = stats;
348
392
  this.worldContainer = worldContainer;
349
393
  this.hudContainer = hudContainer;
394
+ this.cameraAccessor = cameraAccessor;
350
395
  }
351
396
  registry;
352
397
  graphicsPool;
@@ -356,6 +401,7 @@ var DebugRenderSystem = class extends System {
356
401
  stats;
357
402
  worldContainer;
358
403
  hudContainer;
404
+ cameraAccessor;
359
405
  static {
360
406
  __name(this, "DebugRenderSystem");
361
407
  }
@@ -369,6 +415,7 @@ var DebugRenderSystem = class extends System {
369
415
  }
370
416
  this.worldContainer.visible = true;
371
417
  this.hudContainer.visible = true;
418
+ this.syncWorldCamera();
372
419
  this.graphicsPool.resetFrame();
373
420
  this.textPool.resetFrame();
374
421
  for (const [name, contributor] of this.registry.contributors) {
@@ -383,6 +430,22 @@ var DebugRenderSystem = class extends System {
383
430
  }
384
431
  }
385
432
  }
433
+ syncWorldCamera() {
434
+ const cam = this.cameraAccessor.findCamera();
435
+ if (!cam) {
436
+ this.worldContainer.position.set(0, 0);
437
+ this.worldContainer.scale.set(1, 1);
438
+ this.worldContainer.rotation = 0;
439
+ return;
440
+ }
441
+ const vw = this.cameraAccessor.viewportWidth;
442
+ const vh = this.cameraAccessor.viewportHeight;
443
+ const rotatedPos = cam.effectivePosition.scale(cam.zoom).rotate(-cam.rotation);
444
+ this.worldContainer.position.x = vw / 2 - rotatedPos.x;
445
+ this.worldContainer.position.y = vh / 2 - rotatedPos.y;
446
+ this.worldContainer.scale.set(cam.zoom);
447
+ this.worldContainer.rotation = -cam.rotation;
448
+ }
386
449
  };
387
450
 
388
451
  // src/contributors/FpsContributor.ts
@@ -463,22 +526,26 @@ var DebugPlugin = class {
463
526
  __name(this, "DebugPlugin");
464
527
  }
465
528
  name = "debug";
466
- version = "2.0.0";
529
+ version = "3.0.0";
467
530
  dependencies = ["renderer"];
468
531
  config;
469
532
  registry;
470
533
  stats;
471
- graphicsPool;
472
- textPool;
473
- worldContainer;
474
- hudContainer;
475
- worldApi;
476
- hudApi;
534
+ graphicsPool = null;
535
+ textPool = null;
536
+ worldApi = null;
537
+ hudApi = null;
538
+ renderSystem = null;
477
539
  systemTimings = /* @__PURE__ */ new Map();
478
540
  originalUpdates = /* @__PURE__ */ new Map();
479
541
  keyListener = null;
480
542
  context;
481
543
  renderer;
544
+ scheduler;
545
+ sceneManager;
546
+ debugScene = null;
547
+ provider = null;
548
+ eventUnsubs = [];
482
549
  clock = null;
483
550
  constructor(config) {
484
551
  this.config = config ?? {};
@@ -486,19 +553,6 @@ var DebugPlugin = class {
486
553
  install(context) {
487
554
  this.context = context;
488
555
  this.renderer = context.resolve(RendererKey);
489
- const camera = context.resolve(CameraKey);
490
- const worldLayers = context.resolve(RenderLayerManagerKey);
491
- const debugLayer = worldLayers.getOrCreate("debug", 999999);
492
- this.worldContainer = debugLayer.container;
493
- this.worldContainer.eventMode = "none";
494
- const hudLayers = this.renderer.createScreenContainer("debug-hud");
495
- this.hudContainer = hudLayers.defaultLayer.container;
496
- this.hudContainer.eventMode = "none";
497
- this.graphicsPool = new GraphicsPool(
498
- this.worldContainer,
499
- this.config.maxGraphics
500
- );
501
- this.textPool = new TextPool(this.hudContainer, this.config.maxHudLines);
502
556
  this.registry = new DebugRegistryImpl();
503
557
  this.registry.enabled = this.config.startEnabled ?? false;
504
558
  if (this.config.flags) {
@@ -510,34 +564,14 @@ var DebugPlugin = class {
510
564
  }
511
565
  }
512
566
  this.stats = new StatsStore();
513
- this.worldApi = new WorldDebugApiImpl(
514
- this.graphicsPool,
515
- this.registry,
516
- camera
517
- );
518
- this.hudApi = new HudDebugApiImpl(
519
- this.textPool,
520
- this.registry,
521
- camera.viewportWidth,
522
- camera.viewportHeight
523
- );
524
567
  context.register(DebugRegistryKey, this.registry);
525
568
  }
526
569
  registerSystems(scheduler) {
527
- scheduler.add(
528
- new DebugRenderSystem(
529
- this.registry,
530
- this.graphicsPool,
531
- this.textPool,
532
- this.worldApi,
533
- this.hudApi,
534
- this.stats,
535
- this.worldContainer,
536
- this.hudContainer
537
- )
538
- );
570
+ this.scheduler = scheduler;
539
571
  }
540
- onStart() {
572
+ async onStart() {
573
+ this.sceneManager = this.context.resolve(SceneManagerKey);
574
+ const bus = this.context.resolve(EventBusKey);
541
575
  const toggleKey = this.config.toggleKey ?? "Backquote";
542
576
  const stepKey = this.config.stepKey ?? "Period";
543
577
  this.keyListener = (e) => {
@@ -553,8 +587,7 @@ var DebugPlugin = class {
553
587
  if (typeof window !== "undefined") {
554
588
  window.addEventListener("keydown", this.keyListener);
555
589
  }
556
- const scheduler = this.context.resolve(SystemSchedulerKey);
557
- for (const system of scheduler.getAllSystems()) {
590
+ for (const system of this.scheduler.getAllSystems()) {
558
591
  if (system instanceof DebugRenderSystem) continue;
559
592
  const name = system.constructor.name;
560
593
  const original = system.update.bind(system);
@@ -581,8 +614,21 @@ var DebugPlugin = class {
581
614
  this.clock.setManual(true);
582
615
  }
583
616
  this.attachToGlobal(this.clock);
617
+ this.provider = this.context.tryResolve(SceneRenderTreeProviderKey) ?? null;
618
+ this.attachInspectorDiagnostics(inspector);
619
+ await this.materializeDebugScene();
620
+ const bringToFront = /* @__PURE__ */ __name(() => {
621
+ if (this.debugScene && this.provider?.bringSceneToFront) {
622
+ this.provider.bringSceneToFront(this.debugScene);
623
+ }
624
+ }, "bringToFront");
625
+ this.eventUnsubs.push(bus.on("scene:pushed", bringToFront));
626
+ this.eventUnsubs.push(bus.on("scene:popped", bringToFront));
627
+ this.eventUnsubs.push(bus.on("scene:replaced", bringToFront));
584
628
  }
585
629
  onDestroy() {
630
+ for (const unsub of this.eventUnsubs) unsub();
631
+ this.eventUnsubs.length = 0;
586
632
  for (const [system, original] of this.originalUpdates) {
587
633
  system.update = original;
588
634
  }
@@ -599,9 +645,112 @@ var DebugPlugin = class {
599
645
  contributor.dispose?.();
600
646
  }
601
647
  this.registry.contributors.clear();
602
- this.graphicsPool.destroy();
603
- this.textPool.destroy();
604
- this.renderer.destroyScreenContainer("debug-hud");
648
+ this.tearDownDebugInfra();
649
+ this.teardownDebugScene();
650
+ }
651
+ async materializeDebugScene() {
652
+ const scene = new DebugScene();
653
+ scene.onReady = (worldContainer, hudContainer) => this.setUpDebugInfra(worldContainer, hudContainer);
654
+ scene.onTearDown = () => this.tearDownDebugInfra();
655
+ await this.sceneManager._mountDetached(scene);
656
+ this.debugScene = scene;
657
+ }
658
+ teardownDebugScene() {
659
+ if (!this.debugScene) return;
660
+ this.sceneManager._unmountDetached(this.debugScene);
661
+ this.debugScene = null;
662
+ this.provider = null;
663
+ }
664
+ findActiveCamera() {
665
+ return findTopmostCamera(this.sceneManager);
666
+ }
667
+ setUpDebugInfra(worldContainer, hudContainer) {
668
+ const vw = this.renderer.virtualSize.width;
669
+ const vh = this.renderer.virtualSize.height;
670
+ const self = this;
671
+ const cameraProxy = {
672
+ get zoom() {
673
+ return self.findActiveCamera()?.zoom ?? 1;
674
+ }
675
+ };
676
+ this.graphicsPool = new GraphicsPool(
677
+ worldContainer,
678
+ this.config.maxGraphics
679
+ );
680
+ this.textPool = new TextPool(hudContainer, this.config.maxHudLines);
681
+ this.worldApi = new WorldDebugApiImpl(
682
+ this.graphicsPool,
683
+ this.registry,
684
+ cameraProxy
685
+ );
686
+ this.hudApi = new HudDebugApiImpl(this.textPool, this.registry, vw, vh);
687
+ this.renderSystem = new DebugRenderSystem(
688
+ this.registry,
689
+ this.graphicsPool,
690
+ this.textPool,
691
+ this.worldApi,
692
+ this.hudApi,
693
+ this.stats,
694
+ worldContainer,
695
+ hudContainer,
696
+ {
697
+ findCamera: /* @__PURE__ */ __name(() => self.findActiveCamera(), "findCamera"),
698
+ viewportWidth: vw,
699
+ viewportHeight: vh
700
+ }
701
+ );
702
+ this.scheduler.add(this.renderSystem);
703
+ }
704
+ tearDownDebugInfra() {
705
+ if (this.renderSystem) {
706
+ this.scheduler.remove(this.renderSystem);
707
+ this.renderSystem = null;
708
+ }
709
+ this.graphicsPool?.destroy();
710
+ this.textPool?.destroy();
711
+ this.graphicsPool = null;
712
+ this.textPool = null;
713
+ this.worldApi = null;
714
+ this.hudApi = null;
715
+ }
716
+ attachInspectorDiagnostics(inspector) {
717
+ const g = globalThis["__yage__"];
718
+ if (!g || typeof g !== "object") return;
719
+ const debugSurface = g;
720
+ const diagnostics = inspector;
721
+ debugSurface["inspector"] = inspector;
722
+ diagnostics.getLayerTransform = (sceneName, layerName) => {
723
+ const scene = this.sceneManager.all.find(
724
+ (candidate) => candidate.name === sceneName
725
+ );
726
+ if (!scene) return void 0;
727
+ const layer = this.provider?.getTree(scene)?.tryGet(layerName);
728
+ if (!layer) return void 0;
729
+ const container = layer.container;
730
+ return {
731
+ x: container.position.x,
732
+ y: container.position.y,
733
+ scaleX: container.scale.x,
734
+ scaleY: container.scale.y,
735
+ rotation: container.rotation
736
+ };
737
+ };
738
+ diagnostics.getCameraStack = () => {
739
+ const cameras = [];
740
+ for (const scene of this.sceneManager.all) {
741
+ for (const entity of scene.getEntities()) {
742
+ const cam = entity.tryGet(CameraComponent);
743
+ if (!cam) continue;
744
+ cameras.push({
745
+ scene: scene.name,
746
+ name: cam.cameraName,
747
+ priority: cam.priority,
748
+ enabled: cam.enabled
749
+ });
750
+ }
751
+ }
752
+ return cameras;
753
+ };
605
754
  }
606
755
  attachToGlobal(clock) {
607
756
  const g = globalThis["__yage__"];
@@ -616,6 +765,23 @@ var DebugPlugin = class {
616
765
  }
617
766
  }
618
767
  };
768
+ function findTopmostCamera(sceneManager) {
769
+ const stack = sceneManager.all;
770
+ for (let i = stack.length - 1; i >= 0; i--) {
771
+ const scene = stack[i];
772
+ if (!scene) continue;
773
+ let highestPriorityCamera;
774
+ for (const entity of scene.getEntities()) {
775
+ const cam = entity.tryGet(CameraComponent);
776
+ if (cam && cam.enabled && (!highestPriorityCamera || cam.priority > highestPriorityCamera.priority)) {
777
+ highestPriorityCamera = cam;
778
+ }
779
+ }
780
+ if (highestPriorityCamera) return highestPriorityCamera;
781
+ }
782
+ return void 0;
783
+ }
784
+ __name(findTopmostCamera, "findTopmostCamera");
619
785
  export {
620
786
  DebugPlugin,
621
787
  DebugRegistryImpl,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/DebugPlugin.ts","../src/DebugClock.ts","../src/DebugRegistryImpl.ts","../src/StatsStore.ts","../src/GraphicsPool.ts","../src/TextPool.ts","../src/WorldDebugApiImpl.ts","../src/HudDebugApiImpl.ts","../src/DebugRenderSystem.ts","../src/contributors/FpsContributor.ts","../src/contributors/EntityCountContributor.ts","../src/contributors/SystemTimingContributor.ts"],"sourcesContent":["import { SystemSchedulerKey, InspectorKey, GameLoopKey } from \"@yagejs/core\";\nimport type {\n EngineContext,\n Plugin,\n SystemScheduler,\n System,\n} from \"@yagejs/core\";\nimport { DebugRegistryKey } from \"./types.js\";\nimport { RendererKey, RenderLayerManagerKey, CameraKey } from \"@yagejs/renderer\";\nimport type { RendererPlugin } from \"@yagejs/renderer\";\nimport { Container } from \"pixi.js\";\nimport { DebugClock } from \"./DebugClock.js\";\nimport type { IDebugClock } from \"./DebugClock.js\";\nimport { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport { StatsStore } from \"./StatsStore.js\";\nimport { GraphicsPool } from \"./GraphicsPool.js\";\nimport { TextPool } from \"./TextPool.js\";\nimport { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport { DebugRenderSystem } from \"./DebugRenderSystem.js\";\nimport { FpsContributor } from \"./contributors/FpsContributor.js\";\nimport { EntityCountContributor } from \"./contributors/EntityCountContributor.js\";\nimport { SystemTimingContributor } from \"./contributors/SystemTimingContributor.js\";\n\n/** Configuration for the DebugPlugin. */\nexport interface DebugConfig {\n /** Key code to toggle debug overlay. Default: \"Backquote\" */\n toggleKey?: string;\n /** When true, stop the renderer ticker and advance simulation manually via `window.__yage__.clock`. */\n manualClock?: boolean;\n /** Key code to advance one fixed-timestep frame while manual clock mode is active. Default: \"Period\" */\n stepKey?: string;\n /** Max pooled Graphics objects. Default: 256 */\n maxGraphics?: number;\n /** Max HUD text lines. Default: 32 */\n maxHudLines?: number;\n /** Whether the overlay starts enabled. Default: false */\n startEnabled?: boolean;\n /** Initial flag overrides, keyed by \"contributorName.flagName\". */\n flags?: Record<string, boolean>;\n}\n\n/** Debug overlay plugin. Depends on the renderer plugin. */\nexport class DebugPlugin implements Plugin {\n readonly name = \"debug\";\n readonly version = \"2.0.0\";\n readonly dependencies = [\"renderer\"] as const;\n\n private readonly config: DebugConfig;\n private registry!: DebugRegistryImpl;\n private stats!: StatsStore;\n private graphicsPool!: GraphicsPool;\n private textPool!: TextPool;\n private worldContainer!: Container;\n private hudContainer!: Container;\n private worldApi!: WorldDebugApiImpl;\n private hudApi!: HudDebugApiImpl;\n private systemTimings = new Map<string, number>();\n private originalUpdates = new Map<System, (dt: number) => void>();\n private keyListener: ((e: KeyboardEvent) => void) | null = null;\n private context!: EngineContext;\n private renderer!: RendererPlugin;\n private clock: DebugClock | null = null;\n\n constructor(config?: DebugConfig) {\n this.config = config ?? {};\n }\n\n install(context: EngineContext): void {\n this.context = context;\n\n this.renderer = context.resolve(RendererKey);\n const camera = context.resolve(CameraKey);\n\n // World-space debug layer (child of world container, drawn on top)\n const worldLayers = context.resolve(RenderLayerManagerKey);\n const debugLayer = worldLayers.getOrCreate(\"debug\", 999999);\n this.worldContainer = debugLayer.container;\n this.worldContainer.eventMode = \"none\";\n\n // Screen-space HUD container (sibling of world container, unaffected by camera)\n const hudLayers = this.renderer.createScreenContainer(\"debug-hud\");\n this.hudContainer = hudLayers.defaultLayer.container;\n this.hudContainer.eventMode = \"none\";\n\n this.graphicsPool = new GraphicsPool(\n this.worldContainer,\n this.config.maxGraphics,\n );\n this.textPool = new TextPool(this.hudContainer, this.config.maxHudLines);\n\n this.registry = new DebugRegistryImpl();\n this.registry.enabled = this.config.startEnabled ?? false;\n\n if (this.config.flags) {\n for (const [key, value] of Object.entries(this.config.flags)) {\n const dot = key.indexOf(\".\");\n if (dot > 0) {\n this.registry.setFlag(key.slice(0, dot), key.slice(dot + 1), value);\n }\n }\n }\n\n this.stats = new StatsStore();\n\n this.worldApi = new WorldDebugApiImpl(\n this.graphicsPool,\n this.registry,\n camera,\n );\n this.hudApi = new HudDebugApiImpl(\n this.textPool,\n this.registry,\n camera.viewportWidth,\n camera.viewportHeight,\n );\n\n context.register(DebugRegistryKey, this.registry);\n }\n\n registerSystems(scheduler: SystemScheduler): void {\n scheduler.add(\n new DebugRenderSystem(\n this.registry,\n this.graphicsPool,\n this.textPool,\n this.worldApi,\n this.hudApi,\n this.stats,\n this.worldContainer,\n this.hudContainer,\n ),\n );\n }\n\n onStart(): void {\n // Toggle / step key listener\n const toggleKey = this.config.toggleKey ?? \"Backquote\";\n const stepKey = this.config.stepKey ?? \"Period\";\n this.keyListener = (e: KeyboardEvent) => {\n if (e.code === toggleKey) {\n this.registry.toggle();\n return;\n }\n if (e.code === stepKey && this.clock?.isManual) {\n e.preventDefault();\n this.clock.step();\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", this.keyListener);\n }\n\n // Instrument system timings\n const scheduler = this.context.resolve(SystemSchedulerKey);\n for (const system of scheduler.getAllSystems()) {\n if (system instanceof DebugRenderSystem) continue;\n const name = system.constructor.name;\n const original = system.update.bind(system);\n this.originalUpdates.set(system, original);\n system.update = (dt: number) => {\n const t0 = performance.now();\n original(dt);\n this.systemTimings.set(name, performance.now() - t0);\n };\n }\n\n // Built-in contributors\n const inspector = this.context.resolve(InspectorKey);\n this.registry.register(new FpsContributor());\n this.registry.register(new EntityCountContributor(inspector));\n this.registry.register(new SystemTimingContributor(this.systemTimings));\n\n // Manual clock for deterministic stepping\n const gameLoop = this.context.resolve(GameLoopKey);\n const app = this.renderer.application;\n\n this.clock = new DebugClock(\n gameLoop,\n () => app.stop(),\n () => app.start(),\n () => app.render(),\n );\n\n if (this.config.manualClock) {\n this.clock.setManual(true);\n }\n\n this.attachToGlobal(this.clock);\n }\n\n onDestroy(): void {\n // Restore original system.update methods\n for (const [system, original] of this.originalUpdates) {\n system.update = original;\n }\n this.originalUpdates.clear();\n\n if (this.keyListener) {\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"keydown\", this.keyListener);\n }\n this.keyListener = null;\n }\n\n this.detachFromGlobal();\n this.clock = null;\n\n for (const contributor of this.registry.contributors.values()) {\n contributor.dispose?.();\n }\n this.registry.contributors.clear();\n\n this.graphicsPool.destroy();\n this.textPool.destroy();\n // worldContainer is owned by the world RenderLayerManager — don't destroy it\n this.renderer.destroyScreenContainer(\"debug-hud\");\n }\n\n private attachToGlobal(clock: IDebugClock): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (g && typeof g === \"object\") {\n (g as Record<string, unknown>)[\"clock\"] = clock;\n }\n }\n\n private detachFromGlobal(): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (\n g &&\n typeof g === \"object\" &&\n (g as Record<string, unknown>)[\"clock\"] === this.clock\n ) {\n delete (g as Record<string, unknown>)[\"clock\"];\n }\n }\n}\n","/** Public interface for the manual debug clock, accessible via `window.__yage__.clock`. */\nexport interface IDebugClock {\n readonly isManual: boolean;\n startAuto(): void;\n stopAuto(): void;\n step(dtMs?: number): void;\n stepFrames(count: number, dtMs?: number): void;\n}\n\n/** Minimal view of a game loop needed by the debug clock. */\ninterface GameLoopLike {\n tick(dtMs: number): void;\n readonly fixedTimestep: number;\n}\n\n/**\n * Controls engine time-stepping for deterministic E2E tests.\n *\n * When manual mode is active the renderer ticker is paused and frames\n * advance only via explicit `step()` / `stepFrames()` calls.\n */\nexport class DebugClock implements IDebugClock {\n private _isManual = false;\n\n constructor(\n private readonly gameLoop: GameLoopLike,\n private readonly stopTicker: () => void,\n private readonly startTicker: () => void,\n private readonly render: () => void,\n ) {}\n\n get isManual(): boolean {\n return this._isManual;\n }\n\n startAuto(): void {\n if (!this._isManual) return;\n this.startTicker();\n this._isManual = false;\n }\n\n stopAuto(): void {\n if (this._isManual) return;\n this.stopTicker();\n this._isManual = true;\n }\n\n step(dtMs?: number): void {\n if (!this._isManual) {\n throw new Error(\n \"Manual clock is not active. Call clock.stopAuto() first.\",\n );\n }\n const dt = dtMs ?? this.gameLoop.fixedTimestep;\n this.gameLoop.tick(dt);\n this.render();\n }\n\n stepFrames(count: number, dtMs?: number): void {\n if (!Number.isInteger(count) || count < 0) {\n throw new Error(\n \"stepFrames(count) requires a non-negative integer count.\",\n );\n }\n for (let i = 0; i < count; i++) {\n this.step(dtMs);\n }\n }\n\n /** Enter or exit manual mode. Used by DebugPlugin for config-driven init. */\n setManual(enabled: boolean): void {\n if (enabled === this._isManual) return;\n if (enabled) {\n this.stopTicker();\n } else {\n this.startTicker();\n }\n this._isManual = enabled;\n }\n}\n","import type { DebugContributor, DebugRegistry } from \"./types.js\";\n\n/** Concrete implementation of the DebugRegistry interface. */\nexport class DebugRegistryImpl implements DebugRegistry {\n readonly contributors = new Map<string, DebugContributor>();\n enabled = false;\n private flags = new Map<string, boolean>();\n\n register(contributor: DebugContributor): void {\n if (this.contributors.has(contributor.name)) return;\n this.contributors.set(contributor.name, contributor);\n for (const flag of contributor.flags) {\n this.flags.set(`${contributor.name}.${flag}`, true);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n isFlagEnabled(contributorName: string, flag: string): boolean {\n return this.flags.get(`${contributorName}.${flag}`) ?? true;\n }\n\n toggle(): void {\n this.enabled = !this.enabled;\n }\n\n toggleFlag(contributorName: string, flag: string): void {\n const key = `${contributorName}.${flag}`;\n this.flags.set(key, !(this.flags.get(key) ?? true));\n }\n\n setFlag(contributorName: string, flag: string, value: boolean): void {\n this.flags.set(`${contributorName}.${flag}`, value);\n }\n}\n","import type { StatsApi } from \"./types.js\";\n\nconst WINDOW_SIZE = 120;\n\ninterface RingBuffer {\n data: Float64Array;\n count: number;\n index: number;\n}\n\n/** Rolling-window statistics store backed by Float64Array ring buffers. */\nexport class StatsStore implements StatsApi {\n private rings = new Map<string, RingBuffer>();\n\n push(key: string, value: number): void {\n let ring = this.rings.get(key);\n if (!ring) {\n ring = { data: new Float64Array(WINDOW_SIZE), count: 0, index: 0 };\n this.rings.set(key, ring);\n }\n ring.data[ring.index] = value;\n ring.index = (ring.index + 1) % WINDOW_SIZE;\n if (ring.count < WINDOW_SIZE) ring.count++;\n }\n\n average(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let sum = 0;\n for (let i = 0; i < count; i++) sum += data[i] ?? 0;\n return sum / count;\n }\n\n latest(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n return ring.data[(ring.index - 1 + WINDOW_SIZE) % WINDOW_SIZE] ?? 0;\n }\n\n min(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v < m) m = v;\n }\n return m;\n }\n\n max(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = -Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v > m) m = v;\n }\n return m;\n }\n}\n","import { Graphics, Container } from \"pixi.js\";\n\n/** Allocation-free pool of PixiJS Graphics objects for debug drawing. */\nexport class GraphicsPool {\n private pool: Graphics[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxSize: number;\n\n constructor(container: Container, maxSize = 256) {\n this.container = container;\n this.maxSize = maxSize;\n }\n\n /** Lazily create Graphics objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Graphics[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxSize; i++) {\n const g = new Graphics();\n g.visible = false;\n g.eventMode = \"none\";\n this.container.addChild(g);\n this.pool.push(g);\n }\n return this.pool;\n }\n\n /** Return the next available Graphics, or undefined if the pool is exhausted. */\n acquire(): Graphics | undefined {\n const pool = this.ensure();\n if (this.index >= pool.length) return undefined;\n const g = pool[this.index]!;\n g.visible = true;\n this.index++;\n return g;\n }\n\n /** Clear and hide all previously acquired graphics, reset index. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n const g = this.pool[i]!;\n g.clear();\n g.visible = false;\n g.position.set(0, 0);\n g.rotation = 0;\n g.scale.set(1, 1);\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const g of this.pool) {\n g.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import { Text, Container } from \"pixi.js\";\n\nconst LINE_HEIGHT = 16;\nconst FONT_SIZE = 14;\nconst PADDING = 4;\n\n/** Allocation-free pool of PixiJS Text objects for HUD debug lines. */\nexport class TextPool {\n private pool: Text[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxLines: number;\n\n constructor(container: Container, maxLines = 32) {\n this.container = container;\n this.maxLines = maxLines;\n }\n\n /** Lazily create Text objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Text[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxLines; i++) {\n const t = new Text({\n text: \"\",\n style: {\n fontFamily: \"monospace\",\n fontSize: FONT_SIZE,\n fill: 0xffffff,\n },\n });\n t.visible = false;\n t.eventMode = \"none\";\n this.container.addChild(t);\n this.pool.push(t);\n }\n return this.pool;\n }\n\n /** Show a text line at the next available slot. */\n addLine(text: string): void {\n const pool = this.ensure();\n if (this.index >= pool.length) return;\n const t = pool[this.index]!;\n t.text = text;\n t.visible = true;\n t.position.set(PADDING, PADDING + this.index * LINE_HEIGHT);\n this.index++;\n }\n\n /** Hide all lines and reset for the next frame. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n this.pool[i]!.visible = false;\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const t of this.pool) {\n t.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import type { WorldDebugApi, DebugGraphics } from \"./types.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** WorldDebugApi backed by a GraphicsPool. Contributor name is swapped per iteration. */\nexport class WorldDebugApiImpl implements WorldDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly pool: GraphicsPool,\n private readonly registry: DebugRegistryImpl,\n private readonly _camera: { zoom: number },\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawWorld). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n acquireGraphics(): DebugGraphics | undefined {\n return this.pool.acquire() as unknown as DebugGraphics | undefined;\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n\n get cameraZoom(): number {\n return this._camera.zoom;\n }\n}\n","import type { HudDebugApi } from \"./types.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** HudDebugApi backed by a TextPool. Contributor name is swapped per iteration. */\nexport class HudDebugApiImpl implements HudDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly textPool: TextPool,\n private readonly registry: DebugRegistryImpl,\n public readonly screenWidth: number,\n public readonly screenHeight: number,\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawHud). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n addLine(text: string): void {\n this.textPool.addLine(text);\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport type { Container } from \"pixi.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport type { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport type { StatsStore } from \"./StatsStore.js\";\n\n/** Renders all debug contributors. Runs after DisplaySystem in the Render phase. */\nexport class DebugRenderSystem extends System {\n readonly phase = Phase.Render;\n readonly priority = 9999;\n\n constructor(\n private readonly registry: DebugRegistryImpl,\n private readonly graphicsPool: GraphicsPool,\n private readonly textPool: TextPool,\n private readonly worldApi: WorldDebugApiImpl,\n private readonly hudApi: HudDebugApiImpl,\n private readonly stats: StatsStore,\n private readonly worldContainer: Container,\n private readonly hudContainer: Container,\n ) {\n super();\n }\n\n update(dt: number): void {\n if (!this.registry.enabled) {\n this.worldContainer.visible = false;\n this.hudContainer.visible = false;\n return;\n }\n\n this.worldContainer.visible = true;\n this.hudContainer.visible = true;\n this.graphicsPool.resetFrame();\n this.textPool.resetFrame();\n\n for (const [name, contributor] of this.registry.contributors) {\n contributor.sample?.(this.stats, dt);\n\n if (contributor.drawWorld) {\n this.worldApi.setContributor(name);\n contributor.drawWorld(this.worldApi);\n }\n\n if (contributor.drawHud) {\n this.hudApi.setContributor(name);\n contributor.drawHud(this.hudApi);\n }\n }\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class FpsContributor implements DebugContributor {\n readonly name = \"fps\";\n readonly flags: readonly string[] = [];\n private stats: StatsApi | null = null;\n\n sample(stats: StatsApi, dt: number): void {\n this.stats = stats;\n if (dt > 0) stats.push(\"fps\", 1000 / dt);\n }\n\n drawHud(api: HudDebugApi): void {\n const avg = this.stats?.average(\"fps\") ?? 0;\n api.addLine(`FPS: ${Math.round(avg)}`);\n }\n}\n","import type { DebugContributor, HudDebugApi } from \"../types.js\";\nimport type { Inspector } from \"@yagejs/core\";\n\nexport class EntityCountContributor implements DebugContributor {\n readonly name = \"entities\";\n readonly flags: readonly string[] = [];\n\n constructor(private readonly inspector: Inspector) {}\n\n drawHud(api: HudDebugApi): void {\n const count = this.inspector.snapshot().entityCount;\n api.addLine(`Entities: ${count}`);\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class SystemTimingContributor implements DebugContributor {\n readonly name = \"timing\";\n readonly flags = [\"breakdown\"] as const;\n private stats: StatsApi | null = null;\n\n constructor(private readonly timings: Map<string, number>) {}\n\n sample(stats: StatsApi): void {\n this.stats = stats;\n for (const [name, ms] of this.timings) {\n stats.push(`system.${name}`, ms);\n }\n }\n\n drawHud(api: HudDebugApi): void {\n if (!this.stats) return;\n\n let total = 0;\n const entries: Array<[string, number]> = [];\n for (const name of this.timings.keys()) {\n const avg = this.stats.average(`system.${name}`);\n total += avg;\n entries.push([name, avg]);\n }\n\n api.addLine(`Systems: ${total.toFixed(2)}ms`);\n\n if (api.isFlagEnabled(\"breakdown\")) {\n entries.sort((a, b) => b[1] - a[1]);\n for (const [name, avg] of entries) {\n api.addLine(` ${name}: ${avg.toFixed(2)}ms`);\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/DebugPlugin.ts","../src/DebugClock.ts","../src/DebugRegistryImpl.ts","../src/DebugScene.ts","../src/StatsStore.ts","../src/GraphicsPool.ts","../src/TextPool.ts","../src/WorldDebugApiImpl.ts","../src/HudDebugApiImpl.ts","../src/DebugRenderSystem.ts","../src/contributors/FpsContributor.ts","../src/contributors/EntityCountContributor.ts","../src/contributors/SystemTimingContributor.ts"],"sourcesContent":["import {\n EventBusKey,\n GameLoopKey,\n InspectorKey,\n SceneManagerKey,\n} from \"@yagejs/core\";\nimport type {\n EngineContext,\n EventBus,\n EngineEvents,\n Inspector,\n Plugin,\n SceneManager,\n System,\n SystemScheduler,\n} from \"@yagejs/core\";\nimport { DebugRegistryKey } from \"./types.js\";\nimport { CameraComponent, RendererKey } from \"@yagejs/renderer\";\nimport type { RendererPlugin, SceneRenderTreeProvider } from \"@yagejs/renderer\";\nimport { SceneRenderTreeProviderKey } from \"@yagejs/renderer\";\nimport type { Container } from \"pixi.js\";\nimport { DebugClock } from \"./DebugClock.js\";\nimport type { IDebugClock } from \"./DebugClock.js\";\nimport { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport { DebugScene } from \"./DebugScene.js\";\nimport { StatsStore } from \"./StatsStore.js\";\nimport { GraphicsPool } from \"./GraphicsPool.js\";\nimport { TextPool } from \"./TextPool.js\";\nimport { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport { DebugRenderSystem } from \"./DebugRenderSystem.js\";\nimport { FpsContributor } from \"./contributors/FpsContributor.js\";\nimport { EntityCountContributor } from \"./contributors/EntityCountContributor.js\";\nimport { SystemTimingContributor } from \"./contributors/SystemTimingContributor.js\";\n\n/** Configuration for the DebugPlugin. */\nexport interface DebugConfig {\n /** Key code to toggle debug overlay. Default: \"Backquote\" */\n toggleKey?: string;\n /** When true, stop the renderer ticker and advance simulation manually via `window.__yage__.clock`. */\n manualClock?: boolean;\n /** Key code to advance one fixed-timestep frame while manual clock mode is active. Default: \"Period\" */\n stepKey?: string;\n /** Max pooled Graphics objects. Default: 256 */\n maxGraphics?: number;\n /** Max HUD text lines. Default: 32 */\n maxHudLines?: number;\n /** Whether the overlay starts enabled. Default: false */\n startEnabled?: boolean;\n /** Initial flag overrides, keyed by \"contributorName.flagName\". */\n flags?: Record<string, boolean>;\n}\n\ninterface LayerTransformSnapshot {\n x: number;\n y: number;\n scaleX: number;\n scaleY: number;\n rotation: number;\n}\n\ninterface CameraStackSnapshot {\n scene: string;\n name: string | undefined;\n priority: number;\n enabled: boolean;\n}\n\ninterface InspectorDiagnostics {\n getLayerTransform(\n sceneName: string,\n layerName: string,\n ): LayerTransformSnapshot | undefined;\n getCameraStack(): CameraStackSnapshot[];\n}\n\n/**\n * Debug overlay plugin. Mounts a private `DebugScene` through\n * `SceneManager._mountDetached` so it goes through the same scoped-DI\n * lifecycle as stacked scenes (the renderer's `beforeEnter` hook creates\n * its render tree) while staying off the user-visible scene stack.\n */\nexport class DebugPlugin implements Plugin {\n readonly name = \"debug\";\n readonly version = \"3.0.0\";\n readonly dependencies = [\"renderer\"] as const;\n\n private readonly config: DebugConfig;\n private registry!: DebugRegistryImpl;\n private stats!: StatsStore;\n private graphicsPool: GraphicsPool | null = null;\n private textPool: TextPool | null = null;\n private worldApi: WorldDebugApiImpl | null = null;\n private hudApi: HudDebugApiImpl | null = null;\n private renderSystem: DebugRenderSystem | null = null;\n private systemTimings = new Map<string, number>();\n private originalUpdates = new Map<System, (dt: number) => void>();\n private keyListener: ((e: KeyboardEvent) => void) | null = null;\n private context!: EngineContext;\n private renderer!: RendererPlugin;\n private scheduler!: SystemScheduler;\n private sceneManager!: SceneManager;\n private debugScene: DebugScene | null = null;\n private provider: SceneRenderTreeProvider | null = null;\n private eventUnsubs: Array<() => void> = [];\n private clock: DebugClock | null = null;\n\n constructor(config?: DebugConfig) {\n this.config = config ?? {};\n }\n\n install(context: EngineContext): void {\n this.context = context;\n this.renderer = context.resolve(RendererKey);\n\n this.registry = new DebugRegistryImpl();\n this.registry.enabled = this.config.startEnabled ?? false;\n\n if (this.config.flags) {\n for (const [key, value] of Object.entries(this.config.flags)) {\n const dot = key.indexOf(\".\");\n if (dot > 0) {\n this.registry.setFlag(key.slice(0, dot), key.slice(dot + 1), value);\n }\n }\n }\n\n this.stats = new StatsStore();\n\n context.register(DebugRegistryKey, this.registry);\n }\n\n registerSystems(scheduler: SystemScheduler): void {\n // DebugRenderSystem is registered lazily once the debug scene is ready —\n // its constructor needs the scene's layer containers.\n this.scheduler = scheduler;\n }\n\n async onStart(): Promise<void> {\n this.sceneManager = this.context.resolve(SceneManagerKey);\n const bus = this.context.resolve(EventBusKey) as EventBus<EngineEvents>;\n\n // Key listeners (toggle, manual-clock step)\n const toggleKey = this.config.toggleKey ?? \"Backquote\";\n const stepKey = this.config.stepKey ?? \"Period\";\n this.keyListener = (e: KeyboardEvent) => {\n if (e.code === toggleKey) {\n this.registry.toggle();\n return;\n }\n if (e.code === stepKey && this.clock?.isManual) {\n e.preventDefault();\n this.clock.step();\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", this.keyListener);\n }\n\n // Instrument system timings — reuse the scheduler captured in\n // `registerSystems`, which ran before `onStart`.\n for (const system of this.scheduler.getAllSystems()) {\n if (system instanceof DebugRenderSystem) continue;\n const name = system.constructor.name;\n const original = system.update.bind(system);\n this.originalUpdates.set(system, original);\n system.update = (dt: number) => {\n const t0 = performance.now();\n original(dt);\n this.systemTimings.set(name, performance.now() - t0);\n };\n }\n\n // Built-in contributors\n const inspector = this.context.resolve(InspectorKey);\n this.registry.register(new FpsContributor());\n this.registry.register(new EntityCountContributor(inspector));\n this.registry.register(new SystemTimingContributor(this.systemTimings));\n\n // Manual clock for deterministic stepping\n const gameLoop = this.context.resolve(GameLoopKey);\n const app = this.renderer.application;\n this.clock = new DebugClock(\n gameLoop,\n () => app.stop(),\n () => app.start(),\n () => app.render(),\n );\n if (this.config.manualClock) {\n this.clock.setManual(true);\n }\n this.attachToGlobal(this.clock);\n\n // Materialize the debug scene off-stack. `_mountDetached` routes through\n // the same beforeEnter hooks as `push`, so the renderer materializes the\n // debug scene's tree and registers SceneRenderTreeKey on its scope.\n this.provider = this.context.tryResolve(SceneRenderTreeProviderKey) ?? null;\n this.attachInspectorDiagnostics(inspector);\n await this.materializeDebugScene();\n\n // Keep the debug scene visually on top of the user stack after any\n // push/pop/replace by reordering its root containers.\n const bringToFront = () => {\n if (this.debugScene && this.provider?.bringSceneToFront) {\n this.provider.bringSceneToFront(this.debugScene);\n }\n };\n this.eventUnsubs.push(bus.on(\"scene:pushed\", bringToFront));\n this.eventUnsubs.push(bus.on(\"scene:popped\", bringToFront));\n this.eventUnsubs.push(bus.on(\"scene:replaced\", bringToFront));\n }\n\n onDestroy(): void {\n for (const unsub of this.eventUnsubs) unsub();\n this.eventUnsubs.length = 0;\n\n for (const [system, original] of this.originalUpdates) {\n system.update = original;\n }\n this.originalUpdates.clear();\n\n if (this.keyListener) {\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"keydown\", this.keyListener);\n }\n this.keyListener = null;\n }\n\n this.detachFromGlobal();\n this.clock = null;\n\n for (const contributor of this.registry.contributors.values()) {\n contributor.dispose?.();\n }\n this.registry.contributors.clear();\n\n this.tearDownDebugInfra();\n this.teardownDebugScene();\n }\n\n private async materializeDebugScene(): Promise<void> {\n const scene = new DebugScene();\n scene.onReady = (worldContainer, hudContainer) =>\n this.setUpDebugInfra(worldContainer, hudContainer);\n scene.onTearDown = () => this.tearDownDebugInfra();\n await this.sceneManager._mountDetached(scene);\n this.debugScene = scene;\n }\n\n private teardownDebugScene(): void {\n // If destroy is called while `_mountDetached` is still pending, we don't\n // yet hold a reference to the partially-mounted scene. Skipping unmount\n // here is safe: onDestroy still runs `tearDownDebugInfra` below, and the\n // engine teardown tears down the renderer next which destroys any\n // half-created provider entries.\n if (!this.debugScene) return;\n this.sceneManager._unmountDetached(this.debugScene);\n this.debugScene = null;\n this.provider = null;\n }\n\n private findActiveCamera(): CameraComponent | undefined {\n return findTopmostCamera(this.sceneManager);\n }\n\n private setUpDebugInfra(\n worldContainer: Container,\n hudContainer: Container,\n ): void {\n const vw = this.renderer.virtualSize.width;\n const vh = this.renderer.virtualSize.height;\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n // Lazy camera accessor — reads from whichever stacked scene has a camera\n const cameraProxy = {\n get zoom() {\n return self.findActiveCamera()?.zoom ?? 1;\n },\n };\n\n this.graphicsPool = new GraphicsPool(\n worldContainer,\n this.config.maxGraphics,\n );\n this.textPool = new TextPool(hudContainer, this.config.maxHudLines);\n\n this.worldApi = new WorldDebugApiImpl(\n this.graphicsPool,\n this.registry,\n cameraProxy,\n );\n this.hudApi = new HudDebugApiImpl(this.textPool, this.registry, vw, vh);\n\n this.renderSystem = new DebugRenderSystem(\n this.registry,\n this.graphicsPool,\n this.textPool,\n this.worldApi,\n this.hudApi,\n this.stats,\n worldContainer,\n hudContainer,\n {\n findCamera: () => self.findActiveCamera(),\n viewportWidth: vw,\n viewportHeight: vh,\n },\n );\n this.scheduler.add(this.renderSystem);\n }\n\n private tearDownDebugInfra(): void {\n if (this.renderSystem) {\n this.scheduler.remove(this.renderSystem);\n this.renderSystem = null;\n }\n this.graphicsPool?.destroy();\n this.textPool?.destroy();\n this.graphicsPool = null;\n this.textPool = null;\n this.worldApi = null;\n this.hudApi = null;\n }\n\n private attachInspectorDiagnostics(inspector: Inspector): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (!g || typeof g !== \"object\") return;\n\n const debugSurface = g as Record<string, unknown>;\n const diagnostics = inspector as Inspector & InspectorDiagnostics;\n debugSurface[\"inspector\"] = inspector;\n\n diagnostics.getLayerTransform = (sceneName, layerName) => {\n const scene = this.sceneManager.all.find(\n (candidate) => candidate.name === sceneName,\n );\n if (!scene) return undefined;\n\n const layer = this.provider?.getTree(scene)?.tryGet(layerName);\n if (!layer) return undefined;\n\n const container = layer.container;\n return {\n x: container.position.x,\n y: container.position.y,\n scaleX: container.scale.x,\n scaleY: container.scale.y,\n rotation: container.rotation,\n };\n };\n\n diagnostics.getCameraStack = () => {\n const cameras: CameraStackSnapshot[] = [];\n for (const scene of this.sceneManager.all) {\n for (const entity of scene.getEntities()) {\n const cam = entity.tryGet(CameraComponent);\n if (!cam) continue;\n cameras.push({\n scene: scene.name,\n name: cam.cameraName,\n priority: cam.priority,\n enabled: cam.enabled,\n });\n }\n }\n return cameras;\n };\n }\n\n private attachToGlobal(clock: IDebugClock): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (g && typeof g === \"object\") {\n (g as Record<string, unknown>)[\"clock\"] = clock;\n }\n }\n\n private detachFromGlobal(): void {\n const g = (globalThis as Record<string, unknown>)[\"__yage__\"];\n if (\n g &&\n typeof g === \"object\" &&\n (g as Record<string, unknown>)[\"clock\"] === this.clock\n ) {\n delete (g as Record<string, unknown>)[\"clock\"];\n }\n }\n}\n\n/**\n * Find the highest-priority enabled camera on the topmost scene that has one.\n * `sceneManager.all` is bottom→top, so we walk in reverse — a pause/HUD\n * scene's camera wins over a frozen scene beneath it.\n */\nexport function findTopmostCamera(\n sceneManager: SceneManager,\n): CameraComponent | undefined {\n const stack = sceneManager.all;\n for (let i = stack.length - 1; i >= 0; i--) {\n const scene = stack[i];\n if (!scene) continue;\n let highestPriorityCamera: CameraComponent | undefined;\n for (const entity of scene.getEntities()) {\n const cam = entity.tryGet(CameraComponent);\n if (\n cam &&\n cam.enabled &&\n (!highestPriorityCamera ||\n cam.priority > highestPriorityCamera.priority)\n ) {\n highestPriorityCamera = cam;\n }\n }\n if (highestPriorityCamera) return highestPriorityCamera;\n }\n return undefined;\n}\n","/** Public interface for the manual debug clock, accessible via `window.__yage__.clock`. */\nexport interface IDebugClock {\n readonly isManual: boolean;\n startAuto(): void;\n stopAuto(): void;\n step(dtMs?: number): void;\n stepFrames(count: number, dtMs?: number): void;\n}\n\n/** Minimal view of a game loop needed by the debug clock. */\ninterface GameLoopLike {\n tick(dtMs: number): void;\n readonly fixedTimestep: number;\n}\n\n/**\n * Controls engine time-stepping for deterministic E2E tests.\n *\n * When manual mode is active the renderer ticker is paused and frames\n * advance only via explicit `step()` / `stepFrames()` calls.\n */\nexport class DebugClock implements IDebugClock {\n private _isManual = false;\n\n constructor(\n private readonly gameLoop: GameLoopLike,\n private readonly stopTicker: () => void,\n private readonly startTicker: () => void,\n private readonly render: () => void,\n ) {}\n\n get isManual(): boolean {\n return this._isManual;\n }\n\n startAuto(): void {\n if (!this._isManual) return;\n this.startTicker();\n this._isManual = false;\n }\n\n stopAuto(): void {\n if (this._isManual) return;\n this.stopTicker();\n this._isManual = true;\n }\n\n step(dtMs?: number): void {\n if (!this._isManual) {\n throw new Error(\n \"Manual clock is not active. Call clock.stopAuto() first.\",\n );\n }\n const dt = dtMs ?? this.gameLoop.fixedTimestep;\n this.gameLoop.tick(dt);\n this.render();\n }\n\n stepFrames(count: number, dtMs?: number): void {\n if (!Number.isInteger(count) || count < 0) {\n throw new Error(\n \"stepFrames(count) requires a non-negative integer count.\",\n );\n }\n for (let i = 0; i < count; i++) {\n this.step(dtMs);\n }\n }\n\n /** Enter or exit manual mode. Used by DebugPlugin for config-driven init. */\n setManual(enabled: boolean): void {\n if (enabled === this._isManual) return;\n if (enabled) {\n this.stopTicker();\n } else {\n this.startTicker();\n }\n this._isManual = enabled;\n }\n}\n","import type { DebugContributor, DebugRegistry } from \"./types.js\";\n\n/** Concrete implementation of the DebugRegistry interface. */\nexport class DebugRegistryImpl implements DebugRegistry {\n readonly contributors = new Map<string, DebugContributor>();\n enabled = false;\n private flags = new Map<string, boolean>();\n\n register(contributor: DebugContributor): void {\n if (this.contributors.has(contributor.name)) return;\n this.contributors.set(contributor.name, contributor);\n for (const flag of contributor.flags) {\n this.flags.set(`${contributor.name}.${flag}`, true);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n isFlagEnabled(contributorName: string, flag: string): boolean {\n return this.flags.get(`${contributorName}.${flag}`) ?? true;\n }\n\n toggle(): void {\n this.enabled = !this.enabled;\n }\n\n toggleFlag(contributorName: string, flag: string): void {\n const key = `${contributorName}.${flag}`;\n this.flags.set(key, !(this.flags.get(key) ?? true));\n }\n\n setFlag(contributorName: string, flag: string, value: boolean): void {\n this.flags.set(`${contributorName}.${flag}`, value);\n }\n}\n","import { LoggerKey, Scene } from \"@yagejs/core\";\nimport type { Logger } from \"@yagejs/core\";\nimport type { LayerDef } from \"@yagejs/renderer\";\nimport { SceneRenderTreeKey } from \"@yagejs/renderer\";\nimport type { Container } from \"pixi.js\";\n\n/**\n * Scene mounted by the debug plugin via `SceneManager._mountDetached`.\n * Declares two layers:\n * - `\"debug-world\"` — world-space, rides the camera (for collision shapes).\n * - `\"debug-hud\"` — screen-space, fixed overlay (text readouts).\n *\n * `pauseBelow: false` / `transparentBelow: true` so the underlying game\n * keeps running and rendering behind the overlay.\n */\nexport class DebugScene extends Scene {\n readonly name = \"__debug__\";\n override readonly pauseBelow = false;\n override readonly transparentBelow = true;\n readonly layers: readonly LayerDef[] = [\n { name: \"debug-world\", order: 999999 },\n { name: \"debug-hud\", order: 999999 },\n ];\n\n /** Called after `_mountDetached` has materialized the render tree. */\n onReady?: (worldContainer: Container, hudContainer: Container) => void;\n\n /** Called by the plugin when the scene is unmounted. */\n onTearDown?: () => void;\n\n onEnter(): void {\n const tree = this._resolveScoped(SceneRenderTreeKey);\n if (!tree) {\n // Shouldn't happen — DebugPlugin declares `renderer` as a dependency\n // so the renderer's `beforeEnter` hook should have materialized a\n // tree before this runs. Surface it rather than silently skipping\n // the overlay wiring.\n const logger = this.context.tryResolve(LoggerKey) as Logger | undefined;\n const msg =\n \"DebugScene.onEnter: SceneRenderTreeKey missing — debug overlay will not render. Is RendererPlugin registered?\";\n if (logger) logger.warn(\"debug\", msg);\n else console.warn(`[yage] ${msg}`);\n return;\n }\n const worldContainer = tree.get(\"debug-world\").container;\n const hudContainer = tree.get(\"debug-hud\").container;\n worldContainer.eventMode = \"none\";\n hudContainer.eventMode = \"none\";\n this.onReady?.(worldContainer, hudContainer);\n }\n\n onExit(): void {\n this.onTearDown?.();\n }\n}\n","import type { StatsApi } from \"./types.js\";\n\nconst WINDOW_SIZE = 120;\n\ninterface RingBuffer {\n data: Float64Array;\n count: number;\n index: number;\n}\n\n/** Rolling-window statistics store backed by Float64Array ring buffers. */\nexport class StatsStore implements StatsApi {\n private rings = new Map<string, RingBuffer>();\n\n push(key: string, value: number): void {\n let ring = this.rings.get(key);\n if (!ring) {\n ring = { data: new Float64Array(WINDOW_SIZE), count: 0, index: 0 };\n this.rings.set(key, ring);\n }\n ring.data[ring.index] = value;\n ring.index = (ring.index + 1) % WINDOW_SIZE;\n if (ring.count < WINDOW_SIZE) ring.count++;\n }\n\n average(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let sum = 0;\n for (let i = 0; i < count; i++) sum += data[i] ?? 0;\n return sum / count;\n }\n\n latest(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n return ring.data[(ring.index - 1 + WINDOW_SIZE) % WINDOW_SIZE] ?? 0;\n }\n\n min(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v < m) m = v;\n }\n return m;\n }\n\n max(key: string): number {\n const ring = this.rings.get(key);\n if (!ring || ring.count === 0) return 0;\n const { data, count } = ring;\n let m = -Infinity;\n for (let i = 0; i < count; i++) {\n const v = data[i] ?? 0;\n if (v > m) m = v;\n }\n return m;\n }\n}\n","import { Graphics, Container } from \"pixi.js\";\n\n/** Allocation-free pool of PixiJS Graphics objects for debug drawing. */\nexport class GraphicsPool {\n private pool: Graphics[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxSize: number;\n\n constructor(container: Container, maxSize = 256) {\n this.container = container;\n this.maxSize = maxSize;\n }\n\n /** Lazily create Graphics objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Graphics[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxSize; i++) {\n const g = new Graphics();\n g.visible = false;\n g.eventMode = \"none\";\n this.container.addChild(g);\n this.pool.push(g);\n }\n return this.pool;\n }\n\n /** Return the next available Graphics, or undefined if the pool is exhausted. */\n acquire(): Graphics | undefined {\n const pool = this.ensure();\n if (this.index >= pool.length) return undefined;\n const g = pool[this.index]!;\n g.visible = true;\n this.index++;\n return g;\n }\n\n /** Clear and hide all previously acquired graphics, reset index. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n const g = this.pool[i]!;\n g.clear();\n g.visible = false;\n g.position.set(0, 0);\n g.rotation = 0;\n g.scale.set(1, 1);\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const g of this.pool) {\n g.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import { Text, Container } from \"pixi.js\";\n\nconst LINE_HEIGHT = 16;\nconst FONT_SIZE = 14;\nconst PADDING = 4;\n\n/** Allocation-free pool of PixiJS Text objects for HUD debug lines. */\nexport class TextPool {\n private pool: Text[] | null = null;\n private index = 0;\n private readonly container: Container;\n private readonly maxLines: number;\n\n constructor(container: Container, maxLines = 32) {\n this.container = container;\n this.maxLines = maxLines;\n }\n\n /** Lazily create Text objects on first use (ensures PixiJS is fully ready). */\n private ensure(): Text[] {\n if (this.pool) return this.pool;\n this.pool = [];\n for (let i = 0; i < this.maxLines; i++) {\n const t = new Text({\n text: \"\",\n style: {\n fontFamily: \"monospace\",\n fontSize: FONT_SIZE,\n fill: 0xffffff,\n },\n });\n t.visible = false;\n t.eventMode = \"none\";\n this.container.addChild(t);\n this.pool.push(t);\n }\n return this.pool;\n }\n\n /** Show a text line at the next available slot. */\n addLine(text: string): void {\n const pool = this.ensure();\n if (this.index >= pool.length) return;\n const t = pool[this.index]!;\n t.text = text;\n t.visible = true;\n t.position.set(PADDING, PADDING + this.index * LINE_HEIGHT);\n this.index++;\n }\n\n /** Hide all lines and reset for the next frame. */\n resetFrame(): void {\n if (!this.pool) return;\n for (let i = 0; i < this.index; i++) {\n this.pool[i]!.visible = false;\n }\n this.index = 0;\n }\n\n destroy(): void {\n if (!this.pool) return;\n for (const t of this.pool) {\n t.destroy();\n }\n this.pool.length = 0;\n }\n}\n","import type { WorldDebugApi, DebugGraphics } from \"./types.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** WorldDebugApi backed by a GraphicsPool. Contributor name is swapped per iteration. */\nexport class WorldDebugApiImpl implements WorldDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly pool: GraphicsPool,\n private readonly registry: DebugRegistryImpl,\n private readonly _camera: { zoom: number },\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawWorld). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n acquireGraphics(): DebugGraphics | undefined {\n return this.pool.acquire() as unknown as DebugGraphics | undefined;\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n\n get cameraZoom(): number {\n return this._camera.zoom;\n }\n}\n","import type { HudDebugApi } from \"./types.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\n\n/** HudDebugApi backed by a TextPool. Contributor name is swapped per iteration. */\nexport class HudDebugApiImpl implements HudDebugApi {\n private _contributorName = \"\";\n\n constructor(\n private readonly textPool: TextPool,\n private readonly registry: DebugRegistryImpl,\n public readonly screenWidth: number,\n public readonly screenHeight: number,\n ) {}\n\n /** Set the current contributor name (called before each contributor's drawHud). */\n setContributor(name: string): void {\n this._contributorName = name;\n }\n\n addLine(text: string): void {\n this.textPool.addLine(text);\n }\n\n isFlagEnabled(flag: string): boolean {\n return this.registry.isFlagEnabled(this._contributorName, flag);\n }\n}\n","import { System, Phase } from \"@yagejs/core\";\nimport type { Container } from \"pixi.js\";\nimport type { CameraComponent } from \"@yagejs/renderer\";\nimport type { DebugRegistryImpl } from \"./DebugRegistryImpl.js\";\nimport type { GraphicsPool } from \"./GraphicsPool.js\";\nimport type { TextPool } from \"./TextPool.js\";\nimport type { WorldDebugApiImpl } from \"./WorldDebugApiImpl.js\";\nimport type { HudDebugApiImpl } from \"./HudDebugApiImpl.js\";\nimport type { StatsStore } from \"./StatsStore.js\";\n\nexport interface DebugCameraAccessor {\n findCamera(): CameraComponent | undefined;\n viewportWidth: number;\n viewportHeight: number;\n}\n\n/** Renders all debug contributors. Runs after DisplaySystem in the Render phase. */\nexport class DebugRenderSystem extends System {\n readonly phase = Phase.Render;\n readonly priority = 9999;\n\n constructor(\n private readonly registry: DebugRegistryImpl,\n private readonly graphicsPool: GraphicsPool,\n private readonly textPool: TextPool,\n private readonly worldApi: WorldDebugApiImpl,\n private readonly hudApi: HudDebugApiImpl,\n private readonly stats: StatsStore,\n private readonly worldContainer: Container,\n private readonly hudContainer: Container,\n private readonly cameraAccessor: DebugCameraAccessor,\n ) {\n super();\n }\n\n update(dt: number): void {\n if (!this.registry.enabled) {\n this.worldContainer.visible = false;\n this.hudContainer.visible = false;\n return;\n }\n\n this.worldContainer.visible = true;\n this.hudContainer.visible = true;\n\n // Apply camera transform to the debug world container so that\n // world-space debug drawing (collision shapes, etc.) aligns with\n // the active scene's camera.\n this.syncWorldCamera();\n\n this.graphicsPool.resetFrame();\n this.textPool.resetFrame();\n\n for (const [name, contributor] of this.registry.contributors) {\n contributor.sample?.(this.stats, dt);\n\n if (contributor.drawWorld) {\n this.worldApi.setContributor(name);\n contributor.drawWorld(this.worldApi);\n }\n\n if (contributor.drawHud) {\n this.hudApi.setContributor(name);\n contributor.drawHud(this.hudApi);\n }\n }\n }\n\n private syncWorldCamera(): void {\n const cam = this.cameraAccessor.findCamera();\n if (!cam) {\n this.worldContainer.position.set(0, 0);\n this.worldContainer.scale.set(1, 1);\n this.worldContainer.rotation = 0;\n return;\n }\n\n const vw = this.cameraAccessor.viewportWidth;\n const vh = this.cameraAccessor.viewportHeight;\n const rotatedPos = cam.effectivePosition\n .scale(cam.zoom)\n .rotate(-cam.rotation);\n this.worldContainer.position.x = vw / 2 - rotatedPos.x;\n this.worldContainer.position.y = vh / 2 - rotatedPos.y;\n this.worldContainer.scale.set(cam.zoom);\n this.worldContainer.rotation = -cam.rotation;\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class FpsContributor implements DebugContributor {\n readonly name = \"fps\";\n readonly flags: readonly string[] = [];\n private stats: StatsApi | null = null;\n\n sample(stats: StatsApi, dt: number): void {\n this.stats = stats;\n if (dt > 0) stats.push(\"fps\", 1000 / dt);\n }\n\n drawHud(api: HudDebugApi): void {\n const avg = this.stats?.average(\"fps\") ?? 0;\n api.addLine(`FPS: ${Math.round(avg)}`);\n }\n}\n","import type { DebugContributor, HudDebugApi } from \"../types.js\";\nimport type { Inspector } from \"@yagejs/core\";\n\nexport class EntityCountContributor implements DebugContributor {\n readonly name = \"entities\";\n readonly flags: readonly string[] = [];\n\n constructor(private readonly inspector: Inspector) {}\n\n drawHud(api: HudDebugApi): void {\n const count = this.inspector.snapshot().entityCount;\n api.addLine(`Entities: ${count}`);\n }\n}\n","import type { DebugContributor, StatsApi, HudDebugApi } from \"../types.js\";\n\nexport class SystemTimingContributor implements DebugContributor {\n readonly name = \"timing\";\n readonly flags = [\"breakdown\"] as const;\n private stats: StatsApi | null = null;\n\n constructor(private readonly timings: Map<string, number>) {}\n\n sample(stats: StatsApi): void {\n this.stats = stats;\n for (const [name, ms] of this.timings) {\n stats.push(`system.${name}`, ms);\n }\n }\n\n drawHud(api: HudDebugApi): void {\n if (!this.stats) return;\n\n let total = 0;\n const entries: Array<[string, number]> = [];\n for (const name of this.timings.keys()) {\n const avg = this.stats.average(`system.${name}`);\n total += avg;\n entries.push([name, avg]);\n }\n\n api.addLine(`Systems: ${total.toFixed(2)}ms`);\n\n if (api.isFlagEnabled(\"breakdown\")) {\n entries.sort((a, b) => b[1] - a[1]);\n for (const [name, avg] of entries) {\n api.addLine(` ${name}: ${avg.toFixed(2)}ms`);\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yagejs/debug",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "FPS counter, entity inspector, and dev overlays for YAGE",
5
5
  "keywords": [
6
6
  "yage",
@@ -58,8 +58,8 @@
58
58
  "clean": "rm -rf dist"
59
59
  },
60
60
  "dependencies": {
61
- "@yagejs/core": "^0.1.0",
62
- "@yagejs/renderer": "^0.1.0",
61
+ "@yagejs/core": "^0.2.0",
62
+ "@yagejs/renderer": "^0.2.0",
63
63
  "pixi.js": "^8.5.0"
64
64
  }
65
65
  }