Repository navigation
@meterup/pascal-viewer@1.0.0-beta.6
Pre-releaseMinor Changes
-
d3aa350: Let a host bind the 3D camera's gestures.
The bindings were fixed: left drag selects unless you're in preview mode or
holding space, middle pans, right rotates, wheel zooms. A host whose scene is
read-only, or whose users are on laptop trackpads with no middle button, had no
say — panning meant the space bar.cameraInputonuseViewermerges over the defaults rather than replacing
them, so an unset entry keeps whatever the current mode asked for:useViewer.getState().setCameraInput({ mouseButtons: { left: "pan" }, touches: { one: "pan" }, });
Actions are named for what the user sees (
pan,rotate,zoom,dolly,
andzoomPan/dollyPanfor the combined two-finger gestures) rather than
mirroring the camera library's enum, so the binding API doesn't tie a host to
that dependency. The wheel and the one-finger slots take narrower sets than the
others, because a wheel has one axis and a pinch needs two fingers.Merging also covers the modifier path, which rebuilds the bindings on every key
change, so holding space no longer drops a host's overrides. -
2f5c4e1: Rebase the fork onto upstream
pascalorg/editor@4c34032c(2026-08-24) — 478
commits, and a move off the fork's own0.9.xline onto upstream's1.0.0-beta
versioning. The fork now carries nothing but its release machinery and two
editor patches; everything else is upstream.Nothing we previously exported was removed. The public API grew substantially
(core 172 → 388 exports, viewer 106 → 193, editor 156 → 470) without breaking
underneath consumers.What matters most for consumers:
- Near-collinear wall junctions no longer explode.
calculateJunctionIntersectionsnow rejects a miter on its outcome, capped
atMITER_LIMIT(10) half-thicknesses, rather than only rejecting walls that
are exactly parallel. A junction where two walls run straight through each
other but miss collinearity by a fraction of a degree used to put a plan
vertexhalfThickness / sin(θ)away — kilometres out, collapsing the 2D
fit-to-bounds into one flat rectangle and firing beams across the 3D scene. It
now butts. Imported floor plans with off-axis wall runs render correctly. - Level assembly is dramatically faster.
findJunctionsbuckets walls into
a spatial grid by AABB instead of testing every wall against every junction
point. On a 1081-wall imported floor that is 584 ms → 11 ms per call, and
WallSystemrepeats the call every frame while progressively rebuilding. - Vertical building model. Scenes now carry explicit building and level
structure (buildingId,schema/nodes/building.ts), with load-time
migrations for saves that predate it — vertical, site-child, wall-slot,
elevator, retired-floorplan and construction-dimension. Anything synthesizing
aSceneGraphrather than loading a saved one needs to match the new shape;
this is the single change most likely to require work on the consumer side. - New packages:
capture-protocol,capture-viewer,cli. New core
systems alongsidewall/andstair/:fence/,slab/,elevator/. healSceneNodesrepairs already-saved scenes on load, dropping
degenerate nodes such as zero-length walls.
Three fork patches are dropped here because upstream made them redundant:
- The
floorplan-registry-layergeometry cache. Upstream landed its own
geometryCacheRef/levelDataCacheRefmemoisation plus thefindJunctions
prefilter above, which together address the same stall from further up. - The
ThreeElements/lineBasicNodeMaterialnarrowing inviewerthat let
tsgocheck the package. Upstream adopted the TypeScript 7 native compiler
and landed the identical narrowing. crossOriginon the 2D guide image. It forced the 2D<image>to fetch in
the same CORS mode as the 3D texture load so the two shared one browser cache
entry instead of downloading the image twice. Consumers that hand Pascal
same-origin blob URLs never hit the split in the first place, and the flag is
actively wrong for guide images served without CORS headers.
- Near-collinear wall junctions no longer explode.
-
e1d3a5a: Add
showSiteBoundaryto hide the site's boundary geometry.The boundary was always drawn, with no way to turn it off. It is a useful
reference while laying out a site and pure noise on a surface that only presents
a finished building.showSiteBoundaryjoinsuseViewernext toshowGrid/showZonesand
governs both views from one flag, because it is the same polygon in each:useViewer.getState().setShowSiteBoundary(false);
In 2D that drops the dashed polygon, its edge labels and its handles. In 3D it
drops the ground pad and the amber outline. Buildings, items and the horizon
ground are unaffected, so the scene loses its lot outline rather than its floor
— the horizon disc punches holes for slab footprints, not for the site polygon,
so it still covers the ground the pad was covering.Two things stay deliberately outside the flag. The fitted viewport still sizes
itself from the site polygon, so toggling this doesn't reframe the plan. And
sculpted terrain keeps rendering, since that is modelled geometry rather than
boundary chrome.Defaults to
trueand isn't persisted, so nothing changes until a host sets it.
Patch Changes
-
54e1b19: Let a scene theme set the ground grid's line colours and idle opacity.
appearancehardcoded both colours, and in dark mode<Grid>also ignored its
owncellColor/sectionColorprops, so neither a theme nor a host could
adjust how the grid read. That matters because the grid is drawn over the lit
groundfill: its contrast against that surface is a property of the pair, and
a light/dark flag can't settle it.groundandbackgroundSkywere already
carved out ofappearancefor the same reason.const theme = SCENE_THEMES.find((t) => t.id === "night"); theme.grid = { cell: "#2b2d3a", section: "#343747", idleOpacity: 0.18 };
All three keys are optional and fall back to the previous
appearance-derived
values, so existing themes render identically.idleOpacityapplies to the
always-on ground reference only; an active placement patch keeps its own
brightened treatment.