feat(mapeditor): edit the chunked world at 133M scale — top-down paint editor (PR 4a of #229) #234

Merged
panda merged 4 commits from feat/editor-chunked-4a into main 2026-08-01 10:15:19 +02:00
Collaborator

Summary

Fase 4a of the world-map migration (epic #229): the map editor now opens, renders and edits the chunked world at 133M-cell scale, so Andrea can actually draw the planet.

Key changes:

  • EditorGame on ChunkedEditModel (was the dense MapModel): opens a world directory (content/worlds/asterra/) by reading only the manifest, or a fresh ocean of a configurable size (default 13,344×9,984); incremental save (only changed regions); import a legacy world.map once.
  • Flat top-down biome canvas (MapPaintRenderer) instead of iso. The editor is a drawing — the game renders the iso look. Each terrain gets one hex colour (its TileData Tint); the visible window is filled chunk-by-chunk into a single bitmap, uploaded once per view-move/edit and blitted each frame — fast at world scale, no per-cell draw. (WYSIWYG-iso is dropped for the editor; the guardrail is updated to match.)
  • Fill (ChunkedFlood): flood the connected terrain region — draw a coastline, fill the interior with grass. Bounded (per-chunk visited bitmaps + a cell budget) so an unclosed border can't fill the 133M ocean — it aborts with no change.
  • Continuous stroke (Brush.Line/Brush.Stroke, Bresenham): a fast drag paints a gap-free line instead of skipped cells.
  • Configurable brush size (numeric input, up to 256) + paint-on-cell-change; Single / Rect / Fill brushes; terrain / static / erase / spawn / Raise·Lower·Set Z tools.
  • Scale grid: chunk (32) + region (256, brighter) + cell lines (when zoomed in), with a chunk cx,cy + px/cell readout — so the author can tell zoom + position on a flat map.
  • Shared IsoViewport.VisibleCellBounds extracted into Client.Core (the game's ground blend + the editor both use it, tested once).
  • Headless harness: --world / --import / --goto / --cellpx / --screenshot.
  • First authored world committed: content/worlds/asterra/ — a continent draft (grass coast, brown interior, islands, a volcano). A draft: spawn not yet set.

Not in scope (later slices): the full-planet overview / mip (Fase 4b), undo/redo + autosave, statics/Z shown on the map, and — importantly — wiring the chunked world into the client/server (Fase 7): the game still reads the legacy world.map, so this world is authored + tested in the editor, not yet playable in-game.

Screenshots / recording

Piloted via the editor's headless --screenshot — see the comment below (fresh 133M ocean, imported 2304², the scale grid, and the authored asterra continent).

How it was tested

  • Unit tests (Client.Core + MapEditor.Core): IsoViewport.VisibleCellBounds (symmetry / zoom / camera-centred, +3); ChunkedFlood (fills a bordered region, aborts over budget, +2); Brush.Line/Stroke (endpoints + gap-free, +3); model RaiseZ/InBounds (+2).
  • Piloted the editor headlessly: a fresh 13,344×9,984 ocean opens with dirty 0 (no per-cell allocation); the imported 2304² world renders; the authored asterra world opens and round-trips (dirty 0, byte-identical save/reopen).
  • Whole solution builds 0 warnings; dotnet test fully green (MapEditor.Core 42, Client.Core 181, …); just lint + check-docs clean; docs/map-editor.md + the editor guardrail updated.

DoD delta (beyond the base DoD + epic #229)

  • The editor opens + edits the 133M-cell world with memory bounded to the edited chunks, and a fast (bitmap-blit) canvas.
  • Allaga/New-ocean, incremental save, legacy import, and a bounded Fill that cannot run away on the ocean.
  • Save→reopen preserves the authored world (proven on the real asterra map).

Checklist

  • just lint passes (CSharpier + analyzers, zero warnings)
  • just test is green
  • The whole solution builds (client and tools included)
  • Multi-platform preserved (DesktopGL editor; pure managed logic in Core)
  • Tests added/updated for this change
  • Linked the related issue (#229) and its per-PR DoD is met
  • Screenshots (piloted editor) — in the comment below
## Summary Fase 4a of the world-map migration (epic #229): the map editor now **opens, renders and edits the chunked world at 133M-cell scale**, so Andrea can actually draw the planet. Key changes: - **`EditorGame` on `ChunkedEditModel`** (was the dense `MapModel`): opens a world **directory** (`content/worlds/asterra/`) by reading only the manifest, or a fresh ocean of a configurable size (default 13,344×9,984); **incremental save** (only changed regions); **import** a legacy `world.map` once. - **Flat top-down biome canvas** (`MapPaintRenderer`) instead of iso. The editor is a *drawing* — the game renders the iso look. Each terrain gets **one hex colour** (its `TileData` Tint); the visible window is filled chunk-by-chunk into a single bitmap, uploaded once per view-move/edit and blitted each frame — fast at world scale, no per-cell draw. (WYSIWYG-iso is dropped for the editor; the guardrail is updated to match.) - **Fill** (`ChunkedFlood`): flood the connected terrain region — draw a coastline, fill the interior with grass. **Bounded** (per-chunk visited bitmaps + a cell budget) so an unclosed border can't fill the 133M ocean — it aborts with no change. - **Continuous stroke** (`Brush.Line`/`Brush.Stroke`, Bresenham): a fast drag paints a gap-free line instead of skipped cells. - **Configurable brush size** (numeric input, up to 256) + paint-on-cell-change; **Single / Rect / Fill** brushes; terrain / static / erase / spawn / Raise·Lower·Set Z tools. - **Scale grid**: chunk (32) + region (256, brighter) + cell lines (when zoomed in), with a `chunk cx,cy` + `px/cell` readout — so the author can tell zoom + position on a flat map. - **Shared `IsoViewport.VisibleCellBounds`** extracted into `Client.Core` (the game's ground blend + the editor both use it, tested once). - Headless harness: `--world` / `--import` / `--goto` / `--cellpx` / `--screenshot`. - **First authored world committed**: `content/worlds/asterra/` — a continent draft (grass coast, brown interior, islands, a volcano). A draft: spawn not yet set. Not in scope (later slices): the full-planet **overview / mip** (Fase 4b), undo/redo + autosave, statics/Z shown on the map, and — importantly — **wiring the chunked world into the client/server (Fase 7)**: the game still reads the legacy `world.map`, so this world is authored + tested in the editor, not yet playable in-game. ## Screenshots / recording Piloted via the editor's headless `--screenshot` — see the comment below (fresh 133M ocean, imported 2304², the scale grid, and the authored `asterra` continent). ## How it was tested - **Unit tests** (`Client.Core` + `MapEditor.Core`): `IsoViewport.VisibleCellBounds` (symmetry / zoom / camera-centred, +3); `ChunkedFlood` (fills a bordered region, aborts over budget, +2); `Brush.Line`/`Stroke` (endpoints + gap-free, +3); model `RaiseZ`/`InBounds` (+2). - **Piloted the editor headlessly**: a fresh 13,344×9,984 ocean opens with `dirty 0` (no per-cell allocation); the imported 2304² world renders; **the authored `asterra` world opens and round-trips** (`dirty 0`, byte-identical save/reopen). - Whole solution builds **0 warnings**; `dotnet test` fully green (MapEditor.Core 42, Client.Core 181, …); `just lint` + `check-docs` clean; `docs/map-editor.md` + the editor guardrail updated. ### DoD delta (beyond the base DoD + epic #229) - The editor opens + edits the 133M-cell world with memory bounded to the edited chunks, and a fast (bitmap-blit) canvas. - `Allaga`/New-ocean, incremental save, legacy import, and a bounded Fill that cannot run away on the ocean. - Save→reopen preserves the authored world (proven on the real `asterra` map). ## Checklist - [x] `just lint` passes (CSharpier + analyzers, zero warnings) - [x] `just test` is green - [x] The whole solution builds (client and tools included) - [x] Multi-platform preserved (DesktopGL editor; pure managed logic in Core) - [x] Tests added/updated for this change - [x] Linked the related issue (#229) and its per-PR DoD is met - [x] Screenshots (piloted editor) — in the comment below
Author
Collaborator

Screenshot pilotati (editor headless --screenshot):

La world asterra creata da Andrea (continente + vulcano), aperta a 0.5px/cella
asterra_view.png

Griglia di scala (chunk/regione) + import 2304
grid_shot.png

Oceano fresco 13.344x9.984 = 133.226.496 celle, dirty 0
ocean_shot.png

Screenshot pilotati (editor headless `--screenshot`): **La world asterra creata da Andrea (continente + vulcano), aperta a 0.5px/cella** ![asterra_view.png](https://git.homelab.devncode.it/attachments/cf826197-9a1a-4ea0-b112-2a7d34828372) **Griglia di scala (chunk/regione) + import 2304** ![grid_shot.png](https://git.homelab.devncode.it/attachments/1291edc8-010a-424a-8567-5cac1bcf003f) **Oceano fresco 13.344x9.984 = 133.226.496 celle, dirty 0** ![ocean_shot.png](https://git.homelab.devncode.it/attachments/87fc0e1b-c564-4529-9f23-1c68c365d06b)
panda merged commit f3f0243d76 into main 2026-08-01 10:15:19 +02:00
panda deleted branch feat/editor-chunked-4a 2026-08-01 10:15:19 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo!234
No description provided.