# Polygon County Scenery Editor

Polygon County Scenery Editor is a local, browser-based tool for authoring roads,
places, land use, buildings, and vegetation over an existing Polygon County terrain.
It uses TypeScript, Three.js, and WebGL to keep large scenery projects interactive and
exports engine-neutral files for a separate viewer or game runtime.

The primary application is the version 2.0.0 web editor. A preserved Python/Tkinter
prototype is included under `python_reference/` as a behavioural and file-format
reference; it is not required to run the web application.

## What the editor does

- Loads a float32 NPY terrain and its matching terrain descriptor without modifying
  the source files.
- Authors editable place and land-use polygons, roads, hedgerows, prefab instances,
  and manually placed native vegetation.
- Loads an asset catalogue and previews catalogue prefabs as GLB models when their
  resources are available.
- Imports large, non-editable vegetation-v1 placement datasets and resamples their
  runtime elevations against the working terrain.
- Applies optional, non-destructive terrain pads beneath prefabs.
- Provides undo/redo, object locking, visibility controls, project save/open, and
  browser file relinking.
- Generates deterministic settlement surveys, terrain-aware A* roads, road frontage,
  internal street networks, and complete multi-settlement county plans.
- Previews generated work before baking it as ordinary editable project records.
- Uses chunked and instanced GPU rendering for the full 32,498-record vegetation
  benchmark rather than creating one Three.js object per vegetation record.

The editor is an authoring application, not the final Polygon County viewer. Exported
runtime data describes what should exist and where; the consuming viewer remains
responsible for its own final road meshes, junction meshes, asset loading, materials,
lighting, collision, and gameplay behaviour.

## Inputs and outputs

### Typical inputs

- A source float32 `.npy` terrain heightfield.
- The matching terrain JSON descriptor.
- An optional asset catalogue v3.
- Optional imported vegetation placement data v1.
- Optional county-feature reference data.

The browser stores file handles only where the browser permits it. After reopening a
project, the editor may ask you to relink source files. Stored source paths are hints,
not permanent browser filesystem permissions.

### Main outputs

- Editable scenery project v4 JSON.
- Final terrain as a 16-bit greyscale PNG with matching metadata JSON.
- Runtime scenery v3 JSON.
- Resampled imported vegetation v1 JSON.
- A viewer bundle v2 ZIP containing its manifest, final heightmap and metadata,
  runtime scenery, and—when loaded—resampled vegetation and catalogue documents.

The viewer bundle deliberately does not embed GLB models, textures, source NPY data,
or other asset binaries. See
[the runtime export/importer guide](docs/RUNTIME_EXPORT_IMPORTER_GUIDE.md) for the
complete consumer contract. The
[bundle manifest v2 schema](src/schemas/viewer-bundle-manifest-v2.schema.json)
requires both final terrain files. Bundle v2 is the only supported bundle version.

Application version numbers and data-schema versions are independent. Version 2.0.0
of the editor currently saves project schema v4 and exports runtime scenery schema v3.

## Requirements

- Node.js 18.19.1+ in the 18.x line, 20.9+ in the 20.x line, or 22+.
- npm 9 or newer; npm 9.2.0 works with the Node 18 compatibility target.
- A current desktop browser with WebGL support.
- Git, if cloning instead of downloading a source archive.

The production application is static. It requires an HTTP server but no application
backend.

The development tools are pinned to Node 18-compatible releases, including Vite 6.
Use `npm ci` to install the exact dependency tree from `package-lock.json`; no global
Vite, pnpm, or Corepack installation is needed. When intentionally changing
dependencies, use `npm install` and keep the updated lockfile with `package.json`.

## Run on Windows

Open PowerShell:

```powershell
git clone https://github.com/countfuzzball/3JPCS.git
cd 3JPCS

npm ci
npm run dev
```

Open the local URL printed by Vite, normally
[http://localhost:5173](http://localhost:5173).

If PowerShell reports that `node` or `npm` is not recognized after
installing Node.js, close and reopen the terminal so that it receives the updated
`PATH`.

## Run on Linux

Open a terminal:

```bash
git clone https://github.com/countfuzzball/3JPCS.git
cd 3JPCS

npm ci
npm run dev
```

Open the local URL printed by Vite, normally
[http://localhost:5173](http://localhost:5173).

## Create and edit a project

1. Start the development server or production preview.
2. Choose **File → New Project…**.
3. Select **Import terrain ZIP bundle** and choose the terrain editor's **All
   formats (.zip)** export, or select the source float32 NPY and matching descriptor
   individually.
4. The editor loads `assets/catalog.json` automatically, or supplies `house_demo_01`
   if it cannot load a usable catalogue. Select **Place prefab** to start placing.
   Load another catalogue manually whenever needed.
5. Bundled county and vegetation references load automatically. Individual-file
   projects can import these separately.
6. Draw or generate scenery, inspect the preview, and bake the accepted results.
7. Choose **File → Save** or **Save As…** to save the editable project JSON.
8. Export the final terrain and required runtime documents for your viewer.

### Top menus

**File** contains New Project, Open Project, Save, and Save As. Save commands follow
the current project and pending-write state. **Generate** opens non-modal windows
for Build County, Settlement Survey, Road Routing, and Frontage and Population.
Generation settings and actions now live in these windows instead of the sidebar.

Click a menu to open it; click outside or press Escape to dismiss it. Arrow keys
navigate menus and available commands, Home/End select the first/last available
command, and Enter activates the focused command. Editor shortcuts are suspended
while the menubar has focus.

### Generation windows

Several windows can remain open while you work on the terrain. Drag a title bar
to move a window and drag its bottom-right handle to resize it. Focus the Move or
Resize button and use arrow keys for keyboard positioning or resizing; Shift
increases the step. Windows stay inside the workspace and scroll independently.
Choosing an open window from Generate brings it to the front.

Close or press Escape with focus inside a window to hide it. Settings, previews,
and running generation remain intact; use the existing Cancel or Clear actions
to discard work. Closing leaves the active map tool unchanged. Window positions,
sizes, and the frontage tab are remembered for this session only, and reset on
reload. Escape on the terrain retains its usual interaction-cancellation behaviour.

Opening Road Routing activates Route Road. The road-frontage tab of Frontage and
Population activates Frontage Assist; the settlement-population tab enables
selection of a place region. The corresponding sidebar tool buttons also open
these windows. Frontage and Population shares side, setback, gap, and end
clearance between its two tabs, and its house selector updates the placement
asset in the sidebar. Other authoring tools and catalogue loading remain there.
Menus can open before a project is loaded; unavailable controls explain their
prerequisites and remain disabled. Editor shortcuts are suspended while a
generation window has focus.

### Import a terrain-editor ZIP

In **File → New Project…**, select the exported `polygon_county_runtime.zip` under
**Import terrain ZIP bundle**, then choose **Validate & create project**. The ZIP
takes priority over the individual terrain pickers; clearing it enables them again.

The importer reads `terrain_heights.npy` and `terrain_heightmap.json`, plus
`generated_vegetation.json` and `county_features.json` when present. PNG and CSV
entries are not needed. Source files may be at the root or together inside one
folder. A PNG + metadata-only ZIP is insufficient: use **All formats (.zip)** in
the terrain editor. Archives containing multiple exports are rejected.

Terrain dimensions and optional references are validated before the current project
is replaced. Imported vegetation and county features remain reference layers until
explicitly converted to editable objects. The existing automatic asset catalogue
and demo-house fallback still apply. ZIPs and their expanded source files are each
limited to 512 MiB.

To reopen saved scenery, choose **File → Open Project…**, then select its project
JSON and the original ZIP under **Terrain ZIP bundle**. This restores terrain and
available references without picking each source file. Explicit relink fields take
priority over the ZIP. The scenery
project stores source filenames, not the ZIP contents; keep the original bundle.

### Automatic asset catalogue

Place a catalogue v3 file at `3JPCS/assets/catalog.json`. New projects and opened
projects without a supplied catalogue automatically try that URL relative to the
application, including when hosted under a subdirectory. An explicitly relinked or
companion catalogue takes priority on Open. Missing custom source hints are retained
for later relinking, with a warning when automatic assets substitute for them.

A missing, invalid, empty, or unresponsive catalogue falls back to a built-in
`house_demo_01` house entry with a 10 × 8 m footprint and 4.5 m wall height. This
enables the editor's existing footprint/proxy placement without requiring a GLB.
The selected catalogue remains replaceable using **Load asset catalogue v3**.
Discovery runs during New/Open, rather than changing catalogues during editing.

`npm run build` copies the optional root `assets/` directory into `dist/assets/`,
preserving the working set for static hosting. Keep any files you want deployed in
that directory. Saved projects retain catalogue path hints; viewer bundles include
the active catalogue JSON, including the demo catalogue when used.

### Editing controls

Basic viewport controls:

- Mouse wheel: zoom around the cursor.
- Middle- or right-drag: pan.
- `F`: fit the terrain in the viewport.
- `Enter` or double-click: finish a drawn geometry.
- `Backspace`: remove the latest draft point.
- `Escape`: close an open New/Open Project dialog; otherwise cancel the current
  draft or placement mode. Cancel and × also close these dialogs without requiring
  files. Editor shortcuts are suspended while either dialog is open.
- `Delete`: delete the selected object.
- `Shift+Delete`: delete a selected geometry vertex where valid.
- `Ctrl`-click a selected road or hedgerow segment: insert a point.
- `Q` / `E`: rotate a selected prefab or vegetation instance.

The **Place prefab** and **Place vegetation** controls are toggle tools. While enabled,
each click places another instance of the current selection. Toggling the active tool
off returns to selection mode; enabling one placement tool disables the other.

Generated settlement, route, frontage, and county results remain non-mutating previews
until explicitly baked. County baking is atomic, so one undo removes the complete
generated build.

**Build County** plans farm buildings around an open courtyard before routing the
internal track. Each farm targets 5–9 buildings: one farmhouse, one barn, and the
remaining sheds. Courtyard size follows the mapped assets' footprints rather than
the farm polygon size. Buildings face the courtyard, with the farmhouse near its
entrance; a connected track ends inside the yard instead of forming a loop.

Map farmhouse, barn, and shed assets under **Advanced county policy** when available.
Unmapped farm roles use the required house mapping, including `house_demo_01`.
Names such as `Farm 01 — Farmhouse` and `Farm 01 — Shed 1` identify the intended
roles while preserving the actual assets and categories. Optional short service
spurs follow the existing driveway toggle and budget.

Tight sites may fit fewer buildings, with a warning, down to a farmhouse and barn.
If that minimum cluster or its safe connecting track cannot fit, the preview is
incomplete and baking is disabled. Network-only output creates connected farm
access without buildings or a yard loop and needs no asset mapping. Courtyard
outlines follow the Roads preview filter and selected settlement; they are planning
space, not a baked hardstanding surface. Generation policy v2 changes newly
generated farms only: saved scenery and export formats are unchanged.

Saving captures the project when the save starts. You can continue editing during
the write; later edits keep the **UNSAVED** marker and require another save. Save
and Save As remain disabled until the current write completes. Switching projects
does not transfer a pending save's file target or saved status to the new project.
Saving also preserves running Build County generation and its unbaked preview;
changing scenery, sources, or generation settings still invalidates that work.

Runtime and viewer-bundle exports capture the scenery and working terrain together
when export starts. Edits made during hashing or compression belong to the next
export. File formats are unchanged.

## Build for production

The commands are the same on Windows PowerShell and Linux:

```text
npm ci
npm run build
npm run preview
```

The production files are written to `dist/`. Open the HTTP URL printed by the preview
server, normally [http://localhost:4173](http://localhost:4173).

For static deployment, upload the contents of `dist/` to an HTTP server or static
hosting service. Asset URLs are generated relative to the deployment directory, so
the build can be hosted at the domain root or beneath a path such as
`/polygon-county/`.

Do not open `dist/index.html` directly through `file://`. Browsers require an HTTP
origin and correct JavaScript MIME types for ES modules. Opening the file directly, or
using a host that rewrites missing JavaScript assets to an HTML fallback page, can
produce errors such as:

```text
Loading module was blocked because of a disallowed MIME type ("text/html")
```

## Tests and verification

Run the static checks, unit tests, and production build:

```text
npm run lint
npm run typecheck
npm test
npm run build
```

Install Playwright's Chromium browser once, then run the browser workflows:

### Windows

```powershell
npx playwright install chromium
npm run test:browser
```

### Linux

```bash
npx playwright install --with-deps chromium
npm run test:browser
```

The browser tests run against the production `dist/`, so run `npm run build` first.
The unit suite contains 215 Vitest tests; the browser suite has 17 Playwright workflows.

Run the deterministic full-scene performance benchmark with:

```text
npm run benchmark
```

## Optional Python/Tkinter reference

The original v0.2 editor is preserved in
[`python_reference/`](python_reference/README.md). It has its own dependencies and
does not participate in the TypeScript build.

### Windows

```powershell
cd python_reference
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe main.py
```

Run its compatibility tests with:

```powershell
.\.venv\Scripts\python.exe -m pytest -q
```

### Linux

```bash
cd python_reference
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python main.py
```

Run its compatibility tests with:

```bash
python -m pytest -q
```

Some Linux distributions package Tkinter separately; for example, Debian and Ubuntu
users may need the `python3-tk` package.

## Repository layout

```text
src/app/          application composition and editor state
src/model/        authored entities, validation, migrations, and coordinates
src/history/      delta-based commands and undo/redo
src/io/           project persistence, imports, exports, and viewer bundles
src/terrain/      immutable base terrain and derived working terrain
src/rendering/    Three.js projections and GPU vegetation batches
src/interaction/  navigation, picking, editing, frontage, and placement logic
src/generation/   survey, A* routing, frontage, and county generation
src/workers/      background routing and county-build workers
src/schemas/      versioned JSON schema snapshots
tests/            unit, contract, benchmark, and Playwright browser tests
docs/             format guides and implementation milestone records
examples/         example descriptors, catalogues, and scenery documents
scripts/          fixture and benchmark tooling
python_reference/ preserved Python/Tkinter reference implementation
```

## Further documentation

- [Three.js rewrite architecture and implementation record](README_THREEJS_REWRITE.md)
- [Scenery format overview](docs/SCENERY_FORMATS.md)
- [Runtime export/importer guide](docs/RUNTIME_EXPORT_IMPORTER_GUIDE.md)
- [Settlement automation milestones](docs/SETTLEMENT_AUTOMATION_MILESTONE_PLAN.md)
- [Settlement-network automation milestones](docs/SETTLEMENT_NETWORK_AUTOMATION_PLAN.md)
- [Milestone 5 performance benchmark](docs/MILESTONE_5_BENCHMARK.md)

## License

Polygon County Scenery Editor, including the Three.js rewrite and preserved Python
reference implementation, is free software licensed under the GNU General Public
License version 3 or, at your option, any later version (`GPL-3.0-or-later`). See
[LICENSE](LICENSE). Third-party dependencies retain their respective licences.
