Commit Graph
3083 Commits
Author SHA1 Message Date
ramox81andClaude Fable 5.1 842ae461fc Equal: ask for the second object again after a refused pick, name the kind it needs
A second object of the wrong kind (a circle after a line, a line after a
circle) or a pair that already carries Equal now reports and asks for the
second object again instead of ending the command. The mismatch message
names what the first object asks for — `Select a line segment, polyline
segment, text, MText, major or minor axis of ellipse or elliptical arc.`
after a length object, `Select a circle or arc.` after a radius object —
and the same-pick message carries the reference's double space.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-21 09:46:13 +03:00
ramox81andClaude Fable 5.1 ad6f902ed7 Equal follow-ups: one glyph per object, unshown Multiple bars, typed object picks
- An object that carries several Equal relations shows a single "="
  badge, as the reference does, instead of one stacked badge per relation.
- A pick made in the Multiple flow leaves its new constraint bar unshown
  until the object is selected or bars are shown, matching the reference;
  the single flow still shows the bar at once.
- A typed coordinate at the Fix `Select object:` prompt and at the
  Horizontal/Vertical `Select an object or [2Points]` prompt picks the
  object under that point, like a click, instead of being read as a point.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-21 09:18:40 +03:00
Hakan SevenandClaude Fable 5.1 fd2062bdec fix(insert): attribute grips follow ATTMODE 2 and annotative scale
Follow-up to the block-attribute grips picked from #1386.

- Movability no longer includes the invisible flag: an attribute ATTMODE 2
  displays is grippable, so the grip the display-aware list shows can be
  dragged. The document-less grips() still skips invisible attributes,
  since it cannot consult ATTMODE.
- The grip sits on the displayed attribute, which an annotative insert
  scales about its insertion point; Scene::apply_grip now unscales the
  dragged target the same way before the attribute stores it, so the grip
  no longer jumps to twice the drag at scale 2.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-20 21:31:54 +03:00
copilot-swe-agent[bot] 2b92fc5b09 Fix missing brace in insert attribute visibility filter
Co-authored-by: dasmatus <[email protected]>
(cherry picked from commit 6cf16d8621)
2026-09-20 21:29:15 +03:00
dasmatus 4559c8a2d8 Refactor attribute filtering logic in insert.rs
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
(cherry picked from commit a8f75e969d)
2026-09-20 21:29:15 +03:00
copilot-swe-agent[bot] bd89507a6c fix insert attribute grip visibility
Co-authored-by: dasmatus <[email protected]>
(cherry picked from commit 68cc414e4a)
2026-09-20 21:29:15 +03:00
Claude 9af327ed0b feat(insert): grip each block attribute
Selecting a block showed one grip, at its insertion point, so there was
no handle to pick an attribute up by: an attribute could only be moved
by moving the whole block.

Give the INSERT one grip per attribute, taken from the attribute's own
`Grippable` implementation, at ids `1 + index`. A drag on one moves that
attribute alone, through the same `apply_grip` the attribute already has
(which carries `alignment_point` along, so non-left alignments stay put
relative to the text). Grip 0 keeps translating the block and every
attribute with it (#255).

A constant attribute belongs to the block definition and an invisible one
is not drawn, so neither offers a grip; a locked-position attribute
declines on its own.

Fixes HakanSeven12/OpenCADStudio#1259

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01TQzYZsXBwPZ5HwBaGitEUV
(cherry picked from commit 7eb966f6a2)
2026-09-20 21:29:15 +03:00
copilot-swe-agent[bot] 5d4b707214 fix review feedback for OTRACK projection and OtrackHit API
Co-authored-by: dichhead <[email protected]>
(cherry picked from commit 97f94a2bfe)
2026-09-20 21:29:15 +03:00
Claude 033319a4e3 feat(otrack): draw both vectors of an intersection lock
An OTRACK crossing is the meeting of two tracking vectors, but
`OtrackHit` carried only the one a typed distance is measured along, so
the overlay had a single guide to draw. Snapping to the crossing of two
vectors worked and looked like an unexplained point on one line.

Carry the crossed ray out of `otrack_snap` as `OtrackHit::cross`, keep it
on the app beside `otrack_active`, and let the overlay take a list of
guides rather than one. `otrack_active` still drives typed-distance
entry on its own, so distance entry is unchanged.

Fixes HakanSeven12/OpenCADStudio#1313

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01TQzYZsXBwPZ5HwBaGitEUV
(cherry picked from commit 2f6caacece)
2026-09-20 21:29:15 +03:00
copilot-swe-agent[bot] 41101efaa5 fix(trim): skip empty preview polyline segment samples
Co-authored-by: dasmatus <[email protected]>
(cherry picked from commit fb13a7aaa6)
2026-09-20 21:29:15 +03:00
Claude e83c8a28a5 fix(trim): skip polyline segments with no plan-view shape
`sample_entity_xy` walks a polyline's exploded segments and drops the
vertex each segment shares with the previous one. A segment whose curve
plane is upright — any non-horizontal run of a 3D polyline — has no XY
curve, so `entity_curve_xy` declines it and the segment samples to
nothing. With nothing accumulated yet, the seam test compared the two
empty ends as equal and then sliced the empty sample from index 1:

    panicked at src/modules/draw/modify/trim.rs:3982:42:
    range start index 1 out of range for slice of length 0

On the web build that panic unwinds through winit's event-loop runner
and leaves its state borrowed, which is the "RefCell already borrowed"
follow-on in the same report.

Skip an empty sample instead, which leaves the seam handling to the
segments that do have a plan-view shape.

Fixes HakanSeven12/OpenCADStudio#1318

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01TQzYZsXBwPZ5HwBaGitEUV
(cherry picked from commit ac9a6ce91a)
2026-09-20 21:29:15 +03:00
Hakan SevenandClaude Fable 5.1 a1629fd073 fix: closing-segment markers on closed polylines; case-insensitive page-setup names
- resolve_point, set_polyline_vertex and the solver's point_for_marker
  treat the marker one past the last vertex of a closed polyline as
  vertex 0, the way line_segment already did. Equal (#1366), the axis
  pre-alignment (#1365) and the transform pin (#1361) address a picked
  segment's end that way, so on the closing segment they either refused
  the pick or pinned nothing.
- Page-setup dictionary keys compare case-insensitively: page_setup_save
  replaces "site" when "Site" exists instead of adding a second entry
  (PSETUPIN counted it as replaced, #1344), delete and rename match the
  same way, and a rename that only changes case is allowed.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-20 21:12:07 +03:00
Hakan SevenandClaude Fable 5.1 8845095432 fix: DXF attribute rotation converted once; plugin layers refuse unknown linetypes
- The acadrust DXF reader has converted ATTRIB/ATTDEF rotation to radians
  since f226110 (in every codec rev OCS pinned from 2026-08-08 on), while
  fix_dxf_dimension_rotations still applied to_radians a second time on
  load. Only Shape needs the conversion here. Surfaced by #1391's hunk.
- Shape-file text styles are found by their is_shape_file flag instead of
  an empty name (also from #1391).
- #1393's add_layer/modify_layer wrote an unresolved linetype name into
  the LAYER record; a name the drawing (plus the standard set) cannot
  supply is now refused, through one resolve_linetype helper.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-20 20:18:18 +03:00
Hakan Seven 8075caa744 Merge pull request #1393 from yztink/feat/plugin-layer-properties
feat(plugin): add layer creation and modification host API with GUI refresh
2026-09-20 20:14:10 +03:00
Hakan Seven 871b0ab2ec Merge pull request #1392 from buyun14/fix/batch-line-tail
fix(automation): consume and report the tail of a batch command line
2026-09-20 20:14:10 +03:00
buyun14 899af80c2f fix(automation): consume and report the tail of a batch command line
`run_command_line` feeds the tokens after the command verb to the interactive
command and then terminates it as if Enter were pressed. Two gaps left a
headless caller unable to tell what actually happened.

In-place text editor takes over, remaining tokens were dropped
----------------------------------------------------------------
The `TEXT` content step hands over to the in-place editor, at which point the
command has already ended (`active_cmd` is `None`). The feed loop stopped
there, so the rest of the line — including the text itself — vanished:
`TEXT 0,0 5 0 hello` reported `completed` with `added: 0` and created nothing.
The tail is now typed into that editor and committed, and the commit is done
synchronously so its result is observable: `text_inline_commit()` returning
false leaves the tokens in `unconsumed` instead of reporting a successful line.
Dispatch the commit as a queued message instead and a failed commit would look
exactly like a good one — the text dropped, `added: 0`, `unconsumed: []`.

Only an editor this line opens is taken over, and after a successful commit the
line is closed with an escape: `TEXT` re-arms for the next line
(`open_next_line`), which would otherwise let the *next* batch line be eaten as
the next text position.

Leftover tokens are dropped
---------------------------
Any token no prompt ever asked for is recorded in `CommandLine::unconsumed` and
surfaced by the automation `run` response, so over-typed or misplaced input is
visible instead of silently ignored: `CIRCLE 0,0 5 9` reports
`"unconsumed": ["9"]` while a fully consumed line reports an empty list.

Pending surfaces are reported instead of `completed`
----------------------------------------------------
`run` now carries `blocked_by` — `"command"`, `"text_editor"`,
`"mtext_editor"`, `"modal:<Kind>"`, or `null` — and answers `waiting_input`
when something is still open rather than claiming `completed`.

`blocked_by` is attributed to the line that opened the surface: a condition and
its snapshot are taken before the command runs, so an editor left open by an
earlier line, another tab, or a startup dialog does not turn a finished command
into `waiting_input`. Without that attribution a caller polling for `completed`
would wait forever on someone else's editor. `docs/automation` documented
`waiting_input` as "more input is required", which is exactly what a pending
surface is; the two new fields are documented there as well.

Tests
-----
* `batch_text_line_creates_text_and_consumes_every_token` — the regression case
  creates exactly one `Text` entity and leaves nothing unconsumed.
* `multi_word_text_keeps_the_spaces` — asserts the committed string, so an
  off-by-one in the consumed index or a wrong join cannot pass.
* `run_reports_leftover_tokens_instead_of_dropping_them`.
* `text_without_content_reports_the_open_editor`.
* `a_stray_editor_is_not_hijacked_by_the_next_line` — the next line neither
  types into the stray editor nor inherits its blocker (`blocked_by: null`,
  `status: completed`).
* `a_command_still_waiting_is_named_as_the_blocker`.

Verified over the `--serve` protocol: `TEXT 0,0 5 0 hello world` → `completed`,
`added: 1`, and the entity really holds `hello world`; `TEXT 40,0 5 0` →
`waiting_input` + `blocked_by: "text_editor"`; the following `CIRCLE 0,0 5 9` →
`completed`, `blocked_by: null`, `unconsumed: ["9"]`; `LINE` → `waiting_input`
+ `blocked_by: "command"`.

Full lib suite: 1497 passed, 2 failed — both failures
(`io::plot_style::…named_tables_and_missing_files_get_a_reason`,
`scene::parametric_constraints::…arc_grips_drive_center_start_and_end_but_not_midpoint`)
reproduce on the unmodified tree; run with `LC_ALL=C` since several xref tests
otherwise fail on a non-English locale.

Known remaining gap, unchanged here: `MTEXT` / `HATCH` still answer `completed`
with `added: 0` in this path (they need interactive surfaces the feeder has no
tokens to fill). Reported separately in #1390.
2026-09-20 19:15:55 +08:00
Karim Jerbi 70d7e9a31f perf(plotstyle): extract and speed up layer-usage table rebuild
view_window() rebuilt the 256-bucket ACI layer-usage table inline on every
modal view: unconditional 256-Vec allocation plus sort_by_key (lowercase key
recomputed per comparison). Extract pure build_layer_usage(), build it only
when the CTB path needs it (STB path now allocates nothing), and sort with
sort_by_cached_key while skipping trivial buckets.

Tests:
- build_layer_usage_buckets_index_colors: ACI bucketing + case-insensitive order
- build_layer_usage_ignores_non_index_colors: truecolor layers excluded

Bench (cargo bench ui_plotstyle_layer_usage, 200 layers): ~13us median, PASS.
A/B vs pre-change inline code: ~15.7us -> ~12-13us (~22% faster).
2026-09-20 11:17:05 +01:00
Helen Kwok cf004107b2 Keep the task a dispatched command returns
CmdResult::Dispatch and CmdResult::Relaunch end the active command and run the
assembled line through dispatch_command, then discarded the Task it returned
(`let _ =`). A command whose effect is a message carried by that Task was
announced but never applied. VSCURRENT's keyword picker is one: choosing
"Gouraud Shaded" printed "Visual style: Gouraud Shaded." and left the
drawing in wireframe, because SetRenderMode travels in that Task.

Hold the Task and batch it with the focus task that apply_cmd_result_inner
returns. A regression test drives both results through VSCURRENT and checks the
tab's render mode.
2026-09-20 13:17:05 +09:30
Hakan SevenandClaude Fable 5.1 768ce2ca82 chore: pick up cadcodec 5b682ed (upstream acadrust sync) and cadkernel 6f046af
acadrust follows hakanaktt/acadrust main through #107, entity-record
passthrough included; cadkernel pins the same codec rev so one acadrust
stays in the graph. Upstream added BlockFlags::is_xref_unloaded, which
XATTACH now sets to false for a freshly attached reference.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-20 06:22:19 +03:00
yztink 929f185ba5 feat(plugin): add layer creation and modification host API
- Add LayerConfig struct and add_layer / modify_layer methods to HostApi trait
- Implement IPC request/response serialization for AddLayer and ModifyLayer
- Implement HostSession methods with CAD property defaults and selective modification
- Refresh layer panel UI and invalidate scene layer dependencies upon layer changes
- Add unit tests for add_layer with defaults and partial modify_layer
2026-09-19 16:40:41 -07:00
Hakan Seven fbdc97af4a Merge pull request #1381 from huaninstratech/pr/isoplane-session-only
fix(settings): keep isometric drafting session-only
2026-09-19 23:06:51 +03:00
Hakan Seven 7204d4f98d Merge pull request #1380 from huaninstratech/pr/io-locked-drawings
fix(io): open locked, shrinking and cloud-placeholder drawings without crashing
2026-09-19 23:06:51 +03:00
Hakan Seven 97596de147 Merge pull request #1377 from helenkwok/fix/control-accepts-point-with-keywords
Control: a point step that takes keywords accepts points
2026-09-19 23:06:51 +03:00
Hakan SevenandClaude Fable 5.1 92ce142c03 fix: drop the stray lock fixture; align merged plot code across targets
- tests/fixtures/plot/.page-setups-metric.dxf.ocs.lock was the app's own
  single-instance lock file, committed by accident in #1343; remove it and
  ignore *.ocs.lock.
- load_plotsettings_into_dialog: #1343's refresh_custom_scale_fields borrowed
  self while #1360 still wrote through the plot_dialog borrow; write the
  style error first.
- The wasm list_printers stub returns the Result #1358 gave the native one.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-19 23:06:09 +03:00
Hakan Seven 829a69ae6a Merge pull request #1367 from ramox81/codex/axis-hover-markers
Hover an object-mode Horizontal/Vertical glyph without endpoint markers
2026-09-19 23:01:01 +03:00
Hakan Seven 3ba370bcd1 Merge pull request #1366 from ramox81/codex/equal-constraint-parity
Bring the Equal constraint to reference parity

# Conflicts:
#	src/command.rs
2026-09-19 23:01:01 +03:00
Hakan Seven b131102784 Merge pull request #1365 from ramox81/codex/axis-align-perpendicular
Turn an object onto its Horizontal/Vertical axis before solving
2026-09-19 23:00:46 +03:00
Hakan Seven f20c823ffe Merge pull request #1360 from HakanSeven12/plot/b4-ctb-leniency
fix(plot-style): load plot style tables written by other applications

# Conflicts:
#	src/app/update/file.rs
#	src/ui/window/plot.rs
2026-09-19 23:00:19 +03:00
Hakan Seven 996412c405 Merge pull request #1359 from HakanSeven12/plot/b4-windows-printer-media
feat(plot): Windows printer media and printable areas

# Conflicts:
#	locales/ar-SA/opencadstudio.ftl
#	locales/bg-BG/opencadstudio.ftl
#	locales/cs-CZ/opencadstudio.ftl
#	locales/de-DE/opencadstudio.ftl
#	locales/el-GR/opencadstudio.ftl
#	locales/en-US/opencadstudio.ftl
#	locales/es-ES/opencadstudio.ftl
#	locales/fi-FI/opencadstudio.ftl
#	locales/fr-FR/opencadstudio.ftl
#	locales/hi-IN/opencadstudio.ftl
#	locales/hu-HU/opencadstudio.ftl
#	locales/it-IT/opencadstudio.ftl
#	locales/ja-JP/opencadstudio.ftl
#	locales/ko-KR/opencadstudio.ftl
#	locales/nl-NL/opencadstudio.ftl
#	locales/pl-PL/opencadstudio.ftl
#	locales/pt-BR/opencadstudio.ftl
#	locales/ru-RU/opencadstudio.ftl
#	locales/tr-TR/opencadstudio.ftl
#	locales/zh-CN/opencadstudio.ftl
#	locales/zh-TW/opencadstudio.ftl
#	src/locale_catalog.rs
2026-09-19 23:00:18 +03:00
Hakan Seven 377f551b48 Merge pull request #1358 from HakanSeven12/plot/b4-windows-printer-routing
fix(print): send Windows plots to the chosen printer, name the default, report failures

# Conflicts:
#	locales/ar-SA/opencadstudio.ftl
#	locales/bg-BG/opencadstudio.ftl
#	locales/cs-CZ/opencadstudio.ftl
#	locales/de-DE/opencadstudio.ftl
#	locales/el-GR/opencadstudio.ftl
#	locales/en-US/opencadstudio.ftl
#	locales/es-ES/opencadstudio.ftl
#	locales/fi-FI/opencadstudio.ftl
#	locales/fr-FR/opencadstudio.ftl
#	locales/hi-IN/opencadstudio.ftl
#	locales/hu-HU/opencadstudio.ftl
#	locales/it-IT/opencadstudio.ftl
#	locales/ja-JP/opencadstudio.ftl
#	locales/ko-KR/opencadstudio.ftl
#	locales/nl-NL/opencadstudio.ftl
#	locales/pl-PL/opencadstudio.ftl
#	locales/pt-BR/opencadstudio.ftl
#	locales/ru-RU/opencadstudio.ftl
#	locales/tr-TR/opencadstudio.ftl
#	locales/zh-CN/opencadstudio.ftl
#	locales/zh-TW/opencadstudio.ftl
#	src/locale_catalog.rs
2026-09-19 23:00:18 +03:00
Hakan Seven 1c0ef9d7a0 Merge pull request #1353 from HakanSeven12/ui/options-ok-apply-close
feat(options): OK / Apply / Close with a discard guard

# Conflicts:
#	src/app/view/modal.rs
#	src/ui/window/options.rs
2026-09-19 22:59:56 +03:00
Hakan Seven b1080e02ca Merge pull request #1344 from HakanSeven12/plot/b3-psetupin
feat(plot): PSETUPIN, page-setup import and page setup for new layouts
2026-09-19 22:59:36 +03:00
Hakan Seven 879bb70c12 Merge pull request #1343 from HakanSeven12/plot/b2-dialog-options-sysvars
feat(plot): page-setup units, custom scale, dialog options and plot sysvars
2026-09-19 22:59:36 +03:00
Hakan Seven 10827283ee Merge pull request #1339 from mechpanos/snap/line-endpoint-lookup
fix(snap): keep the key-vertex lookup linear and pin the vertex layouts
2026-09-19 22:59:36 +03:00
huanld 8cabadd147 fix(settings): keep isometric drafting session-only
A persisted ISODRAFT flag turned every drawing's crosshair into the
isoplane pair (one vertical, one diagonal arm) on every launch, with no
visible control to switch it back off — F5 (ISOPLANE) only cycles the
plane. Drop the flag when saving and ignore it when an old settings
file still carries it; turning it on stays a per-session choice.
2026-09-19 16:52:25 +07:00
huanld dc23d4073a fix(io): survive locked, shrinking and cloud-placeholder drawings
Opening a drawing that another program or machine holds without read
sharing used to fail with a raw OS error, and the memory-mapped fast
path could kill the process outright: a mapped file that shrinks
mid-parse (a writer saving over it) or a cloud placeholder that cannot
page in raises an in-page exception no Rust code can catch.

Read the DWG through a guarded fast path instead: mmap when possible,
and fall back to one in-memory snapshot read — opened with the most
permissive share mode Windows offers (FILE_SHARE_READ | WRITE |
DELETE) — whenever the map fails or an I/O error surfaces mid-parse.
A snapshot can never fault: a concurrent writer just ends the read
early. Sharing violations (os error 32/33) now answer with a message
that names the file and the remedy, and OneDrive-style placeholder
attributes skip mmap entirely.
2026-09-19 16:52:24 +07:00
Karim Jerbi f8d5099cda fix(block-palette): use theme-aware label colors with contrast coverage 2026-09-19 10:03:44 +01:00
Karim Jerbi 4fdef48502 fix(viewcube): deterministic horizon for obliques, generic opposite
Top Front Right/Left kept Y (north) as up when starting from Top,
tilting the base because orbit is turntable (never banks). Make
snap_to_direction deterministic: world +Z horizon except near +-Z
where north +Y is used, sign-preserved only for intentionally
inverted views. Expand opposite() from faces-only to all 26 regions
so already-there flip works for edges/corners.
2026-09-19 09:37:56 +01:00
Helen Kwok be99983b72 Control: a point step that takes keywords accepts points
active_command_metadata listed one input kind per step. A point step that
also takes keyword letters (point_step_accepts_keywords) reports
SingleToken, so MOVE and COPY's base point with [Displacement] were
described as accepting only token and enter, and the input example was the
D keyword, though the step takes a point. List point as well; the keyword
letters are still listed as token from the options.
2026-09-19 18:01:14 +09:30
ramox81andClaude Fable 5.1 b24d04d620 Hover an object-mode Horizontal/Vertical glyph without endpoint markers
The reference highlights only the object when its Horizontal/Vertical bar
is hovered; the extra cross markers at the line's ends were ours alone.
Point-mode (2Points) relations keep marking their two points.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 23:46:26 +03:00
ramox81andClaude Fable 5.1 4e2fc8c9de Draw the Equal glyph symbol in green
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 23:45:01 +03:00
ramox81andClaude Fable 5.1 3492ae32eb Show the Equal glyph on every object of the relation
The reference places an Equal bar on each object it joins; one glyph on
the first object only left the follower unmarked.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 23:32:42 +03:00
ramox81andClaude Fable 5.1 e32e7e68e4 Equal: apply each Multiple pick at once, take typed coordinates as picks
Multiple now follows the reference flow: every pick after the first is
made equal right away under `Select object to make equal to first:` and
Enter ends the command with `Length of objects made equal` (or `Radius
…`). A typed coordinate at one of the command's object prompts picks the
object under that point instead of being refused as a point.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 23:04:49 +03:00
ramox81andClaude Fable 5.1 8520ee45e8 Bring the Equal constraint to reference parity
Equal was applied through a generic gather-then-apply flow and, with the
default size-retaining solve mode, never changed anything: the solver
held both sizes and the relation could not be met. Now:

- GCEQUAL joins ECONSTRAINT and GEOMCONSTRAINT Equal; both objects are
  picked inside the command (`Select first object or [Multiple]:`,
  `Select second object:`; Multiple gathers `Select objects to make equal
  to the first:`), a selection made beforehand is not used, a miss says
  `No object found.` and re-asks, an unsupported object or the same object
  twice is reported and re-asked, a repeat is refused.
- The follower is resized in place before the relation is added: a line or
  straight polyline segment keeps its start and direction and its end
  moves to the first object's length; a circle or arc keeps its center and
  takes the radius.
- During edits the side that is not being edited follows the same rule:
  its size is not retained, its start (or center) and other vertices are
  held and its direction kept, so only its length or radius changes; a
  chain of Equal relations follows along.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 22:56:31 +03:00
ramox81andClaude Fable 5.1 1f0b888833 Turn an object onto its Horizontal/Vertical axis before solving
The solver cannot start from an axis lying exactly across the datum: the
distance and direction equations are singular there, so a horizontal line,
a text at 0 degrees or an ellipse whose major axis is horizontal stayed
put when Vertical was applied. The command now turns the object about its
anchor (line start, picked segment's first vertex, text insertion point,
ellipse center) onto the axis first — a polyline moves only the segment's
end vertex — and lets the constraint hold what already fits. Two points on
one entity follow the same rule about the first point.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 22:40:39 +03:00
Hakan SevenandClaude Fable 5.1 5ba72ec3e4 chore: pick up cadcodec #47 and cadkernel #66; guard the re-align length
- acadrust 7ea4247: clamped-knot degree and MINSERT reservation fixes
  (cadcodec #47). cadkernel a0b962a: dogleg fails on a non-finite
  Jacobian (cadkernel #66) and pins the same codec rev, so one acadrust
  stays in the graph.
- The axis re-alignment from #1361 retains its transformed length through
  retain_segment_length, which holds a zero-length segment with per-axis
  differences instead of a P2PDistance whose gradient is NaN there.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 22:16:06 +03:00
Hakan Seven edc45caa14 Merge pull request #1363 from ramox81/codex/capture-minimized-guard
Refuse an automation capture while the window is minimized
2026-09-18 22:12:21 +03:00
Hakan Seven f137ce96f1 Merge pull request #1362 from ramox81/codex/axis-point-reprompt
Report a missed first 2Points pick at once for Horizontal/Vertical
2026-09-18 22:12:21 +03:00
ramox81andClaude Fable 5.1 02a75ead50 Refuse an automation capture while the window is minimized
A minimized window has a 0x0 surface; the renderer's screenshot path
panicked on the empty read-back buffer and took the whole application
down. The capture op now checks the window size first and answers with
an error instead of requesting the screenshot.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 20:36:08 +03:00
ramox81andClaude Fable 5.1 cda0627804 Report a missed first 2Points pick at once for Horizontal/Vertical
The first empty-space click of the 2Points flow was only resolved against
the document together with the second one, so "No valid constraint point
found." appeared one pick late. The command now hands the first pick to
the host (`CmdResult::CheckHorizontalPoint`), which resolves it right away:
a miss reports and re-asks for the first point, a hit moves on to the
second point.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 20:36:01 +03:00