107 lines
5.2 KiB
Markdown
107 lines
5.2 KiB
Markdown
---
|
|
id: LSN-0042
|
|
ticket: palette-management-in-studio
|
|
title: Schema-Driven Palette Authoring and Local Metadata Events
|
|
created: 2026-04-23
|
|
tags:
|
|
- studio
|
|
- glyph-bank
|
|
- palette-management
|
|
- color-schema
|
|
- local-events
|
|
---
|
|
|
|
## Context
|
|
|
|
The glyph-bank palette workflow originally treated palette candidates as extracted tile artifacts. That made grouping, recoloring, and final bank palette selection compete in the same surface.
|
|
|
|
The completed palette-management work split the workflow into two authored layers:
|
|
|
|
1. `Color Schema Groups`, where selected tiles are grouped into a shared index structure.
|
|
2. `Palette Overhauling`, where palettes are authored and selected against already-ready schemas.
|
|
|
|
The durable implementation lesson is that schema edits, palette edits, and build selection are all local glyph-material metadata operations first. They should update local metadata projections directly instead of forcing a full asset-details reload.
|
|
|
|
## Key Decisions
|
|
|
|
### Schema Owns Index Semantics
|
|
|
|
**What:** A schema is the authored index structure for a group of selected glyph-bank tiles. It owns `material_indices`, artifact bindings, fingerprint snapshots, version, and status.
|
|
|
|
**Why:** The source PNG stays unchanged, while Studio records how tile colors map into stable bank-local indices. This keeps tile grouping separate from recoloring.
|
|
|
|
**Trade-offs:** Schema invalidation must be explicit. When selected tile fingerprints drift, the schema can become inconsistent and dependent palettes become invalid or stale.
|
|
|
|
### Palettes Are Schema-Scoped
|
|
|
|
**What:** A palette always belongs to exactly one schema. It stores concrete `#RRGGBB` colors for that schema's visible indices and carries the schema version it was authored against.
|
|
|
|
**Why:** Multiple recolors can safely exist for one index structure without duplicating tile grouping metadata.
|
|
|
|
**Trade-offs:** Duplicate detection must use the tuple `schemaId + colors + order`, not display name or source tile identity.
|
|
|
|
### Original Palettes Are Synthetic and Read-Only
|
|
|
|
**What:** The original palette is the synthetic `schema-<schemaId>-original` projection derived from the current schema colors. It is not a persisted user palette.
|
|
|
|
**Why:** Updating the schema should update the original palette automatically. The original represents the schema's source color meaning, not a user-authored recolor.
|
|
|
|
**Trade-offs:** Users cannot edit or delete the original palette directly. If they want a changed palette, they create or edit a separate persisted palette for the same schema.
|
|
|
|
### Local Metadata Events Beat Global Reloads
|
|
|
|
**What:** Schema and palette metadata mutations should publish `StudioGlyphMaterialMetadataChangedEvent` and let interested sections rebind local state.
|
|
|
|
**Why:** Global asset refresh and selection events can close edit mode, reset form state, and make small metadata edits feel destructive.
|
|
|
|
**Trade-offs:** Controls must keep their local coordinators robust: stale button handlers should read the current view model at click time, and metadata replacement must preserve edit-mode drafts where possible.
|
|
|
|
## Patterns and Algorithms
|
|
|
|
### `glyph-material.json`
|
|
|
|
`glyph-material.json` is the Studio-owned support file for glyph-bank material authoring. It persists schemas and user-authored palettes, while derived original palettes remain a view projection.
|
|
|
|
Schema records store:
|
|
|
|
- stable `schema_id`
|
|
- `status`
|
|
- `version`
|
|
- dense visible `material_indices`
|
|
- artifact bindings with fingerprint snapshots
|
|
|
|
Palette records store:
|
|
|
|
- stable `palette_id`
|
|
- persisted `name`
|
|
- parent `schema_id`
|
|
- schema `version`
|
|
- concrete `colors`
|
|
|
|
### Palette Names
|
|
|
|
Palette names are persisted even when the user leaves the name field blank. The blank-name path resolves to a deterministic, simple generated name such as `snow white`, `fog twist`, or `ember bloom`.
|
|
|
|
The generated name is a convenience label only. Palette identity remains `palette_id`, and duplicate detection remains schema plus ordered colors.
|
|
|
|
### Original Palette Projection
|
|
|
|
Every ready schema projects a synthetic original palette from the schema's current `material_indices`.
|
|
|
|
This projection must always exist in the palette view, even if a user-authored palette has the same colors. A saved palette with the same schema and colors is still user-authored and can be deleted.
|
|
|
|
## Pitfalls
|
|
|
|
- Do not treat same colors as proof that a palette is original. Original means "synthetic schema projection", not "matches current schema colors".
|
|
- Do not publish global asset refresh events for local schema or palette metadata changes. Use local metadata events unless pack/runtime state truly changed.
|
|
- Do not let button handlers capture stale preview objects. Fetch the current coordinator view model at click time for destructive actions.
|
|
- Do not let blank palette names remain blank on disk. Resolve the generated name before persisting.
|
|
- Do not open the palette wizard for synthetic original palettes. They are read-only projections.
|
|
|
|
## Takeaways
|
|
|
|
- Schema formation and palette authoring are separate lifecycle stages.
|
|
- Original palettes are derived views, not persisted editable records.
|
|
- User-created palettes remain editable and removable even when they share a schema or colors with an original.
|
|
- Local metadata events preserve form continuity better than full asset refreshes.
|