Commit Graph
593 Commits
Author SHA1 Message Date
NetterSilverandClaude Haiku 5.5 abce3a718b Reject lone '-' or '"' in parse_distance instead of reading 0 (#1444)
Found while testing crates/engine/src/units.rs:107-132

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 02:32:21 -04:00
Kostykandkostyk348 acb28313c6 Layer Off: stay active until Enter or Esc (#1418) (#1426)
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>
2026-10-19 02:32:14 -04:00
william-wwh 2be9d00796 fix(arc): hold Ctrl to switch the arc direction (#1422)
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.
2026-10-19 02:32:08 -04:00
NetterSilverandClaude Haiku 5.5 286d3de0aa Drop minus sign from dimension text that rounds to zero (#1403)
Found while testing crates/render/src/units.rs:139-160 (format_linear, unit 3 and 4 arms) and feet_inches at :101

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 02:32:01 -04:00
NetterSilverandClaude Haiku 5.5 cd3e8478d6 Fix AutoLISP real printing of subnormals and mantissa round-up (#1334)
Found while testing crates/engine/src/lisp/value.rs:401-410 (real_text)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 02:31:56 -04:00
NetterSilverandClaude Haiku 5.5 12d0235b2c Fix table formula range shifting for one-cell and reversed ranges (#1328)
Found while testing crates/engine/src/cmd/table/formula.rs:660

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 02:31:50 -04:00
NetterSilverandClaude Haiku 5.5 1ac2ebaad2 Keep line and arc elevation when lengthening with LENGTHEN (#1313)
Found while testing crates/engine/src/cmd/modify2.rs:764

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 02:31:44 -04:00
wstockandClaude Fable 5.1 a3b3e1281f render: the even-odd fill cuts a slab at the crossings inside it (#927) (#1308)
Slabs ran between vertex rows and paired the active edges by their
order at the slab's middle, so two edges crossing inside a slab (a
bowtie, two loops crossing) were paired across the crossing and the
trapezoids covered the wrong side of it. A slab with such a crossing is
now cut again at that y and each part paired on its own, under a cut
budget so hostile input stays bounded. Tests check coverage against an
even-odd parity oracle for a bowtie, an off-centre bowtie, two crossing
loops and the plain cases; the three crossing cases fail on main.


Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-19 02:31:39 -04:00
Galeno ca5a34be12 UI: let the Chinese and Arabic language gates accept an embedded craft-fonts face (#1294)
can_show only asked the installed-font lookups for those two languages, and
both lookups hard-code None on wasm32, where there are no system fonts. The
Korean gate already falls back to a craft-fonts face (korean_font), but the
web build embeds a Jpan CJK face and an Arabic face precisely as the web's
only fonts, so a Chinese or Arabic interface could never be selected on it,
however complete the catalog; the embedded Arabic face was also never added
to the UI font families (the embedded filter only kept Jpan/Han faces).

Give both gates the embedded-face path the Korean one has:
- can_show("zh"/"ar") answers true when this build embeds a Regular face of
  Hans/Hant or Arab, in addition to an installed font.
- install_fonts picks embedded faces via embedded_ui_faces: every CJK face
  still loads in every language for CJK drawing names (#513), the face of a
  zh interface leads (a Japanese face lacks the simplified-only 图 园 测),
  and an Arabic interface appends its Arabic face.

Nothing changes for a build without CRAFT_FONTS_DIR (CRAFT_FONTS empty):
Chinese still rides on an installed CJK font and Arabic on an installed one.
2026-10-19 02:31:34 -04:00
c400d6d48c Properties: a rotation shows and is typed as the drawing measures directions (#1275)
AutoCAD's Properties shows a block reference's or text's rotation as it shows
any direction: from ANGBASE, clockwise when ANGDIR is 1 (a block turned 2.23°
shows as 87.77 in a drawing measured clockwise from north). CADCraft showed
the raw angle from +X. Properties and Quick Properties now show it that way
and read a typed rotation back the same way (`AngleSettings::shown`,
`unshown`); properties.set still takes the angle from +X counterclockwise.

Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:31:29 -04:00
NetterSilverandClaude Haiku 5.5 e635248b1e Carry engineering distance rounding into the next foot (#1255)
Found while testing crates/engine/src/units.rs:14-20

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 02:31:24 -04:00
Marco Arnulfo 739e083f4b Drafting Settings: polar increment angle no longer shows 15 decimals (fixes #1237) (#1239) 2026-10-19 02:31:18 -04:00
3fa7275e4f DXF: $ANGBASE is in degrees (#1234)
AutoCAD writes $ANGBASE in degrees (a drawing whose angles run clockwise from
north has 90.0); CADCraft read and wrote it as radians, so such a drawing's
angle base came in as 90 radians (about 116.6 degrees), turning typed angles,
polar tracking and angles shown in Properties. The reader now converts to
radians (the variable's unit), the writer back, and the DWG reader's hand-off
of the value in DXF form gives degrees.

Co-authored-by: Cody Vogt <18035288+codyvogt@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:31:12 -04:00
Marco Arnulfo aba903dbb3 CLI: convert to an image warns about the entities it can't draw (#1212)
* CLI: convert to an image warns about the entities it can't draw (fixes #1208)

* CLI: the undrawn-entities warning lists its counts like the skipped-records one
2026-10-19 02:31:06 -04:00
Marco Arnulfo 493addc2dd DXF files that declare no units stay unitless when saved again (fixes #1209) (#1210) 2026-10-19 02:31:01 -04:00
Marco Arnulfo a2bee8b49e LTSCALE typed at the command line asks for the scale factor (fixes #1194) (#1199) 2026-10-19 02:30:56 -04:00
Marco Arnulfo c68420221c New metric drawings get metric Standard multileader and table styles (fixes #1171) (#1195) 2026-10-19 02:30:51 -04:00
Marco Arnulfo a5fa5ca064 Select objects accepts keywords with a leading underscore (_L, _ALL, _W…) (fixes #1172) (#1193) 2026-10-19 02:30:46 -04:00
Marco Arnulfo ef599e58e0 BREAK opens a closed polyline instead of refusing it (fixes #1173) (#1191) 2026-10-19 02:30:41 -04:00
Marco Arnulfo 27fd074f54 AutoLISP entity lists hold angles in radians, as entget does in AutoCAD (fixes #1165) (#1190) 2026-10-19 02:30:36 -04:00
Marco Arnulfo 2db6ab069a DIMRADIUS/DIMDIAMETER: a location outside the circle puts the text at that point (fixes #1170) (#1189) 2026-10-19 02:30:31 -04:00
Marco Arnulfo d33a6e634a AREA, Object: an open polyline's perimeter is its length, without the closing side (fixes #1168) (#1188) 2026-10-19 02:30:26 -04:00
Antoine Boxho 0bfe609567 Add Antoine Boxho to contributors list with GitHub sync (#1186) 2026-10-19 02:30:21 -04:00
Antoine BoxhoandClaude Fable 5.1 7e830044ab BLOCK: a keep value other than convert, retain or delete is an error (fixes #935) (#1160)
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>
2026-10-19 02:30:15 -04:00
Marco Arnulfo 6546f0eecd Parameters Manager: double-click a name to rename the parameter and every expression that uses it (part of #1134) (#1142) 2026-10-19 02:30:10 -04:00
Marco Arnulfo 15b5395c06 Angular constraint between two lines holds the angle it draws, whichever way the lines run (part of #1134) (#1140) 2026-10-19 02:30:05 -04:00
Marco Arnulfo cdc61f32b5 A fixed point stays put when its grip is dragged: Fix locks the position it had before the edit (part of #1134) (#1139) 2026-10-19 02:29:59 -04:00
Marco Arnulfo d4bacce885 Tool Sets: the Parametric category offers Fix, Symmetric, the dimensional constraints and Delete Constraints (part of #1134) (#1138) 2026-10-19 02:29:54 -04:00
Marco Arnulfo 9aea9b16c4 Dynamic Input: the CIRCLE radius prompt shows one distance field, not X/Y (fixes #1135) (#1137) 2026-10-19 02:29:48 -04:00
Marco Arnulfo 9e3f584a68 Status bar toggles don't cancel the running command, as F7-F12 don't (fixes #1108) (#1111) 2026-10-19 02:29:43 -04:00
Marco Arnulfo 3bd7510f2b ARC continuation starts from the last picked end of a clockwise arc (fixes #1107) (#1110) 2026-10-19 02:29:37 -04:00
Marco Arnulfo b464a947ec MEASUREGEOM typed at the command line asks for the option, then the points (fixes #1103) (#1104) 2026-10-19 02:29:31 -04:00
Marco Arnulfo f76ca751cc Collapsed Tool Sets leave a strip on the left edge that expands them again (fixes #1095) (#1101) 2026-10-19 02:29:26 -04:00
Marco Arnulfo e0ad0ef33e DWG dimensions: text at its default position unless it was moved, and bit 32 kept (fixes #1094) (#1096) 2026-10-19 02:29:19 -04:00
56d73ceb21 Dynamic blocks: show a distance's grip only at an end an action follows, and the grips of parameters a visibility state lists (#1090)
* 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>
2026-10-19 02:29:13 -04:00
aldozarandClaude Opus 5.5 691bdbe0b8 Layouts in millimetres plot in millimetres whatever MEASUREMENT says (#1058) (#1085)
Paper-space units followed the drawing's MEASUREMENT only, so a layout
whose page setup is in millimetres (plot paper units 1), common in
drawings from AutoCAD with MEASUREMENT 0, was taken as inches: its PDF
drew everything 25.4 times too large, off the page.

PageSetup gains `paper_mm`, read from LAYOUT group 72 = 1; 72 = 0 still
leaves the units to MEASUREMENT, since earlier CADCraft versions wrote 0
for every layout. The layout's sheet, its PDF/raster plots, PREVIEW and
the pens of what its viewports show use the layout's units, and the
writer stores 72 = 1 for layouts in millimetres (it wrote 0 always).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:29:03 -04:00
aldozarandClaude Opus 5.5 162d5c6820 DWG: entities of a second layout stay on it in AutoCAD (#1057) (#1080)
acadrust writes every paper-space entity with entity mode 1 ("paper
space"), including those of *Paper_Space0, *Paper_Space1… and relies on
each block's entity list; AutoCAD reads mode 1 as the *Paper_Space
block's, so what was drawn on a second layout (and its viewports, in
drawings from AutoCAD with several layouts) landed on the first one, and
the second stayed empty. The DWG bridge now writes those entities owned
by their block (entity mode 0 with the owner handle), as the public DWG
specification describes; the first layout's entities stay mode 1.

The io tests read CADCraft's DWG back with acadrust (a dev-dependency,
the same version as cadcraft-dwg's) to check the modes as written.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:28:58 -04:00
aldozarandClaude Opus 5.5 632c2d4f1f DIMASSOC: reference polyline vertices by segment, as AutoCAD does (#1049) (#1064)
* DIMASSOC: no standard reference to a polyline's vertex or segment (#1049)

A dimension on a polyline vertex was written with an AcDbOsnapPointRef
naming the polyline but no subentity (groups 73 and 91 both 0); AutoCAD
then resolved it to the polyline's first segment when it regenerated
the dimension, and the value changed without warning (210 became 5).
Such points (LWPOLYLINE, 3D polyline, MLINE, also as the second object
of an intersection) are now left out of the DIMASSOC object, as the
report suggests: AutoCAD sees them as non-associative and the values
stay right. CADCraft keeps every link through its own xdata, and
references to single-curve objects (lines, arcs, circles, points) are
written as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* DIMASSOC: reference polyline vertices by segment, as AutoCAD does

Following the black-box observation of AutoCAD 2026 in the PR review: a
polyline vertex is referenced as an end of one of its segments,
subentity type 73 = 2 (edge) and the 1-based segment in 91 (segment k
runs from vertex k-1 to vertex k; a closed polyline's closing segment is
the last), with osnap 1 / parameter 1.0 for a segment's end and 13 / 0.0
for its start. Vertex 0 is written as the start of segment 1, vertex k
as the end of segment k, falling back to the other neighbour when that
one is an arc; a vertex between two arcs (where AutoCAD writes an angle
parameter, not yet tested) still gets no reference, nor do 3D polylines
and multilines.

Reading uses the segment and osnap for polylines: AutoCAD leaves the
reference point at 0,0, so the nearest-vertex fallback attached
AutoCAD's associative dimensions on polylines to the vertex nearest the
origin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:28:52 -04:00
aldozarandClaude Opus 5.5 f0e4fef003 AutoCAD interop: justified text, DIMPOST, current dimension style, *D block colours (#1062)
* AutoCAD interop: justified text, DIMPOST, current dimension style, *D block colours

What AutoCAD takes from CADCraft's DWG/DXF as it is:

- Justified TEXT/ATTRIB/ATTDEF (#1050): group 10 is now where the
  baseline starts, from the alignment point and the text's width, not
  the alignment point itself; AutoCAD drew centred and right-aligned
  text from DWG starting at its alignment point. A stored point close to
  CADCraft's own (AutoCAD's, exact for its fonts) is kept.
- DIMPOST (#1053) is written even when empty: the DWG bridge defaulted a
  missing one to "<>", and AutoCAD then dropped the "R" of radius
  dimensions when it regenerated them.
- The current dimension style (#1051): the DXF header now carries its
  DIM* variables (AutoCAD draws new and updated dimensions from them);
  the DWG bridge points $DIMSTYLE at the style by name (its handle was
  renumbered, so the writer fell back to Standard), and reading a DWG
  gives the current dimension and text styles their names back.
- *D blocks (#1052): lines, arrows, extension lines and text take the
  style's DIMCLRD/DIMCLRE/DIMCLRT instead of ByBlock.

#1054 (group 42 of a rotated linear dimension) was already fixed on
main by #855; acad_interop.rs keeps it covered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test: angular dimensions store their angle in radians (group 42)

Three-point (60°, 174°) and two-line (120°) angular dimensions, read back
from the DWG as DXF. Already right on main since #855; this guards it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Justified text made here: Left Middle and Left Bottom write their baseline start too

text_insert kept a stored insertion point that was within 0.1 x an
estimated width + 0.5 x height of CADCraft's baseline start, taking it for
AutoCAD's own. The width was estimated from the alignment point's offset,
which for Left Middle is only h/2 (vertical), so a text made here, whose
stored point is the alignment point, passed and kept it: AutoCAD drew it
half a height high (Left Bottom: a third). Reported with a test by
@lee-cyrille-maskell.

A stored point equal to the alignment point is now always stale. Otherwise
the offset is split along and across the baseline: along it the same slack
as before (a tenth of the text's width plus half its height, as fonts and
their substitutes differ most in width), across it a fifth of the height.
Multiline attribute values keep the distance-only check, since their lines
are placed by the embedded MTEXT.

On 12 drawings made in AutoCAD (1,055 justified texts) the insertion points
written are the same as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:28:47 -04:00
leonardopbatista 7164b6b5b1 feat(options): save a two-click selection window preference (#1032) 2026-10-19 02:28:41 -04:00
Bihacsy László 38fdfa4ac4 i18n: add Hungarian (hu) interface translation (#1027)
A complete 1,326-entry Hungarian catalog: every key of the Ukrainian reference catalog and the
four menu headings (Méretezés, Rajzolás, Módosítás, Nézet). Written from the meaning of
CADCraft's English strings in general technical drawing vocabulary; no other product's
localization and no other catalog was used. The interface addresses the user informally;
command-line keywords, system variables and osnap tokens stay English.

- Preference::Hungarian (hu); hu-HU and hu_HU.UTF-8 select it. Counts take one form, as a
  Hungarian numeral is followed by the singular (plural_ko, plural_forms: 1).
- hu in REPORTED; tests for locales, saved preference and plurals, menu headings, a live
  switch, dialogs and the Hungarian letters (ő, ű) in the bundled fonts. No gaps are reported
  for Hungarian.
- ATTRIBUTION, README, docs/localization.md, docs/localization-parity.md,
  docs/control-protocol.md and the options doc comment.
2026-10-19 02:28:35 -04:00
Gert Pellin - GPE baa9c00fb7 SVG import: name what was left out instead of dropping it silently (#627) (#1016)
Text, raster images, <use> copies, <style> sheets and rounded rectangle
corners aren't read yet. They were dropped without a word; the reader now
counts them and adds one read note (the channel DWG reading already uses),
which OPEN echoes and returns as a warning. Content that isn't drawn (in
<defs> or hidden) isn't counted.
2026-10-19 02:28:29 -04:00
Dylan M. Taylor 0cc66ad306 ci: configure Dependabot for Cargo and GitHub Actions
Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
2026-10-18 12:30:54 -06:00
Dylan M. Taylor 3370a91fe9 docs: drop references to competing commercial software (#1545) 2026-10-18 10:39:39 -04:00
Brandon ThomasandClaude Opus 5.5 b23d362f6a Release 0.9.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:43:25 -04:00
Brandon ThomasandClaude Opus 5.5 714111d528 Release 0.8.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.8.0
2026-10-17 17:20:02 -04:00
skylar taylor-barrick ff6cc8b3fc Merge pull request #1518 from skylartaylor/control-input
Bound control-port input, and follow stored paths only on this computer or the drawing's share
2026-10-17 12:14:01 -06:00
skylar taylor-barrick 98d22f0c68 Build: take craft-docpath from the merged craft-libs rev
craft-libs#169 is merged, so the fork pin is no longer needed. Pinned to
storytold/craft-libs 82a24b006eefa036b43c09a67fb9a3fbd17ffe63 (main after the merge) rather than the older 12281d07,
which predates resolve_absolute and the Windows colon refusal.
2026-10-17 12:04:10 -06:00
aiongg ba02572b31 Build: use craft-docpath from craft-libs 2026-10-17 02:20:57 +00:00
aiongg 8fe7c421ea Xrefs and data links: follow stored paths only on this computer or the drawing's share
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.
2026-10-16 17:18:34 +00:00