* Zoom and pan regenerate in the background instead of freezing the window
A rebuild that only the view asks for (a new 2x zoom band, a pan out of the
built area) now runs on a worker thread while the canvas keeps drawing the
previous display list, scaled by the view uniform. The worker builds the list,
converts it to vertex data and creates the GPU buffers, so the frame that swaps
it in only swaps buffers. One build runs at a time; a result from an older
drawing revision is dropped. Edits, the first build and the web build (no
threads) still rebuild synchronously.
ZOOM no longer calls touch(): it changes the view, not the drawing, and the
bumped revision made every typed zoom a full blocking rebuild (wheel zoom
never did). REGEN, REGENALL and layout switches still touch.
ui.screenshot waits (up to 6 s) for a background rebuild so agents capture
the new view; ui.inspect perf reports "building".
On a hatched 12k-entity DWG (~340k primitives) the longest UI stall per zoom
went from 2-4.5 s to 26-64 ms.
Also: cargo fmt of a comment in engine/src/prompt.rs that was failing the fmt
gate on main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Cancel a background rebuild when the view moves on
A view that needs a different display list now cancels the build in flight
and starts one for itself, instead of waiting for the outdated build to land
and only then starting the next. A long scroll through many zoom bands builds
only for where it stops: the list lands about one build after the last step
(2.0-2.3 s on a hatched 12k-entity DWG) instead of up to two, and an outdated
build no longer keeps a core busy.
cadcraft_render::Options gains `cancel` (an Arc<AtomicBool>); a set flag stops
the build at the next entity (block contents included) and the hatch sweep at
its next pattern line, returning a partial list the caller discards. The
canvas's Job sets its flag when dropped, so replacing or dropping a job
cancels it; a cancelled worker sends nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* cargo fmt: crates/doc/src/dynblock.rs (fails the fmt gate on main)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Draw object transparency on screen, in exports and in plots
Transparency was read and saved (entity group 440, layer xdata, ByLayer and
ByBlock) but never drawn. Display lists now carry each object's effective
transparency (its own, its layer's, or the block reference's), and:
- the canvas (GPU and CPU paths), ui.render and PNG/SVG exports blend it;
TRANSPARENCYDISPLAY turns it off on screen and is now on by default, as in
AutoCAD (initial value 1);
- plots draw it only when "Plot transparency" is on: a page setup option
(PAGESETUP `plotTransparency`, a checkbox in the Page Setup Manager and the
Plot dialog), overridable per plot, with PLOTTRANSPARENCYOVERRIDE (0 never,
1 the setting, 2 always). PDF gets /ExtGState alpha, PNG plots blend, SVG
uses opacity. Plots without it are byte-identical to before.
The public DXF Reference has no plot layout flag for plot transparency, so
the option is kept in the session and in JSON, not in DXF/DWG.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Transparency fixes: attributes, PDF overlaps, drag previews
- Attributes draw with their own transparency (their definition's, layer 0
meaning the reference's layer, ByBlock the reference's) instead of the
block reference's.
- PDF plots stroke overlapping transparent objects one by one, so they build
up where they cross as in PNG plots; opaque output is unchanged.
- Drag and rubber-band previews follow TRANSPARENCYDISPLAY.
- Effective transparency is worked out only when it is drawn, reusing the
layer the property lookup already found.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Transparency: one PDF stroke per transparent primitive; opaque rebuilt previews
- PDF plots never batch two transparent primitives into one path. Block and
viewport contents share their reference's handle, so the per-object flush
missed them; each primitive now blends on its own, as in PNG plots and on
screen. Opaque output is unchanged.
- Previews the session rebuilds with the current properties (rubber bands,
copies of objects) are drawn opaque again: they carry CLAYER's
transparency, not the objects'. The GPU drag of the objects themselves
keeps following TRANSPARENCYDISPLAY.
- Tests for attributes on a transparent reference layer, attributes without a
definition, and the drag cache across the TRANSPARENCYDISPLAY toggle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Selection like AutoCAD: colour highlight and the Options Selection tab
Selecting or hovering an object outlined each filled primitive (TrueType
glyphs, dimension and leader arrowheads, solid hatches, wide polylines)
by the rectangle around its triangles, and dashed everything else. A
selected dimension's text became a row of dashed boxes, one per glyph,
and its closed arrowheads small rectangles.
Selected objects are now redrawn in the selection colour: lines solid,
fills filled half see-through (so the lines and text on a highlighted
hatch stay visible), and the whole object reads as selected, text and
arrowheads included. A wipeout is always outlined, since filling it would
hide the drawing under it.
The Options dialog's Selection tab is laid out as AutoCAD's, with the
settings CADCraft can act on, each one AutoCAD's variable, kept in the
user profile:
- Selection modes: noun/verb selection (PICKFIRST), Shift to add
(PICKADD), Object grouping (PICKSTYLE bit 1, now saved in the profile).
- Selection effect color (selectionColor, an interface preference; null
is the theme's).
- Grips: Show grips (GRIPS) and the object selection limit for display of
grips (GRIPOBJLIMIT, 100; 0 no limit): grips are neither drawn nor
picked beyond it.
- Selection preview (SELECTIONPREVIEW): the object under the cursor is
highlighted when a command is active (2) and when none is (1).
- Visual Effect Settings: the selection area effect (SELECTIONAREA,
WINDOWAREACOLOR 150, CROSSINGAREACOLOR 100, SELECTIONAREAOPACITY 25)
and the Selection Preview Filter (PREVIEWFILTER 3: 1 objects on locked
layers, 2 xrefs, 4 tables, 8 multiline text, 16 hatches, 32 groups).
As in AutoCAD these are typed, not on the dialog: HIGHLIGHT (0 shows only
the grips of selected objects; not saved, so every session starts
highlighted), SELECTIONEFFECT (1 the selection colour, 0 dashed lines with
fills outlined along their real boundary) and PREVIEWEFFECT (the preview
dashed 0, thicker 1 or both 2).
Left for later, as CADCraft lacks what they control: lasso, grip tips and
menus, group grips, grips within blocks, associative hatch selection,
command and property preview, PICKDRAG, PICKAUTO and PROPOBJLIMIT.
DisplayList::fill_outlines returns the boundary of the region a filled
primitive covers as closed polylines (edges only one triangle has; the
slab filler's horizontal cuts, which need not line up between trapezoids,
are split at every x on their line and kept where an odd number cover
them), falling back to the bounding box over 600,000 vertices. The GPU
and CPU highlight paths and the drawing comparison overlay share the same
looks.
The new labels have Ukrainian rows (the required catalog); other
languages fall back to English.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: EP995LAB <293597958+EP995LAB@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
The view-limited path differs from full detail by ~3e-16 on Windows (float noise from the rotated-frame round trip); the test now compares structure exactly and coordinates within 1e-9.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
* Active viewport: redraw while panning and zooming inside it, without rebuilding the layout (#688)
Inside an active MSPACE viewport, middle-drag, trackpad pan and wheel or
pinch zoom change the viewport's view through set_view_quiet, which makes
no new revision. The layout's display list, which draws model space
through each viewport, was cached on (drawing, revision, zoom band), so it
kept showing the old view until a command such as ZOOM rebuilt it: the
viewport froze, or appeared to ignore the zoom.
The active viewport's contents are now drawn apart from the layout's list,
the way model space itself is drawn. They are built once for an area
around the viewport (half its larger side of margin all round), then moved
and scaled to the current view on the GPU and drawn under the layout's own
objects. They are rebuilt when the drawing changes, when the zoom has
moved 2x from the view they were built for, when the view leaves the built
area, and once a zoom comes to rest, so dash lengths and curve detail
follow the viewport's scale again. A pan step takes about 1 ms with 70,000
polylines, where rebuilding the layout takes about 140 ms per frame.
Rectangular viewports are clipped with the scissor rectangle. A clipped
viewport's outline is drawn into a stencil buffer as a triangle fan that
flips a bit (even-odd, as the outline clips on the CPU), and its contents
draw only where the bit is set; the native window now asks eframe for an
8-bit stencil buffer, and every canvas pipeline names its format. Where
there is no stencil buffer (the CPU canvas, the web runner), a clipped
viewport's contents stay in the layout's list, whose cache now follows the
viewport's view.
Render: Options::skip_viewport leaves a viewport's contents out of a
layout, and viewport_content builds them for any area. Viewport contents
are built on all cores, like model space (130 ms to 37 ms for 70,000
polylines).
* Active viewport highlight: selection on the GPU, hover cached apart, kept inside a clipped outline
Inside an active MSPACE viewport the selection highlight was drawn as
dashed egui shapes on the CPU every frame, about 8-13 ms per frame with
7,000 polylines selected, and its geometry was cached together with the
hover, so moving the cursor over objects tessellated the whole selection
again. The selection and the hover are now cached apart, and the
selection goes through the GPU highlight path model space already uses:
about 0.1 ms per frame. In a clipped viewport it is kept inside the
outline with the stencil mask its contents use; before, it was only cut
to the outline's bounding rectangle.
The options at MTEXT's "Specify opposite corner" prompt printed "not
available yet". Each now asks its question and returns to the corner
prompt: Height (also sets TEXTSIZE), Justify (TL..BR, the insertion point
is the box's attachment point), Line spacing (At least/Exactly, then a
factor such as 1.5x or a distance), Rotation (picked, or typed through the
drawing's angle settings; the box turns with it), Style (? lists them),
Width (replaces the opposite corner) and Columns (No; Dynamic and Static
say columns are not available yet). MText stores the line spacing style
(DXF group 73) so Exactly round-trips.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Island detection style (group 75) picks the loops that take part: outer keeps the
outermost loops and their first islands, ignore only the outermost loops.
- A pattern hatch's background colour is filled under its pattern lines.
- Gradients blend colour 1 to colour 2 (LINEAR, CYLINDER, CURVED, SPHERICAL,
HEMISPHERICAL and the INV forms) along their angle, shifted when not centred, drawn as
bounded colour steps; ByLayer / ByBlock gradient colours resolve to the hatch's layer /
block colour instead of colour 7.
- DXF HATCH pattern definition lines (78, 53, 43-46, 79, 49) of a pattern the library
doesn't define are kept on the hatch (new `patternLines` field), drawn and written back;
hostile counts are capped.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Layer Properties Manager: filter tree (All / All Used Layers) with search, sortable table
(Status, Name, On, Freeze, Lock, Plot, Color, Linetype, Lineweight, Transparency,
New VP Freeze, Description; VP Freeze / VP Color inside an MSPACE viewport), inline
rename and description, ACI + true-colour picker, linetype picker with Load from the
library, lineweight picker, layer states save/restore/delete.
- Engine: qselect rewritten ({type, property, operator =,!=,>,<,*, value, mode new|append|
exclude, applyTo}) + qselect.info; layerstate.list/delete/rename; layer list reports
used layers and states; Layer.vp_freeze_new (DXF flag 2, applied by MVIEW) and
layer.set newVpFreeze; per-viewport layer colours (Viewport.layer_colors, vplayer
colors, honoured by the renderer); vplayer defaults to the active viewport; QPMODE
setting/sysvar/toggle; properties.set length/angle for lines.
- Canvas: constraint bars with code-drawn glyphs and coincident markers, dynamic
dimensional constraints (aligned/horizontal/vertical/radius/diameter/angular) with
name=value labels and lock icon, honouring CONSTRAINTBAR/DCDISPLAY; cached per
drawing revision; double-click a label to edit its expression (parameters).
- Quick Properties palette near the selection (status-bar toggle), Quick Select dialog,
Parameters Manager (edit, add user parameter, delete).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Annotation (M4):
- TrueType text from system fonts (filled/outlined), shared placement for all text
- MTEXT formatting codes: fonts, heights, colours, under/overline, stacks, wrapping
- Full DIMSTYLE variables, per-dimension overrides, all arrowheads and ticks,
unit formats, tolerances, limits, alternate units, colours by role
- Associative dimensions that follow geometry; DIMREASSOCIATE/DIMDISASSOCIATE
- STYLE/DIMSTYLE management commands, DIMTEDIT, DIMSPACE, TABLE create/edit/merge
Parametric (M9):
- New cadcraft-constraints crate: weighted damped Gauss-Newton solver, conflict
and redundancy detection, expressions, AutoConstrain inference
- All GC*/DC* commands, GEOMCONSTRAINT/DIMCONSTRAINT, PARAMETERS, DELCONSTRAINT,
constraint bar / display settings; re-solve after every edit
Also: MODEL/PAPER status bar toggle, cargo xtask alias, roadmap update
(233/491 menu items, 290 commands).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>