Commit Graph
272 Commits
Author SHA1 Message Date
Karim Jerbi 22a9bd602c feat(xref): row-level context menu actions and unified split-button toolbar
Right-click actions bound to the row under the cursor, split-button toolbar groups with shared borders and hover states, and a notice when an operation needs a selection first.
2026-09-15 23:56:31 +01:00
Karim Jerbi 494a872e8d feat(xref): row selection, resizable columns, tree view, and find-replace
Single, multi, and range row selection, resizable table columns, hierarchical tree presentation, and find-and-replace through the command line.
2026-09-15 23:56:31 +01:00
Karim Jerbi 019422d220 feat(xref): docked External References panel with previews and translations
Docked External References panel with host row, thumbnail previews, and translated interface strings.
2026-09-15 23:56:31 +01:00
Karim Jerbi d0d946a568 feat(xref): detach, unload, reload, bind, overlay, and path operations
Detach, unload, reload preserving host layer overrides, bind, overlay, and saved-path editing, with per-tab session state and a read-only web list.
2026-09-15 23:56:31 +01:00
Karim Jerbi 42219a4b8c feat(xref): reference list with stale and orphaned status detection
Reference list rows showing stale and orphaned states with handle-based identity.
2026-09-15 23:56:31 +01:00
Hakan Seven 08bb17b0b8 Fix constraint editing and glyph feedback 2026-09-15 21:55:40 +03:00
Karim Jerbi 0e42e3bf28 fix(ui): keep DSETTINGS tabs on a single tab strip
Replace the wrapping button row with a real single-row tab strip (tab-shaped buttons + divider, matching style-manager editor shell). - Remove Row::wrap() so Selection Cycling can't spill to row 2; clip overflow - Active tab uses primary.strong, inactive weak/strong on hover, top-only radius - Tighten to size 11 / padding [4,8], spacing 2 - Widen Drafting Settings modal 700x480 -> 780x500 to fit 7 tabs
2026-09-15 16:09:00 +01:00
Karim Jerbi 612124b84b feat(ui): implement themed 5-section ribbon object color dropdown 2026-09-15 13:54:56 +01:00
ramox81 c3101919d7 Show constraint action points on hover 2026-09-15 13:54:47 +03:00
Hakan Seven c9eeb6f66e Merge pull request #1284 from ramox81/codex/autoconstrain-parity
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	src/app/view/mod.rs
#	src/ui/overlay.rs
2026-09-15 12:38:41 +03:00
Hakan Seven dfe8b77cca Merge PR #1280 and expose constraint value visibility 2026-09-15 11:55:05 +03:00
Hakan Seven adc8555394 Merge PR #1279 and complete parametric UI actions 2026-09-15 11:48:35 +03:00
ramox81 66be530655 Complete automatic constraint behavior 2026-09-15 11:47:28 +03:00
Hakan Seven d738ebfcc6 Standardize parametric constraints and interoperability 2026-09-15 03:19:52 +03:00
Felix RiestraandClaude Sonnet 5 59ae38ae1a Add per-constraint delete; fix named-parameter reference bugs
Constraint delete: a Properties-panel row delete button, viewport
click-to-select on a constraint glyph pill with Delete-key support, and a
right-click "Delete Constraint" menu item — all routed through one
undoable Scene::selected_constraint-aware path.

Fixes two named-parameter bugs found while testing that feature:
- DIMCONSTRAINT: a parameter named like a mode-switch keyword ("r", "d",
  "a", "x", "y") could never be referenced, since the keyword check ran
  before the parameter-name check.
- PARAMETERS modal Apply rebuilt Scene::named_parameters but never
  refreshed the Properties panel, leaving renamed/deleted rows stale
  until an unrelated refresh (e.g. a selection change) happened to occur.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-15 01:08:34 +02:00
Hakan Seven caec8dc53b Merge remote-tracking branch 'origin/main' 2026-09-14 20:24:54 +03:00
Hakan Seven 293d0796fb Merge pull request #1246 2026-09-14 19:58:35 +03:00
Hakan Seven 2d20bdd51c Merge pull request #1251 2026-09-14 19:51:57 +03:00
Karim Jerbi a0d784502a feat(ui): modernize DSETTINGS dialog with tabbed layout and action controls
- Redesign drafting settings window to landscape 700x480 proportions while preserving interactive resizing
- Add 7-tab navigation: Snap and Grid, Polar Tracking, Object Snap, 3D Object Snap, Dynamic Input, Quick Properties, and Selection Cycling
- Distribute existing drafting modes, snap options, and isometric tools into their respective tabs
- Implement OK, Apply, and Close action buttons with unsaved changes confirmation guard
2026-09-14 17:45:47 +01:00
ramox81 a35c996f9f fix(annotate): complete table and data workflows 2026-09-14 14:54:55 +03:00
Hakan Seven 7b4cef41f7 Complete parametric ribbon and constraint tools 2026-09-14 01:05:39 +03:00
Hakan Seven 5c9ca5b897 Improve constraint glyph placement and readability 2026-09-13 23:08:54 +03:00
Hakan Seven 95bad2a3b2 Fix web folder paths and allow main-only web hotfix deployment 2026-09-13 20:30:12 +03:00
Marcel 0ea220f120 Add parallel offset grip editing for polylines 2026-09-13 19:19:19 +02:00
Hakan Seven 052b6b239d fix: clean up mobile sponsor artwork 2026-09-13 12:53:24 +03:00
Hakan Seven e2b37edd23 feat: add mobile sponsor banner 2026-09-13 10:28:05 +03:00
gianlucafiore 8a45a84c43 fix(stretch): highlight affected vertices during selection 2026-09-12 21:41:34 -03:00
PanosandClaude Opus 5 02b0f4c7d9 Tell the user when the scene is drawn without a GPU
A day of pan/zoom that had suddenly become unusable on a 1.2M-entity
drawing turned out to be no regression at all: an unattended NVIDIA
userspace update had been applied without a reboot, the Vulkan ICD could
no longer talk to the still-loaded kernel module, and wgpu silently fell
through to Mesa's llvmpipe. Nothing in the app said so. iced picks the
adapter and names it only under RUST_LOG, so the only evidence was 32
`llvmpipe-N` threads in /proc. The same silence covers WARP on Windows,
SwiftShader in browsers, and the case where wgpu finds no adapter at all
and iced quietly draws the chrome with tiny-skia while the shader widget
is dropped, leaving a blank viewport. This commit makes all of that
visible, on every platform, without new dependencies.

Detection (src/scene/pipeline/mod.rs)
-------------------------------------
`GpuStatus` is derived from two signals:

* `record_gpu_adapter`, run from `MultiPipeline::new` (once per device,
  next to the existing uncaptured-error handler), reads
  `Device::adapter_info()`, prints one `[gpu] adapter: <name> (<backend>,
  <device type>, driver …)` line — stderr natively, `console.warn` on the
  web, which has no stderr — and keeps a copy.
* `note_scene_draw`, run from `ViewportPane::draw`, counts how often the
  viewport asked for a primitive. Every renderer makes that call; only
  wgpu goes on to `prepare` and create a device. Three draws with no
  device ever recorded therefore mean the primitive is being dropped.

The verdict is one of `Unknown`, `Hardware`, `Software(adapter)` or
`NoRenderer`. `Software` is `DeviceType::Cpu` — what Vulkan reports for
llvmpipe, DX12 for WARP and GL for a renderer string that gives it away —
plus a name match on the fallbacks browsers expose (SwiftShader, llvmpipe,
lavapipe, "Microsoft Basic Render"), because the WebGPU backend reports
every adapter as `Other` (gfx-rs/wgpu#8819). Metal has no software device,
so on macOS only `NoRenderer` can occur (a VM without a GPU); it is caught
by the draw count like everywhere else.

`gpu_status_if_changed` costs one atomic load per app message: a
generation counter moves only when a device is recorded or the draw count
crosses its threshold, so the app re-derives the verdict a handful of
times per session.

Notification (src/app/startup.rs, view/modal.rs, ui/statusbar)
-------------------------------------------------------------
`refresh_gpu_status` runs after every message. On a degraded verdict it
speaks through three channels, because many users never read the command
line:

* A popup, `ModalKind::GpuWarning`, queued once per verdict through the
  startup-modal queue so it waits its turn behind the file open. It names
  the adapter, states the consequence (slow navigation, unstable or
  missing rendering) and gives the remedy that usually applies on the
  running platform: a driver update not yet followed by a reboot on
  Linux, a missing driver or a Remote Desktop / VM session on Windows, a
  VM without a Metal device on macOS, hardware acceleration switched off
  in the browser. "Don't show again for this device" stores
  `GpuStatus::identity()` in `settings.gpu_warning_silenced`; keying it by
  verdict means silencing "software rendering on llvmpipe" does not
  silence a later, different failure.
* A status-bar pill in the theme's warning colours, `⚠ Software rendering`
  or `⚠ No GPU renderer`. It is not a `StatusPill`, so it cannot be hidden,
  and it stays for the session; clicking it reopens the popup, silenced or
  not.
* A command-line entry through the new `CommandLine::push_warning`, which
  is styled like an error but deliberately does not touch `last_error` /
  `error_revision`: automation reads those to decide whether the command it
  just ran failed, and a graphics warning is not a failed command.

`subscription()` requests frames only while the verdict is `Unknown` on a
document tab (the Start page draws no viewport), so the probe costs one
frame on a working GPU, three on none, then stops.

Verification
------------
* Live on the machine that had the incident, with the Vulkan loader
  restricted to Mesa (`VK_DRIVER_FILES=…/lvp_icd.json WGPU_BACKEND=vulkan`):
  popup → OK → pill → click reopens; "Don't show again" → restart → pill
  only, no popup.
* `gpu_tests::the_adapter_is_reported_once_per_device` (ignored, needs an
  adapter) asserts the classification on a real device; it was run on both
  llvmpipe (`Cpu`) and an NVIDIA GT 1030 (`DiscreteGpu`).
* Unit tests cover the name heuristic, the verdict function, the identity
  rule, the warning text with an adapter name that itself contains
  parentheses and commas, the settings round trip and the command-line
  semantics. New strings are in all 21 locales as the `gpu` Fluent group.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-12 16:19:41 +03:00
Hakan Seven 754cc89fab Merge PR #1216: expose MTP in snap menus 2026-09-12 15:12:04 +03:00
Hakan Seven 7c5a388f19 Merge PR #1215: add rectangle grip dimensions 2026-09-12 14:53:37 +03:00
Karim Jerbi f1d5284fb9 fix(mtext): support arabic cursive shaping and bidirectional rtl text layout
- Enable fallback font metrics for HarfBuzz shaping in TTF glyph resolver

- Implement Unicode Bidirectional Algorithm (UBA) paragraph base direction detection

- Anchor right-to-left paragraphs to right container boundaries by default

- Reorder line atoms with base direction level to preserve neutral punctuation attachment

- Right-align RTL single-line TEXT and handle editor caret placement on RTL glyphs
2026-09-12 11:06:11 +01:00
Marcel 01af9d9fb8 Position rectangle dimension labels away from geometry 2026-09-11 21:11:46 +02:00
Marcel 913705106e Support dynamic rectangle resizing via grip editing 2026-09-11 20:52:33 +02:00
Marcel f30b490831 Add rectangle width and height grip editing 2026-09-11 20:15:36 +02:00
odofaro 03075612fa feat(snap): expose MTP in snap override and context menus
The MTP/M2P midpoint-between-two-points modifier existed as a typed transparent command only. Add it to the Shift+RMB snap override menu as an icon-only cell after Parallel (hover tooltip, no text) with a new osnap/mtp.svg marker, plus a context-menu entry while a point prompt is active.
2026-09-11 17:57:55 +02:00
Hakan Seven 9b58ca8a93 Harden parametric sketch constraints 2026-09-11 09:45:57 +03:00
Felix Riestra ad718def3f Merge remote-tracking branch 'origin/main' into merge-test/main-into-constraints
# Conflicts:
#	src/app/command_driver.rs
#	src/command.rs
#	src/ui/ribbon/mod.rs
#	src/ui/window/options.rs
2026-09-10 23:34:50 +02:00
Felix RiestraandClaude Sonnet 5 bd9a2d08f7 Add Properties-panel Constraints/Parameters sections, a constraint-pill
value toggle, and redesigned constraint-ribbon icons

Properties panel:
- New "Parameters" section (shown with no selection) listing every named
  parameter with inline name/formula editing, add, and delete, backed by
  new PropValue::ParamRow/ParamAddRow and command_driver handlers
  (resolve_named_parameter_edit, on_prop_param_commit/_delete/_add_new).
  A fresh parameter's formula now defaults to "1", not "0" — a 0-length
  seed value is a genuine solver singularity for a Distance constraint
  driven by that parameter, with no defined direction to grow back out of.
- New "Constraints" section (shown for a single selected entity) listing
  every constraint touching it as a clickable PropValue::EntityLink that
  selects the linked entities in the viewport, danger-tinted when the
  constraint conflicts.

Constraint pills:
- New Options > General toggle, "Show values and parameter names on
  constraint markers" (on by default, persisted). Off, every pill shows
  just its bare glyph instead of glyph+driven-value/parameter-name — the
  glyph alone is enough to see a constraint is present, without the value
  text covering nearby geometry on a dense sketch.

Constraint-ribbon icons:
- Replaced all 18 unicode/letter glyph icons (including the plain "F",
  "L", "M", "S" letters) with proper SVGs under assets/icons/constrain/,
  matching the Modify section's two-color style (#B4B6B9 white / #6DB7ED
  blue, consistent stroke width). Tangent reuses the Draw section's
  white-arc-plus-blue-dots motif.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-10 23:16:11 +02:00
Hakan Seven 14ef6c7bcd fix(i18n): translate render mode choices 2026-09-10 19:16:30 +03:00
MarcelP102 d47e3234d8 Add dynamic input for grip-based geometry editing (#1138) 2026-09-10 18:23:28 +03:00
Felix RiestraandClaude Sonnet 5 3d0a41b69a Extend sketch constraints toward FreeCAD parity, staying DWG-native-compatible
Arcs are now full constraint participants (center/radius via the existing
Circle-shaped solver path, plus real endpoints kept consistent by arc-rules
CurveValue constraints); adds Diameter/DistanceX/DistanceY/ArcLength/Normal
constraint kinds and initial Ellipse entity support (center-based
constraints only). DWG-native class mappings and gaps (ArcLength, Ellipse)
are grounded against real ObjectARX headers rather than guessed, so files
saved with DWG-native constraints stay honest about what AutoCAD can
actually represent.

Also fixes a case-sensitivity bug where a lowercase named-parameter
reference typed at a dimensional constraint's value prompt was rejected
(the command line uppercases SingleToken input before the parameter-name
lookup), and adds a "Used by" column to the Named Parameters panel.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-10 10:58:21 +02:00
PanosandClaude Opus 5 7ea1aef95e Add a Files page, and links out to the editors that own their own dialogs
The application has no support-file search path — the four folders it uses
are functions returning fixed paths, not settings. Rather than build a Files
page that pretends otherwise, this one answers the question people actually
open it to ask: where does this thing keep my plot styles. Each row shows the
location and opens it in the file manager, and a row whose path the platform
could not give says so with its button disabled.

General gains buttons through to the plugin manager, the keyboard shortcut
editor and the alias editor. Those three have good dialogs of their own and
are not absorbed; Options simply stops being a place you cannot reach them
from.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 08:45:20 +03:00
PanosandClaude Opus 5 5a638f243a Make the view toggles survive a restart, and give them a page
The ViewCube, the UCS icon, its at-origin placement and selection cycling all
have commands and status-bar pills, and all four kept their value only on the
app struct. Turn the ViewCube off with NAVVCUBE, restart, and it is back.
Nothing failed — the setting evaporated — so a checkbox for any of them would
have been a checkbox that forgets. They are persisted first, with a
round-trip test, and only then given controls.

The new 3D Modeling page carries the three view tools plus the drawing
variables that decide how solids are tessellated: ISOLINES, DISPSILH, SURFU,
SURFV, SURFTYPE, SOLIDHIST and SHOWHIST. Those are saved in the DWG rather
than in preferences, so the page says so beside each group and hides them
entirely when no drawing is open.

Changing them also rebuilds the geometry. The SETVAR path never did, which is
why the comment beside LTSCALE's invalidation exists — the same reasoning
applies here, and without it a new isoline count does not appear until some
unrelated edit rebuilds the solid.

Selection cycling joins the Selection page next to the other two selection
modes, since that is what it is.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 08:41:26 +03:00
PanosandClaude Opus 5 b5f4b4d1cc Add a Drafting page for the rotation angle and the polar increment
Two drafting preferences had no proper home. The Drafting Settings dialog
displays the drafting rotation and offers only a Reset button — there was no
way to type an angle short of `SETVAR SNAPANG`. The polar tracking increment
existed in exactly one place: a pop-up hanging off the status-bar pill.

The rotation is a text field over an edit buffer rather than the value
itself, so clearing it to retype does not snap the crosshair to zero on the
way through; the buffer is reseeded whenever the value is restored from
behind it. Angles render without a trailing `.0`, matching how the polar
pop-up has always shown them — same kind of number, same reader.

Snap modes, grid spacing and object snap stay in Drafting Settings, where
they belong; the page links to it.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 08:33:19 +03:00
PanosandClaude Opus 5 9c3f3625da Add a User Preferences page for six command-only settings
Zoom direction and factor, whether TEXTEDIT ends after one object, whether
continued dimensions inherit the base dimension's style, which points QDIM
measures from, and which annotative objects pick up a newly set scale. All
six work today; none had a control.

Two of them needed their meaning worked out rather than copied.

ANNOAUTOSCALE stores the mode in the magnitude and on/off in the sign, and
the four modes are not documented anywhere in the app — the command prompt
just says `[-4..4]`. Reading `add_annotation_scale_to_objects` gives them:
1 skips layers that are off, frozen, locked or frozen in the viewport, 2
keeps the locked ones, 3 skips only locked, 4 takes everything. The dropdown
names them instead of showing bare numbers, and choosing Off negates rather
than zeroing, so the mode survives being switched off and back on — which is
the convention the status-bar pill already follows.

The QDIM origin priority had no system variable at all; it could only be
reached through a keyword inside the running command.

Drawing units stay in their own dialog; this page links to it.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 08:29:48 +03:00
PanosandClaude Opus 5 a0027a8977 Put text fill and the command-line preferences on the Display page
Three settings that work, persist, and could only be reached by typing their
name: TEXTFILL, CLIPROMPTLINES and COMMANDLINEFADETIME. The last two govern
how much of the command window is prompt and how long its history lingers —
the kind of thing people fiddle with once and then leave, which is exactly
what a settings dialog is for.

One fix rides along. TEXTFILL is a process-global, so changing it invalidates
the text in every open drawing; the SETVAR path rebuilt only the active tab,
leaving the others rendering the previous setting until an unrelated edit
happened to rebuild them. Both paths now go through
`invalidate_text_everywhere`, so the checkbox and the command cannot disagree.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 08:26:20 +03:00
PanosandClaude Opus 5 ec8d733857 Give saving its own page, with the two settings that had no control
General had become three unrelated controls: a language picker, a save format
and a file association. The last two move to an Open and Save page, where
they join the two saving preferences that have never had a widget.

Automatic save has worked since the SAVETIME command was added and is
persisted; the only way to change the interval was to type it. Same for the
`.bak` copy from #205 and its ISAVEBAK command. Both are settings people
expect to find in a dialog, and neither was in one.

The page also carries a button through to the Plot dialog. Options holds the
preferences; the plot device, paper and plot styles stay where they already
work well. Note that the modal stack shows one dialog at a time, so the
button replaces Options rather than stacking on it.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 08:22:36 +03:00
PanosandClaude Opus 5 b1d2ac2744 Give the Options dialog a tab rail that can hold more pages
The dialog laid its pages out as a row of buttons across the top, which is
what AutoCAD does and what fits while there are four of them. The pages this
series adds take it to nine, and the names are translated into 21 languages —
a row of nine German or Russian page names does not fit at any dialog width
worth having.

The rail is now a vertical list down the left, the dialog is 880×620 rather
than 540×560, and the content pane scrolls on its own.

Which page was open is now remembered. With four pages, reopening on General
was a shrug; with nine it means hunting for the one you were last in.

The ribbon's Options tool has existed all along — `ToolDef`, icon and all —
but was marked `#[allow(dead_code)]` and never added to a group, so the
dialog could only be reached by typing OPTIONS or from the start page. It
now sits in Manage ▸ Application, beside About.

No settings change in this commit; it is only the shell the rest needs.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 08:18:23 +03:00
Felix RiestraandClaude Sonnet 5 d675244fb8 Merge branch 'main' into feature/parametric-constraint-system
Brings in 54 commits from origin/main: a selection-performance overhaul,
surface thickening, GPU-native wide/tapered stroke rendering, continued
ocs_doc_api evolution, and assorted fixes/polish (block double-click
editing, DWG hatch/database repair, clipboard, collapsible Properties
sections).

Six real conflicts, all where this branch had independently re-applied
a fix upstream later revised or already carried natively:

- src/app/automation.rs, src/app/command_driver.rs: combined both
  sides — kept this branch's sketch-constraint/named-parameter loading
  on "new"/"open", adopted main's Scene::clear()/material_base_dir and
  its newer rebuild_derived_caches() over the older bump_geometry().
  Scene::clear() (src/scene/entity.rs) now also resets
  sketch_constraints/named_parameters, so every caller gets this for
  free instead of each call site repeating it.
- src/io/mod.rs, src/scene/render_graph.rs: adopted main's design
  outright (commit 973af87d, authored by Hakan directly) — a large
  MINSERT is no longer purged as "corrupt" at load, only its rendering
  is bounded, preserving the source data. This branch's own earlier
  design (reject at load) predates that revision.
- src/scene/pipeline/mesh_gpu.rs: adopted main's valid_rgba_size()
  guard (a real robustness improvement over this branch's version).
- src/snap.rs: replaced wholesale with main's version — this branch's
  copy was an explicit verbatim snapshot from an earlier upstream PR
  (commit 4c264b8c) with zero constraint-system-specific content, and
  main has since evolved it considerably further.

Also removed two now-dead duplicates the merge surfaced without a
conflict marker (both branches had independently fixed the same
things): the OPTIONS/OP command dispatch/autocomplete entries, and
automation.rs's open_finalizes_and_purges_like_the_ui_open_path test
(kept main's version, which covers strictly more: solid_models/
material_base_dir reset on "new").

Full workspace suite passes (812 lib tests + this branch's own 24
constraint/persistence integration tests) except the one pre-existing,
unrelated font-test failure already present on main. Zero clippy
findings in the hand-written merge resolution itself; the ~1,171
warnings clippy reports are pre-existing in the 54 absorbed commits,
not introduced here.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-09 20:44:38 +02:00
Felix RiestraandClaude Sonnet 5 31b5ef4ec3 Add 8 geometric constraint kinds and an opt-in DWG-native persistence toggle
New ConstraintKind variants — Concentric, CenterPoint, Colinear, Midpoint,
Fixed, PointOnCurve, EqualDistance, Symmetric — each built entirely from
existing ocs_gcs (FreeCAD planegcs) primitives, no new solver math needed.
build_constraint now returns Vec<Rc<dyn Constraint>> instead of
Option<Rc<...>>, generalizing the old Coincident-only "needs a second
system-level constraint" special case to every kind that needs one.
Wired into the ribbon (7 new buttons), a new point+pre-selected-entity
command for CenterPoint/Midpoint/PointOnCurve, a new 4-point command for
EqualDistance, and the existing DWG-native class-name mapping (all 8 reuse
the same generic "plain Geometrical node" path already built for
Coincident/Horizontal/etc.). Deliberately not modeled: Normal and
EqualCurvature, which for this app's Line/Circle-only entity model would
just be Perpendicular and Equal wearing different DWG class names.

Also makes DWG-native constraint persistence opt-in (Options > General,
off by default) rather than unconditional: a scope that doesn't yet have
the native graph is only given one when the setting is on, but a scope
that already has one — from an earlier save, or a file that came from
real AutoCAD — keeps getting it resynced regardless of the setting, so
toggling it off never freezes a stale graph in place.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-09 19:38:31 +02:00