Issue #234 Paint in Place: Image Preview Modal#335
Issue #234 Paint in Place: Image Preview Modal#335jrconway3 wants to merge 208 commits intoLiberatedPixelCup:masterfrom
Conversation
…tter during recolor
…tter during recolor
…al-LPC-Spritesheet-Character-Generator into paint-in-place-for-real
…rate' into feature/issue-234-paint-in-place-remove-image-changes
…place-remove-image-changes
✅ Deploy Preview for liberatedpixelcup ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
Adds a palette-based recoloring system (including previews/modals) to support “paint in place” workflows, and migrates many sprite definitions from explicit variants to palette-driven recolors.
Changes:
- Introduces runtime palette recoloring (CPU + shared WebGL path) and uses it in render/export pipelines.
- Adds UI for recolorable items, including preview canvases and a palette selection modal.
- Updates metadata generation + many
sheet_definitions/**to userecolors, and addspalette_definitions/**content.
Reviewed changes
Copilot reviewed 140 out of 417 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| sources/utils/helpers.js | Adds ucwords() for display formatting in the new palette UI. |
| sources/utils/credits.js | Adjusts credit path resolution for items without variant subfolders. |
| sources/state/zip.js | Passes recolor selections into export rendering paths. |
| sources/state/state.js | Adds selection helpers and new item selection model supporting recolors/sub-selections. |
| sources/state/path.js | Updates sprite path building to support recolor-based (non-variant) spritesheets. |
| sources/state/palettes.js | Introduces palette selection/recolor utilities used by UI + renderer. |
| sources/state/hash.js | Extends hash encoding/decoding to include recolor and sub-selection data. |
| sources/main.js | Exposes palette recolor debug helpers and refactors DEBUG/profiler exports. |
| sources/components/tree/TreeNode.js | Routes recolorable items to a new ItemWithRecolors component. |
| sources/components/tree/PaletteSelectModal.js | New modal for selecting palettes with live preview. |
| sources/components/tree/ItemWithVariants.js | Uses centralized selectItem() instead of inline selection logic. |
| sources/components/tree/ItemWithRecolors.js | New UI component showing recolor previews + palette pickers. |
| sources/components/tree/CategoryTree.js | Updates match-body-color behavior to propagate recolors. |
| sources/components/preview/FullSpritesheetPreview.js | Adds loading indicator tied to state.isRenderingCharacter. |
| sources/components/preview/AnimationPreview.js | Adds loading indicator tied to state.isRenderingCharacter. |
| sources/canvas/webgl-palette-recolor.js | New shared-context WebGL recoloring implementation. |
| sources/canvas/renderer.js | Integrates recoloring into character/item/animation rendering. |
| sources/canvas/palette-recolor.js | New recolor orchestration (CPU/WebGL), preview rendering, debug stats. |
| sheet_definitions/head/nose/head_nose_straight.json | Migrates nose from variants to palette recolors. |
| sheet_definitions/head/nose/head_nose_large.json | Migrates nose from variants to palette recolors. |
| sheet_definitions/head/nose/head_nose_elderly.json | Migrates nose from variants to palette recolors. |
| sheet_definitions/head/nose/head_nose_button.json | Migrates nose from variants to palette recolors. |
| sheet_definitions/head/nose/head_nose_big.json | Migrates nose from variants to palette recolors. |
| sheet_definitions/head/heads/undead/heads_zombie.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/undead/heads_vampire.json | Migrates head from variants to palette recolors. |
| sheet_definitions/head/heads/undead/heads_frankenstein.json | Migrates head from variants to palette recolors. |
| sheet_definitions/head/heads/reptile/heads_lizard_male.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/reptile/heads_lizard_female.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/reptile/heads_lizard_child.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/reptile/heads_alien.json | Migrates head from variants to palette recolors. |
| sheet_definitions/head/heads/human/heads_human_male_small.json | Adds multi-recolor support (skin + eyes) via recolors.color_1/color_2. |
| sheet_definitions/head/heads/human/heads_human_male_plump.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_male_gaunt.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_male_elderly.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_male.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_female_small.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_female_elderly.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_female.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_elderly_small.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/human/heads_human_child.json | Adds multi-recolor support (skin + eyes). |
| sheet_definitions/head/heads/farm/heads_sheep_child.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/farm/heads_sheep.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/farm/heads_rat_child.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/farm/heads_rat.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/farm/heads_rabbit_child.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/farm/heads_rabbit.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/farm/heads_pig_child.json | Migrates head from variants to palette recolors. |
| sheet_definitions/head/heads/farm/heads_pig.json | Migrates head from variants to palette recolors. |
| sheet_definitions/head/heads/farm/heads_mouse_child.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/farm/heads_mouse.json | Migrates head from variants to palette recolors + updates credits. |
| sheet_definitions/head/heads/fantasy/heads_troll_child.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/fantasy/heads_troll.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/fantasy/heads_orc_male.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/fantasy/heads_orc_female.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/fantasy/heads_orc_child.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/fantasy/heads_goblin_child.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/fantasy/heads_goblin.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_wolf_male.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_wolf_female.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_wolf_child.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_wartotaur.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_minotaur_female.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_minotaur_child.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_minotaur.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_boarman_child.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/heads/beast/heads_boarman.json | Migrates head from variants to palette recolors (with base override). |
| sheet_definitions/head/head_wrinkles.json | Migrates wrinkles from variants to palette recolors. |
| sheet_definitions/head/furry_ears/top/head_ears_wolf_skin.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/furry_ears/top/head_ears_cat_skin.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/furry_ears/side/head_ears_zabos_skin.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/furry_ears/side/head_ears_lykon_skin.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/furry_ears/side/head_ears_avyon_skin.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/faces/face_shock.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_shame.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_sad2.json | Migrates face from variants to palette recolors. |
| sheet_definitions/head/faces/face_sad.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_neutral.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_look_r.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_look_l.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_happy2.json | Migrates face from variants to palette recolors. |
| sheet_definitions/head/faces/face_happy.json | Migrates face from variants to palette recolors. |
| sheet_definitions/head/faces/face_eyeroll.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_closing.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/faces/face_closed.json | Migrates face from variants to palette recolors. |
| sheet_definitions/head/faces/face_blush.json | Migrates face from variants to palette recolors. |
| sheet_definitions/head/faces/face_angry2.json | Migrates face from variants to palette recolors. |
| sheet_definitions/head/faces/face_angry.json | Migrates face from variants to multi-recolors (skin + eyes). |
| sheet_definitions/head/eyes_child.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/meta_eyes.json | Adds/updates label for eyes category. |
| sheet_definitions/head/eyes/eyes_elderly_shock.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_shame.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_sad.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_look_r.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_look_l.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_eyeroll.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_default.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_closing.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eyes_elderly_anger.json | Removes legacy eyes definition (variants-based). |
| sheet_definitions/head/eyes/eye_color.json | Removes legacy eye-color system definition (variants-based). |
| sheet_definitions/head/ears/head_ears_medium.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/ears/head_ears_long.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/ears/head_ears_hang.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/ears/head_ears_elven.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/ears/head_ears_dragon.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/ears/head_ears_down.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/ears/head_ears_big.json | Migrates ears from variants to palette recolors. |
| sheet_definitions/head/appendages/head_fins_fin_short.json | Migrates fins from variants to palette recolors. |
| sheet_definitions/head/appendages/head_fins_fin.json | Migrates fins from variants to palette recolors. |
| sheet_definitions/body/lizard/wings_lizard_bat.json | Migrates wings from variants to palette recolors. |
| sheet_definitions/body/lizard/wings_lizard.json | Migrates wings from variants to palette recolors. |
| sheet_definitions/body/lizard/tail_lizard.json | Migrates tail from variants to palette recolors. |
| sheet_definitions/body/body.json | Migrates body from variants to palette recolors. |
| scripts/zPositioning/z_positions.csv | Updates z-positioning source list to reflect removed legacy eye definitions. |
| scripts/zPositioning/update_zpos.js | Refactors update script path handling + wraps file writes in try/catch. |
| scripts/zPositioning/parse_zpos.js | Refactors parse script path handling for recursive directory reads. |
| scripts/generate_sources.js | Generates palette metadata, rewires credits parsing, and emits window.paletteMetadata. |
| palette_definitions/metal/metal_ulpc.json | Adds ULPC metal palettes. |
| palette_definitions/metal/metal_lpcr.json | Adds LPCR metal palettes. |
| palette_definitions/metal/meta_metal.json | Adds metal material metadata. |
| palette_definitions/meta_ulpc.json | Adds ULPC version metadata. |
| palette_definitions/meta_lpcr.json | Adds LPCR version metadata. |
| palette_definitions/hair/meta_hair.json | Adds hair material metadata. |
| palette_definitions/hair/hair_ulpc.json | Adds ULPC hair palettes. |
| palette_definitions/hair/hair_lpcr.json | Adds LPCR hair palettes. |
| palette_definitions/eye/meta_eye.json | Adds eye material metadata. |
| palette_definitions/eye/eye_ulpc.json | Adds ULPC eye palettes. |
| palette_definitions/eye/eye_lpcr.json | Adds LPCR eye palettes. |
| palette_definitions/cloth/meta_cloth.json | Adds cloth material metadata. |
| palette_definitions/cloth/cloth_ulpc.json | Adds ULPC cloth palettes. |
| palette_definitions/body/meta_body.json | Adds body (skintone) material metadata. |
| palette_definitions/body/body_ulpc.json | Adds ULPC body palettes. |
| palette_definitions/body/body_lpcr.json | Adds LPCR body palettes. |
| palette_definitions/all/meta_all.json | Adds “Any” (all) material metadata. |
| index.html | Updates stylesheet paths to styles/* locations. |
| README.md | Documents the palette recoloring system + debug console commands. |
| .github/workflows/validate-site-sources.yml | Adds paint-in-place-master branch to workflow triggers. |
| .github/workflows/lint.yml | Adds paint-in-place-master branch to workflow triggers. |
| .github/workflows/ci.yml | Adds paint-in-place-master branch to workflow triggers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
One thing you can't do is combine both colors into one. I think it wouldn't be feasible to implement this. However, I did a dumb thing where I didn't even allow it to maintain the current colors of the parent element. It should probably take selectedColors, but override the specific selection group. I'll look into implementing this today so it takes the selectedColors, and the modal only replaces that asset. This would let you keep the skintone from the current set skintone, then you can replace the eye color with whatever you want. Or if you choose an eye color, you can open the skintone modal and see the skintone with different eyes. |
…ng the Modal Itself
|
Here it is: It won't be on this repo, though. |
Version of #330 but with the modal now containing a preview image of the repalette.
I opted to restructure it to include my palette swatch as well because I liked this mechanic a lot.
Also contains another fix I missed:
If the modal opened while on a responsive view, it seems like the chooser height was the height of the whole page, so the modal wasn't properly being restricted only to the max of the browser. I fixed it so the modal doesn't go beyond the current browser window's height.
Another update:

The modal keeps colors now that don't match the current color. This only matters for assets with multiple colors.