feat(sprite-generation): Add SpriteCoveragePage for sprite visualization and update registry logic to handle new sprite definitions

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-29 22:56:43 -07:00
parent 685dd19067
commit 445d4f91ec
5 changed files with 51 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View file

@ -421,7 +421,7 @@ class SpriteRegistry:
with self.conn:
if dimension_id is not None:
self.conn.execute(
"UPDATE variants SET is_approved=0 WHERE dimension_id=?",
"UPDATE variants SET is_approved=0, rating=-1 WHERE dimension_id=?",
(dimension_id,),
)
self.conn.execute(
@ -430,7 +430,7 @@ class SpriteRegistry:
)
else:
self.conn.execute(
"UPDATE variants SET is_approved=0 WHERE sprite_id=? AND dimension_id IS NULL",
"UPDATE variants SET is_approved=0, rating=-1 WHERE sprite_id=? AND dimension_id IS NULL",
(sprite_id,),
)
self.conn.execute(

View file

@ -427,6 +427,7 @@ export function SpriteCoveragePage(): ReactNode {
const [variantCache, setVariantCache] = useState<Map<string, Variant[]>>(new Map())
const [variantsLoading, setVariantsLoading] = useState(false)
const [search, setSearch] = useState('')
const [batchState, setBatchState] = useState<BtnState>('idle')
const load = useCallback((): void => {
fetchPipeline()
@ -467,6 +468,18 @@ export function SpriteCoveragePage(): ReactNode {
}
}
const handleBatchGenerate = async (): Promise<void> => {
if (batchState !== 'idle' || filtered.length === 0) return
setBatchState('loading')
try {
await Promise.all(filtered.map((r) => triggerGenerate({ sprite_id: r.sprite_id, variants: 3 })))
setBatchState('queued')
setTimeout(() => setBatchState('idle'), 2000)
} catch {
setBatchState('idle')
}
}
const filtered = search.trim()
? coverage.filter((r) =>
r.sprite_id.includes(search.toLowerCase()) ||
@ -565,7 +578,42 @@ export function SpriteCoveragePage(): ReactNode {
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
<thead>
<tr>
<th style={{ ...thS, width: 36 }} />
<th style={{ ...thS, width: 36, paddingRight: 4 }}>
<Tooltip text={`Queue +3 variants for all ${filtered.length} visible sprites`} placement="bottom">
<button
onClick={() => { void handleBatchGenerate() }}
disabled={batchState !== 'idle' || filtered.length === 0}
style={{
border: `1px solid ${
batchState === 'queued' ? '#22c55e66' :
batchState === 'loading' ? colors.muted + '44' :
'#3b82f644'
}`,
borderRadius: 5,
padding: '2px 5px',
fontSize: 9,
fontWeight: 700,
cursor: batchState === 'idle' ? 'pointer' : 'default',
background:
batchState === 'queued' ? '#16543a' :
batchState === 'loading' ? colors.accent :
'#0f346030',
color:
batchState === 'queued' ? '#4ade80' :
batchState === 'loading' ? colors.muted :
'#60a5fa',
fontFamily: 'monospace',
display: 'block',
width: '100%',
textAlign: 'center',
transition: 'all 0.15s',
letterSpacing: '0.3px',
}}
>
{batchState === 'queued' ? '✓ all' : batchState === 'loading' ? '…' : '+3 all'}
</button>
</Tooltip>
</th>
<th style={thS}>Sprite</th>
<th style={{ ...thS, textAlign: 'center' }}>Var</th>
<th style={{ ...thS, textAlign: 'center' }}>Proc</th>