Ctrl+click on a polyline selects the segment under the cursor (again to
drop it); several segments can be picked. Only the picked segments are
highlighted, and MOVE, ROTATE, SCALE and MIRROR then change just their
vertices, so the neighbouring segments stretch to follow. Any other
selected objects are transformed whole as before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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 <[email protected]>
- VPCLIP arc mode takes Angle, CEnter, Direction, Radius and Second pt with
the reference prompts, and CLose closes with a tangent arc; the arc math
is shared with PLINE.
- Viewport clip boundaries from MVIEW and VPCLIP stay visible; picking or
erasing a boundary takes its viewport along.
- XCLIP Clipdepth: a rejected front plane keeps the old front plane and
clears the back plane.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The codec and kernel repositories and crates are renamed opencadcodec and
opencadkernel. Inside OCS they are depended on under short keys, so code
reads `codec::`, `kernel::` and the new `graph::` (opencadgraph, the node
graph engine). File-format and protocol spellings stay as they were: the
ACIS product id `acadrust`, the ACADRUST_* switches and the plugin
version keys `acadrust_version` / `acadrust_source`.
A button left of MCP on the command line opens a translucent node graph
over the viewport, with a palette of object, input, math, logic, list,
text and geometry nodes added by click or drag. An object node owns
drawing entities and its rows are the Properties panel's own rows for
them: the single-object page is extracted from refresh_properties as
entity_property_sections, values use the control protocol's
property_json, and writes go through set_property_value with a property
target override, so the panel, MCP and the graph share one read/write
path. A list reaching an object row makes one entity per element. Each
graph action is one undo step; the canvas pans and zooms.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The operations docs/automation/API-SPEC.md (PR #1383) describes, brought
over from huaninstratech/OpenCADStudio so the specification no longer runs
ahead of the code:
- entity CRUD: entities_create, entities_delete, entities_transform,
entities_copy_to, and `where` filters on query
- blocks and export: block_define, block_delete, a normalised wblock
- publishing: layout_create, page_setup_set, plot (per_page included)
- metadata: sysvar, xdata_set / xdata_get, file_identity
- collections: group_create, selection_set_save / load
- control plane: batch, events, view_focus, close
- the REST transport: `--http <port>`, the /api/v1 routes and their
OpenAPI 3 description
- person-in-the-loop picks: user_select and getpoint, hosted by the GUI
over the same REST routes, with on-screen pending signals
Taken from the fork's commits b7a7ed80, 69396b42, 64f1cf6a, c3aafc8e,
bb5a7bfa, 52317a5c, 50d293ba, b90e194f, 517c6397, 53a5c4c9, a49ac045,
37de5a46, a78b1822, 6d9aed2a, 33f522da, 5b5cafe2, 02a7e78d, 94df40dc,
fd5bc14d, 485fac61 and 2c5fc994.
Left out on purpose: 37de5a46 also removed the donation surface (the
Patreon fetch, the donation prompt, the Start-page supporters rail, the
DONATE command and its locale strings) and replaced the About dialog's call
to action; that is the fork's own product decision and stays out. The
fork's version bump and its unrelated IFC/BIM work are not part of this.
Adapted while porting: the REST server and the GUI bridge are desktop-only
and a template start is refused in the web build, so the wasm target still
compiles; the two plot tests read the PDF through the shared stream helper,
because exported streams are Flate-compressed; the benches set the new
crosshair field; comments and docs describe each operation in its own
terms rather than by another product's API names.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PropValue::ParamRow/ParamAddRow, the PropParamInput/Commit/Delete/AddNew
messages, their command_driver handlers (on_prop_param_commit/_delete/
_add_new, resolve_named_parameter_edit), and their render functions all
already existed — but nothing ever constructed the "Parameters" section
that would route data to them, so the whole inline add/rename/redefine/
delete workflow was unreachable from the UI. Adds that missing section
to the no-selection page in refresh_properties, alongside a new
PropValue::ParamsVisibilityToggle header row (mirrors the existing
show_constraint_values setting) for toggling whether constraint pills
show their driven value/parameter name.
Users can now manage named parameters inline in the Properties panel
(live resolved values, add/rename/redefine/delete) as an alternative to
the separate PARAMETERS modal, which continues to work unchanged.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
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]>
Entities that carry the standard PE_URL XDATA record (what HYPERLINK writes)
can now be followed from the canvas: Ctrl+click opens the link in the system
browser and consumes the click, so no box/lasso selection starts.
- scene::selection::pe_url_of() reads the record with the same rule as the
Properties panel hyperlink field; unit-tested.
- The ViewCube/compass hit region wins over a hyperlink drawn beneath it.
- Unchanged behaviour when Ctrl is not held or the entity has no link.
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]>
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.
Selecting a whole drawing was unusable on a 186 468-entity file. Four costs
scaled with the selection where they did not have to.
Every selected handle triggered a walk of the entire document to find LEADERs
pointing at it. On the file this came from, selecting 471 583 entities in a
585 786-entity drawing did not finish inside eight minutes. A reverse index
built once per geometry epoch answers the same question; a test asserts it
returns exactly what the walk returned, including the case of two leaders on
one annotation.
Group expansion asked the selection about every group: for each selected
handle it scanned each group's own member list. Asking each group once
whether it holds anything selected turns that around.
Selecting and deselecting went one entity at a time, and `deselect_entity`
rebuilt the ordered list with a `retain` per handle, so removing N of M
walked the order list N times. Both now take a slice.
Grips were built for every selected entity. AutoCAD stops at GRIPOBJLIMIT,
and the DWG header does not carry the variable, so its default of 100 stands
in for it.
The remaining two commits are measurement: `select-commit` reports the phases
of a selection separately, which is what showed the bulk paths had been added
to the press-drag branch while a click-move-click window goes through a
different one entirely.
`view-detail` on an edit frame:
total=105.6ms chrome=105.4 [every other section 0.0]
and the edit latency measurement puts ~102 ms of a 192 ms drawn point in
the gap between the handler returning and the scene primitive being built
— which is that same `chrome`.
The status bar asks for `entity_type_names_in_layout` on every frame to
populate the selection-filter menu, and the cache behind it was keyed on
`geometry_epoch`. Every drawn point bumps that epoch, so every drawn point
walked all 444 937 handles a model space owns to answer a question the
line did not change: adding a line to a drawing that already has lines
leaves the set of type names exactly as it was.
The cache now carries the set alongside the list, and folds edits in from
the delta journal — the same incremental shape `entity_index` already
uses. Additions can only grow the set, so they are applied directly and
the existing `Arc` is handed back untouched when nothing new appeared. A
removal can retire a type and cannot be resolved from a handle that is
already gone, so those still fall back to the full walk.
`entity_type_name` returns a literal for every arm but one — `Extended`
borrows its class name from the entity — so the set holds owned strings,
and the hot path tests `contains` before allocating.
Tested: a second line of an existing type must hand back the same `Arc`,
a new type must still appear, and the folded answer must equal what a
rebuild from scratch produces.
Co-Authored-By: Claude Opus 5 <[email protected]>
Reuse the application library from the binary entry point instead of compiling the module tree twice. Keep desktop-only transports and caches out of web builds, remove unused test code, and check executable targets in CI.
Pan and even plain cursor movement over the canvas ran at ~8 fps on a
large drawing. Nothing rendered was responsible: the GPU idled at 0-8%,
encoding no scene at all changed nothing, and vertices, pixels and draw
calls could each be cut without moving the number. `view` was the frame
-- 110 ms of it against 3-6 ms on a small drawing -- and inside `view`
it was the status bar.
The status bar builds the selection-filter menu, which asks for the
distinct entity type names in the layout. That call cloned the layout's
entire handle list (1 166 357 handles, ~9 MB), then did a map lookup, a
String allocation and a BTreeSet insert for each one. About 107 ms of a
110 ms frame, to produce roughly twenty names, for a menu that is only
visible when opened.
Cache the result against geometry_epoch and the layout block, since it
only changes when entities are added or removed, and make the scan
itself borrow the handle list rather than clone it and collect &str,
allocating only for the names it returns.
The immediate-mode UI rebuilds every widget on every mouse move, which is
fine as long as nothing in that path is O(document). This was.
Co-Authored-By: Claude Opus 5 <[email protected]>
Resolve ByBlock alpha independently from color and keep explicit opaque values from falling back to layer transparency.
Pin the matching cadcodec API across desktop, plugin, and web targets.
Refs HakanSeven12/cadcodec#2
Sync current main and companion codec changes before preserving unsupported frame rows, rendering in the entity plane, and sharing final layout metrics with placement preview.
Enable in-place editing of inherited properties in the Properties panel:
- Transparency: Switch to PropValue::EditChoice with ByLayer and ByBlock presets to allow direct typing of any numeric percentage value (0..90%) without combo_box autocomplete interference.
- Select-all-on-click: Integrate EditChoice text inputs into build_field_key_map with dedicated widget IDs, preserving click-to-select-all across editable fields.
- Material: Provide bounded preset choices (ByLayer, ByBlock, Global, and active custom material) to avoid scanning large drawing dictionaries.
- Plot style: Implement mode-aware behavior with interactive Choice in STB mode and ReadOnlyWithTooltip in CTB mode.
- Read-only tooltips: Introduce PropValue::ReadOnlyWithTooltip to provide contextual explanations for locked fields while preserving mouse text selection and clipboard copying.
- Dropdown alignment & unified borders: Fix EditChoice internal input/caret background clipping so the container's 1px neutral/active border surrounds the entire control identically to Lineweight and text inputs.
- Document defaults & aggregation: Synchronize document header defaults when editing with No selection, and aggregate heterogeneous multi-selections (*VARIES*).
Avoid full document, cache, and GPU rebuilds for entity deltas so add, delete, history, selection, and live polyline edits stay responsive on large drawings.
Replace full-document snapshots with Arc first-touch deltas and batch cache invalidation. Reuse interaction and GPU category caches across unrelated edits.
- Block reference Name (Misc) is editable: the dropdown re-points the
insert to another definition; typing a new name renames the definition
everywhere (record re-key, Block marker, every INSERT reference).
Anonymous (*) and xref blocks stay read-only, with the same guards
added to Scene::rename_block.
- Custom single-control dropdown (text field + caret) built on the
shared floating_below overlay so the list always opens downward,
unlike iced's space-based menu placement.
- Consecutive "<Base> X/Y/Z" rows (Position, Scale, Start, Center, ...)
collapse into one expandable summary row across all entities; the
expand state persists across rebuilds and selection changes.
- The BEDIT block tab no longer offers the layout Rename/Delete
context menu.
Co-Authored-By: Claude Fable 5 <[email protected]>