diff --git a/tools/sprite-generation/gui/src/pages/SpritePage.tsx b/tools/sprite-generation/gui/src/pages/SpritePage.tsx index 1a255a02..3a3ba710 100644 --- a/tools/sprite-generation/gui/src/pages/SpritePage.tsx +++ b/tools/sprite-generation/gui/src/pages/SpritePage.tsx @@ -9,11 +9,34 @@ import { regenerateSprite, updatePrompt, } from '../api' -import type { Sprite, Variant } from '../types' +import type { RecentVariant, Sprite, Variant } from '../types' import { colors, statusColors } from './theme' -import { DimensionSection, ImageModal, VariantCard, variantSrc } from './SpriteComponents' +import { DimensionSection, ImageModal, variantSrc } from './SpriteComponents' +import { Card } from './TheaterCard' import { Tooltip } from '../components/Tooltip' +function variantToRecent(v: Variant, sprite: Sprite): RecentVariant { + return { + variant_id: v.id, + sprite_id: v.sprite_id, + category: sprite.category, + entity_id: sprite.entity_id, + raw_path: v.raw_path ?? '', + processed_path: v.processed_path, + seed: v.seed, + created_at: v.created_at, + rating: v.rating, + notes: v.notes, + is_approved: v.is_approved, + scored_by: null, + review_tier: null, + quality_json: null, + gates_json: null, + reject_reason: v.reject_reason, + quality_scorer: null, + } +} + export function SpritePage(): ReactNode { const params = useParams() const navigate = useNavigate() @@ -342,29 +365,28 @@ export function SpritePage(): ReactNode {

Variants

- Keys 1-{Math.min(8, variants.length)} to select, Enter to approve selected, Esc to deselect + Keys 1-{Math.min(8, variants.length)} to select · Enter to approve selected · Esc to deselect

{variants.map((v, i) => ( - { - setSelectedIndex(i) - const src = variantSrc(v) - if (src) { - setModalSrc(src) - } - }} - onApprove={(): void => { - void handleApprove(v.id) - }} - onReject={(): void => { - void handleRejectVariant(v.id) - }} - /> + style={{ width: 220, flexShrink: 0, outline: selectedIndex === i ? `2px solid ${colors.highlight}` : 'none', borderRadius: 8 }} + > + { + setSelectedIndex(i) + const src = variantSrc(v) + if (src) setModalSrc(src) + }} + onApprove={(): void => { load() }} + onReject={(): void => { void handleRejectVariant(v.id) }} + /> +
))}
diff --git a/tools/sprite-generation/gui/src/pages/TheaterCard.tsx b/tools/sprite-generation/gui/src/pages/TheaterCard.tsx index ac58fdb7..2572e70d 100644 --- a/tools/sprite-generation/gui/src/pages/TheaterCard.tsx +++ b/tools/sprite-generation/gui/src/pages/TheaterCard.tsx @@ -232,9 +232,11 @@ export interface CardProps { onApprove: (variantId: number) => void onReject: (variantId: number) => void onSelect?: (v: RecentVariant) => void + /** Show Approve/Reject buttons even when no scoring notes exist */ + alwaysShowActions?: boolean } -export const Card = memo(forwardRef(function Card({ v, isNew, index, onApprove, onReject, onSelect }, ref) { +export const Card = memo(forwardRef(function Card({ v, isNew, index, onApprove, onReject, onSelect, alwaysShowActions }, ref) { const conf = useMemo(() => confidence(v), [v.notes]) const scores = useMemo(() => parseScores(v.notes), [v.notes]) const gateOk = useMemo(() => gatePassed(v), [v.notes]) @@ -360,15 +362,48 @@ export const Card = memo(forwardRef(function Card({ v {/* ── Art frame ───────────────────────────────────────────── */}
onSelect?.(v)} - style={{ display: 'block', cursor: 'pointer' }} + style={{ display: 'block', cursor: 'pointer', position: 'relative' }} title={`#${v.variant_id} — ${v.sprite_id} (click for details)`} > - {v.entity_id} + {imgUrl ? ( + {v.entity_id} + ) : ( +
+ + no image +
+ )} + {v.rating === -1 && ( +
+ + Rejected + +
+ )}
{/* ── Text box ────────────────────────────────────────────── */} @@ -458,7 +493,28 @@ export const Card = memo(forwardRef(function Card({ v }}> APPROVED - ) : scores && ( + ) : v.rating === -1 ? ( +
+ + + +
+ ) : (scores || alwaysShowActions) && imgUrl ? (
- )} + ) : null} ) }))