Commit Graph
3768 Commits
Author SHA1 Message Date
Hakan Seven 80f2d5fd72 fix: solve concentric geometry in kernel 2026-09-17 17:39:01 +03:00
Christopher Overbeck 5b06b6f3fb docs(dimension): before and after screenshots for regenerated dimension layout 2026-09-17 09:32:54 -05:00
Afonsop 5ea4294d3d fix(print): complete Windows printer discovery, honor the true default, surface failures; make CTB loading usable (#1261)
Printer enumeration used EnumPrinters level 4 only, which is served
from the local registry cache and misses Win11 per-user network
printers; an empty result now retries with level 2 (spooler RPC) and
merges the resolved default. The dialog's 'System default printer'
used to delegate to the shell print verb — the default PDF handler's
own printer choice, not the system default; it now resolves
GetDefaultPrinterW and dispatches printto naming that printer
explicitly. Every dispatch probes OpenPrinterW first, so a printer
that vanished between listing and printing produces a clear error
instead of ShellExecute's silent nothing, and all SE_ERR_* codes carry
readable reasons.

Legacy CTB: picking an unparseable table used to swallow the failure
(.ok()) — the user saw nothing at all. Load errors now reach the
command line, the picker accepts .stb alongside .ctb (the container
gains the STBVER1 header; .stb application errors state the actual
reason), and a table loaded from anywhere is copied into the user's
plot-styles folder so it persists in the dialog, matching AutoCAD.
Buffer parsing for both EnumPrinters layouts is unit-tested; the
missing-printer path was exercised against the real spooler (existence
probe only, no job).
2026-09-17 15:26:51 +01:00
Afonsop 02d9273a19 fix(osnap): snap to 3D solids and meshes through edge wires (#1030)
Volume entities (Solid3D/Region/Body/Surface, OBJ-imported and SubD
meshes, polyface meshes) render through the mesh pipeline and their
wire path was deliberately empty, so the snapper had no candidates:
END/MID/NEA/PER/INT never fired on them — only Insertion at the
reference point. Each volume entity now contributes one interaction-
only edge wire (B-rep edge chains where the entity stores them, LOD-0
triangle edges otherwise, 100k-point cap), invisible to rendering and
PDF export, riding the normal wire set so the interaction index,
tiers, and 2D-wins priority apply unchanged. The SubD key_vertices
list no longer fabricates floating midpoints. Scene-level test drives
the exact OBJ-import path (Solid3D + meshes cache) through the real
snapper; INSERT-nested solids remain scoped out (block-cache path has
no mesh cache yet).
2026-09-17 15:26:50 +01:00
Afonsop 99fca8b74b fix(otrack): draw every tracking vector, not just the locked one (#1313)
otrack_snap reports a single active ray, and the overlay painted only
that — with two acquired points the second vector was invisible even
while the cursor locked to their intersection. Each acquired point now
gets its own infinite dashed vector (active full strength, others at
half alpha along their cursor-relevant direction), and when a non-
active vector passes through the locked point an intersection X marks
the crossing, mirroring the OSNAP intersection glyph. Pure view-layer
change; snap math and state machines untouched.
2026-09-17 15:26:34 +01:00
Hakan Seven 16c417f81d Merge pull request #1332 from ramox81/codex/concentric-constraint-parity
# Conflicts:
#	src/entities/arc.rs
#	src/entities/ellipse.rs
#	src/modules/parametric/mod.rs
#	src/scene/parametric_solve.rs
#	src/ui/overlay.rs
2026-09-17 17:24:14 +03:00
Hakan Seven e8125c8702 fix: preserve selected smooth curve geometry 2026-09-17 17:19:09 +03:00
ramox81 059906f347 Fix horizontal geometric constraint behavior 2026-09-17 17:18:59 +03:00
Hakan Seven 76451f7298 Merge pull request #1331 from ramox81/codex/smooth-constraint-parity
# Conflicts:
#	src/app/commands/styleprops.rs
2026-09-17 17:10:49 +03:00
Hakan Seven b6478b3b89 fix: solve perpendicular placement in kernel 2026-09-17 17:08:49 +03:00
Christopher Overbeck 0fdbc80e16 fix(dimension): measured cell width, DIMTMOVE 1 hook start, diameter sign, #1323 offset kept
- The per-character width estimate is 0.66 text heights, measured by
  rendering the text of 106 saved dimension pictures with the bundled
  fonts; the old 0.60 left every fit and hook estimate ten percent narrow.
  With it, the "text plus DIMGAP must clear the arrowheads" rule reproduces
  AutoCAD's arrow placement for 1047 of 1078 pictured linear dimensions
  whose text sits between the extension lines.
- DIMTMOVE 1 stores where the leader's hook starts, not where it ends: on 39
  such radial dimensions the stored point sits DIMASZ plus DIMGAP before the
  text. The hook now runs from the stored point one arrow toward the text.
- The diameter prefix is U+2205, matching the %%c expansion and the pictures.
- A diameter whose text the user dragged keeps the DIMTAD lift from #1323;
  the four AutoCAD-authored diameters with DIMTAD above in the sample all
  store the lifted point directly, so this applies only to dragged text.
2026-09-17 09:06:54 -05:00
Christopher Overbeck 8463c830f7 fix(text): resolve %%c to U+2205, the diameter sign AutoCAD writes
Saved dimension pictures across 1311 diameter dimensions carry U+2205 (806) or a
literal %%c (168); U+2300 never appears. The bundled romans and simplex fonts
have U+2205 and lack Latin O-stroke, so one character now serves the %%c
expansion and, in the dimension formatter, the diameter prefix.
2026-09-17 09:06:54 -05:00
Hakan Seven b546f9b161 Merge pull request #1327 from ramox81/codex/perpendicular-parity-followup 2026-09-17 16:56:56 +03:00
Hakan Seven c5eec2a507 fix: preserve exact mixed polyline intersections 2026-09-17 16:56:52 +03:00
Hakan Seven fa6bf5e7e4 Merge pull request #1326 from yztink/fix-polyline-intersection-snap 2026-09-17 16:52:27 +03:00
Christopher Overbeck 9e18f855cc fix(dimension): size a limits stack from the MText stack layout
The fit and break estimates used two halves at STACK_HALF_SCALE; the stack
is laid out from the lower half's baseline to the upper half's cap, which is
STACK_RAISE + STACK_HALF_SCALE of the run height. The taller estimate flips
arrows outside for a few more stacked texts that AutoCAD drew that way.
2026-09-17 08:41:14 -05:00
Christopher Overbeck 533365dc91 fix(dimension): apply a negative DIMLFAC only where AutoCAD applied it
A negative DIMLFAC scales a paper-space dimension only when it measures
model space through a viewport. AutoCAD records the factor it used as
ACAD_DIMASSOC_CALC_DIMLFAC; a zero there marks a dimension of paper-space
geometry, which reads its sheet distance unscaled. Regenerating such a
dimension multiplied it by the factor anyway, turning 4.457 into 18.110.
2026-09-17 08:41:14 -05:00
Christopher Overbeck 2cf0fc2c42 fix(dimension): run the dimension line out to outside text, straight radial leaders near horizontal
Text placed past an extension line along the dimension's own axis pulls the
dimension line out to its near edge rather than stopping at the two-arrow
stub. A radial leader already within 15 degrees of horizontal runs straight to
the text instead of turning a hook, and a diameter with outside text draws its
single leader for every DIMTMOVE except 2, which keeps only the arrowhead.

Subset parity: 870 of 1076 pictured dimensions now regenerate as drawn.
2026-09-17 08:41:14 -05:00
Christopher Overbeck 85619f49d6 fix(dimension): lay out regenerated dimensions the way their pictures were drawn
Comparing the saved picture block of every dimension in a set of production
drawings with the geometry regenerated after a refresh showed half of them
differing. The differences trace to a few layout rules:

- The stored text middle point (group 11) is where the text was drawn, for
  automatic and hand-placed text alike; a regenerated dimension keeps it and
  only a cleared point is placed from the style.
- Arrows move outside when the text, where it is drawn, would run into an
  arrowhead. The text is measured along the dimension line, so horizontal
  text on a vertical dimension counts its height, a limits stack its two
  lines and `\P` continuation lines their number.
- Text pushed outside starts past the two-arrow stub and a gap; arrow
  length is DIMASZ, not the text height.
- Horizontal text outside a non-horizontal dimension gets a leg to its
  height and a hook one arrow long that it sits against, both when drawn
  and when auto-placed.
- A radius with outside text draws no line to the centre unless DIMTOFL,
  a leader to a hook the text sits against, and an arrowhead whose body
  points toward the text. A diameter with outside text and no DIMTOFL is a
  single leader with one arrowhead, no line across the circle.
- DIMTMOVE 1 stores the hook end; the leader is drawn to it exactly.
- Width estimates measure the widest `\P` line and skip MText format codes.

On a 30-drawing subset with 1076 pictured dimensions the regenerated
drawing now matches the picture for 838 of them, up from 584.
2026-09-17 08:41:14 -05:00
ramox81 d9f3d71342 Fix Concentric build integration 2026-09-17 16:21:39 +03:00
Panos 8e05ed552c Merge pull request #1330 from mechpanos/feat/right-click-menus
feat(ui): right-click context menus with command keywords, PLINE/ARC keyword parity, grip menu
2026-09-17 16:05:31 +03:00
Karim Jerbi 4aa699e08d feat: editable grid spacing and major grid lines in Drafting Settings
The Snap and Grid tab showed static grid values with dead checkboxes, and every grid line stroked identically.

Grid X/Y spacing and Major-line-every are now editable inputs (validated 2-100 for majors, dirty-tracked, applied with an error message on bad input); Adaptive-grid and Display-beyond-Limits checkboxes are wired to live state. Every Nth line partitions into major_segments and strokes subtly brighter (1.5x alpha, 0.75px) for the reference hierarchy. GRIDMAJOR state persists to UserSettings. Covers partition, invalidation, and parse tests.
2026-09-17 13:52:37 +01:00
Karim Jerbi 05f462f294 fix: honor GRIDUNIT X/Y spacing and LIMITS option in grid display
The viewport grid ignored the configured spacing and forced square grids: compute_grid_step hardcoded a 1.0 base, a single shared step drove both line families (including the tangent derivative used for gap measurement), and the display always clipped to LIMITS despite the beyond-Limits option.

Grid spacing now scales per-axis from GRIDUNIT via compute_grid_steps (adaptive 5x growth, fixed passthrough), GridParams carries step_x/step_y, snap tolerances follow the visible steps, and the LIMITS clip is skipped when beyond-Limits is set. Also fixes a per-axis overflow fallback that returned the X base for Y. Spacing state (X/Y, adaptive, beyond-Limits) is stored on the app and persisted to UserSettings at defaults; dialog wiring follows separately.
2026-09-17 13:52:37 +01:00
ramox81 a6a70420c4 fix: align concentric constraint behavior 2026-09-17 15:31:26 +03:00
Afonsop ebee7e5489 feat(help): open a generated command reference instead of Discussions (#1049)
HELP now opens docs/command-reference.md on GitHub — a 600-command
reference grouped by category with default shortcuts and selection
behavior, generated from the in-repo command registry. A staleness
test fails when the registry and the page drift apart; regenerate
with UPDATE_COMMAND_REFERENCE=1 cargo test command_reference. The
command-line notice is localized in all 21 languages.
2026-09-17 13:14:06 +01:00
Afonsop 334960fcf3 perf(pdf): dedupe glyph outlines into Form XObjects, round coordinates (#702)
A text-heavy sheet re-emitted every glyph occurrence as a full page-
space outline (~4 KB per character at f32 round-trip precision), so
PRINT of a simple Vietnamese-text A4 produced ~128 MB. Each unique
glyph is now baked once into a shared compressed Form XObject keyed
by atlas tile (mirroring the image XObject cache, shared across
pages); repeats replay one cm + /Do. Glyph path points, CTM entries,
and decoration quads round to 0.01 pt (~3.5 µm, visually lossless);
run-level colors dedupe outside the per-glyph q/Q so state persists;
the stroke-font pen is re-set per glyph under its CTM, pre-divided by
the quad's area scale.

200-entity Vietnamese repro: 51.5 MB -> 1.28 MB (40x, ~99 B per
glyph occurrence); stroke-font pages 2.0x; hatch/polyline pages
byte-identical. Validated lossless by 300 dpi Ghostscript pixel diff
(residuals confined to 2 px glyph-edge phase) and pypdf structure
check. Raster quality presets and vector geometry are untouched.
2026-09-17 13:01:12 +01:00
Afonsop 4985ab42cf fix(osnap): intersection snap is inexact for polyline shapes (#1319)
The analytic intersection path accepted only wires carrying exactly
one tangent geom, so a triangle drawn as one closed LwPolyline (three
Line geoms) fell back to the segment sweep against the circle's
48-chord tessellation — every crossing sits r*(1-cos(pi/48)) ~ 5.3e-3
inside the true circle, and MEASURE reads 2.9947 instead of 3.0000
(END is exact because key_vertices are f64).

Decompose a wire into one analytic curve per geom (declining
entirely if any geom fails to convert, so nothing silently drops),
recover f64 line endpoints from the double-single tessellation for
survey-scale coordinates, and extend line pieces by ~|world|*4*eps so
crossings exactly on a shared endpoint survive the kernel's bounded
extent test. Vertex snap error drops from 5.3e-3 to <= 4.4e-16; tests
cover the 3-4-5 circumcircle at 16 approach directions, survey
coordinates, and the previously fixed all-Line case.
2026-09-17 13:01:02 +01:00
Afonsop 9e4c3837dd fix(extrude): typed height is ignored on web (#1082)
On wasm the canvas holds focus, so a typed value reaches the dynamic
Distance field through CommandAppendChar+CommandFinalize — and
try_dyn_commit only commits as text when wants_text() && !
point_step_accepts_keywords(), or dyn_commit_as_text(). EXTRUDE's
Height step accepts keywords and never overrode dyn_commit_as_text
(unlike PRESSPULL and REVOLVE), so the value resolved as an in-plane
point whose height is ~0 and silently re-prompted. Commit the Height
step as text, matching its siblings; regression test drives the
exact web message sequence.
2026-09-17 13:01:02 +01:00
Afonsop a60b52a462 fix(trim): don't panic on degenerate polyline segments (#1318)
sample_entity_xy stitches exploded segment samples with
pts[sp[1..]] guarded only by last()==first(); a segment that samples
to EMPTY (zero-length edge, or an edge-on-OCS arc whose
entity_curve_xy returns None) while the accumulator is still empty
made None==None true and sliced a length-0 vec — 'range start index
1 out of range' — and on web the unwind then tripped winit's held
RefCell borrow. Guard both stitching sites (the EXTRIM preview
sibling had the same pattern) and pin the join semantics plus the
degenerate cases with tests.
2026-09-17 13:01:01 +01:00
ramox81 025398bbb1 Preserve spline grip display mode after smooth solve 2026-09-17 14:54:33 +03:00
Hakan Seven bb29b987c2 fix: compact repeated nested block geometry 2026-09-17 14:34:10 +03:00
ramox81 5497f455ef Complete spline fit and control grip modes 2026-09-17 14:29:26 +03:00
Karim Jerbi 84e85ae693 Merge pull request #1329 from ramox81/codex/windows-printer-handle
Update Windows printer handle type
2026-09-17 12:09:12 +01:00
ramox81 6260723937 Revert "Match Smooth connected-endpoint workflow"
This reverts commit dfa75f45b5.
2026-09-17 13:50:15 +03:00
ramox81 dfa75f45b5 Match Smooth connected-endpoint workflow 2026-09-17 13:37:25 +03:00
ramox81 7c6665153c Complete Smooth G2 constraint workflow 2026-09-17 12:39:23 +03:00
PanosandClaude Opus 5 0fbb5bcb4f ui: neutral wording in code and help text; keywords first in the command menu
Comments and the Options help text describe the behaviour of commercial
solutions without naming any product. The command menu puts the command's
keywords directly under Enter / Cancel, with Recent Input and Snap
Overrides below them, so the choices that change from step to step are the
closest to the pointer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:15 +03:00
PanosandClaude Opus 5 02cd98e790 feat(ui): feature-parity context menu — Snap Overrides, transparent Pan/Zoom, ARC keyword flow
The command menu now follows the commercial solutions' layout row for row: Enter, Cancel,
Recent Input ▸, the command's keywords, Snap Overrides ▸ (every object snap
with its glyph, Mid Between 2 Points, None, Osnap Settings…), then Pan and
Zoom. Pan / Zoom run transparently while a command is active ('PAN,
'ZOOM …): navigation modes leave the command untouched and an interactive
ZOOM Window parks it and resumes it afterwards. Rows carry an icon gutter
so labels align; the Enter row shows a default value ("<0.5000>") as its
hint instead of a second finish row.

ARC gets the commercial solutions' prompt flow with all keywords: start [Center], second
point [Center/End], end; after Center: end [Angle/chord Length]; after
End: center [Angle/Direction/Radius]; Enter continues tangent. The
previous default (Center/Start/End with method codes) stays as ARC_CSE.

Object snaps gain a one-shot "None" override. New strings in all locales.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:15 +03:00
PanosandClaude Opus 5 96df4928c7 ui: fit the context menu above the command area; right-button control actions
Rows are 22 px (as the grip popup), the edit menu drops Select All and
Zoom Extents (both stay on the idle menu, matching the commercial solutions' edit menu),
and cursor-anchored panels now reserve the overlaid prompt lines
(CLIPROMPTLINES) as well as the input row, so a long menu is never hidden
behind the command area — it scrolls inside the visible canvas instead.

The automation port gains `pointer_right_press` / `pointer_right_release`
actions so scripts and MCP clients can exercise the context menu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:15 +03:00
PanosandClaude Opus 5 426af2d3a5 i18n: catalogue entries for the context menu, PLINE and modify options
Every new UI string (menu rows, Options → Right-click Customization, the
PLINE sub-prompts and keyword labels, MOVE/COPY/OFFSET prompts) gets its
Fluent attribute in all 21 locales plus the source → attribute rows in
locale_catalog.rs; the SETVAR help line lists SHORTCUTMENU and
SHORTCUTMENUDURATION. Tests that compared prompt text now check command
state so they pass under any UI language.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:15 +03:00
PanosandClaude Opus 5 a5fd040745 feat(grips): compatible grip shortcut menu
A right-click while a grip is hot opens the grip menu: Enter places the
grip, Stretch / Move / Rotate / Scale / Mirror switch how the gripped
objects are edited (the latter four hand the selection to the matching
command with the grip as its base point), Base Point re-bases the gesture
at the next click, Copy leaves the originals in place and adds the moved
shapes as new entities while keeping the grip hot, Undo snaps the shapes
back to where the gesture started, Exit drops the edit.

The grip commit path moves out of the left-release handler into
`commit_active_grip_edit` so the menu, Enter and the placement click share
it; Enter with a hot grip now places it instead of repeating the last
command.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:14 +03:00
PanosandClaude Opus 5 d753874fe4 feat(modify): commercial solutions keyword options for MOVE, COPY, FILLET, CHAMFER, OFFSET
MOVE: Displacement, Enter at the second point uses the base as the vector.
COPY: Displacement, mOde (Single/Multiple), Undo of the last copy.
FILLET: Undo of the last fillet (the command refreshes its entity cache
through the new CadCommand::on_document_undone hook after the host undoes
the document step). CHAMFER: Multiple and Undo. OFFSET: Erase (the offset
replaces its source), Layer (Current/Source), Undo, Exit.
POLY3D, TRACE, MIRROR and MEASUREGEOM expose the keywords they already
accepted as options, so the context menu and option buttons list them.

The pinned prompt now keeps informational bracket groups such as
"[3 objects]" and only drops real option listings when the buttons take over.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:14 +03:00
PanosandClaude Opus 5 c0bc44c4f6 feat(pline): commercial solutions keyword parity — Width/Halfwidth/Length and arc sub-modes
PLINE now offers the commercial solutions' full option set: Arc/Close/Halfwidth/Length/
Undo/Width in line mode and Angle/CEnter/CLose/Direction/Halfwidth/Line/
Radius/Second pt/Undo/Width in arc mode, including the nested prompts
(Angle → CEnter/Radius, CEnter → Angle/Length, Radius → Angle → chord
direction). Widths land in the LwPolyline vertices (start/end per segment,
the end width carrying into the next segment) and PLINEWID persists per
session. Undo / Escape inside a sub-prompt only back out of it; every
sub-step previews its arc at the cursor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:14 +03:00
PanosandClaude Opus 5 e623c053ab feat(ui): compatible right-click context menu driven by command options
The viewport context menu is now built from a pure model
(ui::popup::context_menu) rendered by the overlay: while a command runs it
offers Enter / Cancel / every keyword of the command's options() with the
keyword shown as a hint, a Recent Input submenu and M2P; when idle it offers
Repeat, Recent Input, Clipboard, Undo/Redo with history labels, the edit
block (Erase/Move/Copy/Scale/Rotate/Mirror/Draw Order), Isolate, Pan/Zoom,
selection tools, Properties and Options. The default row is anchored under
the pointer and the menu is keyboard-navigable (arrows, Enter, mnemonic
letters; any other key closes it and types into the command line).

Right-click behaviour is a user preference (Options → User Preferences,
SHORTCUTMENU / SHORTCUTMENUDURATION): shortcut menu (commercial solutions default),
time-sensitive, or the previous Enter-first cycle.

LINE gains options() (Close/Undo/eXit).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:05:14 +03:00
ramox81 5bbd61d6a5 Update Windows printer handle type 2026-09-17 10:49:29 +03:00
ramox81 cbf1e76c69 Fix perpendicular constraint behavior 2026-09-17 10:48:44 +03:00
Ryan 395256c296 Fix analytical intersection snapping for multi-segment polylines 2026-09-17 00:00:03 -07:00
Hakan Seven 65c0fe5494 fix: align dynamic angle input with drawing units 2026-09-17 09:50:41 +03:00
Hakan Seven 58405025ee Merge pull request #1325 from MarcelP102/codex/formating-fix 2026-09-17 09:41:31 +03:00
Marcel fca96b57de Use shared unit formatters across property and dynamic views 2026-09-17 08:30:20 +02:00