6 Commits
Author SHA1 Message Date
[as] a4443d9abd Merge pull request #2 from gittrahan/review-fixes-per-fin-removal
Review fixes for per-fin removal (state/UX/perf)
2026-09-23 11:39:15 +07:00
kodin00 d13b8f505e dev: configurable bind address for dev-server (--host)
Add a --host option to both dev-server.py entry points so the dev
server can be reached from other devices on the LAN (e.g. a headless
Raspberry Pi behind a firewall). Default stays 127.0.0.1 (localhost);
pass --host 0.0.0.0 (or ::) to expose it. When bound to a wildcard,
the script also prints the machine's LAN address to open.

Both scripts move to argparse, so --help documents the options and bad
input errors cleanly instead of tracebacking. The positional [port] is
unchanged for backwards compatibility (python3 dev-server.py 8080).

web/dev-server.py previously bound "" (all interfaces) by default; it
now defaults to 127.0.0.1 to match the safe-by-default principle and
the other entry point. Use --host 0.0.0.0 for the old behavior.

stdout is flushed before serve_forever() so the startup lines (and the
LAN hint) land immediately in a redirected log.

README documents the new option.
2026-09-22 13:07:02 +07:00
kodin00 c92661ae9e feat: click to remove individual auto-generated fins
Auto mode generated fins as one flat triangle soup in a single mesh, so a
user who wanted fewer had to scrap all of them and redraw the ones they
wanted by hand. Now each fin carries its triangle segment(s) so you can
drop just the one you don't want.

Data model (additive): every generator already had a `before = out.length`
hook, so each fin record now carries `triRanges` (vertex-indexed segments
into built.triangles), an `id`, a `kind` ('prop' | 'wedge'), and its
contact `line`. `buildFins` assembles a unified `fins` array where each
entry owns its geometry. The merged `built.triangles` is byte-identical.

UI (app.js + index.html): a "Remove fins" button (Auto mode, fins on)
arms a click-to-remove mode -- hover highlights a fin red, click drops
just that one. "Restore all" + undo bring it back. Removals are keyed by
a spatial signature (rounded line midpoint + bearing + height + kind),
not the volatile sequential id, so a fin stays removed across a same-
orientation rebuild (slider tweak) and survives an orientation round-trip.

Export needs no change: `finTris` is now the filtered set, so
`activeAdded()` / stl.js / threemf.js serialize it as-is and the grams
receipt + export triangle count drop with each removal.

Undo/redo snapshots `removedSigs` alongside pose/walls, so each removal
and each restore is one undo step.

Tests: new tests/fins.test.js pins that triRanges are in-bounds, non-
overlapping, cover every fin triangle exactly once, that each fin is a
watertight closed solid in isolation, and that filtering out one fin
excludes exactly its triangles and keeps the rest watertight. Existing
geometry suite unchanged (records only gain additive fields).
2026-09-22 12:28:30 +07:00
kodin00 0095995834 Merge remote-tracking branch 'upstream/main' 2026-09-22 11:26:34 +07:00
[as] e2996d3385 Merge pull request #1 from kodin00/add-docker-deployment
docker: add compose + nginx image for one-command local deploy
2026-09-21 20:32:26 +07:00
kodin00 b401a656d1 docker: add compose + nginx image for one-command local deploy
The web app is a buildless static SPA (three.js is vendored in web/), so the
deploy image is just nginx serving web/ on :80. This adds:

- Dockerfile: nginx:stable-alpine, copies web/ + LICENSE, OCI labels.
- nginx.conf: port 80 site config that mirrors web/_redirects
  (/index.html and /index 301 -> /) via a $request_uri guard that cannot
  loop with the `index` directive's internal redirect; cache policy mirrors
  dev-server.py (no-store on the app's own JS/CSS/HTML) while long-caching
  the vendored three.js tree (immutable per image tag); absolute_redirect
  off so the redirect stays relative behind a reverse proxy.
- docker-compose.yml: one `web` service, host 8731:80 so the URL matches
  `python3 dev-server.py`, with a wget healthcheck.
- .dockerignore: excludes prototype/, plugin/, tests/, docs/, the dev
  servers and model files so the build context is just the web artifact.
- README: "Run with Docker" block pointing at the new files.

Validated: image builds, `nginx -t` passes, GET / -> 200 no-store,
GET /index.html|/index -> 301 relative /, GET /vendor/... -> immutable
long-cache, no redirect loop on /.
2026-09-21 20:29:14 +07:00