mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-18 03:00:38 +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
152
packages/coding-agent/examples/extensions/doom-overlay/doom/build.sh
Executable file
152
packages/coding-agent/examples/extensions/doom-overlay/doom/build.sh
Executable file
|
|
@ -0,0 +1,152 @@
|
|||
#!/bin/bash
|
||||
# Build DOOM for pi-doom using doomgeneric and Emscripten
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
DOOM_DIR="$PROJECT_ROOT/doom"
|
||||
BUILD_DIR="$PROJECT_ROOT/doom/build"
|
||||
|
||||
echo "=== pi-doom Build Script ==="
|
||||
|
||||
# Check for emcc
|
||||
if ! command -v emcc &> /dev/null; then
|
||||
echo "Error: Emscripten (emcc) not found!"
|
||||
echo ""
|
||||
echo "Install via Homebrew:"
|
||||
echo " brew install emscripten"
|
||||
echo ""
|
||||
echo "Or manually:"
|
||||
echo " git clone https://github.com/emscripten-core/emsdk.git ~/emsdk"
|
||||
echo " cd ~/emsdk && ./emsdk install latest && ./emsdk activate latest"
|
||||
echo " source ~/emsdk/emsdk_env.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clone doomgeneric if not present
|
||||
if [ ! -d "$DOOM_DIR/doomgeneric" ]; then
|
||||
echo "Cloning doomgeneric..."
|
||||
cd "$DOOM_DIR"
|
||||
git clone https://github.com/ozkl/doomgeneric.git
|
||||
fi
|
||||
|
||||
# Create build directory
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
# Copy our platform file
|
||||
cp "$DOOM_DIR/doomgeneric_pi.c" "$DOOM_DIR/doomgeneric/doomgeneric/"
|
||||
|
||||
echo "Compiling DOOM to WebAssembly..."
|
||||
cd "$DOOM_DIR/doomgeneric/doomgeneric"
|
||||
|
||||
# Resolution - 640x400 is doomgeneric default, good balance of speed/quality
|
||||
RESX=${DOOM_RESX:-640}
|
||||
RESY=${DOOM_RESY:-400}
|
||||
|
||||
echo "Resolution: ${RESX}x${RESY}"
|
||||
|
||||
# Compile with Emscripten (no sound)
|
||||
emcc -O2 \
|
||||
-s WASM=1 \
|
||||
-s EXPORTED_FUNCTIONS="['_doomgeneric_Create','_doomgeneric_Tick','_DG_GetFrameBuffer','_DG_GetScreenWidth','_DG_GetScreenHeight','_DG_PushKeyEvent','_malloc','_free']" \
|
||||
-s EXPORTED_RUNTIME_METHODS="['ccall','cwrap','getValue','setValue','FS']" \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s INITIAL_MEMORY=33554432 \
|
||||
-s MODULARIZE=1 \
|
||||
-s EXPORT_NAME="createDoomModule" \
|
||||
-s ENVIRONMENT='node' \
|
||||
-s FILESYSTEM=1 \
|
||||
-s FORCE_FILESYSTEM=1 \
|
||||
-s EXIT_RUNTIME=0 \
|
||||
-s NO_EXIT_RUNTIME=1 \
|
||||
-DDOOMGENERIC_RESX=$RESX \
|
||||
-DDOOMGENERIC_RESY=$RESY \
|
||||
-I. \
|
||||
am_map.c \
|
||||
d_event.c \
|
||||
d_items.c \
|
||||
d_iwad.c \
|
||||
d_loop.c \
|
||||
d_main.c \
|
||||
d_mode.c \
|
||||
d_net.c \
|
||||
doomdef.c \
|
||||
doomgeneric.c \
|
||||
doomgeneric_pi.c \
|
||||
doomstat.c \
|
||||
dstrings.c \
|
||||
f_finale.c \
|
||||
f_wipe.c \
|
||||
g_game.c \
|
||||
hu_lib.c \
|
||||
hu_stuff.c \
|
||||
i_cdmus.c \
|
||||
i_input.c \
|
||||
i_endoom.c \
|
||||
i_joystick.c \
|
||||
i_scale.c \
|
||||
i_sound.c \
|
||||
i_system.c \
|
||||
i_timer.c \
|
||||
i_video.c \
|
||||
icon.c \
|
||||
info.c \
|
||||
m_argv.c \
|
||||
m_bbox.c \
|
||||
m_cheat.c \
|
||||
m_config.c \
|
||||
m_controls.c \
|
||||
m_fixed.c \
|
||||
m_menu.c \
|
||||
m_misc.c \
|
||||
m_random.c \
|
||||
memio.c \
|
||||
p_ceilng.c \
|
||||
p_doors.c \
|
||||
p_enemy.c \
|
||||
p_floor.c \
|
||||
p_inter.c \
|
||||
p_lights.c \
|
||||
p_map.c \
|
||||
p_maputl.c \
|
||||
p_mobj.c \
|
||||
p_plats.c \
|
||||
p_pspr.c \
|
||||
p_saveg.c \
|
||||
p_setup.c \
|
||||
p_sight.c \
|
||||
p_spec.c \
|
||||
p_switch.c \
|
||||
p_telept.c \
|
||||
p_tick.c \
|
||||
p_user.c \
|
||||
r_bsp.c \
|
||||
r_data.c \
|
||||
r_draw.c \
|
||||
r_main.c \
|
||||
r_plane.c \
|
||||
r_segs.c \
|
||||
r_sky.c \
|
||||
r_things.c \
|
||||
s_sound.c \
|
||||
sha1.c \
|
||||
sounds.c \
|
||||
st_lib.c \
|
||||
st_stuff.c \
|
||||
statdump.c \
|
||||
tables.c \
|
||||
v_video.c \
|
||||
w_checksum.c \
|
||||
w_file.c \
|
||||
w_file_stdc.c \
|
||||
w_main.c \
|
||||
w_wad.c \
|
||||
wi_stuff.c \
|
||||
z_zone.c \
|
||||
dummy.c \
|
||||
-o "$BUILD_DIR/doom.js"
|
||||
|
||||
echo ""
|
||||
echo "Build complete!"
|
||||
echo "Output: $BUILD_DIR/doom.js and $BUILD_DIR/doom.wasm"
|
||||
File diff suppressed because one or more lines are too long
BIN
packages/coding-agent/examples/extensions/doom-overlay/doom/build/doom.wasm
Executable file
BIN
packages/coding-agent/examples/extensions/doom-overlay/doom/build/doom.wasm
Executable file
Binary file not shown.
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* pi-doom platform implementation for doomgeneric
|
||||
*
|
||||
* Minimal implementation - no sound, just framebuffer and input.
|
||||
*/
|
||||
|
||||
#include "doomgeneric.h"
|
||||
#include "doomkeys.h"
|
||||
#include <emscripten.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Key event queue
|
||||
#define KEY_QUEUE_SIZE 256
|
||||
static struct {
|
||||
int pressed;
|
||||
unsigned char key;
|
||||
} key_queue[KEY_QUEUE_SIZE];
|
||||
static int key_queue_read = 0;
|
||||
static int key_queue_write = 0;
|
||||
|
||||
// Get the framebuffer pointer for JS to read
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
uint32_t *DG_GetFrameBuffer(void) { return DG_ScreenBuffer; }
|
||||
|
||||
// Get framebuffer dimensions
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int DG_GetScreenWidth(void) { return DOOMGENERIC_RESX; }
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int DG_GetScreenHeight(void) { return DOOMGENERIC_RESY; }
|
||||
|
||||
// Push a key event from JavaScript
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void DG_PushKeyEvent(int pressed, unsigned char key) {
|
||||
int next_write = (key_queue_write + 1) % KEY_QUEUE_SIZE;
|
||||
if (next_write != key_queue_read) {
|
||||
key_queue[key_queue_write].pressed = pressed;
|
||||
key_queue[key_queue_write].key = key;
|
||||
key_queue_write = next_write;
|
||||
}
|
||||
}
|
||||
|
||||
void DG_Init(void) {
|
||||
// Nothing to initialize
|
||||
}
|
||||
|
||||
void DG_DrawFrame(void) {
|
||||
// Frame is in DG_ScreenBuffer, JS reads via DG_GetFrameBuffer
|
||||
}
|
||||
|
||||
void DG_SleepMs(uint32_t ms) {
|
||||
// No-op - JS handles timing
|
||||
(void)ms;
|
||||
}
|
||||
|
||||
uint32_t DG_GetTicksMs(void) {
|
||||
return (uint32_t)emscripten_get_now();
|
||||
}
|
||||
|
||||
int DG_GetKey(int *pressed, unsigned char *key) {
|
||||
if (key_queue_read != key_queue_write) {
|
||||
*pressed = key_queue[key_queue_read].pressed;
|
||||
*key = key_queue[key_queue_read].key;
|
||||
key_queue_read = (key_queue_read + 1) % KEY_QUEUE_SIZE;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DG_SetWindowTitle(const char *title) {
|
||||
(void)title;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue