* usage: a read-only cross-reference of layers, blocks, styles and linetypes
USAGE reports, for every layer, block, text style and linetype, how many
objects use it in model space and the layouts, how many inside block
definitions, whether it is used only inside block definitions, and whether
it is empty or unused. Its unused lists are PURGE's own scan (candidates and
block reachability), shared read-only; PURGE's behaviour is unchanged.
The JSON form takes {type?, limit?, offset?}, returns schema 1 with a paged
items list, per-kind summary and PURGE's unused names in table order.
Fixes#1439
* docs: document the functions touched by #1439
* usage: mark a scan cut at its limit as incomplete (#1439)
USAGE's one pass over model space, the layouts and the block definitions was
capped at 5,000,000 objects with `take`, so a larger drawing silently omitted
later references while the counts, statuses, summary and message looked
complete — an unused layer or block could be reported as used, or vice versa.
The limit is now `MAX_SCAN`, and `Scan::new` takes it as a parameter: it counts
the drawing's objects first and records an `Incomplete { scanned, total }` when
the limit cuts the scan short. The report carries `incomplete: true` and an
`incompleteReason` naming both counts, and the message ends with a note, so a
partial report can never be mistaken for a complete one. A drawing holding
exactly the limit is still complete.
PURGE's scan limit and candidate behaviour are untouched; USAGE only reads
PURGE's unused lists as before.
Tests: unit tests cut a small drawing at a small limit (a 5,000,000-object
drawing is impractical) and check the boundary and the miscount the signal
prevents; the integration test checks a complete drawing says so. Also adds the
missing Ukrainian translation for the command label, which the i18n gate
requires.
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Two tests that start in the same millisecond got the same instance_id(), so this test's
shutdown() removed the other test's lock from the process-wide SAVEFILEPATH (after #1868).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* analysis: report found/analyzed/skipped, caps and implausible values (fixes#1440)
* docs: document the functions touched by #1440
Add doc comments to the self-check helpers, the COUNT/SHAPES/MASSPROP entry points and helpers, and the tests and fixtures the analysis self-check change touches, so CodeRabbit's docstring coverage check passes.
* analysis: tolerate rounding past a bound, and skip area checks without extents (#1440)
The self-check's implausible() compared value > bound exactly, so a border
rectangle whose shoelace area equals the extents' width * height could be
flagged by one ulp of rounding. Allow a 1e-9 relative slack past the bound
(the roundings of two ways of measuring the same thing), while a clearly
larger value is still flagged.
MASSPROP and SHAPES fell back to an extents area of 0 when nothing visible
gave the drawing extents, so every region or shape with area got a false
"area is larger than the drawing extents" flag. Pass f64::INFINITY instead:
implausible() already skips non-finite bounds, because no bound applies.
Tests: one ulp past the bound is not flagged while 1e-6 past is; an
extents-filling rectangle is not flagged; invisible-only masses/shapes with
no visible extents are not flagged.
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* DXF/DWG: angular, diametric and radial dimensions get DIMASSOC (#1651)
std_assoc_refs had slots only for linear/aligned and ordinate dimensions, so
every other associative kind was saved without a DIMASSOC object: AutoCAD
did not follow angular, diameter or radius dimensions, although CADCraft
itself did through its xdata.
Write the references AutoCAD writes for each kind: both lines of an angular
dimension (4 point references; the 3-point kind its three definition points)
and, for radial and diametric dimensions, the single centre reference to the
circle or arc (associativity flag 2), which is how AutoCAD files store them.
Read the same references back, with the circle's definition points
reconstructed, so files from other writers associate those kinds too.
Curve start references now use osnap 13 as AutoCAD writes them (1 is the
end), which also lets a stored point of 0,0,0 resolve to the right end.
Tests: the issue's commands through the engine, and a DXF/DWG round trip
with CADCraft's xdata stripped so only the standard objects remain.
* docs: document the functions touched by #1651
* DXF read: a line's osnap 1 with a stored point still picks the nearer end (other writers)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* MEASUREINIT: choose the units of new drawings, kept in the profile
NEW, QNEW and the first drawing at startup were always imperial unless a
template or {"metric": true} was given, and nothing kept a metric choice
across restarts. MEASUREINIT (0 imperial, the default; 1 metric) is now a
profile variable: NEW without `metric` or a template follows it, the app's
startup drawing follows it, and Options > Files shows it as "Units of new
drawings". QNEWTEMPLATE and an explicit `metric` still win.
Part of #1182.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dxn7PD9WzP4ET2LU7BRLDK
* contributors: add Richard Sauer (aussieboer61)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dxn7PD9WzP4ET2LU7BRLDK
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* STRETCH moves only the multiline vertices inside the area (#1712)
* STRETCH selects a multiline when a crossing area holds one of its vertices (#1712)
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Close hatch boundaries where a line ends just short of a flattened ellipse (#1690)
* Bound the hatch endpoint snap scan by segment count and visited segments (#1690)
* test: LINE returns its new objects as `handles`
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The *D block and EXPLODE's MTEXT took the dimension's decoded text, so
%%c arrived as U+2300, which no SHX font has: other programs plotted a
diameter dimension in an SHX style without its sign. They now write
DimGeometry::mtext_contents(): the sign as %%c, which every font draws
(and CADCraft decodes), a % that would run into a code as %%%.
Co-authored-by: Brandon Thomas <echelon@gmail.com>
A pick inside a multiline wall found the band between the wall's lines
as the outer boundary, but the rooms the inner lines enclose were
dropped as islands: island_curve accepted lines, arcs, polylines and
splines, not multilines. The rooms were filled along with the walls. A
multiline's lines can now make up an island like the other open curves.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* loops: implied closed loops from loose LINE and ARC chains
LOOPS is a read-only inquiry command that chains LINE and ARC endpoints
meeting within a tolerance. Closed loops report their member handles,
perimeter, area and winding (exact with arcs, like SHAPES); open chains
report the endpoint gap, where it is and their length; branch junctions
(three or more ends at one point) are reported but excluded from the
chains rather than resolved.
The tolerance defaults to 1e-9 x the extents diagonal and is an option.
The quadratic endpoint pairing is capped (maxPairs, 1,000,000 by default)
and reports capped/pairTestsNeeded instead of guessing from a partial
pairing. Degenerate lines and arcs are counted under skipped; full-circle
arcs close on their own. The command is read-only.
Fixes#1437
* loops: cap maxPairs at 100,000,000 so a caller can't ask for unbounded work
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* OFFSET uses a single preselected object (#1610)
With exactly one offsettable object selected before OFFSET, take it and go
to the side prompt instead of asking to select an object again; a multiple
selection keeps the select-object loop. AutoCAD ignores preselection here,
but this is the requested behaviour for users coming from other tools.
* docs: document the functions touched by #1610
Autosave files are unsaved drawings. The autosave folder was made with
create_dir_all, by the first write or for the lock file, so on Unix it
got the default mode and other accounts on the machine could read the
files. A folder the autosaver creates is now 0o700. A folder that already
exists keeps its mode, since SAVEFILEPATH can be any folder the user
picked.
The same change as storytold/pdfcraft#3320 and storytold/vectorcraft#3406.
* DXF/DWG: keep a file's own arrowhead blocks with standard names
Reading dropped every block with a standard arrowhead name (`_Dot`,
`_DotSmall`, ...) that no INSERT used, since CADCraft regenerates its own on
save. A block only a dimension style names (DIMBLK) was dropped too, so
AutoCAD's `_Dot` (a polyline with width) or a user's redefinition came back
as CADCraft's disc of 24 SOLIDs. Now only blocks whose content is exactly what
CADCraft writes are dropped; any other content is kept and saved as it was,
through DXF and DWG. PURGE keeps arrowhead blocks that dimension styles or
dimension overrides name.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Arrowheads: compare all properties, trim names in PURGE, test every standard arrow
is_generated_arrow now requires the whole Common to match, so only blocks
exactly as CADCraft writes them are regenerated. PURGE trims arrowhead names
from dimension styles and overrides. A new test writes every standard
arrowhead to DXF and DWG and checks none reads back as a user block. Review
of #1694.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: ffishman <20211677+ffishman@users.noreply.github.com>
* Build: line tables only in dev, no debug info for dependencies
* Tests: one integration-test binary per crate
Each crate's tests/*.rs becomes a module of tests/it/main.rs. Files that
install process-wide state (the file io hooks, user aliases, SAVETIME and
SAVEFILEPATH, user linetype and pattern files, registered fonts) stay their
own test binaries.
* xtask ci: nextest, tests without examples, one wasm check call
AREA's Object option reported a full ellipse's perimeter with
Ramanujan's closed-form estimate, which falls short as the ellipse
flattens: 46.0256 for a 10 x 4 ellipse (exactly 46.0262), 39.8741 for a
10 x 0.1 one (exactly 40.0110, 0.34% short). It now integrates the
perimeter with the geometry crate's ellipse arc length, the one LENGTHEN
measures with, so both report the same length for the same ellipse.
Ellipse::arc_length_from halves a panel where it needs it (the same
adaptive Gauss-Legendre as spline arc lengths): with fixed panels a
100:1 ellipse came out 4e-8 long, as it turns sharply at its ends.
Tests check four ellipses (round to 100:1) against the
arithmetic-geometric mean to 1e-9, and the printed AREA line.
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/modify.rs:1457 (break_entity; helpers `line()`/`arc()`/`lwpoly()` in crates/engine/src/cmd/helpers.rs:10-23)
Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
## 변경 내용
- entities 명령에 selected 불리언 필터를 추가해 현재 공간의 선택 객체만 조회
- 기존 종류·레이어·영역 필터와 결합하고 필터 적용 후 페이지 처리
- MCP query_entities 스키마와 명령·제어 프로토콜 문서에 옵션 공개
- 빈 선택, 중복·오래된 핸들, 다른 공간 객체, 잘못된 입력 및 조회 전후 상태 보존 회귀 테스트 추가
## 검증
- cargo xtask ci 6단계 통과: fmt, clippy, 테스트 2,012개, assets, layers, wasm
- 별도 .NET 클라이언트와 실제 헤드리스 엔진의 localhost 통합 검증 통과
- 실제 데스크톱 UI 조작 및 고객 DWG 왕복 검증은 수행하지 않음
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
At a point prompt with a base point, holding Shift turns ortho on when
ORTHOMODE is off and off when it is on; releasing it restores the setting.
ORTHOMODE itself is never changed. While the override turns ortho on, polar
tracking is off, as with ortho on.
The UI already passed the Shift state to Session::snap_cursor (for POLARMODE
bit 8's Shift to acquire), so the change is in the engine only: snap_cursor
applies the override to its copy of the settings. Window corners (ZOOM
Window) and prompts without a base point are unaffected.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Selection cycling: a click over overlapping objects lists them, Shift+Space steps through them (fixes#1143, fixes#1145)
* canvas: keep viewport_content's doc comment on it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Dynamic blocks: a grip drag previews the reference in its own colours
The preview of a dynamic grip drag is the reference re-evaluated at the
cursor. It was drawn in the preview colour, fills left out, so on a filled
label the text was white on white. Commands can now give preview objects
with their own properties (`Interactive::preview_objects`, drawn under the
rubber band); the grip drag gives the block's objects with the properties
they draw with in the reference (layer 0 on its layer, ByBlock its
colour, linetype, lineweight and transparency) and its attributes with their
definitions', fills included in the block's order.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Preview: the rubber band is grip blue over objects previewed in their own colours
Over a block previewed in its own colours the rubber band and tick marks,
in the current layer's colour, could vanish on its fill (white on white).
They are drawn in the grip blue there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Inquiry: SHAPES reports closed-shape geometry facts
`shapes` is a read-only command that reports, for every closed shape in the
current space (closed polylines, circles, full ellipses, closed splines),
its perimeter, area, centroid, winding, first self-intersection and
coincident vertices, exact with arcs and bulges. It filters and pages like
`entities` and counts other matches under `skipped` with the reason.
`Polyline::centroid` and `polygon_centroid` give the area centroid.
Fixes#1436.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* shapes: cap the quadratic self-intersection test at 4000 edges
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>
* feat(engine): support AUDITCTL system variable and .adt log generation (gaps F4)
* audit: write the .adt log only beside a saved drawing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Properties: a dimension's text height, arrow size, overall scale and precision (#1259)
The Properties palette showed only a dimension's text override and style,
so the only way to change its text height was a new dimension style.
It now shows Text height (DIMTXT), Arrow size (DIMASZ), Dim scale overall
(DIMSCALE) and Precision (DIMDEC) with the values the dimension draws
with. Editing one sets a per-dimension override (DIMOVERRIDE) on the
selected dimensions, as AutoCAD's Properties palette does; the style is
left alone. properties.set takes textHeight, arrowSize, dimScale and
precision for dimensions and refuses bad values before changing anything.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* props: keep DIMOVERRIDE's doc comment on dim_override
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>
ID always printed Z = 0, DIST's Delta Z and angle from the XY plane were
0, and LIST printed Z = 0 for lines, circles, arcs and polyline vertices,
though the drawing kept every Z: a topographic drawing's levels could not
be read in CADCraft.
Points reach these commands in 2D, so the Z is that of what is drawn at
the point, as AutoCAD reports a snapped point's: the object a pick finds
there (a point, a 3D line or 3D polyline interpolated, a polyline's
elevation, down Z for a mirrored one, a circle, arc, text, block or the
plane of a 3D face), else the current elevation (ELEVATION). A Z given
with a JSON point wins. DIST gives the 3D distance, Delta Z and the angle
from the XY plane; LIST the Z of lines, circles, arcs and text, a line's
3D length and deltas, and a polyline's elevation.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
LAYOFF ended after a single pick, so turning off five layers took five command
invocations. AutoCAD's Layer Off keeps prompting: you pick object after object
and the command ends on Enter or Esc only.
`SelectRun` grows a `repeat` mode next to the existing single-pick and plain
select modes: `SelectRun::repeat(..)` acts on every pick, seeds the next prompt
straight away, and finishes on Enter (or Esc through the usual cancel path).
The non-repeating paths are untouched — a repeating run must not let one pick
end the command, so `sel.single` is disabled for it and Enter is handled before
the selection machine's own keywords.
The whole run stays a single undo step, because the command body is still
called once per pick but the running command records one step, as before.
Tests: `crates/engine/tests/layoff_repeat.rs`
cargo test -p cadcraft-engine --test layoff_repeat -> 4 passed
- keeps asking until Enter, two layers off, one undo takes both back
- Esc ends it and keeps what was already turned off
- an empty pick ("0 found") keeps it running
- pickfirst and JSON calls are unchanged
Co-authored-by: kostyk348 <kostyk348@users.noreply.github.com>
ARC advertised "hold Ctrl to switch direction" but the engine never saw modifier
keys: the UI dropped `mods` when building `Input::Point`. PR #407 recorded this as
a known limit.
The UI now writes `Session::ctrl_down` every frame (next to the cursor update, not
only while a command prompts, so previews see it too) and the two ARC paths read it:
- Continue: negating the start tangent makes `arc_sed` pick the mirror arc through
the same two endpoints.
- Center,Start,End: swapping the start/end angles walks the other way around the
same circle; its end-point prompt now carries the same Ctrl hint.
Tests: crates/engine/tests/arc_ctrl_direction.rs.
make_block erased the selected objects for every `keep` value except
"retain" and only converted them for "convert", so a misspelt value such
as "retian" removed the objects from the drawing without a reference to
the new block.
`keep` is now parsed into an enum before anything is touched; a value
that is not documented is an error naming the three accepted values. The
documented values are accepted in any case. BLOCK and -BLOCK share the
check.
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* Dynamic blocks: a distance's grip shows only at an end an action follows
A linear parameter's grip at an end no action is attached to moves nothing,
and AutoCAD doesn't show it on the reference: a stretch that follows only the
end's change (EndXDelta, EndYDelta) leaves the base without a grip, and the
other way round. A connection to the distance itself follows both ends, as
does a distance measured from its midpoint; a parameter no action is attached
to keeps the grips the block gives it. (A block saved with one grip has no
base grip at all, which was already honoured.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Dynamic blocks: a visibility state that lists a parameter shows its grips
AutoCAD shows a parameter's grips in a visibility state that lists the
parameter, though the state doesn't list the grips themselves (a label block's
Label state lists Position1 and Distance2 but not their grips, and AutoCAD
shows the square and the arrow). A grip now shows when the state lists it or
its parameter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
With ORTHOMODE on, the opposite corner of STRETCH's crossing window was bent
onto an axis, so the window collapsed and caught nothing. The prompt set only
the rubber-band base; it now marks it as a window corner (Prompt::corner), as
ZOOM Window and RECTANG already do.
Same fix for the other two-corner rectangles: the Window/Crossing/Box selection
modes, PLOTWINDOW, MVIEW (and its Restore), -VIEW Window and REVCLOUD
Rectangular. Regression tests in crates/engine/tests/stretch_window_ortho.rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Xref paths saved in a drawing (on open, on Reload, in the External
References list, XOPEN, nested xrefs) and table data-link paths re-read by
DATALINKUPDATE go through doc_path::resolve (craft-docpath): relative
paths resolve beside the drawing that stores them, and paths to other
computers, devices and URLs are not opened. Such an xref is Unresolved
with the reason, unless a file of its name is beside the host drawing.
Paths given to XATTACH, -XREF Path and DATALINK are used as given.
One load of xrefs reads at most 1 GB from referenced files in total.
* 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>
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: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Block Editor: BEDIT, BSAVE, BSAVEAS and BCLOSE for static blocks
BEDIT opens a block definition in the drawing's own tab with its base point
at the origin, and the block's objects are edited with the ordinary commands.
BSAVE writes them back into the definition, so every reference in the drawing
updates (one undo step in the drawing); BSAVEAS saves under a new name;
BCLOSE goes back to the drawing, asking whether to save unsaved changes.
- The drawing waits untouched while the editor is open (blockedit.rs): its
undo history, selection and views come back on BCLOSE. Objects left
unchanged are saved back exactly, so no coordinate drifts.
- Files save the drawing outside the editor; autosave keeps the editor's
unsaved changes in the block; the close/quit prompt's Save puts them into
the block first.
- Right-click a selected block reference: Block Editor. In the editor the
canvas is tinted, the base point is marked, and a bar offers Save Block,
Save Block As and Close Block Editor (also in the right-click menu). The
Block tool set's Block Editor button is now live. BLOCKEDITOR sysvar.
- Layout and paper-space commands are refused while the editor is open; a
block can't be saved to contain a reference to itself.
- Dynamic blocks: their data is kept; the editor says it can't edit their
parameters yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Edit Block Definition dialog; BEDIT can start a new block
BEDIT typed or started from a menu or the Tool Sets with no block reference
selected opens the Edit Block Definition dialog: the drawing's blocks sorted
by name, a preview and the description. OK opens the Block Editor on the
block named; a name no block has yet starts a new block, which BSAVE creates
(`bedit {name, create: true}`). A selected block reference still opens at
once, and JSON calls never open the dialog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Edit Block Definition: centred window, list box; gaps.md F3
The dialog opens centred on the window, the blocks are a full-width list
in a list box of fixed height, and gaps.md F3 mentions the dialog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* BEDIT: find dynamic block data on the block's BLOCK_RECORD
A dynamic block's ACAD_ENHANCEDBLOCK dictionary hangs off its BLOCK_RECORD
table entry, not the BLOCK entity, so the "parameters are kept" note never
showed for AutoCAD files. Regression test with the data laid out as an
AutoCAD DXF has it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* BEDIT: a dynamic block reference opens its dynamic block
A dynamic block reference with values of its own shows an anonymous block
(`*U12`), so the right-click Block Editor (and BEDIT on a picked or selected
reference) refused it and asked for a name. The anonymous block's record
names its dynamic block in AcDbBlockRepBTag xdata; BEDIT now opens that, as
AutoCAD does. Regression test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Block Editor on the current drawing; opening a drawing with authoring elements offers it
A dynamic block's own drawing (model space with authoring elements: its
block record's ACAD_ENHANCEDBLOCK) opened from the UI asks, as AutoCAD does,
"<file> contains authoring elements. Open in Block Editor?" Yes / No /
Cancel. Yes opens the Block Editor on <Current Drawing>: the drawing's own
objects, edited where they are; BSAVE keeps them, BCLOSE without saving puts
the drawing back. <Current Drawing> heads the Edit Block Definition list.
BSAVEAS is not available there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>