mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 20:03:05 +00:00
Add OverlayOptions for configurable positioning (anchor, margins, offsets, percentages). Add OverlayHandle for programmatic visibility control with hide/setHidden/isHidden. Add visible callback for responsive overlays. Extension API: ctx.ui.custom() now accepts overlayOptions and onHandle callback. Examples: overlay-qa-tests.ts (10 test commands), doom-overlay (DOOM at 35 FPS).
74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
/**
|
|
* DOOM Overlay Demo - Play DOOM as an overlay
|
|
*
|
|
* Usage: pi --extension ./examples/extensions/doom-overlay
|
|
*
|
|
* Commands:
|
|
* /doom-overlay - Play DOOM in an overlay (Q to pause/exit)
|
|
*
|
|
* This demonstrates that overlays can handle real-time game rendering at 35 FPS.
|
|
*/
|
|
|
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
import { DoomOverlayComponent } from "./doom-component.js";
|
|
import { DoomEngine } from "./doom-engine.js";
|
|
import { ensureWadFile } from "./wad-finder.js";
|
|
|
|
// Persistent engine instance - survives between invocations
|
|
let activeEngine: DoomEngine | null = null;
|
|
let activeWadPath: string | null = null;
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
pi.registerCommand("doom-overlay", {
|
|
description: "Play DOOM as an overlay. Q to pause and exit.",
|
|
|
|
handler: async (args, ctx) => {
|
|
if (!ctx.hasUI) {
|
|
ctx.ui.notify("DOOM requires interactive mode", "error");
|
|
return;
|
|
}
|
|
|
|
// Auto-download WAD if not present
|
|
ctx.ui.notify("Loading DOOM...", "info");
|
|
const wad = args?.trim() ? args.trim() : await ensureWadFile();
|
|
|
|
if (!wad) {
|
|
ctx.ui.notify("Failed to download DOOM WAD file. Check your internet connection.", "error");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Reuse existing engine if same WAD, otherwise create new
|
|
let isResume = false;
|
|
if (activeEngine && activeWadPath === wad) {
|
|
ctx.ui.notify("Resuming DOOM...", "info");
|
|
isResume = true;
|
|
} else {
|
|
ctx.ui.notify(`Loading DOOM from ${wad}...`, "info");
|
|
activeEngine = new DoomEngine(wad);
|
|
await activeEngine.init();
|
|
activeWadPath = wad;
|
|
}
|
|
|
|
await ctx.ui.custom(
|
|
(tui, _theme, _keybindings, done) => {
|
|
return new DoomOverlayComponent(tui, activeEngine!, () => done(undefined), isResume);
|
|
},
|
|
{
|
|
overlay: true,
|
|
overlayOptions: {
|
|
width: "75%",
|
|
maxHeight: "95%",
|
|
anchor: "center",
|
|
margin: { top: 1 },
|
|
},
|
|
},
|
|
);
|
|
} catch (error) {
|
|
ctx.ui.notify(`Failed to load DOOM: ${error}`, "error");
|
|
activeEngine = null;
|
|
activeWadPath = null;
|
|
}
|
|
},
|
|
});
|
|
}
|