Commit Graph
1334 Commits
Author SHA1 Message Date
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 Seven a7ab5314f2 Merge pull request #1356 from ramox81/codex/fixed-constraint-parity
Let other constraints reconcile a partly fixed entity's free points
2026-09-18 18:59:26 +03:00
Hakan Seven 3ba7b38934 Merge pull request #1357 from ramox81/codex/vertical-constraint-parity
Match Vertical geometric constraint behavior

# Conflicts:
#	src/app/commands/draw.rs
#	src/scene/parametric_constraints.rs
#	src/ui/overlay.rs
2026-09-18 18:54:12 +03:00
Hakan Seven 7ef4e9f336 Merge pull request #1356 from ramox81/codex/fixed-constraint-parity
Match Fix geometric constraint behavior

# Conflicts:
#	src/scene/parametric_constraints.rs
#	src/scene/parametric_solve.rs
2026-09-18 18:53:18 +03:00
Hakan Seven da02e38208 Merge pull request #1352 from ramox81/codex/symmetric-constraint-parity
Complete Symmetric constraint behavior
2026-09-18 18:52:41 +03:00
Hakan Seven ce6db72c78 Merge pull request #1346 from huaninstratech/fix/block-text-wipeout-depth
fix: keep block text above its own block's wipeouts (compose glyph depth through the scene graph)
2026-09-18 18:52:37 +03:00
Hakan Seven 3c1ad62e9b Merge pull request #1340 from CiberNin/fix/editor-crashes
Fix editor crashes from typed input, text, and degenerate geometry
2026-09-18 18:52:37 +03:00
Hakan Seven 37b24296d8 Merge pull request #1338 from ramox81/codex/properties-hyperlink-control
Fix Properties hyperlink collection editing
2026-09-18 18:52:37 +03:00
ramox81andClaude Fable 5.1 d837109076 Let other constraints reconcile a partly fixed entity's free points
8) A moved entity that a Fixed holds only in part no longer pins its free
   points as hard anchors: they stay where the edit put them unless another
   constraint on the entity (e.g. Vertical) moves them, so the fixed point
   holds and the solve no longer fails when the two disagree.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 18:49:48 +03:00
ramox81andClaude Fable 5.1 26e458d6f7 Match Vertical geometric constraint behavior
1) VCONSTRAINT (and the new GCVERTICAL name) uses the axis constraint flow:
   "Select an object or [2Points] <2Points>:", 2Points mode with the
   reference's re-prompts and messages, and the same object types as
   Horizontal — line, polyline segment, text, MText, ellipse axis.
2) Object mode turns the object about its first vertex; a two-point relation
   across two objects slides the second object rigidly onto the axis.
3) Re-applying an axis constraint reports that the constraint already
   exists; Vertical follows the UCS Y direction.
4) The constraint bar draws Vertical as the reference's axis mark, with the
   point marker for a two-point relation.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 18:19:49 +03:00
ramox81andClaude Fable 5.1 45f3088a89 Draw the Fix constraint bar glyph as a padlock
7) The constraint bar draws Fix as a padlock instead of the letter F: a
   white lock with a small orange point marker when one point is held, a
   red lock when a whole curve or polyline segment is held.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 16:55:11 +03:00
ramox81andClaude Fable 5.1 f998b59193 Match Fix geometric constraint behavior
1) FXCONSTRAINT (and the new GCFIX name) prompts "Select point or [Object]
   <Object>:" — a pick fixes that constraint point; Enter or O asks for one
   line, polyline segment, circle, arc, ellipse or spline; misses and
   unsupported objects report the reference messages and re-prompt.
2) Point, block, text, MText, attribute and table insertion points are
   addressable constraint points.
3) Re-applying Fixed to the same point or object reports that the constraint
   already exists instead of adding a duplicate.
4) A persistent Fixed holds its pre-edit geometry through MOVE, ROTATE,
   SCALE, STRETCH, grip and Properties edits: fixed points stay, free points
   of a partly fixed entity follow the edit, and size retention skips fixed
   entities.
5) Object mode on a polyline fixes the picked segment (natively persisted)
   instead of the whole polyline; arc segments pin endpoints, center and
   radius.
6) Ribbon label "Fix" with a padlock icon.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 15:38:33 +03:00
ramox81 9aadc97c11 feat: complete symmetric constraint behavior 2026-09-18 10:27:00 +03:00
huanld 36d5c4db79 fix(render): compose PLOTSTYLE wire-fill depth like the wire pipeline
When a display plot style maps an ACI to a fill pattern, wire fill
triangles are re-emitted as PLOTSTYLE hatches. Those took
depth_override raw — a per-block child label for block wires and 0.0
for top-level ones — while everything else in the hatch/wipeout pass
sorts at the composed depths[insert] + label * half. The fill could
land outside its host's band and get buried under its own block's
masks (same shape as the block-text bug).

Both the display and PDF paths now travel through wire_draw_depth /
the PlotWire's composed depth, and the display cache key rides the
depth generation so a DRAWORDER edit re-ranks the fills without
needing a wire rebuild.
2026-09-18 08:38:35 +07:00
huanld 454d99b1d3 fix(scene): block text keeps its draw-order slot against sibling wipes
Unselected block text (the BS33-11 Mark/SectionMark labels) was erased by
its own block's wipeout pass and only came back through the selection
xray. Two compounding causes:

- Glyph quads rendered at the bare insert level, an exact depth tie with
  every sibling fill, so the later wipeout pass won LessEqual. Wire
  batches now carry the composed child rank as depth_override (the same
  units the scene graph composes: depths[insert] + label * half), which
  the block-text upload resolves per instance. Glyph vertices stay
  neutral on purpose — baking the raw per-block label into them
  double-counts and, for a negative rank, sinks the text BELOW its own
  masks.
- The wipeout pipeline's depth bias (-8 quanta) was larger than the
  whole within-block band: once child ranks compress into the insert's
  half-band, sibling steps are ~3 quanta and a wipeout-to-text gap is
  only 9-16 quanta of the 24-bit buffer. The mask only needs to break
  exact ties, so the bias is now WIPEOUT_DEPTH_BIAS_QUANTA = 2.

block_text_draw_depth regression pins the contract: neutral vertices,
override carrying the rank, and a margin over the wipe that exceeds the
bias on a 600-entity scene.
2026-09-18 08:38:35 +07:00
Christopher OverbeckandClaude Opus 5 1ac9309f85 Guard constraint solving and DWG export against degenerate geometry
Retaining a line's length added a P2PDistance constraint, whose gradient
divides by the current distance. For a zero-length line the solver got a NaN
Jacobian and its SVD fallback never returned, freezing the editor (e.g.
ECONSTRAINT on a line drawn by clicking one point twice). Hold coincident
endpoints together with per-axis differences instead.

Control-point splines read without knots are given a degree their control
points can carry (at most n - 1) and a clamped knot vector when a drawing
loads. Generating knots for fewer points than the degree underflowed during
DWG write: a panic in debug builds, an unbounded allocation in release, and
reachable from autosave. A lone control point with no knots or fit points is
purged as corrupt.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-17 10:33:18 -05:00
ramox81 6a1c649016 Fix Properties hyperlink collection editor 2026-09-17 18:17:25 +03:00
Panos 472bb9883d Merge pull request #1337 from HakanSeven12/plot/b1-plot-settings-compat
fix(plot): write page setups in the file format's canonical form
2026-09-17 18:14:17 +03:00
PanosandClaude Opus 5 8e09bd8463 fix(plot): follow the fixture's page-setup conventions
A drawing saved by a commercial CAD application (tests/fixtures/plot,
provided by Panos: one 10 m line, three layouts) corrects several
assumptions of the previous commit:

- rotation is relative to the medium's own orientation: an unchanged sheet
  keeps the driver's exact medium (its PDF driver lists landscape media of
  its own, written with rotation 0; a system printer's portrait A3 plotted
  landscape carries 90); only a newly picked sheet is written as the
  catalogue's portrait medium
- the stored scale factor (DXF 147) is the ratio × 25.4 on millimetre page
  setups and the plain ratio on inch ones; the "use standard scale" bit
  stays clear for standard and custom scales and is set for fit-to-paper;
  a standard code is kept across a paper-unit conversion ("1:1" on an
  inch page setup over a millimetre paper space is 1 in = 25.4 units)
- layout plots take the same scale path as every other area, so a foreign
  layout's paper-space unit survives
- "plot with plot styles" / "display plot styles" round-trip as the
  dialog's checkboxes, independent of a style table being named
- layout limits place the sheet at minus its displayed margins, the way the
  source application does (the printable corner is the paper-space origin);
  the margin ↔ rotation mapping shared by the printable-area guide now
  turns the medium's top margin into the layout's left one at 90°

The fixture round-trips through the dialog with every stored field
unchanged; picking a new sheet on it writes the canonical form.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-17 18:04:38 +03:00
PanosandClaude Opus 5 276e7c7bf1 fix(plot): write page setups in the file format's canonical form
One writer (plot_settings_from_dialog) now serves both the layout's embedded
settings and named page setups, so the two can no longer drift apart:

- media are stored as the portrait sheet with the orientation in the
  rotation code (0/90/180/270; upside-down adds a half turn) instead of
  swapped width/height with rotation limited to 0/180
- standard scales are written by their code (1:1 … 100:1) with matching
  numerator/denominator; other scales as a readable custom ratio in the
  layout's own paper unit, converting from the drawing's scale-family unit
  (a metre drawing plotting "1:100" stores 10 mm = 1 unit, an inch layout
  stores 1 in = 2540 units); reading converts back and keeps a ratio the
  scale list has no name for instead of snapping to 1:1
- the layout's paper unit and every flag the dialog does not edit survive a
  round trip untouched; layout limits follow the paper-space unit
- new drawings, new layouts, CLEAR and the automation "new" op share one
  default page setup (canonical A4 name, rotation 90, none_device, 1:1
  layout plot) through Scene::reset_to_new_drawing

Scene gains scale_family_unit_mm, scale_ratio and a scale-name ratio parser
(ratios and architectural names). Round-trip tests cover orientation,
standard/custom/fit scales, unit conversion, named-setup parity, preserved
flags and the default layout.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-17 18:04:38 +03:00
Hakan Seven f0a3336302 fix: retain horizontal constraint axes 2026-09-17 17:55:56 +03:00
Hakan Seven f9c59503f0 Merge pull request #1334 from ramox81/codex/horizontal-constraint-parity 2026-09-17 17:39:44 +03:00
Hakan Seven 80f2d5fd72 fix: solve concentric geometry in kernel 2026-09-17 17:39:01 +03: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
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
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
ramox81 a6a70420c4 fix: align concentric constraint behavior 2026-09-17 15:31:26 +03: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
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 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 <[email protected]>
2026-09-17 12:05:14 +03:00
ramox81 cbf1e76c69 Fix perpendicular constraint behavior 2026-09-17 10:48:44 +03:00
Hakan Seven a27545c379 fix: resolve review regressions and align dependencies 2026-09-17 07:47:15 +03:00
Hakan Seven df53117541 Merge pull request #1323 from ghost/diameter-grip-text-alignment 2026-09-17 07:15:26 +03:00
Hakan Seven dfe7904308 Merge pull request #1312 from ghost/ordered-tangent 2026-09-17 07:08:54 +03:00
Hakan Seven 7cd62a68f7 Merge pull request #1315 from ghost/ordered-perpendicular 2026-09-17 07:00:52 +03:00
Hakan Seven 03f4e7cb86 Merge pull request #1309 from ghost/embed-print-fonts 2026-09-17 06:57:42 +03:00
codallos 1f71a70580 Fix diameter dimension grip and text alignment 2026-09-16 19:21:03 -06:00
Hakan Seven 144abc96fe fix(parametric): order polyline constraints by drawing direction 2026-09-16 23:15:40 +03:00
Karim Jerbi ca0ee37d26 feat(snap): independent 3D object-snap system with six modes
Grid snap locks to SNAPUNIT instead of magnetizing; snapped 3D points keep elevation instead of flattening to z=0. New SnapTypes Vertex/EdgeMidpoint/FaceCenter/Knot/FacePerpendicular/NearestFace with their own F4 master toggle and mode set, tiers, and markers, fully independent of the 2D master. Solid B-rep corners/edge-midpoints/face-centers from mesh edges and kernel faces, spline knot points, and live perpendicular/nearest-to-face on mesh triangles merged priority-aware in move/click paths. Drafting Settings 3D Object Snap tab is fully live (was dead placeholders); Nearest-to-face off by default. TDD: behavioral LINE-to-solid tests plus engine/scene unit tests.
2026-09-16 16:43:37 +01:00