A new drawing already follows the reference's metric template
(MEASUREMENT 1, ISO-25); its insertion units were millimetres while the
reference's new drawing uses metres (INSUNITS 6). Blocks and references
inserted into a new drawing now convert with the same factor.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The bundled `opencad.python` plugin drives OCS through plugin API v7: all
43 canvas entity kinds, the drawing tables, and OCS's own commands run
step by step. RustPython stays in the plugin process — the plugin crate is
outside the workspace with its own lock file, so the application's own
dependencies are unchanged.
Reconciled with the plugin command work that landed as #1425, which the
branch was written before:
- Both added `impl Drop for PluginProcessInteractiveAdapter`, which git
merges silently into two impls that do not compile. One body now
cancels the command and then drops it from the runner, in that order: a
plugin waiting on a step has to be released before the runner forgets
the command.
- `execute_command` (#1425) and `run_command` (#1423) are both routes from
a script to the command line, and only the second was guarded. The
SCRIPTCOMMANDS switch and the denylist are shared now, so neither route
is the unguarded one.
- `run_command` dispatched with plugin dispatch still enabled, so a script
naming a plugin command re-entered the plugin that was blocked waiting
for it. It sets the suppression flag for the length of the dispatch, as
`execute_command` does.
The denylist read the command as typed, while the dispatcher resolves
aliases: a user-defined `Q` for `QUIT` (ALIASEDIT writes those) walked
past it. It resolves the alias first.
Also: the active-command comparison ran on every message, a mouse move
included, allocating two strings for names that are already `&'static
str`; SCRIPTCOMMANDS' own messages go through the translation macros; and
`docs/.DS_Store` (now ignored) and an unrelated RTF note about constraint
commands are out of the tree.
Co-Authored-By: Claude Opus 5 <[email protected]>
Implement the complete Block Definition dialog window launched via BLOCK
and BMAKE commands, featuring standard CAD layout, workflows, and entity
creation pipelines.
- Dialog UI & Layout:
- 2-column compact CAD grid with synchronized vertical heights (580 × 390px).
- Editable combobox with existing block names, invalid character validation,
and inline redefinition badge.
- Multi-line text editor widget for block descriptions (replacing single-line input).
- Quick Select (QSELECT) button integration restoring dialog state upon completion.
- Confirmation guard when attempting to redefine an existing block definition.
- Centered radio buttons, clean coordinate inputs, and accessible keyboard shortcuts.
- Base Point & On-Screen Workflow:
- BlockOnScreenCommand strictly enforces prompt sequencing: Base point is
prompted before object selection.
- Dynamically recalculates world_to_block and block_to_world affine transforms
when base point is specified on-screen, preventing stale (0,0,0) normalization.
- Supports Retain, Convert to block (INSERT placement), and Delete modes.
- Explode Enforcement:
- Guarded EXPLODE command to prevent decomposing blocks flagged as non-explodable.
- Dynamic Themed Icons:
- Added pick_point.svg, select_objects.svg, quick_select.svg, and warning_triangle.svg.
- Routed all icons through the semantic theming engine so line work (#B4B6B9)
and accents (#6DB7ED) adapt automatically to the active theme.
- Tests:
- Added unit tests for retain/convert/delete modes, redefinition, explodable flag,
on-screen base point transform recalculation, and command sequencing.
A new drawing (#1441) recorded ISO-25 as the current dimension style by
name only. Every other place that changes it sets the header's handle as
well, and a DWG carries the current style by handle alone, so a saved new
drawing reopened on Standard. The style's handle now comes back from the
helper that adds it.
A radius constraint (#1443) anchored the circle's centre from the shape of
its references — one whole entity — but a single whole reference is also a
line's length, whose start is what stays. The entity decides now.
The two tests that encoded the replaced rules follow them: a negative
radius validates by its magnitude, as a negative distance already did, and
only zero is refused; a new drawing's dimension text reads at ISO-25's
comma separator.
Co-Authored-By: Claude Opus 5 <[email protected]>
A new drawing is metric (measurement 1, millimetre insertion units) and
carries the reference's ISO-25 dimension style as its current style, so
dimensions and annotational constraints draw at readable metric sizes
instead of Standard's imperial 0.18 text.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Placements (entity lookups, intersections, String labels, projections)
recomputed per view() and per mouse-move hit-test, with overlay re-clones
and 2-3x offset recomputes. New constraints_epoch bumped on every set
mutation/visibility/undo/DWG-load (plus new set_constraint_enabled API);
single-slot Arc<[GlyphEntry]> memo on an 11-field key (hover/selection
excluded); overlay de-cloned/de-duped to the single geometry source;
hit paths reuse the cache.
Tests:
- cached_glyph_placements_hit_returns_same_arc: same-key Arc identity
- cached_glyph_placements_invalidated_by_metadata_edit: edit + selection change yield new Arc
- glyph_hit_test_entries_matches_precomputed_boxes: shared hit-test helper
Bench (cargo bench glyph, 60 constraints): 8.18us -> 0.05-0.15us (~55x).
A/B reference deleted.
The dynamic dimension of a dimensional constraint is now linked in the
drawing file (AcDbAssocDependency + AcDbAssocDimDependencyBody on the
constraint node), reread on load, hidden by DCHIDE/DYNCONSTRAINTDISPLAY
and never plotted; it carries a lock mark before its text. New
CONSTRAINTNAMEFORMAT and DYNCONSTRAINTDISPLAY variables and the
DIMCONSTRAINT option front end. A transformed entity whose own end points
a driving dimension measures keeps only the first constraint point, so a
scaled line returns to its dimension value.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
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]>
- IMAGEEMBED: pack raster images into OLE2FRAME entities so a .dwg is
self-contained; 'Embed Image' entry in the XREF attach menu; control/MCP
op embed_image for external tools; dxf_name for OLE2FRAME queries.
- Scene: populate_images_from_document now rebuilds OLE2FRAME and PDF
underlay models too (they used to vanish after any XREF op).
- Printing: add PRINTER_ENUM_NETWORK pass when listing printers; GDI
spooler fallback (hayro raster at 300 DPI + StretchDIBits) for hosts
whose PDF handler registers no print verb; DEVMODE orientation with a
90-degree raster rotation fallback for v4 drivers; fix the fit-scale
precedence bug that printed blank pages.
- PDF export dialogs on Windows use the async file dialog so the native
overwrite confirmation no longer deadlocks the UI thread.
- Plot dialog: persist the chosen printer (saved on selection) and the
picked plot window across sessions; page setups with no device no
longer reset the output device.
- Community fonts: detect unresolvable .shx references on open and offer
a download from the repository's fonts/ folder (contribution guide in
fonts/README.md); custom font source URL setting for intranet font
servers; downloaded fonts resolve from the per-user fonts directory.
Recover failed small spline boundaries with the kernel chord-error
sampler, using the same coordinate frame as the fill mesh. Preserve
source curves and enforce recovery and total hatch vertex limits.
Fixes#1268
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]>
Resolve curve intersections through cadkernel, retain empty exact results, gather analytic candidates independently of tessellation, and bound material uploads. Preserve large MINSERT data while limiting rendering work; remove obsolete review narratives.
Implement the AutoCAD compatible HATCHTOBACK (HB) command and enhance the interactive DRAWORDER command pipeline with comprehensive verb selection and viewport entity picking.
Key implementations and architectural details:
1. HATCHTOBACK command execution
* Isolates entities belonging to the active layout block record or global space.
* Filters out entities residing on locked layers using an efficient hash set lookup.
* Records targeted delta undo operations on SortEntitiesTable objects (~100 bytes) rather than snapshotting full document structures.
* Performs granular draw depth cache invalidation via Scene::invalidate_draw_depth, preserving existing geometry tessellations and spatial indices.
* Emits localized user notifications when no qualifying hatch entities are found.
2. Interactive DrawOrderCommand state machine
* Supports preselected entities as well as interactive on demand selection gathering.
* Implements subverb selection supporting single character shortcuts (A for Above, U for Under, F for Front, B for Back) and case insensitive keyword parsing.
* Enables interactive reference object picking directly in the viewport via needs_entity_pick and on_entity_pick callbacks.
* Supports hexadecimal handle specification directly from the command line interface.
3. Ecosystem and system integration
* Bumps DEFAULT_ALIASES_VERSION from 2 to 3 to register the HB alias while preserving existing user overrides.
* Integrates HATCHTOBACK and HB into dynamic autocomplete registries.
* Adds localized message strings across all 20 Fluent translation catalogs.
* Corrects hatch boundary serialization flags to ensure outermost boundary rings consistently carry the external attribute.
Persist camera, render state, and solid fallback geometry across saves. Generate previews from a clean live viewport and refresh recent-file thumbnails immediately.
Creating a block from selected entities now bumps the geometry epoch, so the
block palette's per-update stale check notices the new definition and refreshes
its list in place instead of requiring the user to close and reopen the panel.