mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-19 19:04:41 +00:00
feat(tui): overlay positioning API with CSS-like values
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).
This commit is contained in:
parent
d29f268f46
commit
a4ccff382c
22 changed files with 1344 additions and 103 deletions
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue