Skip to content

feat(island): data-driven island + standalone Spline-like designer#74

Merged
rezailmi merged 15 commits into
mainfrom
island-editor
Jun 16, 2026
Merged

feat(island): data-driven island + standalone Spline-like designer#74
rezailmi merged 15 commits into
mainfrom
island-editor

Conversation

@rezailmi

Copy link
Copy Markdown
Collaborator

Summary

Turns the island from a hard-coded Three.js scene into a data-driven world, adds a standalone Spline-like island designer, and removes the experimental in-product editor overlay in favor of that dedicated tool.

Data-driven island (live app — load-bearing)

  • IslandLayout + SpeciesPalette state slices with stable uuid object ids and a working-copy layered over committed defaults
  • defaultIslandLayout.json + defaultSpeciesPalette.json — every user boots from these; Tree/Flowers/Fruits/Mailbox/Telescope render from the slices
  • JSON export/import + localStorage persistence of the spec

Standalone island designer (island-editor/)

  • Greenfield Vite app, r3f + @react-three/drei + three — isolated from the product app
  • Coastline-handle terrain editing, undo/redo, autosave, export/import, reset
  • Exports an engine-agnostic island spec

Removed: in-app editor overlay

  • Deleted IslandEditorPanel (the #editor hash overlay) and its dev-only engine wiring (Game/View/edit/: EditController, editableViews, CommandStack, Selection)
  • The data model above is retained — only the in-product authoring surface is gone

Testing

  • pnpm check passes (tsc clean; 15 pre-existing Biome warnings in kept tests)
  • pnpm test: 11 failures remain, all pre-existing on main and unrelated to this branch (history/trajectory sheets, edupass login, dev pipeline, vips loader). Island data-model tests (IslandLayout, SpeciesPalette, defaults, export) pass.

🤖 Generated with Claude Code

Reza Ilmi added 15 commits June 15, 2026 15:23
…inspector, undo/redo, preview

- Tree/Flowers/Fruits: ensureFromLayout reconciles live scene after addObject/removeObject
- Tree: _teardownPlacements() for clean rebuild; ensureFromLayout calls _placeAll() + re-applies visibility
- Flowers: diff by layoutId, disposes gone entries, _buildOne for new entries
- Fruits: diff by layoutId, builds new bushes, defers via _pendingEnsure if not yet placed
- editableViews: spawn/remove now call ensureFromLayout instead of no-op stubs
- EditController: subscribes to objectAdded/objectRemoved/layoutReplaced; _reconcileAfterStructural delegates to correct view kind
- IslandEditorPanel: dev-only hash-gated React panel (Add palette, Inspector, Undo/Redo, Diverged badge, Preview toggle)
- EngineHost: mounts IslandEditorPanel under import.meta.env.DEV
- Tests: 5 spawn/remove reconcile tests (all pass)
…landLayout.json

- IslandEditorPanel: Export (↓) downloads island-layout-<stamp>.json; Import (↑) loads JSON via FileReader → setLayout (live update, no reload)
- islandLayout.js: defaultIslandLayout() now loads from committed defaultIslandLayout.json (merged through mergeIslandLayout), falls back to defaultIslandLayoutFromConstants() if empty/invalid
- defaultIslandLayout.json: 31-object seed committed from defaultIslandLayoutFromConstants() — replacing it with an exported edit changes the boot island with no other code change
- Tests: serialize/setLayout round-trip, layoutReplaced event, invalid-input rejection, JSON validity guard (8 pass, 1 seed-parity skipped)
- U3 (decorOffsets index→uuid re-key) deferred: high-touch change to Sprouts state + View/Sprouts; escape hatch invoked per plan 004 spec — will be its own plan
…te editor UI

- speciesPalette.js: data model with defaultSpeciesPaletteFromConstants() (oak/cherry tree colors, 6 flower + 6 fruit species as #rrggbb)
- defaultSpeciesPalette.json: committed default (seed from constants, visual no-op)
- schema.js: mergeSpeciesPalette() — lenient merge with hex color validation per slot
- SpeciesPalette.js: working-copy-over-committed-base slice (get/setColor/list/isDiverged/revertToDefault/subscribe/hydrate/serialize); fires paletteChanged / paletteReplaced
- Persistence: speciesPalette added to KEY/SLICES/empty
- State.js + Game.js: construct/hydrate speciesPalette, null singleton on dispose
- Fruits.js: subscribes to paletteChanged → live _berryMats[species].color.set(); applies persisted overrides at boot
- Tree.js: subscribes to paletteChanged → live uniforms.uColorA/uColorB.value.set(); applies after _loadAndBuild
- Flowers: reload fallback (palette read at _buildOne; live re-skin deferred as U4 escape hatch)
- IslandEditorPanel: Palette section with per-species color inputs, Export/Import palette JSON, diverged badge + Revert palette
- Tests: 12 SpeciesPalette tests (model, setColor, paletteChanged, isDiverged, revert, serialize/hydrate round-trip)
Standalone, isolated workspace package (own three/r3f/drei + separate pnpm root) that does not touch the product app or its pinned three@0.149. Editable terrain: closed 2D coastline spline (point-in-polygon + distance-to-coast), analytic height profile, additive sculpt relief; seeded from today's island silhouette. Draggable coastline handles, hover-reveal tool panel, sculpt brush (raise/lower/smooth/flatten) with a cached base-field for fast strokes. Pure terrain/brush math unit-tested (9 tests); typecheck + build green.
The dedicated standalone designer (island-editor/, r3f + drei) replaces the
in-product authoring overlay. Remove the editor surface and its dev-only engine
wiring while keeping the load-bearing data model (islandLayout + speciesPalette
slices and default*.json) that now drives live world rendering.

- delete IslandEditorPanel + its EngineHost mount/import
- delete Game/View/edit/ (EditController, editableViews, CommandStack, Selection)
- unwire editController from View.js construction + dispose loop
- delete editor-only tests (selection / spawn / transform)

pnpm check passes; the 11 remaining test failures are pre-existing on main and
unrelated to this change.
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sensemaking-agents Building Building Preview, Comment Jun 16, 2026 7:20am

@rezailmi rezailmi merged commit b6dc287 into main Jun 16, 2026
3 of 4 checks passed
@rezailmi rezailmi deleted the island-editor branch June 16, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant