Commit Graph
25 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 <[email protected]>
2026-09-25 07:34:23 +03:00
gianlucafiore cc7894cd92 fix: honor drawing units in annotation and viewport scales 2026-08-11 22:41:26 -03:00
Hakan Seven b8889ccd20 feat(mview): add viewport creation options
Support polygonal and object viewports through native clip-boundary handles, including clipped rendering and selection.

Closes #525
2026-07-27 19:28:51 +03:00
Hakan Seven ece5598372 fix: correct viewport stretch and SHX plots
Anchor the opposite viewport corner during grip and STRETCH resizing.
Match plotted stroke-font pen widths to the SDF atlas unless CTB overrides.

Closes #435
2026-07-24 19:26:10 +03:00
Hakan SevenandClaude Opus 4.8 1523eda00f feat(properties): fill solid-history + viewport clipped rows
Bump acadrust to ef0e231 (region/body history handle + viewport clip
boundary now stored) and populate the rows the builders left blank:

- Solid3D / Body "Show History": derived from the history handle's
  presence (there is no separate stored bool — the DWG carries only the
  H 350 history link).
- Body "History": the history handle, matching how Solid3D already shows
  it.
- Viewport "Clipped": Yes when the clip-boundary handle is non-NULL.

Hatch Origin X/Y and Boundary retention stay blank by design: they are
not part of the persisted AcDbHatch record in DWG or DXF (retention is a
BHATCH command setting), so there is nothing to read.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-03 00:17:58 +03:00
Hakan SevenandClaude Opus 4.8 4398341632 chore(properties): remove dead helpers left by property-builder rewrite
The spec-conforming property builders dropped the rows that used these
helpers, leaving them unreferenced: hookline_dir_str (leader),
length_and_area (lwpolyline), render_mode_label / STD_VIEWS /
viewport_view_label (viewport). No behavior change.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-02 23:34:01 +03:00
Hakan SevenandClaude Opus 4.8 b9cebab951 feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.

Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-02 23:03:18 +03:00
Hakan SevenandClaude Opus 4.8 b2b2bfb246 refactor(properties): entity property groups return Vec<PropSection>
Groundwork for making the Properties panel conform to the per-entity group/row
spec (PROPERTIES.md). The panel already renders a Vec of sections, but each
entity could only express a single geometry section.

Change PropertyEditable::geometry_properties (and the EntityTypeOps enum
dispatch) to return Vec<PropSection>, update the two impl macros, and flatten
in properties_sectioned so the panel shows [General] + the entity's groups.
Every entity builder is wrapped to return its existing section as a one-element
Vec — pure mechanical change, no rows or titles altered, panel output identical.

Enables Phase 2: rewriting each entity's groups/rows to match the spec.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-02 22:46:19 +03:00
Hakan SevenandClaude Opus 4.8 56d507fd88 refactor: remove dead world_offset plumbing (RTE migration is complete)
Now that geometry reaches the GPU/CPU as absolute coordinates via the
double-single relative-to-eye path, world_offset is always [0,0,0]. Strip
the parameter that was threaded through the whole tessellation / block-
expansion / fallback / camera-decode chain and the ExpandCtx field that
carried it — ~340 references across 20 files, all subtracting zero.

- truck_tess: to_local / to_local_low / tessellate_* drop the offset arg;
  to_local is now a pure double-single split.
- tessellate: offset_to_ds → points_to_ds (pure DS split); tessellate(),
  tessellate_entity(), fallback_geometry(), solid_wire_fallback(),
  entity_aabb(), expand_insert(), expand_block_meshes(), the dimension
  helpers (vec3_local, dimension_snap_pts, …), text_support, leader,
  multileader, image_model, xclip and camera_from_view all lose the param.
- block_cache: ExpandCtx loses its world_offset field.
- Remove the now-dead offset_snap_pts and the unused set_grid_snap.

Behaviour is unchanged (the offset was zero everywhere); the compiler
verifies every call site.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 18:35:02 +03:00
Hakan SevenandClaude Opus 4.8 dd1f2e49bb fix(render): UTM-precise UCS icon + fallback outlines (hatch etc.)
Two UTM-scale rendering defects.

- UCS icon jittered: it projects only axis DIRECTIONS but went through the
  full view_proj, whose ~5.7e6 translation cancels catastrophically in f32.
  Feed it the rotation-only view_proj_rte instead (translation dropped).

- Fallback outline geometry (hatch boundary, viewport/insert/ole2frame
  frames, Solid3D edge wires) built absolute f32 points with an empty
  points_low, so at UTM the outline sat ~0.5 m off its own fill (the hatch
  fill renders precisely via the world_origin-relative HatchModel pipeline).
  FallbackGeometry now carries absolute f64 points + key vertices; the
  tessellate dispatcher splits them into the double-single high/low pair the
  relative-to-eye wire pass needs, so outlines land exactly on their fills.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 10:09:19 +03:00
Hakan SevenandClaude Opus 4.8 7fe7e0230d refactor(scene): group modules into role-based subfolders
Move the 30 flat modules under src/scene/ into six folders by role:
convert (entity→geometry), text (fonts/shaping), model (render models),
pick (hit-test/selection/grips/xclip), view (camera/transform/render),
cache (block + property caches). pipeline/ is unchanged.

Full path migration — all `scene::X` references become
`scene::<group>::X`, no compatibility re-exports. render.rs items that
were `pub(super)` (parent was scene) become `pub(in crate::scene)` to
keep their original scene-wide visibility.

No behavior change; build and tests are green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 11:33:46 +03:00
Hakan SevenandClaude Opus 4.8 25715d1b03 fix(grips): compute grip positions in f64 so they sit on the wire
Grip markers drew visibly offset from the entity on large-coordinate
(UTM-scale) drawings: every Grippable impl cast the f64 entity coordinates
to f32 BEFORE the world-offset subtraction, and at 1e7 magnitude an f32
holds ~0.9 drawing units of rounding error. The wires subtract the offset
in f64 first (precision-preserving), so the grips landed up to ~1 unit
away from the geometry they belong to.

GripDef.world is now DVec3: producers fill it straight from the f64
entity data, refresh_selected_grips subtracts the world offset in f64,
and only the small offset-local result is cast to f32 for screen-space
projection (grips_to_screen / find_hit_grip) and drag state.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-11 00:04:37 +03:00
Hakan SevenandClaude Opus 4.8 edc8cbc969 feat(scale): drive scales from the drawing's scale list
Read the model-space annotation scale from the standard CANNOSCALE /
CANNOSCALEVALUE header variables instead of a user-variable hack, and
populate both the status-bar scale picker and the viewport Scale
property purely from the drawing's ACAD_SCALELIST — no built-in
fallback set. Xref-derived scales (`_XREF` suffix, `name|` prefix)
are filtered out so only the host drawing's own scales appear.

Bumps the patched acadrust to the commit that adds CANNOSCALE/
CANNOSCALEVALUE read/write.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-04 16:18:01 +03:00
Hakan Seven 5755c2e130 refactor(grip): square-only marker set + oriented stretch handles
Phase 1 of bringing the grip vocabulary in line with the standard
CAD convention: drop the per-position-type shape encoding (Diamond
for translate, Circle for parameter) and use a plain square for
every endpoint / vertex / centre grip. The behavioural midpoint vs
vertex distinction stays — it lives on `GripDef::is_midpoint` and
drives `Translate` vs `Absolute` in the grip-edit dispatcher — only
the marker shape collapses.

- `GripShape` keeps `Square`, `Rectangle`, `Triangle`. Diamond /
  Circle are gone.
- `GripDef` gains `dir: Option<[f32; 2]>` — a world-XY direction
  vector consumed by `Rectangle` to orient the box along its
  segment.
- `entities::common` exposes `square_grip`, `center_grip` (same
  square marker, flagged as translate), `rectangle_grip(id, world,
  dir)` for oriented mid-segment handles, and a kept-for-Phase-2
  `triangle_grip`.
- `overlay::GripMarker` / `grips_to_screen[_paper]` thread `dir`
  through to the canvas painter; the Rectangle path rotates the
  box around the grip centre using the world-XY direction (flipping
  the sin for screen-Y).

Every existing `diamond_grip(id, w)` call becomes `center_grip(id,
w)` — the visual change is square-replacing-diamond at line
midpoints / arc midpoints / circle centres / ellipse centres /
viewport / hatch loop centroids / dimension grips / image corners /
multileader / ray / underlay / ole2frame / solid3d.

`LwPolyline` grows a stretch handle on every segment (straight or
arc), drawn as the new oriented rectangle. The grip-edit path
translates both segment endpoints for straight segments and
adjusts the arc bulge from the new midpoint for arc segments.
2026-05-29 02:07:34 +03:00
Hakan SevenandClaude Opus 4.7 9b5073752d refactor(entities): collapse trait wrapper boilerplate via macro
Every entity file ended with the same three-trait wrapper block:

    impl Grippable for T {
        fn grips(&self) -> Vec<GripDef> { grips(self) }
        fn apply_grip(&mut self, ...) { apply_grip(self, ...) }
    }
    impl PropertyEditable for T { ... }
    impl Transformable for T { ... }

— 23 lines of pure delegation around five same-named free functions.

Replace with `crate::impl_entity_basics!(T);` (a macro in
entities/traits.rs that expands to the three trait impls).

Applied where the file already follows the free-fn delegation
convention (Arc, Circle, Ellipse, Insert, Leader, Line, LwPolyline,
MultiLeader, Ole2Frame, Point, Spline, Viewport). Files that inlined
the trait method bodies directly (Ray, XLine, Shape, Solid, Tolerance,
MLine, Mesh, Solid3D/Region/Body, Table, RasterImage, Wipeout,
Underlay, Hatch, Polyline, Polyline2D, Polyline3D, Dimension) left
alone — they already skip the indirection. Text/MText/Attribute use
the with-text-style flavour and will move once that variant is needed
beyond the existing two manual impls.

A second macro `impl_entity_basics_with_text_styles!` is included for
the text-like flavour but no entity uses it yet.

Net: -204 lines.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-26 17:16:06 +03:00
Hakan SevenandClaude Opus 4.7 b413fe0efe refactor(tess): rename LegacyTess → FallbackTess
The trait isn't deprecating anything — it carries the path entities
take when they're not covered by the truck topology pipeline
(Viewport, Insert, Hatch outline, Ole2Frame). "Fallback" names the
purpose; "Legacy" implied retirement that isn't actually on the
roadmap.

Same rename for LegacyGeometry → FallbackGeometry,
legacy_geometry() → fallback_geometry().

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 23:16:57 +03:00
Hakan SevenandClaude Opus 4.7 aadb64860d refactor(tess): move per-entity tessellation into entities/
Each entity's tessellation now lives alongside its definition in
entities/*.rs, attached to the entity type via a local trait:

  LegacyTess     — Viewport / Insert / Hatch / Ole2Frame
                   (fallback path for entities not on the truck pipeline)
  LeaderTess     — Leader
  MultiLeaderTess — MultiLeader
  DimensionTess  — Dimension (carries its dim-only helpers too:
                   ~1700 lines of dim_geometry, dim_text_*, format_*,
                   tolerance, suppression, etc.)

scene/tessellate.rs keeps only the cross-entity dispatcher plus the
shared dim machinery reused by leader/multileader/dimension
(ArrowKind, DimGeom, append_arrow, arrow_from_block, add_segment,
add_polyline, normalized_or, push_tri, color_or_inherit, entity_z,
offset_snap_pts). Cross-entity arc helpers + aci_to_rgba moved to
scene/tess_util.rs.

scene/tessellate.rs shrinks from ~3300 to 809 lines. Compile clean,
all 9 tests pass.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 23:12:27 +03:00
Hakan SevenandClaude Opus 4.7 0b4facc50d feat(entities): surface remaining 2D + Region fields in properties
Closes out the 2D-entity audit (and the Region partner that ships next
to Solid3D / Body). Round-trip-only metadata fields plus a few editable
ones gain Properties-panel rows so the values the parser populates are
visible and don't get silently dropped on save:

- Hatch: seed_points count, pixel_size, normal
- Polyline2D: smooth_surface, default_start_width, default_end_width,
  thickness, normal (with editors for the widths/thickness)
- Region: uid, silhouettes (shared file with Solid3D / Body)
- Underlay: clip_inverted
- RasterImage: class_version, definition_handle, definition_reactor_handle
- Wipeout: class_version, clip_mode, definition_handle,
  definition_reactor_handle
- Leader: annotation_handle, override_color
- Tolerance: dimension_style_name, dimension_style_handle, dimension_gap,
  text_height (editable), direction, normal
- MLine: style_handle, style_element_count, justification picker
- Ole2Frame: version, source_application, binary_data size, dwg_mode,
  dwg_trailing_byte, is_paper_space
- Viewport: snap_base/spacing/angle, twist_angle, front/back clip Z,
  circle_sides, grid_flags, grid_major, base_ucs_handle, ucs_ortho_type,
  background_handle, shade_plot_handle, visual_style_handle,
  default_lighting, default_lighting_type, ambient_color (with editors
  for the snap / clip / circle_sides values)

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-19 21:28:16 +03:00
Hakan Seven 66243e53ca feat: correct viewport scale calculation with correct dimension and text scaling 2026-05-19 00:26:08 +03:00
Hakan ca07268c7c cargo fmt 2026-05-12 10:36:15 +03:00
Hakan SevenandClaude Sonnet 4.6 2434427583 fix: viewport grip resize preserves scale instead of zooming content
When a corner grip is dragged, view_height is now updated proportionally
with the new frame height so that scale = height/view_height stays constant.
The visible model-space area grows/shrinks with the frame instead of the
content appearing to zoom.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-01 21:26:02 +03:00
Hakan SevenandClaude Sonnet 4.6 5ad2f4a8cb Feat: Phase 3 — perspective projection and per-viewport UCS properties
- viewport_content_wires(): conditional perspective divide using
  camera_dist = view_height * lens_length / 24.0 (35mm-film equiv.);
  points behind the camera are mapped to NaN for safe clipping
- viewport.rs: expose lens_length, ucs_per_viewport, ucs_origin,
  ucs_x_axis, ucs_y_axis as editable properties; handle all new
  fields in apply_geom_prop()

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-01 00:22:02 +03:00
Hakan SevenandClaude Sonnet 4.6 73b224c191 Feat: viewport display lock, extended properties, VPLAYER and VPORTS commands
- Enforce status.locked in pan_active_viewport and zoom_active_viewport:
  locked viewports now reject pan/zoom inputs entirely
- Add perspective, render_mode, shade_plot_mode, hide_plot, ucs_icon_visible
  fields to the viewport property panel with appropriate pickers/toggles
- Add VPORTS command: lists all user viewports in the current layout
  (id, size, position, scale, on/locked state) in the command line
- Add VPLAYER command: per-viewport layer freeze/thaw from the command line
  (F <layer> to freeze, T <layer> to thaw, Enter to exit)
- Add CmdResult::VpLayerUpdate variant and its handler in apply_cmd_result

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-31 23:52:18 +03:00
Hakan SevenandClaude Sonnet 4.6 031d2311ed Phase 4: Viewport control and properties
- Viewport ID uniqueness: commit_entity assigns max_existing_id+1
  instead of always using id=2
- Lock/On boolean toggles in Properties panel (vp_locked, vp_on)
  backed by status.locked / status.is_on fields
- Standard scale Choice picker: 1:500 to 10:1 (also syncs view_height)
- Numeric scale edit now syncs view_height when changed
- Standard view Choice picker: Top/Bottom/Front/Back/Left/Right/4×Iso
  updates view_direction vector via apply_geom_prop
- Viewport content not rendered when status.is_on is false
- current_layout_block_handle_pub() added for external access

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-03-31 07:27:03 +03:00
Hakan Seven d2fdac7f1e first commit 2026-03-22 14:56:27 +03:00