forked from 1b-agent/opencadstudio-upstream
refactor(scene): reference-only designation becomes a scene-scoped set (API v9)
Per the upstream review of the XDATA-based storage: the host no longer writes its own state into the saved file. The marker record under the host-owned OCS APPID, the on-first-use APPID registration and the verbatim-EED rewrite handling are removed; the single source of truth is a scene-scoped in-memory set of entity handles (Scene::reference_only) that dies with the drawing tab, so a reopened file starts undesignated and the owning plugin re-marks on the document-opened notification. All behaviour sites are unchanged, driven by the set: the wire stamp moves from an XDATA read to a set lookup threaded through the tessellation pipelines (tessellate_entity and the dimension text path take the handle set as a plain parameter), and the pick filters, selection retains and update/erase refusals read Scene::is_reference_only. Undo keeps the entity-write contract: set mutations are recorded as explicit first-touch before/after values on each history delta (the parametric- constraints channel pattern). A designation inside a plugin push_undo scope joins it, a scope-less change is one step of its own, an idempotent re-mark records nothing, erasing a designated entity drops the set entry with the entity, and undo/redo restores entity and designation together. The round-trip test is inverted: reference_only_designation_is_not_written_ to_dwg_or_dxf now asserts the marker appears in neither format's bytes, that no OCS APPID or marker record survives a reload, and that the designation stays live in memory.
This commit is contained in:
1 parent
06ee0798a8
commit
50db12b169
17 files changed
+623
-232
No files matched your search
@@ -400,3 +400,33 @@ and `box_selections_skip_reference_only_wires`; the record surface test
|
||||
`entities_records_expose_the_reference_only_designation`; and the IPC round-trip
|
||||
`reference_only_request_and_response_roundtrip`. Like the XRecord API, a Python mapping is future
|
||||
work.
|
||||
|
||||
**Reference-only rework: scene-scoped storage (2026-10-14, API v9).**
|
||||
Supersedes the storage decision above after the upstream review: the designation is no longer
|
||||
written to the file at all. The XDATA marker under the host-owned `OCS` APPID (and the APPID
|
||||
registration, the verbatim-EED rewrite handling and the storage unit tests built on it) is removed;
|
||||
the single source of truth is now a scene-scoped in-memory set of entity handles
|
||||
(`Scene::reference_only`, `scene::reference_only`), deliberately not serialized — the host writes
|
||||
nothing of its own into the saved DWG/DXF, the set dies with the drawing tab, and a reopened file
|
||||
starts undesignated. Every behaviour site is unchanged and driven by the set: the wire
|
||||
`tessellate_entity` stamp (threaded through the tessellation pipelines as a plain handle-set
|
||||
parameter), the pick-side wire filters, the selection-gather retains, the update/erase refusals
|
||||
and the MCP `entities` boolean. Undo keeps the entity-write contract through an explicit
|
||||
designation channel on each history delta (the `parametric_constraints` pattern): a marking inside
|
||||
a plugin-opened `push_undo` scope joins it, a scope-less change is one step of its own, an
|
||||
idempotent re-mark records nothing, erasing a designated entity drops the set entry in the same
|
||||
step, and undo/redo restores entity and designation together. The round-trip test is inverted:
|
||||
`reference_only_designation_is_not_written_to_dwg_or_dxf` now asserts the marker appears in
|
||||
neither format's bytes, that no `OCS` APPID or marker record survives a reload, and that the
|
||||
designation stays live in memory. Evidence: the set-storage tests
|
||||
`marking_and_unmarking_report_and_track_membership`, `removing_a_handle_forgets_it`,
|
||||
`retain_present_drops_entries_of_absent_entities`, `scene_membership_is_guarded_by_entity_presence`
|
||||
and `tessellated_wires_stamp_from_the_designation_set`; the host tests
|
||||
`reference_only_refusals_record_no_undo_step`,
|
||||
`reference_only_designation_composes_undo_like_entity_writes`,
|
||||
`reference_only_designation_is_not_written_to_dwg_or_dxf`,
|
||||
`erasing_a_designated_entity_undoes_designation_with_it`,
|
||||
`user_paths_refuse_and_plugin_paths_write_reference_only_entities`,
|
||||
`select_all_visible_skips_reference_only_entities`,
|
||||
`entities_records_expose_the_reference_only_designation`; the unchanged pick tests; and the IPC
|
||||
round-trip `reference_only_request_and_response_roundtrip` (unchanged).
|
||||
@@ -123,13 +123,23 @@ re-designation that would not change the state succeeds without recording an
|
||||
undo step. Undo composition is the entity-write contract: a change inside a
|
||||
plugin-opened `push_undo` scope joins it, so an operation composed of several
|
||||
writes is a single undo step under the plugin's label; with no scope open a
|
||||
change is one undo step of its own. The designation survives DWG and DXF
|
||||
save/reload, stored as a marker value in an XDATA record under the host-owned
|
||||
`OCS` application namespace — plugins register their own APPIDs through their
|
||||
manifest, so the two cannot collide. Out of scope today: entities nested
|
||||
inside block instances (the block cache rebuilds instance wires without the
|
||||
flag) and a Python mapping. The MCP `entities` read exposes the flag as a
|
||||
`reference_only` boolean on every entity record.
|
||||
change is one undo step of its own.
|
||||
|
||||
**Storage is a scene-scoped in-memory set, not a file format.** The host
|
||||
writes nothing of its own into the saved DWG/DXF — no APPID registration, no
|
||||
XDATA marker on the entity — so a saved drawing never depends on host state
|
||||
to load correctly. The set lives and dies with the drawing tab: closing a
|
||||
tab forgets its designations, and a freshly opened drawing starts
|
||||
undesignated. Because the designation is per handle, an in-place refresh
|
||||
(clone → edit → replace) keeps it by construction. Undo keeps the contract
|
||||
through an explicit designation channel on each history step (the same
|
||||
pattern the parametric-constraint directory uses): undo/redo restores the
|
||||
designation together with the entity it belongs to — erasing a designated
|
||||
entity inside a scope, then undoing, brings back the entity *and* its
|
||||
designation. Out of scope today: entities nested inside block instances
|
||||
(the block cache rebuilds instance wires without the flag) and a Python
|
||||
mapping. The MCP `entities` read exposes the flag as a `reference_only`
|
||||
boolean on every entity record.
|
||||
|
||||
### Usage from a plugin
|
||||
|
||||
@@ -169,6 +179,9 @@ Notes for plugin authors:
|
||||
no undo step.
|
||||
- The designation travels with the entity: a clone → edit → replace refresh
|
||||
keeps it, so a plugin marks its display data once and refreshes freely.
|
||||
- The designation is scene state, not file state: it does not survive
|
||||
DWG/DXF save and reload — a plugin re-marks its display data when the
|
||||
document opens, and idempotent re-marks keep that loop finite.
|
||||
- Rendering and object snap are unaffected; grips, picking and the built-in
|
||||
write paths are the only observers.
|
||||
- Plugins that read the document through the IPC client (the
|
||||
|
||||
Reference in new issue
Block a user