Commit Graph
1554 Commits
Author SHA1 Message Date
Hakan SevenandClaude Opus 5.5 81bb8d48cf Cargo: codec aad7053, kernel 1a52eaf, graph 263de59; honour viewport clipping
Brings codec PRs #84 (cross-version visual styles, table styles,
subentity managers), #88 (viewport clipping flag, DXF boundary handle),
#89 (DXF viewport snap/twist in degrees) and #92 (field format codes,
event updates).

With #88 a viewport keeps a stored boundary whether or not clipping is
on, so a linked boundary alone no longer means "clipped": rendering,
paper picking, VPCLIP and the Clipped property check the clipping flag
too, and VPCLIP / MVIEW Object and Polygon set it. Before, OCS never set
the flag, so its clipped viewports opened rectangular elsewhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:57:55 +03:00
Hakan Seven fbe55bab37 Merge pull request #1613 from ramox81/codex/sheet-set-manager
Sheet Set Manager, NEWSHEETSET / OPENSHEETSET and sheet set fields, with review fixes.

# Conflicts:
#	Cargo.lock
#	src/app/control/actions.rs
#	src/app/mod.rs
#	src/app/settings.rs
#	src/app/update/dialog.rs
#	src/app/update/file.rs
#	src/app/update/mod.rs
#	src/app/view/mod.rs
#	src/ui/dock.rs
#	src/ui/ribbon/mod.rs
#	src/ui/window/field_dialog.rs
#	src/ui/window/mod.rs
2026-10-06 09:49:38 +03:00
Hakan SevenandClaude Opus 5.5 8fb4a692c6 fix(count): redraw only app-edited table blocks; recolour count mode in place
- refresh_table_block no longer runs for every table change: only tables
  whose picture reference this app dropped while editing them (and new
  tables without one), never on appearance-only bumps. Moved, restyled or
  freshly opened tables keep their authored *T block. TABLE edits now drop
  the picture reference like the other table edit paths.
- set_count_display recolours just the handles whose count class changed
  (restyle path + recolor_meshes_for_handles); only entering or leaving
  count mode rebuilds the whole drawing.
- Count colouring keeps insert instancing: counted and duplicate wires get
  their own instance groups instead of dropping render_instance.
- The hatch backdrop takes the count colour too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 09:33:07 +03:00
Hakan SevenandClaude Opus 5.5 40847d72a1 fix(sheetset): safer sheet edits
- Place on Sheet gives its viewport a unique id (shared
  `Scene::next_viewport_id`, also used by the normal viewport commit).
- Renaming a sheet's layout in an open tab records undo and marks the tab
  modified; in a closed drawing the previous file is kept as `.bak`
  (ISAVEBAK) before it is written back.
- New Sheet saves the drawing before the `.dst`: a failed save leaves no
  sheet behind.
- Rename & Renumber Previous/Next no longer panics on an empty list.
- Leftovers: unused binding, a hard-coded localized Documents path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 09:29:23 +03:00
Hakan SevenandClaude Opus 5.5 8b9049c604 fix(view): keep named views of earlier versions at their place, in f64
A VIEW record's centre is an offset from its target in view coordinates.
Views saved by earlier versions stored the target itself as the centre;
treating that as an offset put them (and VIEW plots) at about twice the
coordinates. One shared `named_view_center` now resolves the centre in
f64 (DVec3/DQuat), taking a centre equal to a non-zero target as the old
convention; VIEW RESTORE, the view plot window and Place on Sheet use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 09:29:22 +03:00
Hakan Seven 078306d8fc Merge pull request #1613 from ramox81/codex/sheet-set-manager
Sheet Set Manager, NEWSHEETSET / OPENSHEETSET and sheet set fields
2026-10-06 09:17:20 +03:00
Hakan Seven 6da9675c55 Merge pull request #1614 from ramox81/codex/count-feature
Count: COUNT / COUNTAREA count mode, Count palette, count fields and tables
2026-10-06 09:16:57 +03:00
Hakan SevenandClaude Opus 5.5 7c76d2c27f fix: review follow-ups for #1602 and #1606
- #1602 changed the COMMANDLINEFADETIME help text and added "Never"
  without catalog entries, so both showed in English everywhere. Add
  them to the catalog and all 21 locales; drop the "0 skips them" key.
- #1606 named another CAD vendor in a doc comment and two test names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:32:30 +03:00
Hakan Seven 240eb0a95d Merge pull request #1606 from yztink/fix/ucs-face-selection
UCS FACE picks solid faces again; the UCS snaps to the nearest face corner with X along the nearest edge.
2026-10-06 00:20:59 +03:00
ramox81andClaude Opus 5.5 a3c79be278 Sheet sets: fly-out submenus, block previews, window-aspect named views
- Row menus open Set category / Place Callout Block as fly-out submenus
  (hover or right press; leftwards when the palette is docked right).
- List of Blocks and Select Block show the Blocks palette's preview.
- VIEW SAVE keeps the window's width/height ratio.
- Placing view content in model space is refused with the reference message.
- Drawings read for views, placement and blocks are cached by modification time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:05:47 +03:00
Hakan SevenandClaude Opus 5.5 de6e27304d perf(layers): toggle layer visibility without re-tessellating
Turning a 141k-entity layer off/on took 1.5-5 s; it now takes ~0.6-0.9 s.

- Off/freeze toggles go through invalidate_layer_visibility: entities on
  the layer keep their tessellation memo (visibility gates them before
  tessellation); only block users re-expand. No mesh recolor.
- The resident patch reuses a surviving memo entry instead of
  re-tessellating, guarded by the same display-context hash as the full
  build.
- The patch looked up `layout.order` linearly per re-shown entity, which
  made turning a big layer back on quadratic.
- recolor_meshes_for_handles resolved materials for handles with no mesh.
- Wire arena: a hidden slab keeps its instances and sets a `hidden` flag
  in its consts (collapsed in the vertex shader); an unchanged re-show only
  clears the flag. Const writes are batched into merged spans.
- The `layer_visible` automation action indexed the document's layer
  table instead of the sortable panel rows the Layer* messages use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:53:27 +03:00
ramox81andClaude Opus 5.5 7ad6e5b094 Count: Invalid Area dialog, table block kept with the table
- When the count area's boundary is gone the approved Invalid Area dialog
  asks: undo the change (also its X and Cancel) or count all of model space;
  "always" keeps the choice in the settings. An edited boundary moves the area.
- A table's *T block is brought up to date whenever the table changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:40:02 +03:00
ramox81andClaude Opus 5.5 0d0fbafaa8 Sheet sets: Place on Sheet, sheet view menus, block lists, missing status, field refresh
Model Views lists named model views and places them on the current sheet
(xref, viewport, paper-space named view, view label with navigation
fields, sheet view record); sheet view rows get Display, Rename & Renumber
View, Set category, Place Callout Block and Place View Label Block; the
View Category dialog's Add Blocks opens List of Blocks / Select Block; a
sheet whose relative path is gone shows missing; sheet set fields store
their values when a set changes; named views keep their centre relative to
the target. Codec pin moves to the revision with these field helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:13:33 +03:00
ramox81andClaude Opus 5.5 0a26709d13 Count: measured messages and listing, groups, Current area, boundary checks, fills and solids recoloured
- COUNTCOLOR / COUNTERRORCOLOR / COUNTSERVICE reject any other value with
  the range message; COUNTTABLE ? lists in the reference order, padded,
  22 lines a page with Press ENTER to continue:, then the totals.
- Target picks report N found / N found, M total; several objects (or one
  that is not a block reference) count their copies, shown as Geometries
  in the palette.
- Current area is the area in use (kept aside by Entire model space),
  otherwise all of model space; an invalid Object boundary ends with the
  reference message.
- Count colours reach solids and fills; the palette list and the count
  are recomputed only when the drawing changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 11:36:24 +03:00
ramox81 88d8a33572 Merge remote-tracking branch 'origin/main' into codex/count-feature
# Conflicts:
#	Cargo.lock
#	src/app/commands/field.rs
#	src/app/control/actions.rs
#	src/ui/window/field_dialog.rs
2026-10-05 09:21:43 +03:00
Hakan SevenandClaude Opus 5.5 6b5c2758e1 fix(hatch): keep the association when TRIM splits a boundary
Splitting a boundary object erased it and added the pieces, so the hatch
lost that source and rebuilt from what was left, often the whole circle.
The pieces now take over the old object's association before it is
erased.

Fixes #1572

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:44:08 +03:00
Hakan SevenandClaude Opus 5.5 fd01a36ad3 fix(osnap): a POINT snaps as a Node only
A point carried a key vertex, so Endpoint (which outranks Node) claimed
it, and an absolute-size glyph's strokes were indexed for Nearest and
Intersection. Points now offer only their Node, in the indexed and the
unindexed snap paths alike.

Fixes #1570

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:44:08 +03:00
Hakan SevenandClaude Opus 5.5 d6dfd0d46d fix(render): miter the joints of wide polyline bands
Each band segment was a rectangle ending square at its vertex, so the
outer corner of every joint showed a notch. Every segment end now carries
the tangent of half its turn, and the shader slides that end's corners
onto the joint's bisector so neighbours meet in a miter. Turns sharper
than the limit keep butt ends. Constant-width runs inside a polyline split
around its arcs no longer count as tapered, which had kept them unmitred.

Fixes #1565

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:44:08 +03:00
yztink 973d7b0bb6 feat(ucs): align UCS Face origin and axes to nearest vertex and edge 2026-10-03 22:32:57 -07:00
Hakan SevenandClaude Opus 5.5 e3c0d456f2 fix(layer): keep auto-registered layer names verbatim; one sync helper
ensure_layer had started trimming the name, so an entity on " A" got a
table entry "A" it never resolves to. Register the name as given again
and drop the unused return value. The five copies of the dirty-flag check
become sync_registered_layers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:59:30 +03:00
yztink 9345c7799c fix(layer): refresh ribbon and layer panel when entities register novel layers 2026-10-02 23:17:08 -07:00
Hakan SevenandClaude Opus 5.5 54a4a02d62 Merge PR #1589 from ramox81/codex/history-frame-lift: centre-framed boxes and wedges; no double transform after ACIS lift
The PR pinned codec and kernel to its fork through [patch]; codec #77 and
kernel #73 are merged upstream, so the patch sections are replaced by
the upstream pins (codec 8d23408, kernel d22a270, graph 9b5ae39) in this
same commit: the kernel now applies the body transform during the lift,
and an OCS without this PR's change would apply it twice. The new codec
also brings AssocCurveValue, registered with the plugin API's type
registry, and EmbeddedEntity::Body, named as a polyline profile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 20:08:19 +03:00
ramox81 e29b408bda WIP count feature 2026-10-02 17:52:13 +03:00
ramox81andClaude Opus 5.5 07facf465c fix(solids): box and wedge histories framed at the bounding-box centre; no second transform after ACIS lift
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 15:10:37 +03:00
Hakan Seven 0de1e91f99 Merge PR #1585 from ramox81/codex/field-command: FIELD command and Field dialog; attribute definition field buttons
The PR pinned the codec to its fork through [patch]; codec #75 is merged
upstream and main already points at it, so the patch section is dropped.
The two windows-sys features it adds (Globalization, Identity) stay.
2026-10-02 14:14:15 +03:00
Hakan Seven 34cc5cf435 Merge PR #1586 from ramox81/codex/solid-history-graph: no history on edge fillet/chamfer of plain solids; undo evaluation graph
The PR pinned codec and kernel to its fork through [patch]; codec #76 and
kernel #71 are merged upstream and main already points at them, so the
patch sections are dropped.
2026-10-02 14:11:15 +03:00
Hakan Seven 403a277588 Merge PR #1587 from mechpanos/fix/zoomfactor-range-and-exponential-zoom: hold ZOOMFACTOR to its own range, finish the exponential zoom 2026-10-02 14:09:44 +03:00
ramox81andClaude Opus 5.5 a735b10b34 feat(field): Formula, Hyperlink and plot fields; local-time field dates, file times and display name; header dates on save
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 12:38:49 +03:00
Hakan SevenandClaude Opus 5.5 d6b3bb13ab fix(text): copy a fallback face's font file only for an exporter
#1580 built a GlyphSource for every fallback glyph, so drawing a CJK
character on screen copied the whole fallback font (tens of MB) into a
process-wide cache whether or not a PDF was ever exported. The source is
now built only when fallback_source asks for it, through the same search.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 12:19:23 +03:00
Hakan Seven c492539fde Merge PR #1580 from Chrisyeh1983/fix/pdf-embed-truetype-text: export TrueType text as embedded subset fonts
Conflicts with 02c470aa (invisible searchable text layer): main already
depends on allsorts 0.16 with the same features, so its line stays. Both
layers would put the text into the PDF twice, so a run drawn wholly in
faces the PDF can embed now goes out as embedded-font text and skips the
invisible layer; any other run (stroke fonts, mixed scripts) keeps its
outlines and the invisible layer. Faces only probed for such a run are
not installed. The PR's test follows layout_glyph_quads' new tuple.
2026-10-02 12:16:38 +03:00
ramox81andClaude Opus 5.5 d7a19e5d8e fix(sweep): store the sweep profile placed on the path with flag 295, as the reference reads it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:57:53 +03:00
ramox81andClaude Opus 5.5 f6f2b81441 feat(field): FIELDDISPLAY gray field background (screen only, profile setting)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:20:02 +03:00
PanosandClaude Opus 5 9fe2e4fa58 fix(view): hold ZOOMFACTOR to its own range, finish the exponential zoom
The exponential camera step is the right call. `0.9 ^ delta` is strictly
positive for every real delta, in and out cancel exactly where the
subtraction lost a percent of the view on every round trip, and the file's
own header has promised an "exponential feel" since it was written. Three
surfaces were left behind it, and the wider range exposed a fourth thing.

The range of the system variable. 3 to 100 is the range ZOOMFACTOR has, and
the User Preferences page was built against it; `SETVAR ZOOMFACTOR` accepts
that and nothing else again. A faster wheel is the Options window's business
instead: the slider covers the variable's own range, the field beside it
reaches 500, and a read-out says what a notch actually does ("10.0% a
notch") so the number being set is readable rather than implied. A value
above 100 therefore lives only in this application's own configuration file,
where it is nobody else's to read, and a bare `SETVAR ZOOMFACTOR` still
reports it. The bounds and the clamp live in one place now
(`settings::clamp_zoom_factor`): four literal copies of `3, 100` are what
let a surface be missed in the first place.

A floating viewport in MSPACE. It zooms its own view through
`zoom_active_viewport`, which kept subtracting: the factor reached zero at
6.67 steps, so from ZOOMFACTOR 360 up every notch inside a viewport bottomed
out on the clamp — a tenfold jump a notch, and the top third of the slider
doing nothing at all. Exponential there too, from a base of 0.85 so the
default notch still moves a viewport the 15% it always has. Each surface
keeps its own long-standing feel rather than inheriting the other's.

The trackpad pinch. `pinch_zoom_steps` was calibrated against the
subtraction (`1 - step / 10 = 1 / (1 + m)`) so that a pinch of m leaves the
view exactly 1 + m times closer — the property docs/trackpad.md documents
and the reason the gesture tracks the fingers at all. Inverting the zoom law
by hand is what let the two drift apart, so the step is asked of the camera
now (`Camera::zoom_steps_for_ratio`), which cannot drift by construction.
`pinch_is_one_to_one` recomputed the old formula rather than the camera's,
so it kept passing through all of this; it zooms a real camera and measures
the distance it lands at instead.

Also: `zoom` had a floor and no ceiling, and zooming out multiplies. At
ZOOMFACTOR 500 a notch out is x2.4, so about ninety notches — a couple of
seconds of scrolling — ran the distance past what an f32 far plane
(`distance * 1000`) can hold, and the viewport went black on an infinite
projection. A degenerate pinch magnification of -1 or beyond reached the
same place through the other side. Both are bounded now.

Also: two doc comments quoted the linear law (`zoom_view_at_cursor` and the
one on `pinch_zoom_steps`), and docs/trackpad.md stated the pinch identity
and claimed the tests covered it against the camera. All updated, with what
a notch does and where each surface's range comes from written down.

Tests, each confirmed against the behaviour it describes: the zoom law at
every factor the application can hold (positive, monotonic in the setting,
in and out cancelling), the ceiling under a long scroll out in both
projections, the published inverse and what it does with a nonsense ratio,
the viewport factor and a real viewport zoomed three notches at the top of
the range, the SETVAR range including a value the Options field set, the
Options field (above 100, above the ceiling, cleared, not a number), its
agreement with the slider, Close putting both the value and the field back,
and the read-out's percentages. 1882 lib tests pass.

The two new Options strings are not in the locale catalog yet, so they
render in English until it is regenerated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-02 10:51:26 +03:00
ramox81andClaude Opus 5.5 eb90b68129 fix(solids): keep history-less solids without history on edge fillet/chamfer; undo the evaluation graph
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 10:45:09 +03:00
Hakan Seven a1d0cf3873 Merge PR #1574 from ramox81/codex/attdef-parity: ATTDEF dialog, -ATTDEF, tag display, Properties and Block Definition ribbon
Conflicts with #1573: the locale files and the catalog take both PRs'
entries (one "Insertion Point" mapping kept); the Home and Insert Block
panels take #1574's layout with #1573's Insert Block gallery.
2026-10-02 10:17:54 +03:00
Hakan Seven 7a6908c7ca Merge PR #1573 from ramox81/codex/blocks-palette-parity: Blocks palette tabs, insertion options, drag insertion and -INSERT 2026-10-02 10:10:51 +03:00
Hakan Seven e8a4f1316f Merge PR #1577 from mechpanos/fix/zoom-cursor-and-extents: zoom cursor per navigation tool, and ZOOM EXTENTS frames everything 2026-10-02 10:06:43 +03:00
Hakan Seven db838e8645 Merge PR #1579 from mechpanos/fix/erased-image-placeholder-text: erasing a broken raster reference clears its placeholder text 2026-10-02 09:58:44 +03:00
Hakan Seven f44d03f472 Merge PR #1581 from F4brizi/feature/increase-zoomfactor-limit: expand ZOOMFACTOR range to 500 2026-10-02 09:58:36 +03:00
ramox81 53f2983e9c Merge remote-tracking branch 'origin/main' into codex/attdef-parity
# Conflicts:
#	Cargo.lock
#	src/modules/draw/draw/attdef.rs
2026-10-02 09:09:21 +03:00
Karim Jerbi 02c470aac7 feat(pdf): searchable text layer with per-style subset font embedding
Real BT/Tj text objects ride alongside the vector outlines (Tr 3,
zero visual change): runs preserved at layout time, TTF styles embedded
as allsorts subsets with ToUnicode, width-matched Tm, clip-culled.
WireModel literals moved to ..Default::default() tails.
2026-10-01 23:30:35 +01:00
F4brizi e131843826 feat(viewport): expand ZOOMFACTOR range to 500 2026-10-01 18:49:23 -03:00
Hakan SevenandClaude Opus 5.5 443b935a3f chore: bump codec d28fd71, kernel a03e4f0, graph 79bdc4b
Codec: PRs #71-#74 merged (MPOLYGON layout, multiline ATTDEF/ATTRIB DXF,
DXF MATERIAL/ACSH matrix, restorable SAT/SAB + history roots) and issues
#55 #64-#69 fixed. EntityType now boxes Surface, Extended, Table,
MultiLeader and Helix (2344 B -> 848 B per entity): construction sites
wrap in Box, the entity traits forward through Box, and the python
plugin generator converts with into(). Kernel: PR #70 (cuboid ring
winding).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:08:55 +03:00
Chris YehandClaude Opus 5.5 a8dc6534f9 fix(pdf): export TrueType text as embedded subset fonts, not triangles
PDF export filled every TrueType glyph's tessellated outline, one triangle
per triple. A stroke-heavy CJK face such as DFKai-SB tessellates into
hundreds of triangles per character, so a 28-layout schematic set
exported at 320.9 MB and viewers crawled through it. The atlas export
table was also rebuilt for every text wire, which made the same export
take 566 s.

- ttf_glyph: GlyphSource records the face, glyph id and font-unit scale a
  filled outline came from; glyph_source / fallback_source resolve the
  same face as glyph / fallback_glyph (fallback picks both in one search).
- Face::glyph_source mirrors Face::glyph; stroke glyphs (LFF, SHX, big
  font) return None and keep their polyline export.
- GlyphExport carries the char and the source (filled glyphs only, so
  TEXTFILL 0 still exports hollow outlines).
- pdf_export draws a sourced glyph as text (Tf 1 + a Tm that maps its em
  onto the SDF quad), subsets each face with allsorts after all pages
  (keeping cvt/fpgm/prep for tricky fonts), renumbers glyph ids, and
  snapshots the glyph table once per export.

Same set: 566 s / 320.9 MB -> 27 s / 1.42 MB; text is searchable and
lands on the same pixels as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 23:07:15 +08:00
PanosandClaude Opus 5 7e12dab89e fix(image): erasing a broken raster reference clears its placeholder text
A raster reference that cannot be resolved is the only framed entity whose
to_render emits a RenderObject::Text: the frame and its diagonals are lines,
but the saved file path becomes a real glyph run in the SDF text buffer.

gather_text_verts reuses the whole previous vertex buffer when
text_unchanged(epoch) says no text-bearing entity moved, and that asks
entity_affects_text_cache -- which enumerated Text, MText, Dimension,
MultiLeader, Leader, Table, Tolerance, attributes and Insert, but not
RasterImage. So an erase never raised CACHE_CATEGORY_TEXT, the stale buffer
was taken as valid, and the path kept drawing over empty space. The reuse
branch then re-stamps that buffer with the current epoch, which froze it
until a full rebuild. CACHE_CATEGORY_IMAGE did not cover the gap: it is set
from images.contains_key(handle), and a missing reference has no ImageModel
at all.

The same gap broke three more flows from the Added/Modified side: ATTACH of
a missing reference showed no text, MOVE and grip-drag left the text behind
while the frame followed, and UNDO after an erase did not bring it back.

entity_affects_text_cache now counts a RasterImage whose reference does not
resolve, reusing the converter's memoised resolve_image probe so the two
cannot disagree. Kept a probe rather than a blanket type match so a healthy
image does not rebuild every glyph in the drawing on each mouse move of a
grip-drag.

Four regression tests, each confirmed to fail without the fix. The main one
is end-to-end on the buffer the GPU draws: before, the erased placeholder
left 300 glyph vertices on screen (50 chars x 6).

Also: to_render ran the same resolve probe twice; now once, shared by the
outline and placeholder branches. Moved text_unchanged's doc comment off
draw_ranks_stable, where it had drifted, and recorded the rule that every
entity able to emit a GlyphRun must be declared there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-01 17:42:38 +03:00
PanosandClaude Opus 5 d596b5a6be fix(view): zoom cursor per navigation tool, and ZOOM EXTENTS frames everything
Two viewport-navigation defects, both measured against commercial solutions.

The cursor stayed a hand during a zoom. `selection_overlay` took one boolean
for all three interactive navigation tools, so ZOOM Dynamic and ORBIT both
showed PAN's grab hand — which reads as "drag the sheet", the wrong promise
for either. Split it into a `NavCursor` enum: PAN keeps the open/closed hand,
ORBIT gets four-way arrows, and ZOOM Dynamic gets the magnifier carrying the
sign of the zoom actually under way — "+" dragging up, "-" dragging down,
latched with a 2 px dead zone so a hand held still cannot strobe the glyph.
ZOOM Dynamic also reused `box_anchor` to remember where a drag began, so a
selection marquee rubber-banded across the screen while the view zoomed; the
drawing is now suppressed, the state left alone for `reproject_box_anchor`.

ZOOM EXTENTS did not reach the whole drawing, for three separate reasons, now
answered by one shared `Scene::visible_block_bounds`:

  - A quartile filter dropped any wire whose centroid sat outside the
    inter-quartile consensus of the others. It was meant to stop one junk wire
    from a bad parse poisoning the box, but it could not tell parser junk from
    an outlying detail, a survey point, or a block placed away from the rest,
    and silently refused to frame them. Gone; the absolute 1e16 sentinel gate
    the paper path already used is the only filter, and the XLine / Ray display
    segments that motivated the heuristic are handled explicitly.

  - HATCH tessellates to no wires at all, and the model path never read the
    fill models, so a drawing whose outermost geometry is a fill — or which is
    nothing but fills — had nothing to frame. It now folds them in, reusing the
    renderer's own warm cache on the hot path rather than re-exploding every
    INSERT per ZOOM EXTENTS.

  - Inside a floating viewport the fit came from `compute_model_space_extents`,
    which walked only `key_vertices` — empty for every tessellated curve.
    Circles, arcs, ellipses and splines contributed nothing. Fixing it also
    corrects plot Extents, sheet-set framing, viewport auto-fit and SpaceMouse
    model bounds, which all inherited that blind spot.

Bounds stay f64 into the camera: a UTM drawing lost whole metres to the old
f32 round-trip. Drawing extents also no longer read the camera — the result is
cached per geometry epoch, and a floating viewport's camera is derived FROM
the extents, so `camera_for_viewport` recursed into a stack overflow.

`model_space_extents_mixed_entities_accuracy` asserted the curve-blind result;
it now asserts the true bounds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-01 16:27:26 +03:00
ramox81andClaude Opus 5.5 c5790c74a9 ATTDEF: dialog, -ATTDEF prompts, tag display, Properties and ribbon
Attribute Definition dialog and Edit Attribute Definition dialog, -ATTDEF
with the reference prompts and modes (AFLAGS), tag shown in the drawing,
justification-aware grips, reworked Properties with validation, Home Block
slide-out and Insert Block Definition panel, and the codec patch for
ATTDEF DXF output and the R2013+ solid wire cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 13:55:32 +03:00
ramox81andClaude Opus 5.5 0826101c5e Blocks palette: tabs, options, drag insertion and -INSERT
Rebuild the Blocks palette with Current Drawing / Recent / Favorites /
Libraries tabs, wildcard filter, six views, insertion options, click and
drop insertion and a block context menu. INSERT opens the palette, the
new -INSERT runs on the command line, the ribbon Insert button becomes a
block gallery, and BLOCKMRULIST, BLOCKREDEFINEMODE, BLOCKNAVIGATE,
BLOCKSTATE, EXPLMODE and INSNAME are added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:17:38 +03:00
Hakan SevenandClaude Opus 5.5 3dcebf0dc6 Merge pull request #1553 from ramox81/codex/pointcloud-attach
Point clouds: drawn from their scans, attached, cropped and stylized.

The fork's codec patch is resolved to the upstream pins: the point cloud
records landed in opencadcodec 5ef9376, carried through opencadkernel
68eeda1 and opencadgraph e204966.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 01:49:25 +03:00
Hakan SevenandClaude Opus 5.5 95a4419d0d fix(blocks): each dashed line in a block starts its own pattern
Block children of one style are batched into a single wire, and a
plinegen wire carries its dash distance across the joins. Every LINE
wire is plinegen, so each line in a block began mid-dash wherever the
previous one had stopped. PLINEGEN governs a wire's own breaks; a member
without any now enters its batch as non-plinegen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:27:42 +03:00