@yagejs/debug 0.2.0 → 0.4.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 +116 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -6
- package/dist/index.d.ts +37 -6
- package/dist/index.js +116 -83
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -40,42 +40,55 @@ var import_renderer3 = require("@yagejs/renderer");
|
|
|
40
40
|
|
|
41
41
|
// src/DebugClock.ts
|
|
42
42
|
var DebugClock = class {
|
|
43
|
-
constructor(
|
|
44
|
-
this.
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
gameLoop;
|
|
50
|
-
stopTicker;
|
|
51
|
-
startTicker;
|
|
52
|
-
render;
|
|
43
|
+
constructor(host) {
|
|
44
|
+
this.host = host;
|
|
45
|
+
this.deltaMs = host.fixedTimestep;
|
|
46
|
+
}
|
|
47
|
+
host;
|
|
53
48
|
static {
|
|
54
49
|
__name(this, "DebugClock");
|
|
55
50
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
_isFrozen = false;
|
|
52
|
+
deltaMs;
|
|
53
|
+
frame = 0;
|
|
54
|
+
get isFrozen() {
|
|
55
|
+
return this._isFrozen;
|
|
59
56
|
}
|
|
60
57
|
startAuto() {
|
|
61
|
-
if (!this.
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
58
|
+
if (!this._isFrozen) return;
|
|
59
|
+
this.host.thaw();
|
|
60
|
+
this._isFrozen = false;
|
|
64
61
|
}
|
|
65
62
|
stopAuto() {
|
|
66
|
-
if (this.
|
|
67
|
-
this.
|
|
68
|
-
this.
|
|
63
|
+
if (this._isFrozen) return;
|
|
64
|
+
this.host.freeze();
|
|
65
|
+
this._isFrozen = true;
|
|
66
|
+
}
|
|
67
|
+
freeze() {
|
|
68
|
+
this.stopAuto();
|
|
69
|
+
}
|
|
70
|
+
thaw() {
|
|
71
|
+
this.startAuto();
|
|
72
|
+
}
|
|
73
|
+
setDelta(ms) {
|
|
74
|
+
if (!Number.isFinite(ms) || ms <= 0) {
|
|
75
|
+
throw new Error("DebugClock.setDelta(ms) requires a positive number.");
|
|
76
|
+
}
|
|
77
|
+
this.deltaMs = ms;
|
|
78
|
+
}
|
|
79
|
+
getFrame() {
|
|
80
|
+
return this.frame;
|
|
69
81
|
}
|
|
70
82
|
step(dtMs) {
|
|
71
|
-
if (!this.
|
|
72
|
-
throw new Error(
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
if (!this._isFrozen) {
|
|
84
|
+
throw new Error("DebugClock is not frozen. Call clock.freeze() first.");
|
|
85
|
+
}
|
|
86
|
+
const dt = dtMs ?? this.deltaMs;
|
|
87
|
+
if (!Number.isFinite(dt) || dt <= 0) {
|
|
88
|
+
throw new Error("DebugClock.step(dtMs) requires a positive number.");
|
|
75
89
|
}
|
|
76
|
-
|
|
77
|
-
this.
|
|
78
|
-
this.render();
|
|
90
|
+
this.host.advance(dt);
|
|
91
|
+
this.frame++;
|
|
79
92
|
}
|
|
80
93
|
stepFrames(count, dtMs) {
|
|
81
94
|
if (!Number.isInteger(count) || count < 0) {
|
|
@@ -87,16 +100,6 @@ var DebugClock = class {
|
|
|
87
100
|
this.step(dtMs);
|
|
88
101
|
}
|
|
89
102
|
}
|
|
90
|
-
/** Enter or exit manual mode. Used by DebugPlugin for config-driven init. */
|
|
91
|
-
setManual(enabled) {
|
|
92
|
-
if (enabled === this._isManual) return;
|
|
93
|
-
if (enabled) {
|
|
94
|
-
this.stopTicker();
|
|
95
|
-
} else {
|
|
96
|
-
this.startTicker();
|
|
97
|
-
}
|
|
98
|
-
this._isManual = enabled;
|
|
99
|
-
}
|
|
100
103
|
};
|
|
101
104
|
|
|
102
105
|
// src/DebugRegistryImpl.ts
|
|
@@ -578,6 +581,9 @@ var DebugPlugin = class {
|
|
|
578
581
|
install(context) {
|
|
579
582
|
this.context = context;
|
|
580
583
|
this.renderer = context.resolve(import_renderer2.RendererKey);
|
|
584
|
+
if (this.config.deterministicSeed !== void 0) {
|
|
585
|
+
context.resolve(import_core4.InspectorKey).setDefaultSceneSeed(this.config.deterministicSeed);
|
|
586
|
+
}
|
|
581
587
|
this.registry = new DebugRegistryImpl();
|
|
582
588
|
this.registry.enabled = this.config.startEnabled ?? false;
|
|
583
589
|
if (this.config.flags) {
|
|
@@ -604,7 +610,7 @@ var DebugPlugin = class {
|
|
|
604
610
|
this.registry.toggle();
|
|
605
611
|
return;
|
|
606
612
|
}
|
|
607
|
-
if (e.code === stepKey && this.clock?.
|
|
613
|
+
if (e.code === stepKey && this.clock?.isFrozen) {
|
|
608
614
|
e.preventDefault();
|
|
609
615
|
this.clock.step();
|
|
610
616
|
}
|
|
@@ -629,18 +635,12 @@ var DebugPlugin = class {
|
|
|
629
635
|
this.registry.register(new SystemTimingContributor(this.systemTimings));
|
|
630
636
|
const gameLoop = this.context.resolve(import_core4.GameLoopKey);
|
|
631
637
|
const app = this.renderer.application;
|
|
632
|
-
this.clock = new DebugClock(
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
() => app.start(),
|
|
636
|
-
() => app.render()
|
|
637
|
-
);
|
|
638
|
-
if (this.config.manualClock) {
|
|
639
|
-
this.clock.setManual(true);
|
|
640
|
-
}
|
|
638
|
+
this.clock = new DebugClock(createPixiTickerHost(app, gameLoop.fixedTimestep));
|
|
639
|
+
inspector.attachTimeController(this.clock);
|
|
640
|
+
inspector.setEventLogEnabled(true);
|
|
641
641
|
this.attachToGlobal(this.clock);
|
|
642
642
|
this.provider = this.context.tryResolve(import_renderer3.SceneRenderTreeProviderKey) ?? null;
|
|
643
|
-
this.
|
|
643
|
+
this.registerInspectorDiagnostics();
|
|
644
644
|
await this.materializeDebugScene();
|
|
645
645
|
const bringToFront = /* @__PURE__ */ __name(() => {
|
|
646
646
|
if (this.debugScene && this.provider?.bringSceneToFront) {
|
|
@@ -665,6 +665,15 @@ var DebugPlugin = class {
|
|
|
665
665
|
this.keyListener = null;
|
|
666
666
|
}
|
|
667
667
|
this.detachFromGlobal();
|
|
668
|
+
const inspector = this.context.resolve(import_core4.InspectorKey);
|
|
669
|
+
inspector.removeExtension("debug");
|
|
670
|
+
if (this.clock) {
|
|
671
|
+
inspector.detachTimeController(this.clock);
|
|
672
|
+
}
|
|
673
|
+
inspector.setEventLogEnabled(false);
|
|
674
|
+
if (this.config.deterministicSeed !== void 0) {
|
|
675
|
+
inspector.setDefaultSceneSeed(void 0);
|
|
676
|
+
}
|
|
668
677
|
this.clock = null;
|
|
669
678
|
for (const contributor of this.registry.contributors.values()) {
|
|
670
679
|
contributor.dispose?.();
|
|
@@ -738,44 +747,42 @@ var DebugPlugin = class {
|
|
|
738
747
|
this.worldApi = null;
|
|
739
748
|
this.hudApi = null;
|
|
740
749
|
}
|
|
741
|
-
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
(
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
priority: cam.priority,
|
|
773
|
-
enabled: cam.enabled
|
|
774
|
-
});
|
|
750
|
+
registerInspectorDiagnostics() {
|
|
751
|
+
const diagnostics = {
|
|
752
|
+
getLayerTransform: /* @__PURE__ */ __name((sceneName, layerName) => {
|
|
753
|
+
const scene = this.sceneManager.all.find(
|
|
754
|
+
(candidate) => candidate.name === sceneName
|
|
755
|
+
);
|
|
756
|
+
if (!scene) return void 0;
|
|
757
|
+
const layer = this.provider?.getTree(scene)?.tryGet(layerName);
|
|
758
|
+
if (!layer) return void 0;
|
|
759
|
+
const container = layer.container;
|
|
760
|
+
return {
|
|
761
|
+
x: container.position.x,
|
|
762
|
+
y: container.position.y,
|
|
763
|
+
scaleX: container.scale.x,
|
|
764
|
+
scaleY: container.scale.y,
|
|
765
|
+
rotation: container.rotation
|
|
766
|
+
};
|
|
767
|
+
}, "getLayerTransform"),
|
|
768
|
+
getCameraStack: /* @__PURE__ */ __name(() => {
|
|
769
|
+
const cameras = [];
|
|
770
|
+
for (const scene of this.sceneManager.all) {
|
|
771
|
+
for (const entity of scene.getEntities()) {
|
|
772
|
+
const cam = entity.tryGet(import_renderer2.CameraComponent);
|
|
773
|
+
if (!cam) continue;
|
|
774
|
+
cameras.push({
|
|
775
|
+
scene: scene.name,
|
|
776
|
+
name: cam.cameraName,
|
|
777
|
+
priority: cam.priority,
|
|
778
|
+
enabled: cam.enabled
|
|
779
|
+
});
|
|
780
|
+
}
|
|
775
781
|
}
|
|
776
|
-
|
|
777
|
-
|
|
782
|
+
return cameras;
|
|
783
|
+
}, "getCameraStack")
|
|
778
784
|
};
|
|
785
|
+
this.context.resolve(import_core4.InspectorKey).addExtension("debug", diagnostics);
|
|
779
786
|
}
|
|
780
787
|
attachToGlobal(clock) {
|
|
781
788
|
const g = globalThis["__yage__"];
|
|
@@ -790,6 +797,32 @@ var DebugPlugin = class {
|
|
|
790
797
|
}
|
|
791
798
|
}
|
|
792
799
|
};
|
|
800
|
+
function createPixiTickerHost(app, fixedTimestep) {
|
|
801
|
+
let syntheticTime = 0;
|
|
802
|
+
let savedMinFPS = null;
|
|
803
|
+
return {
|
|
804
|
+
fixedTimestep,
|
|
805
|
+
freeze() {
|
|
806
|
+
app.stop();
|
|
807
|
+
syntheticTime = 0;
|
|
808
|
+
app.ticker.lastTime = 0;
|
|
809
|
+
savedMinFPS = app.ticker.minFPS;
|
|
810
|
+
app.ticker.minFPS = 0;
|
|
811
|
+
},
|
|
812
|
+
thaw() {
|
|
813
|
+
if (savedMinFPS !== null) {
|
|
814
|
+
app.ticker.minFPS = savedMinFPS;
|
|
815
|
+
savedMinFPS = null;
|
|
816
|
+
}
|
|
817
|
+
app.start();
|
|
818
|
+
},
|
|
819
|
+
advance(dtMs) {
|
|
820
|
+
syntheticTime += dtMs;
|
|
821
|
+
app.ticker.update(syntheticTime);
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
__name(createPixiTickerHost, "createPixiTickerHost");
|
|
793
826
|
function findTopmostCamera(sceneManager) {
|
|
794
827
|
const stack = sceneManager.all;
|
|
795
828
|
for (let i = stack.length - 1; i >= 0; i--) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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":"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","names":["import_core","import_renderer","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 {\n DebugConfig,\n DebugDiagnostics,\n LayerTransformSnapshot,\n CameraStackSnapshot,\n} 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 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 { Application, Container } from \"pixi.js\";\nimport { DebugClock } from \"./DebugClock.js\";\nimport type { DebugClockHost, 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 /** Key code to advance one fixed-timestep frame while the debug clock is frozen. 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 * If set, every scene's RNG is initialized with this seed instead of an\n * unspecified default. Use for deterministic E2E runs. Leave undefined for\n * normal debug builds so randomness behaves the same as in production.\n */\n deterministicSeed?: number;\n}\n\nexport interface LayerTransformSnapshot {\n x: number;\n y: number;\n scaleX: number;\n scaleY: number;\n rotation: number;\n}\n\nexport interface CameraStackSnapshot {\n scene: string;\n name: string | undefined;\n priority: number;\n enabled: boolean;\n}\n\n/**\n * Renderer-aware diagnostics exposed through the inspector extension\n * namespace `debug`. Kept out of the core Inspector surface so the core\n * package stays renderer-agnostic while plugins can still publish optional\n * runtime helpers in a uniform way.\n */\nexport interface DebugDiagnostics {\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 if (this.config.deterministicSeed !== undefined) {\n context\n .resolve(InspectorKey)\n .setDefaultSceneSeed(this.config.deterministicSeed);\n }\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?.isFrozen) {\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. The host drives `app.ticker`\n // directly so a manual `step()` fires every ticker subscriber\n // (AnimatedSprite, pixi-filters, render, user `app.ticker.add` callbacks)\n // with the same synthetic dt as gameplay state.\n const gameLoop = this.context.resolve(GameLoopKey);\n const app = this.renderer.application;\n this.clock = new DebugClock(createPixiTickerHost(app, gameLoop.fixedTimestep));\n inspector.attachTimeController(this.clock);\n inspector.setEventLogEnabled(true);\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.registerInspectorDiagnostics();\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 const inspector = this.context.resolve(InspectorKey);\n inspector.removeExtension(\"debug\");\n // Only detach our own clock — passing undefined would clear whatever\n // controller is registered, which could belong to another plugin if\n // onDestroy runs after a failed onStart.\n if (this.clock) {\n inspector.detachTimeController(this.clock);\n }\n inspector.setEventLogEnabled(false);\n if (this.config.deterministicSeed !== undefined) {\n inspector.setDefaultSceneSeed(undefined);\n }\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 registerInspectorDiagnostics(): void {\n const diagnostics: DebugDiagnostics = {\n 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 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 this.context.resolve(InspectorKey).addExtension(\"debug\", diagnostics);\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 * Wire a `DebugClockHost` against a Pixi v8 `Application`. Driving\n * `app.ticker.update(syntheticTime)` while the ticker is stopped fires every\n * subscriber — Pixi's `Ticker.update` doesn't gate on `started`, only the\n * rAF-driven `_tick` does — so a single advance replaces the old\n * `gameLoop.tick(dt)` + `app.render()` quad and along the way fixes the\n * AnimatedSprite / pixi-filters / `app.ticker.add` subscriber freeze.\n */\nfunction createPixiTickerHost(\n app: Application,\n fixedTimestep: number,\n): DebugClockHost {\n let syntheticTime = 0;\n let savedMinFPS: number | null = null;\n return {\n fixedTimestep,\n freeze(): void {\n app.stop();\n // Reset both to zero so synthetic time starts from a clean origin\n // and `(syntheticTime + dt) - syntheticTime` stays an exact `dt`\n // — keeps deltaMS deterministic regardless of how long the page\n // ran in auto mode before the freeze.\n syntheticTime = 0;\n app.ticker.lastTime = 0;\n // Default minFPS=10 clamps deltaMS at 100ms — `step(200)` would\n // silently see deltaMS=100. Disable for the duration of the freeze.\n savedMinFPS = app.ticker.minFPS;\n app.ticker.minFPS = 0;\n },\n thaw(): void {\n if (savedMinFPS !== null) {\n app.ticker.minFPS = savedMinFPS;\n savedMinFPS = null;\n }\n // `app.start()` calls `Ticker._requestIfNeeded` which resets\n // `lastTime` to `performance.now()` itself, so the next rAF\n // doesn't see `realNow - 0` as a giant first-frame delta. No\n // need to set it manually here.\n app.start();\n },\n advance(dtMs: number): void {\n syntheticTime += dtMs;\n app.ticker.update(syntheticTime);\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 isFrozen: boolean;\n startAuto(): void;\n stopAuto(): void;\n step(dtMs?: number): void;\n stepFrames(count: number, dtMs?: number): void;\n freeze(): void;\n thaw(): void;\n setDelta(ms: number): void;\n getFrame(): number;\n}\n\n/**\n * Hooks the clock uses to drive the host. The host owns the synthetic-time\n * bookkeeping and the ticker plumbing — `DebugClock` stays a pure state\n * machine. Production wires this against Pixi's `app.ticker` so a manual\n * `step()` fires every ticker subscriber (GameLoop, AnimatedSprite,\n * pixi-filters, render) with the same synthetic dt.\n */\nexport interface DebugClockHost {\n readonly fixedTimestep: number;\n /** Advance one synthetic frame of `dtMs`. Fires every ticker subscriber. */\n advance(dtMs: number): void;\n /** Stop auto-advance. Capture state needed to make `advance` deterministic. */\n freeze(): void;\n /** Resume auto-advance. Restore captured state so the next rAF is sane. */\n thaw(): void;\n}\n\n/**\n * Controls engine time-stepping for deterministic E2E tests.\n *\n * While frozen the renderer ticker is paused and frames advance only via\n * explicit `step()` / `stepFrames()` calls. `freeze()` / `thaw()` and\n * `startAuto()` / `stopAuto()` are equivalent verbs for the same toggle.\n */\nexport class DebugClock implements IDebugClock {\n private _isFrozen = false;\n private deltaMs: number;\n private frame = 0;\n\n constructor(private readonly host: DebugClockHost) {\n this.deltaMs = host.fixedTimestep;\n }\n\n get isFrozen(): boolean {\n return this._isFrozen;\n }\n\n startAuto(): void {\n if (!this._isFrozen) return;\n this.host.thaw();\n this._isFrozen = false;\n }\n\n stopAuto(): void {\n if (this._isFrozen) return;\n this.host.freeze();\n this._isFrozen = true;\n }\n\n freeze(): void {\n this.stopAuto();\n }\n\n thaw(): void {\n this.startAuto();\n }\n\n setDelta(ms: number): void {\n if (!Number.isFinite(ms) || ms <= 0) {\n throw new Error(\"DebugClock.setDelta(ms) requires a positive number.\");\n }\n this.deltaMs = ms;\n }\n\n getFrame(): number {\n return this.frame;\n }\n\n step(dtMs?: number): void {\n if (!this._isFrozen) {\n throw new Error(\"DebugClock is not frozen. Call clock.freeze() first.\");\n }\n const dt = dtMs ?? this.deltaMs;\n if (!Number.isFinite(dt) || dt <= 0) {\n throw new Error(\"DebugClock.step(dtMs) requires a positive number.\");\n }\n // Increment after a successful advance — if a ticker subscriber throws\n // (system exception, render failure) the frame counter shouldn't advance\n // ahead of state.\n this.host.advance(dt);\n this.frame++;\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","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":["import_core","import_renderer","import_core","import_pixi","import_core"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -5,9 +5,7 @@ import { DebugRegistry, DebugContributor, StatsApi } from './api.cjs';
|
|
|
5
5
|
interface DebugConfig {
|
|
6
6
|
/** Key code to toggle debug overlay. Default: "Backquote" */
|
|
7
7
|
toggleKey?: string;
|
|
8
|
-
/**
|
|
9
|
-
manualClock?: boolean;
|
|
10
|
-
/** Key code to advance one fixed-timestep frame while manual clock mode is active. Default: "Period" */
|
|
8
|
+
/** Key code to advance one fixed-timestep frame while the debug clock is frozen. Default: "Period" */
|
|
11
9
|
stepKey?: string;
|
|
12
10
|
/** Max pooled Graphics objects. Default: 256 */
|
|
13
11
|
maxGraphics?: number;
|
|
@@ -17,6 +15,35 @@ interface DebugConfig {
|
|
|
17
15
|
startEnabled?: boolean;
|
|
18
16
|
/** Initial flag overrides, keyed by "contributorName.flagName". */
|
|
19
17
|
flags?: Record<string, boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* If set, every scene's RNG is initialized with this seed instead of an
|
|
20
|
+
* unspecified default. Use for deterministic E2E runs. Leave undefined for
|
|
21
|
+
* normal debug builds so randomness behaves the same as in production.
|
|
22
|
+
*/
|
|
23
|
+
deterministicSeed?: number;
|
|
24
|
+
}
|
|
25
|
+
interface LayerTransformSnapshot {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
scaleX: number;
|
|
29
|
+
scaleY: number;
|
|
30
|
+
rotation: number;
|
|
31
|
+
}
|
|
32
|
+
interface CameraStackSnapshot {
|
|
33
|
+
scene: string;
|
|
34
|
+
name: string | undefined;
|
|
35
|
+
priority: number;
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Renderer-aware diagnostics exposed through the inspector extension
|
|
40
|
+
* namespace `debug`. Kept out of the core Inspector surface so the core
|
|
41
|
+
* package stays renderer-agnostic while plugins can still publish optional
|
|
42
|
+
* runtime helpers in a uniform way.
|
|
43
|
+
*/
|
|
44
|
+
interface DebugDiagnostics {
|
|
45
|
+
getLayerTransform(sceneName: string, layerName: string): LayerTransformSnapshot | undefined;
|
|
46
|
+
getCameraStack(): CameraStackSnapshot[];
|
|
20
47
|
}
|
|
21
48
|
/**
|
|
22
49
|
* Debug overlay plugin. Mounts a private `DebugScene` through
|
|
@@ -57,18 +84,22 @@ declare class DebugPlugin implements Plugin {
|
|
|
57
84
|
private findActiveCamera;
|
|
58
85
|
private setUpDebugInfra;
|
|
59
86
|
private tearDownDebugInfra;
|
|
60
|
-
private
|
|
87
|
+
private registerInspectorDiagnostics;
|
|
61
88
|
private attachToGlobal;
|
|
62
89
|
private detachFromGlobal;
|
|
63
90
|
}
|
|
64
91
|
|
|
65
92
|
/** Public interface for the manual debug clock, accessible via `window.__yage__.clock`. */
|
|
66
93
|
interface IDebugClock {
|
|
67
|
-
readonly
|
|
94
|
+
readonly isFrozen: boolean;
|
|
68
95
|
startAuto(): void;
|
|
69
96
|
stopAuto(): void;
|
|
70
97
|
step(dtMs?: number): void;
|
|
71
98
|
stepFrames(count: number, dtMs?: number): void;
|
|
99
|
+
freeze(): void;
|
|
100
|
+
thaw(): void;
|
|
101
|
+
setDelta(ms: number): void;
|
|
102
|
+
getFrame(): number;
|
|
72
103
|
}
|
|
73
104
|
|
|
74
105
|
/** Concrete implementation of the DebugRegistry interface. */
|
|
@@ -94,4 +125,4 @@ declare class StatsStore implements StatsApi {
|
|
|
94
125
|
max(key: string): number;
|
|
95
126
|
}
|
|
96
127
|
|
|
97
|
-
export { type DebugConfig, DebugPlugin, DebugRegistryImpl, type IDebugClock, StatsStore };
|
|
128
|
+
export { type CameraStackSnapshot, type DebugConfig, type DebugDiagnostics, DebugPlugin, DebugRegistryImpl, type IDebugClock, type LayerTransformSnapshot, StatsStore };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,9 +5,7 @@ import { DebugRegistry, DebugContributor, StatsApi } from './api.js';
|
|
|
5
5
|
interface DebugConfig {
|
|
6
6
|
/** Key code to toggle debug overlay. Default: "Backquote" */
|
|
7
7
|
toggleKey?: string;
|
|
8
|
-
/**
|
|
9
|
-
manualClock?: boolean;
|
|
10
|
-
/** Key code to advance one fixed-timestep frame while manual clock mode is active. Default: "Period" */
|
|
8
|
+
/** Key code to advance one fixed-timestep frame while the debug clock is frozen. Default: "Period" */
|
|
11
9
|
stepKey?: string;
|
|
12
10
|
/** Max pooled Graphics objects. Default: 256 */
|
|
13
11
|
maxGraphics?: number;
|
|
@@ -17,6 +15,35 @@ interface DebugConfig {
|
|
|
17
15
|
startEnabled?: boolean;
|
|
18
16
|
/** Initial flag overrides, keyed by "contributorName.flagName". */
|
|
19
17
|
flags?: Record<string, boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* If set, every scene's RNG is initialized with this seed instead of an
|
|
20
|
+
* unspecified default. Use for deterministic E2E runs. Leave undefined for
|
|
21
|
+
* normal debug builds so randomness behaves the same as in production.
|
|
22
|
+
*/
|
|
23
|
+
deterministicSeed?: number;
|
|
24
|
+
}
|
|
25
|
+
interface LayerTransformSnapshot {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
scaleX: number;
|
|
29
|
+
scaleY: number;
|
|
30
|
+
rotation: number;
|
|
31
|
+
}
|
|
32
|
+
interface CameraStackSnapshot {
|
|
33
|
+
scene: string;
|
|
34
|
+
name: string | undefined;
|
|
35
|
+
priority: number;
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Renderer-aware diagnostics exposed through the inspector extension
|
|
40
|
+
* namespace `debug`. Kept out of the core Inspector surface so the core
|
|
41
|
+
* package stays renderer-agnostic while plugins can still publish optional
|
|
42
|
+
* runtime helpers in a uniform way.
|
|
43
|
+
*/
|
|
44
|
+
interface DebugDiagnostics {
|
|
45
|
+
getLayerTransform(sceneName: string, layerName: string): LayerTransformSnapshot | undefined;
|
|
46
|
+
getCameraStack(): CameraStackSnapshot[];
|
|
20
47
|
}
|
|
21
48
|
/**
|
|
22
49
|
* Debug overlay plugin. Mounts a private `DebugScene` through
|
|
@@ -57,18 +84,22 @@ declare class DebugPlugin implements Plugin {
|
|
|
57
84
|
private findActiveCamera;
|
|
58
85
|
private setUpDebugInfra;
|
|
59
86
|
private tearDownDebugInfra;
|
|
60
|
-
private
|
|
87
|
+
private registerInspectorDiagnostics;
|
|
61
88
|
private attachToGlobal;
|
|
62
89
|
private detachFromGlobal;
|
|
63
90
|
}
|
|
64
91
|
|
|
65
92
|
/** Public interface for the manual debug clock, accessible via `window.__yage__.clock`. */
|
|
66
93
|
interface IDebugClock {
|
|
67
|
-
readonly
|
|
94
|
+
readonly isFrozen: boolean;
|
|
68
95
|
startAuto(): void;
|
|
69
96
|
stopAuto(): void;
|
|
70
97
|
step(dtMs?: number): void;
|
|
71
98
|
stepFrames(count: number, dtMs?: number): void;
|
|
99
|
+
freeze(): void;
|
|
100
|
+
thaw(): void;
|
|
101
|
+
setDelta(ms: number): void;
|
|
102
|
+
getFrame(): number;
|
|
72
103
|
}
|
|
73
104
|
|
|
74
105
|
/** Concrete implementation of the DebugRegistry interface. */
|
|
@@ -94,4 +125,4 @@ declare class StatsStore implements StatsApi {
|
|
|
94
125
|
max(key: string): number;
|
|
95
126
|
}
|
|
96
127
|
|
|
97
|
-
export { type DebugConfig, DebugPlugin, DebugRegistryImpl, type IDebugClock, StatsStore };
|
|
128
|
+
export { type CameraStackSnapshot, type DebugConfig, type DebugDiagnostics, DebugPlugin, DebugRegistryImpl, type IDebugClock, type LayerTransformSnapshot, StatsStore };
|
package/dist/index.js
CHANGED
|
@@ -15,42 +15,55 @@ import { SceneRenderTreeProviderKey } from "@yagejs/renderer";
|
|
|
15
15
|
|
|
16
16
|
// src/DebugClock.ts
|
|
17
17
|
var DebugClock = class {
|
|
18
|
-
constructor(
|
|
19
|
-
this.
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
gameLoop;
|
|
25
|
-
stopTicker;
|
|
26
|
-
startTicker;
|
|
27
|
-
render;
|
|
18
|
+
constructor(host) {
|
|
19
|
+
this.host = host;
|
|
20
|
+
this.deltaMs = host.fixedTimestep;
|
|
21
|
+
}
|
|
22
|
+
host;
|
|
28
23
|
static {
|
|
29
24
|
__name(this, "DebugClock");
|
|
30
25
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
_isFrozen = false;
|
|
27
|
+
deltaMs;
|
|
28
|
+
frame = 0;
|
|
29
|
+
get isFrozen() {
|
|
30
|
+
return this._isFrozen;
|
|
34
31
|
}
|
|
35
32
|
startAuto() {
|
|
36
|
-
if (!this.
|
|
37
|
-
this.
|
|
38
|
-
this.
|
|
33
|
+
if (!this._isFrozen) return;
|
|
34
|
+
this.host.thaw();
|
|
35
|
+
this._isFrozen = false;
|
|
39
36
|
}
|
|
40
37
|
stopAuto() {
|
|
41
|
-
if (this.
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
38
|
+
if (this._isFrozen) return;
|
|
39
|
+
this.host.freeze();
|
|
40
|
+
this._isFrozen = true;
|
|
41
|
+
}
|
|
42
|
+
freeze() {
|
|
43
|
+
this.stopAuto();
|
|
44
|
+
}
|
|
45
|
+
thaw() {
|
|
46
|
+
this.startAuto();
|
|
47
|
+
}
|
|
48
|
+
setDelta(ms) {
|
|
49
|
+
if (!Number.isFinite(ms) || ms <= 0) {
|
|
50
|
+
throw new Error("DebugClock.setDelta(ms) requires a positive number.");
|
|
51
|
+
}
|
|
52
|
+
this.deltaMs = ms;
|
|
53
|
+
}
|
|
54
|
+
getFrame() {
|
|
55
|
+
return this.frame;
|
|
44
56
|
}
|
|
45
57
|
step(dtMs) {
|
|
46
|
-
if (!this.
|
|
47
|
-
throw new Error(
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
if (!this._isFrozen) {
|
|
59
|
+
throw new Error("DebugClock is not frozen. Call clock.freeze() first.");
|
|
60
|
+
}
|
|
61
|
+
const dt = dtMs ?? this.deltaMs;
|
|
62
|
+
if (!Number.isFinite(dt) || dt <= 0) {
|
|
63
|
+
throw new Error("DebugClock.step(dtMs) requires a positive number.");
|
|
50
64
|
}
|
|
51
|
-
|
|
52
|
-
this.
|
|
53
|
-
this.render();
|
|
65
|
+
this.host.advance(dt);
|
|
66
|
+
this.frame++;
|
|
54
67
|
}
|
|
55
68
|
stepFrames(count, dtMs) {
|
|
56
69
|
if (!Number.isInteger(count) || count < 0) {
|
|
@@ -62,16 +75,6 @@ var DebugClock = class {
|
|
|
62
75
|
this.step(dtMs);
|
|
63
76
|
}
|
|
64
77
|
}
|
|
65
|
-
/** Enter or exit manual mode. Used by DebugPlugin for config-driven init. */
|
|
66
|
-
setManual(enabled) {
|
|
67
|
-
if (enabled === this._isManual) return;
|
|
68
|
-
if (enabled) {
|
|
69
|
-
this.stopTicker();
|
|
70
|
-
} else {
|
|
71
|
-
this.startTicker();
|
|
72
|
-
}
|
|
73
|
-
this._isManual = enabled;
|
|
74
|
-
}
|
|
75
78
|
};
|
|
76
79
|
|
|
77
80
|
// src/DebugRegistryImpl.ts
|
|
@@ -553,6 +556,9 @@ var DebugPlugin = class {
|
|
|
553
556
|
install(context) {
|
|
554
557
|
this.context = context;
|
|
555
558
|
this.renderer = context.resolve(RendererKey);
|
|
559
|
+
if (this.config.deterministicSeed !== void 0) {
|
|
560
|
+
context.resolve(InspectorKey).setDefaultSceneSeed(this.config.deterministicSeed);
|
|
561
|
+
}
|
|
556
562
|
this.registry = new DebugRegistryImpl();
|
|
557
563
|
this.registry.enabled = this.config.startEnabled ?? false;
|
|
558
564
|
if (this.config.flags) {
|
|
@@ -579,7 +585,7 @@ var DebugPlugin = class {
|
|
|
579
585
|
this.registry.toggle();
|
|
580
586
|
return;
|
|
581
587
|
}
|
|
582
|
-
if (e.code === stepKey && this.clock?.
|
|
588
|
+
if (e.code === stepKey && this.clock?.isFrozen) {
|
|
583
589
|
e.preventDefault();
|
|
584
590
|
this.clock.step();
|
|
585
591
|
}
|
|
@@ -604,18 +610,12 @@ var DebugPlugin = class {
|
|
|
604
610
|
this.registry.register(new SystemTimingContributor(this.systemTimings));
|
|
605
611
|
const gameLoop = this.context.resolve(GameLoopKey);
|
|
606
612
|
const app = this.renderer.application;
|
|
607
|
-
this.clock = new DebugClock(
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
() => app.start(),
|
|
611
|
-
() => app.render()
|
|
612
|
-
);
|
|
613
|
-
if (this.config.manualClock) {
|
|
614
|
-
this.clock.setManual(true);
|
|
615
|
-
}
|
|
613
|
+
this.clock = new DebugClock(createPixiTickerHost(app, gameLoop.fixedTimestep));
|
|
614
|
+
inspector.attachTimeController(this.clock);
|
|
615
|
+
inspector.setEventLogEnabled(true);
|
|
616
616
|
this.attachToGlobal(this.clock);
|
|
617
617
|
this.provider = this.context.tryResolve(SceneRenderTreeProviderKey) ?? null;
|
|
618
|
-
this.
|
|
618
|
+
this.registerInspectorDiagnostics();
|
|
619
619
|
await this.materializeDebugScene();
|
|
620
620
|
const bringToFront = /* @__PURE__ */ __name(() => {
|
|
621
621
|
if (this.debugScene && this.provider?.bringSceneToFront) {
|
|
@@ -640,6 +640,15 @@ var DebugPlugin = class {
|
|
|
640
640
|
this.keyListener = null;
|
|
641
641
|
}
|
|
642
642
|
this.detachFromGlobal();
|
|
643
|
+
const inspector = this.context.resolve(InspectorKey);
|
|
644
|
+
inspector.removeExtension("debug");
|
|
645
|
+
if (this.clock) {
|
|
646
|
+
inspector.detachTimeController(this.clock);
|
|
647
|
+
}
|
|
648
|
+
inspector.setEventLogEnabled(false);
|
|
649
|
+
if (this.config.deterministicSeed !== void 0) {
|
|
650
|
+
inspector.setDefaultSceneSeed(void 0);
|
|
651
|
+
}
|
|
643
652
|
this.clock = null;
|
|
644
653
|
for (const contributor of this.registry.contributors.values()) {
|
|
645
654
|
contributor.dispose?.();
|
|
@@ -713,44 +722,42 @@ var DebugPlugin = class {
|
|
|
713
722
|
this.worldApi = null;
|
|
714
723
|
this.hudApi = null;
|
|
715
724
|
}
|
|
716
|
-
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
(
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
priority: cam.priority,
|
|
748
|
-
enabled: cam.enabled
|
|
749
|
-
});
|
|
725
|
+
registerInspectorDiagnostics() {
|
|
726
|
+
const diagnostics = {
|
|
727
|
+
getLayerTransform: /* @__PURE__ */ __name((sceneName, layerName) => {
|
|
728
|
+
const scene = this.sceneManager.all.find(
|
|
729
|
+
(candidate) => candidate.name === sceneName
|
|
730
|
+
);
|
|
731
|
+
if (!scene) return void 0;
|
|
732
|
+
const layer = this.provider?.getTree(scene)?.tryGet(layerName);
|
|
733
|
+
if (!layer) return void 0;
|
|
734
|
+
const container = layer.container;
|
|
735
|
+
return {
|
|
736
|
+
x: container.position.x,
|
|
737
|
+
y: container.position.y,
|
|
738
|
+
scaleX: container.scale.x,
|
|
739
|
+
scaleY: container.scale.y,
|
|
740
|
+
rotation: container.rotation
|
|
741
|
+
};
|
|
742
|
+
}, "getLayerTransform"),
|
|
743
|
+
getCameraStack: /* @__PURE__ */ __name(() => {
|
|
744
|
+
const cameras = [];
|
|
745
|
+
for (const scene of this.sceneManager.all) {
|
|
746
|
+
for (const entity of scene.getEntities()) {
|
|
747
|
+
const cam = entity.tryGet(CameraComponent);
|
|
748
|
+
if (!cam) continue;
|
|
749
|
+
cameras.push({
|
|
750
|
+
scene: scene.name,
|
|
751
|
+
name: cam.cameraName,
|
|
752
|
+
priority: cam.priority,
|
|
753
|
+
enabled: cam.enabled
|
|
754
|
+
});
|
|
755
|
+
}
|
|
750
756
|
}
|
|
751
|
-
|
|
752
|
-
|
|
757
|
+
return cameras;
|
|
758
|
+
}, "getCameraStack")
|
|
753
759
|
};
|
|
760
|
+
this.context.resolve(InspectorKey).addExtension("debug", diagnostics);
|
|
754
761
|
}
|
|
755
762
|
attachToGlobal(clock) {
|
|
756
763
|
const g = globalThis["__yage__"];
|
|
@@ -765,6 +772,32 @@ var DebugPlugin = class {
|
|
|
765
772
|
}
|
|
766
773
|
}
|
|
767
774
|
};
|
|
775
|
+
function createPixiTickerHost(app, fixedTimestep) {
|
|
776
|
+
let syntheticTime = 0;
|
|
777
|
+
let savedMinFPS = null;
|
|
778
|
+
return {
|
|
779
|
+
fixedTimestep,
|
|
780
|
+
freeze() {
|
|
781
|
+
app.stop();
|
|
782
|
+
syntheticTime = 0;
|
|
783
|
+
app.ticker.lastTime = 0;
|
|
784
|
+
savedMinFPS = app.ticker.minFPS;
|
|
785
|
+
app.ticker.minFPS = 0;
|
|
786
|
+
},
|
|
787
|
+
thaw() {
|
|
788
|
+
if (savedMinFPS !== null) {
|
|
789
|
+
app.ticker.minFPS = savedMinFPS;
|
|
790
|
+
savedMinFPS = null;
|
|
791
|
+
}
|
|
792
|
+
app.start();
|
|
793
|
+
},
|
|
794
|
+
advance(dtMs) {
|
|
795
|
+
syntheticTime += dtMs;
|
|
796
|
+
app.ticker.update(syntheticTime);
|
|
797
|
+
}
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
__name(createPixiTickerHost, "createPixiTickerHost");
|
|
768
801
|
function findTopmostCamera(sceneManager) {
|
|
769
802
|
const stack = sceneManager.all;
|
|
770
803
|
for (let i = stack.length - 1; i >= 0; i--) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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":";;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYP,SAAS,iBAAiB,mBAAmB;AAE7C,SAAS,kCAAkC;;;ACEpC,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,SAAS,WAAW,aAAa;AAGjC,SAAS,0BAA0B;AAY5B,IAAM,aAAN,cAAyB,MAAM;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,kBAAkB;AACnD,QAAI,CAAC,MAAM;AAKT,YAAM,SAAS,KAAK,QAAQ,WAAW,SAAS;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,SAAS,gBAA2B;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,SAAS;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,SAAS,YAAuB;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,KAAK;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,SAAS,QAAQ,aAAa;AAiBvB,IAAM,oBAAN,cAAgC,OAAO;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,MAAM;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;;;AZ8CO,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,WAAW;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,eAAe;AACxD,UAAM,MAAM,KAAK,QAAQ,QAAQ,WAAW;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,YAAY;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,WAAW;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,0BAA0B,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,eAAe;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,eAAe;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":[]}
|
|
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 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 { Application, Container } from \"pixi.js\";\nimport { DebugClock } from \"./DebugClock.js\";\nimport type { DebugClockHost, 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 /** Key code to advance one fixed-timestep frame while the debug clock is frozen. 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 * If set, every scene's RNG is initialized with this seed instead of an\n * unspecified default. Use for deterministic E2E runs. Leave undefined for\n * normal debug builds so randomness behaves the same as in production.\n */\n deterministicSeed?: number;\n}\n\nexport interface LayerTransformSnapshot {\n x: number;\n y: number;\n scaleX: number;\n scaleY: number;\n rotation: number;\n}\n\nexport interface CameraStackSnapshot {\n scene: string;\n name: string | undefined;\n priority: number;\n enabled: boolean;\n}\n\n/**\n * Renderer-aware diagnostics exposed through the inspector extension\n * namespace `debug`. Kept out of the core Inspector surface so the core\n * package stays renderer-agnostic while plugins can still publish optional\n * runtime helpers in a uniform way.\n */\nexport interface DebugDiagnostics {\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 if (this.config.deterministicSeed !== undefined) {\n context\n .resolve(InspectorKey)\n .setDefaultSceneSeed(this.config.deterministicSeed);\n }\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?.isFrozen) {\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. The host drives `app.ticker`\n // directly so a manual `step()` fires every ticker subscriber\n // (AnimatedSprite, pixi-filters, render, user `app.ticker.add` callbacks)\n // with the same synthetic dt as gameplay state.\n const gameLoop = this.context.resolve(GameLoopKey);\n const app = this.renderer.application;\n this.clock = new DebugClock(createPixiTickerHost(app, gameLoop.fixedTimestep));\n inspector.attachTimeController(this.clock);\n inspector.setEventLogEnabled(true);\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.registerInspectorDiagnostics();\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 const inspector = this.context.resolve(InspectorKey);\n inspector.removeExtension(\"debug\");\n // Only detach our own clock — passing undefined would clear whatever\n // controller is registered, which could belong to another plugin if\n // onDestroy runs after a failed onStart.\n if (this.clock) {\n inspector.detachTimeController(this.clock);\n }\n inspector.setEventLogEnabled(false);\n if (this.config.deterministicSeed !== undefined) {\n inspector.setDefaultSceneSeed(undefined);\n }\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 registerInspectorDiagnostics(): void {\n const diagnostics: DebugDiagnostics = {\n 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 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 this.context.resolve(InspectorKey).addExtension(\"debug\", diagnostics);\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 * Wire a `DebugClockHost` against a Pixi v8 `Application`. Driving\n * `app.ticker.update(syntheticTime)` while the ticker is stopped fires every\n * subscriber — Pixi's `Ticker.update` doesn't gate on `started`, only the\n * rAF-driven `_tick` does — so a single advance replaces the old\n * `gameLoop.tick(dt)` + `app.render()` quad and along the way fixes the\n * AnimatedSprite / pixi-filters / `app.ticker.add` subscriber freeze.\n */\nfunction createPixiTickerHost(\n app: Application,\n fixedTimestep: number,\n): DebugClockHost {\n let syntheticTime = 0;\n let savedMinFPS: number | null = null;\n return {\n fixedTimestep,\n freeze(): void {\n app.stop();\n // Reset both to zero so synthetic time starts from a clean origin\n // and `(syntheticTime + dt) - syntheticTime` stays an exact `dt`\n // — keeps deltaMS deterministic regardless of how long the page\n // ran in auto mode before the freeze.\n syntheticTime = 0;\n app.ticker.lastTime = 0;\n // Default minFPS=10 clamps deltaMS at 100ms — `step(200)` would\n // silently see deltaMS=100. Disable for the duration of the freeze.\n savedMinFPS = app.ticker.minFPS;\n app.ticker.minFPS = 0;\n },\n thaw(): void {\n if (savedMinFPS !== null) {\n app.ticker.minFPS = savedMinFPS;\n savedMinFPS = null;\n }\n // `app.start()` calls `Ticker._requestIfNeeded` which resets\n // `lastTime` to `performance.now()` itself, so the next rAF\n // doesn't see `realNow - 0` as a giant first-frame delta. No\n // need to set it manually here.\n app.start();\n },\n advance(dtMs: number): void {\n syntheticTime += dtMs;\n app.ticker.update(syntheticTime);\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 isFrozen: boolean;\n startAuto(): void;\n stopAuto(): void;\n step(dtMs?: number): void;\n stepFrames(count: number, dtMs?: number): void;\n freeze(): void;\n thaw(): void;\n setDelta(ms: number): void;\n getFrame(): number;\n}\n\n/**\n * Hooks the clock uses to drive the host. The host owns the synthetic-time\n * bookkeeping and the ticker plumbing — `DebugClock` stays a pure state\n * machine. Production wires this against Pixi's `app.ticker` so a manual\n * `step()` fires every ticker subscriber (GameLoop, AnimatedSprite,\n * pixi-filters, render) with the same synthetic dt.\n */\nexport interface DebugClockHost {\n readonly fixedTimestep: number;\n /** Advance one synthetic frame of `dtMs`. Fires every ticker subscriber. */\n advance(dtMs: number): void;\n /** Stop auto-advance. Capture state needed to make `advance` deterministic. */\n freeze(): void;\n /** Resume auto-advance. Restore captured state so the next rAF is sane. */\n thaw(): void;\n}\n\n/**\n * Controls engine time-stepping for deterministic E2E tests.\n *\n * While frozen the renderer ticker is paused and frames advance only via\n * explicit `step()` / `stepFrames()` calls. `freeze()` / `thaw()` and\n * `startAuto()` / `stopAuto()` are equivalent verbs for the same toggle.\n */\nexport class DebugClock implements IDebugClock {\n private _isFrozen = false;\n private deltaMs: number;\n private frame = 0;\n\n constructor(private readonly host: DebugClockHost) {\n this.deltaMs = host.fixedTimestep;\n }\n\n get isFrozen(): boolean {\n return this._isFrozen;\n }\n\n startAuto(): void {\n if (!this._isFrozen) return;\n this.host.thaw();\n this._isFrozen = false;\n }\n\n stopAuto(): void {\n if (this._isFrozen) return;\n this.host.freeze();\n this._isFrozen = true;\n }\n\n freeze(): void {\n this.stopAuto();\n }\n\n thaw(): void {\n this.startAuto();\n }\n\n setDelta(ms: number): void {\n if (!Number.isFinite(ms) || ms <= 0) {\n throw new Error(\"DebugClock.setDelta(ms) requires a positive number.\");\n }\n this.deltaMs = ms;\n }\n\n getFrame(): number {\n return this.frame;\n }\n\n step(dtMs?: number): void {\n if (!this._isFrozen) {\n throw new Error(\"DebugClock is not frozen. Call clock.freeze() first.\");\n }\n const dt = dtMs ?? this.deltaMs;\n if (!Number.isFinite(dt) || dt <= 0) {\n throw new Error(\"DebugClock.step(dtMs) requires a positive number.\");\n }\n // Increment after a successful advance — if a ticker subscriber throws\n // (system exception, render failure) the frame counter shouldn't advance\n // ahead of state.\n this.host.advance(dt);\n this.frame++;\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","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.
|
|
3
|
+
"version": "0.4.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.
|
|
62
|
-
"@yagejs/renderer": "^0.
|
|
61
|
+
"@yagejs/core": "^0.4.0",
|
|
62
|
+
"@yagejs/renderer": "^0.4.0",
|
|
63
63
|
"pixi.js": "^8.5.0"
|
|
64
64
|
}
|
|
65
65
|
}
|