#!/usr/bin/env bash # SANDONIETTE asset generation — 2D ONLY, 100% local/free, via MODELBEAST. # ./scripts/gen-assets.sh # generate all missing 2D assets # Seeds fixed so every asset is re-generatable. Style token shared for coherence. # The game NEVER blocks on these — procedural fallbacks cover every prop. set -uo pipefail MB_DIR="$HOME/MODELBEAST" [ -d "$MB_DIR" ] || MB_DIR="$HOME/Documents/MODELBEAST" REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" OUT_IMG="$REPO/public/assets/img" mkdir -p "$OUT_IMG" cd "$MB_DIR" || exit 1 # shellcheck disable=SC1091 if [ -f data/agent.env ]; then source data/agent.env else set -a; source "$HOME/Documents/backnforth/.env"; set +a; fi export MB_HOST="${MB_HOST:-http://100.89.131.57:8777}" STYLE="japanese shadow puppet theatre, flat black silhouette with cut-out details, warm washi paper backdrop, edo period, high contrast, hand-crafted paper texture" # ponytail: m4pro venvs dead (2026-07-17) — jobs there fail in ~1s, so retry up # to 10x with 60s pauses until a healthy node takes it. Drop once m4pro is fixed. MB_TRIES=10 MB_PAUSE=60 run_flux() { local seed="$1" prompt="$2" w="${3:-1024}" h="${4:-1024}" i out for i in $(seq 1 "$MB_TRIES"); do out=$(./mb run flux_local -p prompt="$prompt" -p model=flux2-klein-4b -p steps=4 \ -p seed="$seed" -p width="$w" -p height="$h" --wait 2>/dev/null \ | awk '/image/{print $1}' | tail -1) [ -n "$out" ] && { echo "$out"; return; } sleep "$MB_PAUSE" done } run_cutout() { local asset="$1" i out for i in $(seq 1 "$MB_TRIES"); do out=$(./mb run bg_remove_local --asset "$asset" -p resolution=2048 --wait 2>/dev/null \ | awk '/image/{print $1}' | tail -1) [ -n "$out" ] && { echo "$out"; return; } sleep "$MB_PAUSE" done } # gen_2d [w] [h] [cut] gen_2d() { local name="$1" seed="$2" prompt="$3" w="${4:-1024}" h="${5:-1024}" cutout="${6:-no}" if [ -f "$OUT_IMG/$name.png" ]; then echo " = $name.png exists, skipping"; return; fi echo "→ [$name] flux..." local img; img=$(run_flux "$seed" "$prompt, $STYLE" "$w" "$h") [ -z "$img" ] && { echo " ! $name: flux failed"; return 1; } if [ "$cutout" = "cut" ]; then echo "→ [$name] cutout..." local c; c=$(run_cutout "$img"); [ -n "$c" ] && img="$c" fi local tmp; tmp=$(mktemp -d) ./mb get "$img" -o "$tmp" >/dev/null 2>&1 local f; f=$(find "$tmp" -iname '*.png' -o -iname '*.jpg' | head -1) [ -n "$f" ] && { mv "$f" "$OUT_IMG/$name.png"; echo " ✓ $name.png"; } rm -rf "$tmp" } # ---- the samurai: SAME seed, only the expression phrase varies (judge-portrait trick) ---- SAMURAI="a seated japanese samurai looming over a kitchen, ornate armor and helmet, one hand near a katana at his hip, shown as a dramatic flat black paper-cut silhouette against a warm glowing washi paper screen" gen_2d bg_washi 301 "empty kitchen stage, shoji paper screen backdrop lit warm from behind, wooden theatre framing, no characters, no text" 1280 768 gen_2d floor_boards 303 "seamless dark wooden stage floor boards texture, worn edo-period timber, flat even light, no objects, no text" 1024 512 gen_2d samurai_calm 320 "$SAMURAI, calm neutral expression, katana fully sheathed" 768 900 cut gen_2d samurai_watch 320 "$SAMURAI, one eyebrow raised, watchful, hand resting on hilt" 768 900 cut gen_2d samurai_annoyed 320 "$SAMURAI, annoyed frown, thumb pushing the katana guard, ten centimeters of blade showing" 768 900 cut gen_2d samurai_angry 320 "$SAMURAI, angry glare, half the blade drawn and gleaming" 768 900 cut gen_2d samurai_fury 320 "$SAMURAI, furious wide-eyed glare, katana fully drawn overhead ready to slash" 768 900 cut gen_2d title_art 330 "the word SANDONIETTE in giant dramatic japanese calligraphy brush strokes, black sumi ink" 1024 768 cut gen_2d ticket_paper 340 "a single blank narrow paper order ticket, faint fold marks, plain, no text" 512 640 gen_2d slash_frame 350 "one single diagonal white katana slash streak on transparent background, motion blur, sharp" 1024 1024 cut # food faces — comical, slightly alarmed gen_2d face_bread 360 "a comical slightly alarmed cartoon face for a slice of bread, simple cut-out paper eyes and mouth, worried" 512 512 cut gen_2d face_tomato 362 "a comical nervous cartoon face for a round tomato, simple cut-out paper features, sweating" 512 512 cut gen_2d face_cheese 364 "a comical dopey cartoon face for a wedge of cheese, simple cut-out paper features" 512 512 cut gen_2d face_katsu 366 "a comical brave cartoon face for a breaded pork katsu cutlet, simple cut-out paper features" 512 512 cut gen_2d face_egg 368 "a comical wide-eyed cartoon face for a boiled egg, simple cut-out paper features, startled" 512 512 cut # splat decals gen_2d splat_wet 370 "a single messy wet food splat splatter shape, flat black silhouette, on transparent background" 512 512 cut echo "done." # ---- build-out batch 2 (seeds 400+): serve counter, S-grade bow, cutout faces v2 ---- gen_2d samurai_bow 320 "$SAMURAI, head bowed slightly in approval, eyes closed, serene" 768 900 cut gen_2d counter_wood 402 "a low wooden serving counter table, edo period, side view, flat black silhouette on transparent background, hand-crafted paper cut-out style" 768 384 cut gen_2d face_cut_bread 410 "simple face cut out of black paper: two round holes for eyes and a small worried oval mouth hole, white background, minimal, high contrast, paper-cut stencil" 512 512 cut gen_2d day_stamp 420 "a round red japanese hanko seal stamp, blank center, worn ink edges, on transparent background" 512 512 cut