Files
matthewtrahanandRemusTL 08c0a2b1ce blender: Draw wall + Lay face flat -- click the part for one hand-placed wall (the site's Draw), or the face to put on the bed
Draw wall: two clicks under an overhang make one wall through drawWall, with an orange
preview line between the first click and the mouse; a line the engine refuses says why.
Each drawn wall keeps its ends in the part's frame, so Generate re-stands it for the
part's current pose (the site's rebuildDrawn) or says why it no longer fits; a drawn
wall alone marks the fins out of date when the part moves. Lay face flat turns the part
so the clicked face is down, keeping its lowest point, and drops the old pose's fins.

The tools start from the sidebar but cast from the 3D View's window region, and any
error ends them cleanly (no preview handler or header text left behind).

Co-authored-by: RemusTL <336249490+RemusTL@users.noreply.github.com>
2026-10-01 14:24:13 -05:00

4.6 KiB

Support Fins — shared plugin code

Code every plugin that can run JavaScript shares, so they all run the website's engine (web/*.js), unmodified, instead of keeping their own copy of the geometry. A fix on the site reaches a plugin the next time it is built.

engine/fins_entry.js    posed triangle soup in (mm, z up) -> fin + bed-pad triangles out,
                        plus `pieces` (which triangles are which fin, for a host that
                        shows one object per fin), `overFaces` and `smallFaces` (the
                        faces the site paints red, and amber: too small to fin)
engine/draw_entry.js    Draw mode: the same soup + two points -> one hand-drawn wall
                        (web/draw.js drawnWall, called the way the site calls it)
engine/seat.js          what both entries do first: centre + snap the part, pick the
                        material's clearances -- so a wall doesn't move with plate position
engine/bridge.js        base64 in/out for Python hosts running the bundle in V8 (mini-racer)
engine/options.json     the settings every plugin dialog is built from: key, type, default,
                        range or choices, label, tooltip, section, when it shows. Defaults,
                        ranges and choices are pinned to the website's controls (web/index.html)
                        by tests/options.test.js; fins_entry.js takes its defaults from it.
                        A host builds its dialog from it and passes the values through
                        optionsFromDialog() (and optionVisible() for show/hide; from Python,
                        host_options / host_visible), never by hand
engine/report.js        the one-line result (walls, tines, overhangs not reached, floating
                        pieces) for JS hosts (the CLI); Python hosts' host_report says
                        the same words
vendor.py               mini-racer vendored into a plugin folder, per platform, for hosts
                        that can't pip-install (Cura, FreeCAD): their build.py uses it
bundle.py               esbuild: bridge.js + web/*.js -> one IIFE, global SupportFinsEngine
py/supportfins_host.py  Python side for plugins that run the bundle in mini-racer: start V8
                        (host_engine), run the engine on a soup and map the fins back to
                        the caller's frame (host_compute; host_compute_pieces adds the
                        per-fin pieces and overhang faces; host_draw_wall draws one wall);
                        a settings dialog's values to
                        engine options (host_schema, host_options, host_visible). Orca inlines it
                        at build time
py/supportfins_slice.py mesh -> per-layer polygons (split_shells, slice_soup, group_loops),
                        for hosts whose API takes layer polygons, not a mesh. Pure numpy.
                        Orca inlines it at build time
tests/                  Deno tests: same fins as the website, anywhere on the plate;
                        the base64 bridge round-trips exactly
ENGINE-SENSITIVITY.md   engine note: tine placement moves under 1e-13 mm of noise, and
                        how fins_entry.js neutralises it
python3 plugins/shared/bundle.py out.js     # needs esbuild (npx fetches it on demand)
deno test --allow-read plugins/shared/tests/
python3 -m pytest -q plugins/shared/py/tests/   # needs numpy, trimesh, mini-racer==0.14.1

What goes where. Anything two plugins could use lives here: engine host, mesh slicing, and next the options every dialog is built from. plugins/<host>/ only calls into that host's API (read the part, show a dialog, add the result). A plugin that needs a new piece of geometry adds it here, with its own tests, instead of in its adapter. Fusion is the exception: its fins_core/ is pure Python because Fusion has no numpy, and moves here only when another plugin wants per-fin objects.

Used by: Orca (inlines the bundle into its single-file plugin), Cura and FreeCAD (ship the bundle and the Python host next to the plugin), and Blender (the same, with mini-racer as a wheel Blender installs; it uses the per-fin pieces and drawWall). Onshape (FeatureScript) and Prusa (Lua) can't run JavaScript, so they don't use this.

CI: .github/workflows/plugins.yml rebuilds and tests the plugins on every PR and push that touches web/ or plugins/, and on main publishes the builds to the plugins-latest pre-release.