A drawing that owns no annotation scales is shown the standard set, which
`scale_list` substitutes whenever the drawing's own list is empty. The
first thing to need a real scale object — an annotative dimension, a pick
from the status bar, a viewport scale — wrote just the one it wanted. The
drawing then had a list of its own, of exactly one entry, so the
substitution stopped and every other scale disappeared from the picker.
Bring the whole set in before writing that first scale. It is the set the
drawing was already being shown, so nothing appears that was not on offer
a moment earlier, and the drawing ends up owning its scales the way one
that shipped with a list does.
The seeding itself already existed for the scale manager, which stages it
on open; it simply was not reachable from the path that writes a scale.
Closes#666Closes#683
Co-Authored-By: Claude Opus 5 <[email protected]>
Only Previous and Last were on offer, so Window, Crossing, Fence, the two
polygons and All could not be reached at all -- and with no keyboard to
type them into, the buttons were the only way in.
Window and Crossing fix the sense of the next box. Dragging derives that
from the direction the corner travels and would overwrite it the moment
the corner moved, so the derivation stands down while a keyword holds it.
Add and Remove decide what a pick does for the rest of the round: Remove
subtracts the way Shift already does, rather than through PICKADD, which
decides whether a pick *replaces* the set and so would have wiped
everything gathered so far. Both are dropped when the next command
starts, since neither outlives the selection that asked for them.
Fence and the polygons are picked point by point, which TRIM and EXTEND
already ask for. That gesture -- the points, the rubber-banded dashed
preview, whether the path closes -- moves into one place both bind to,
and the two preview builders duplicated in trim.rs go with it.
A fence is not the polygon test with crossing set: that closes the point
list and counts whatever lies inside, so a line drawn past a row of
objects would take everything behind it too. It gets a hit test that only
counts a real intersection, and skips the area-based geometry entirely.
The lasso gathered its hits from wires, hatches, block hatches, meshes and
block meshes inline; the new modes need the same list, and a second copy
would drift. Both now come through `Scene::path_hit_handles`.
Closes#596
Co-Authored-By: Claude Opus 5 <[email protected]>
A revolution comes back from rsweep as three 120-degree segment faces,
but every hole was attached to the first of them. A window wider than a
segment cannot sit on one face, so that face turned invalid and its
whole third of the tube vanished -- the pump's cylinders lost 120
degrees of wall each and the solid read as open where they met the body.
One of them shed a segment with no hole involved at all, so chasing the
individual causes would not have covered it.
Measure the result instead: after a cone face whose boundary closes the
revolution is triangulated, check that the meshed vertices actually span
it, and hand the face to the parametric sampler when they do not. That
catches a tear whatever produced it, while genuinely partial cones and
every non-cone surface pass straight through -- the tee's pierced run
cylinder still meshes through the kernel.
Also bring truck's chord tolerance in line with the detailed LOD. Truck
emits a single mesh rather than an LOD ladder, so a tenth of the radius
left a wide pipe as a hexagonal prism whose flats sank nine units inside
the true surface, pulling the wall away from the caps and planar faces
that meet it.
Co-Authored-By: Claude Opus 5 <[email protected]>
The cone-surface record's trailing real is a parameter scale, not
geometry. It equals the radius on many bodies, so cylinders generally
came out right, but where the two diverge the lateral surface was built
at the wrong size while the flat caps stayed on their own rims -- a
gauge dial drew as a ring around its own face, its band at 43.2 against
caps at 34.56.
The major axis is the radius vector at the reference cross-section, so
its length is the radius. Route every read through one helper and keep
the record's field only as a fallback for a degenerate major axis, so
the band, the silhouette generators, the isolines and the coaxial-rim
check all size themselves the same way. Taper is unchanged: the major
axis is still the h=0 radius that radius + h*tan(a) extends.
Co-Authored-By: Claude Opus 5 <[email protected]>
Sphere faces drew as complete balls. ACIS parametrises a sphere about
any pole, so a vessel's dished head is commonly bounded by a circle that
is no line of latitude in that frame, and a theta/phi bounding box of
such a boundary covers nearly the whole ball. Derive the window
analytically instead: when a face's loops are circles lying on the
sphere, re-pole the frame onto their common axis, where each seam is an
exact latitude at acos(d / R). One ring bounds a cap, two bound a zone;
the material side comes from the boundary winding, reusing the helper
the torus path already had.
Separately, the longitude wrap flag was resetting the colatitude window
to the whole meridian. A cap centred on the pole covers every longitude
while still ending at its seam, so that reset grew every cap back into a
ball. Trim the two angles independently and rename the flag theta_full
so the split reads at each use, including the silhouette generator,
which skipped the colatitude test the same way.
Cone faces took their height span from the first boundary loop alone. A
lateral face closed off by one rim and one pierce curve -- a pipe branch
meeting its run -- carries its two ends on different loops, so the tube
was sized to whichever came first and the leg above the junction went
undrawn. Read every loop.
Co-Authored-By: Claude Opus 5 <[email protected]>
Add a searchable block palette with previews, file import, collision-safe nested definitions, and dependency/table-record import. Keep palette thumbnails current across drawing switches and block-definition edits.
Route model, paper, viewport and nested block content through one traversal while preserving leaf renderers. Carry decoded material state into mesh shading and harden solid geometry conversion.
- Keep the floating panel near the selection and inside the viewport
- Persist the toggle and hide the panel without a selection
- Show only Material in 3D Visualization
Scope revolution spans to face boundaries and preserve pierced cylinders and rational spline lofts so valid bodies no longer produce stretched or missing shells.
Preload one language-aware font resource across the interface, drawing text, and navigation labels.\n\nRender the navigation cube, ring, outlines, and labels through a 4x MSAA target.
Keep Layout output on the selected physical sheet and preserve hatch lineweights and plot styles through paper, viewport, and nested block paths.\n\nRefs #607
- unify Model and Paper Space plot area behavior
- add CTB discovery, read/write, and bundled defaults
- apply scale, render mode, and output options consistently
Use the same area pipeline as model space while keeping Layout bound to the physical sheet and printable margins. Share scale, rotation, clipping, and viewport fills across preview, PDF, and printer output.
Pin Iced 0.15 so dialogs can measure content before distributing the resolved frame across child panels. Keep the web plugin notice compact and non-resizable.\n\nCloses #582