Commit Graph
10 Commits
Author SHA1 Message Date
Hakan SevenandClaude Opus 5.5 f537aff75c feat: node graph overlay; move to opencadcodec/opencadkernel/opencadgraph
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 <noreply@anthropic.com>
2026-09-25 07:34:23 +03:00
Hakan Seven d10a0cf798 Merge pull request #1301: Add associative viewport dimensions
Refresh associations after complete SpaceMouse camera updates and recognize imported paper-space owners without Layout objects. Use kernel containment, intersection, perpendicular and spline tangent solving; pin cadkernel 7ce27f2 and add regressions.
2026-09-16 09:56:33 +03:00
Christopher Overbeck 5424a19482 Track mixed paper and viewport dimension references 2026-09-15 16:00:11 -05:00
Christopher Overbeck 7f018ab0f1 Merge viewport creation fixes and current upstream into associations 2026-09-15 14:14:33 -05:00
Christopher Overbeck 2ee3782850 Fix viewport dimension acquisition and preserve measurement scaling 2026-09-15 14:13:19 -05:00
Christopher OverbeckandClaude Fable 5.1 be7ba3d68e Record viewport associations for new dimensions
Removes PR3's `viewport_frame` seam in `viewport_ref.rs`; the frame is
PR1's camera-derived one everywhere.

The five dimension commands (DIMLINEAR / DIMALIGNED / DIMRADIUS /
DIMDIAMETER / DIMANGULAR) now record a real association when they
measure through a viewport. The commit path's one association gate
(`dimension_association_allowed`, added when PR2 was stacked) gains an
else-branch: where PR2 committed the dimension unassociated and PR1's
inference guard returned an empty source list, `Scene::attach_viewport_
dimension_association` now stores the whole chain — dimension ->
viewport -> block path -> entity -> feature — from the AcceptedSnaps PR1
captured, in definition-point slot order.

* `Scene::dimension_association_slot_points` names that order, including
  the radial dimensions `dimension_reference_points` does not cover.
* `OpenCADStudio::viewport_dimension_snaps` builds the slot array. A snap
  whose paper point is no longer the definition point it fills has its
  model point recomputed from that definition point through the frame:
  the object pick records one click for both extension origins, and a
  rotated DIMLINEAR projects its origins onto the measuring axis.
* Radial dimensions take their own path inside
  `attach_viewport_dimension_association`. Their single reference is an
  osnap type 10 carrying the radial marker (which circle / which polyline
  arc segment) and the angle around it; `source_reference` would hand
  back the generic curve-parameter marker -2, which
  `radial_source_for_marker` cannot find.

One measurement rule, documented in `viewport_ref::measurement_rule`:
`actual_measurement` is always the RAW measurement in the dimension's own
space (paper, for a viewport dimension), and the viewport compensation
lives only in the magnitude of the negative DIMLFAC override, applied
once by the formatter. PR2's persistence already followed it; PR3's
refresh did not — it substituted the model distance times
`model_factor()`, which made a refreshed dimension read `user_lfac` times
too much versus an identical freshly-created one. Refresh now writes the
paper measurement (a debug assert pins resolved paper points to the model
points through the frame), and `axis_distance` goes with it.

Block sub-entity snaps: verified that `block_cache` stamps the top-level
INSERT's handle onto every expanded and clipped sub-wire, so
`wire_source` can only ever report the INSERT — nested inserts included.
`OpenCADStudio::resolve_source_block_path` now descends from that INSERT
at accept time (using the object-pick path's existing
`resolve_measurable_entity`, so arbitrary depth, not just one level) and
fills `SnapSourceRef.block_path` with the real inner entity. Where the
descent cannot identify one — a non-planar-pickable type such as text,
hatch, spline or solid, or nesting past eight levels — the source stays
the INSERT with an empty path, which is coarser but never wrong. Both the
limitation and where it bites are documented on
`Scene::resolve_block_snap_source` and `SnapResult::source`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 12:52:00 -05:00
Christopher OverbeckandClaude Fable 5.1 417e8e3676 Add a viewport frame seam for dimension association resolution
PR3 has to map a resolved model point onto the sheet, which needs the
layout viewport's paper<->model mapping. PR1 (feat/viewport-snap) owns
`Scene::viewport_frame` and is not visible from this branch, so this adds
the minimal stand-in the shared contract in `viewport_ref.rs` describes:
paper_center from the viewport rectangle's centre, model_target from the
saved view target, scale from `vp_effective_scale`, twist from the saved
view twist.

It is fenced off in one clearly marked block with merge instructions.
PR1's version is camera-derived, because it must agree with what is
actually drawn — including the auto-fit rescue `camera_for_viewport`
applies to stale saved views. Nothing else in PR3 reads viewport fields
directly, so replacing this one function is the whole merge.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 12:46:03 -05:00
Christopher OverbeckandClaude Fable 5.1 9ee809d389 Resolve the DIMLFAC sign convention and add the viewport measurement seams
DXF gives DIMLFAC a sign convention: a positive value scales every
dimension, a negative one applies |DIMLFAC| only to dimensions that live in
a paper-space layout (where it compensates a viewport's scale). The linear
formatter multiplied by the raw signed value, so a drawing with negative
DIMLFAC (e.g. 115448.dxf) rendered negative measurements.

Resolve the sign once, in `resolved_dimension_style`, the single place an
effective style is derived, so dimension text, alternate units, exploded and
baked text and the properties panel all agree. `extended_data` keeps the raw
signed value, so DXF/DWG export is unchanged. The properties "Measurement"
row now reports the value the text shows rather than the raw distance, while
`actual_measurement` (group 42) stays raw as the format requires.

Also adds the PR2 seams the dimension work builds on:
  * MeasurementScale::user_lfac_for_space / viewport_dimlfac_override —
    the persisted representation of viewport compensation.
  * Scene::viewport_frame and paper-point viewport resolution.
  * Model-geometry hit testing through a content viewport, including
    descent into block instances with the instance transform baked in.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 12:40:44 -05:00
Christopher OverbeckandClaude Fable 5.1 6def465ba5 feat(snap): snap paper space through layout viewports
Paper-space commands could not pick model geometry displayed by a layout
viewport: `hit_test_wires` deliberately excludes viewport content in PSPACE,
and that has to stay true for selection. This adds the capability as a separate
query rather than by changing those semantics.

`OpenCADStudio::paper_viewport_snap` walks the current layout's displayed
content viewports top-most first, skips those whose display is off or whose
clip boundary excludes the cursor, and for each one runs the EXISTING snap
engine against that viewport's model wires using the viewport's own camera and
screen rectangle (`viewport_edit_frame_for`). The accepted model point is
mapped back onto the sheet with `ViewportFrame::model_to_paper`, so everything
downstream keeps working in paper coordinates — LINE still draws at the
projected paper point. Grid snap and the paper-space rubber-band origin are
suppressed for that pass; results outside the clip are rejected so no snap
lands on a clip cut. Locked viewports snap like unlocked ones.

No projected geometry is rebuilt per pointer event: the wire set is the
renderer's resident per-viewport Arc (`model_wires_for_viewport_arc`) and the
broad phase reuses the shared interaction index over it.

The result is merged with the ordinary paper-sheet snap by `snap::merge_snap`,
which applies the engine's own priority-then-distance rule, in both the
cursor-move and the click paths.

`SnapResult` gains Copy fields `viewport: Option<Handle>` and
`source: Option<DimensionAssociationSource>`; the engine fills `source` from
the owning wire wherever it knows it. `AcceptedSnap::from_snap` converts a
result plus frame into the shared PR2/PR3 contract type.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 12:27:25 -05:00
Christopher OverbeckandClaude Fable 5.1 49fe48f89c Add shared viewport frame, accepted snap, and measurement scale interfaces
Contract module for the viewport snapping, viewport dimension measurement,
and dimension association work that builds on it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 12:10:28 -05:00