Commit graph

149 commits

Author SHA1 Message Date
Hakan Seven
c12b30ad3d feat: 4× MSAA anti-aliasing for main drawing pipelines
All main render pipelines (wire, hatch, image, mesh) now use 4×
multisampling. Drawing passes render to a dedicated MSAA color buffer;
a final empty resolve pass transfers the anti-aliased result to the
iced surface target. The ViewCube renders post-resolve at 1× to avoid
pipeline incompatibility. Depth buffer also upgraded to 4× MSAA.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:52:38 +03:00
Hakan Seven
25b91bc09e feat: STL export (STLOUT / EXPORTSTL command)
Exports all tessellated 3D mesh models in the current drawing to a
binary STL file via a save-file dialog. Normals are taken from the
MeshModel where available, otherwise computed from triangle vertices.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:46:05 +03:00
Hakan Seven
9ede70ef1c feat: 3D ARRAY (ARRAY3D / 3DARRAY command)
Three-dimensional rectangular array: prompts for rows, columns, levels
and their respective spacings, then generates copies translated along
X (columns), Z (rows in drawing plane), and Y (levels / height).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:43:21 +03:00
Hakan Seven
3cdd86a674 feat: right-click context menu + CONSTRUCTIONLINE alias
Viewport right-click now shows a proper widget-based context menu:
- When a command is active: Cancel / Enter
- Otherwise: Repeat last commands, Delete/Move/Copy (if selected),
  Select All, Zoom Extents

CONSTRUCTIONLINE added as an alias for XLINE (XL).
Canvas-drawn placeholder removed; context menu closes on Escape,
click-outside, or when any action is taken.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:41:01 +03:00
Hakan Seven
a20558a024 feat: ATTREQ — attribute prompting during INSERT
When inserting a block that contains AttributeDefinition entities,
the INSERT command now enters an attribute-filling phase: each attdef
is prompted tag-by-tag (showing its prompt text and default value).
Pressing Enter accepts the default. The completed AttributeEntity list
is embedded in the Insert before committing.

Blocks without attdefs continue to insert immediately as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:33:56 +03:00
Hakan Seven
f73d38f0a2 feat: Object Snap Tracking (OTRACK / F11)
- snap/mod.rs: Snapper gains otrack_enabled, tracking_points, dwell state;
  update_otrack_dwell() acquires a snap point after DWELL_THRESHOLD=4
  consecutive moves near the same position; otrack_snap() returns an
  H/V alignment snap position; clear_tracking() resets state on command end
- overlay.rs: selection_overlay accepts ost_points + cursor_screen;
  draws light-blue dashed H/V lines from acquired points + small cross marker
- statusbar.rs: OTRACK pill (F11) added next to DYN
- view.rs: projects tracking_points to screen, passes to selection_overlay
- update.rs: calls update_otrack_dwell + otrack_snap in ViewportMove;
  overrides effective point with OST alignment when no normal snap is active
- ROADMAP.md: Object Snap Tracking marked 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:26:54 +03:00
Hakan Seven
d2a58bdd08 feat: DIMORDINATE + mark Named UCS saving and DIMORDINATE complete
- ordinate_dim.rs: OrdinateDimCommand picks feature point then leader
  endpoint; auto-detects X vs Y ordinate from movement direction
- Ordinate dim added to the Dimensions dropdown in the Annotate ribbon
- ROADMAP.md: DIMORDINATE , Named UCS (already implemented) 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:21:35 +03:00
Hakan Seven
6f741a92e0 feat: ATTEDIT — edit block attribute values interactively
- attedit.rs: AtteditCommand picks an INSERT entity then iterates through
  each attribute tag prompting for a new value (Enter keeps existing)
- attedit_pending_handle() / attedit_set_attrs() trait methods inject
  attribute data into the command after entity-pick (avoids document access
  in the command itself)
- cmd_result.rs: NeedPoint handler injects attr data; ReplaceEntity detects
  the __ATTEDIT__ sentinel and calls apply_attedit() on the document
- apply_attedit() encodes tag/value pairs as __ATTEDIT__tag\x01val\x02...
- ROADMAP.md: ATTEDIT marked 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:19:43 +03:00
Hakan Seven
0fc3766da7 feat: SPLINEDIT — close, open, reverse spline control-point editing
- splinedit.rs: SplineditCommand picks a spline (entity-pick phase) then
  accepts CLOSE/OPEN/REVERSE/EXIT sub-commands via text input
- apply_spline_op() mutates the spline in the document directly, with knot
  vector regeneration via generate_clamped_knots()
- Sentinel XLine trick: ReplaceEntity with a magic __SPLINEDIT_* layer name
  is intercepted in cmd_result.rs before erasing the original entity
- Control-point dragging already works via the existing grip editing system
- ROADMAP.md: SPLINEDIT marked 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:16:44 +03:00
Hakan Seven
51e6c4b359 feat: Dynamic Input overlay (DYNMODE / F12)
- overlay.rs: dynamic_input_overlay() canvas widget draws a semi-transparent
  coordinate tooltip near the cursor; shows X/Y in absolute mode or
  dist/angle relative to last_point when a command base point exists
- statusbar: DYN toggle pill with F12 tooltip (calls ToggleDynInput)
- app/mod.rs: dyn_input: bool field (default true), ToggleDynInput message
- view.rs: builds DYN label and pushes overlay into viewport_stack when
  dyn_input=true and a command is active
- document.rs: last_cursor_screen: iced::Point — updated on every ViewportMove
- ROADMAP.md: Dynamic Input overlay marked 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:12:09 +03:00
Hakan Seven
f80d694818 feat: DATAEXTRACTION — export entity data to CSV
- DATAEXTRACTION / EATTEXT / ATTEXT commands trigger an async save dialog
- Extracts all model-space entities with: Type, Handle, Layer, Color,
  Linetype, and a geometry summary per entity type (coords, radius, etc.)
- DataExtractionSave / DataExtractionSaveResult message pair drives
  the rfd save-file dialog asynchronously
- CSV fields are properly escaped (commas, quotes, newlines)
- ROADMAP.md: 12 DATAEXTRACTION marked 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:07:58 +03:00
Hakan Seven
b15be3af3d feat: WBLOCK — write block or selected entities to external file
- src/modules/insert/wblock.rs: extract_block_to_doc() copies a named
  block's entities into a fresh CadDocument; extract_entities_to_doc()
  does the same for a selection set; layer definitions are carried over
- WBLOCK <name> writes the named block; WBLOCK * writes selected entities
- WblockSave / WblockSaveResult messages drive the async save-dialog flow
- ROADMAP.md: 1.10 WBLOCK marked 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:05:04 +03:00
Hakan Seven
64837e9aed feat: XREF management — auto-resolve, XATTACH, XREF, XRELOAD
- src/io/xref.rs: resolve_xrefs() scans block_records for is_xref flags,
  resolves paths relative to the opened file's directory, loads the
  referenced DWG/DXF and merges model-space entities into the xref block
- src/modules/insert/xattach.rs: XATTACH command with file-picker flow
  (XAttachPick/XAttachPickResult messages), prepare_xref_block() creates
  BlockRecord + Block entities and immediately resolves content
- XREF command: lists all external references in the drawing
- XRELOAD command: re-resolves all xref paths and rebuilds scene caches
- Auto-resolve on FileOpened: reports Loaded/NotFound per xref block
- CadCommand trait: added optional xattach_path() method
- ROADMAP.md: 1.9 XREF management marked 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 00:02:38 +03:00
Hakan Seven
4c1c13cab6 feat: Grid snap adaptive spacing + Polar tracking improvements
Grid snap (F9):
  • snap spacing now tracks the visible grid zoom level — computed via
    compute_grid_step() (same adaptive pow-of-5 logic as draw_grid),
    updated on every ViewportMove so zooming in/out keeps snap aligned
    with the grid lines on screen

Polar tracking (F10):
  • configurable angle increment stored in polar_increment_deg (default 45°)
  • right-click the POLAR pill to cycle through 15 → 30 → 45 → 90°
  • pill label shows current angle ("POLAR 45°")
  • visual guide line: while drawing with polar on, a dashed cyan line is
    drawn from last_point along the snapped direction across the viewport
  • SetPolarAngle message + handler; all polar_constrain() calls use the
    stored increment instead of the hardcoded 45°

ROADMAP updated: Grid snap and Polar tracking marked .

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 19:30:25 +03:00
Hakan Seven
b3dcbe6eb9 chore: remove unused imports and variables (zero warnings)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 19:20:24 +03:00
Hakan Seven
a99115bda5 feat: Solid3D (3DSOLID) ACIS tessellation
Parse SAT geometry directly into GPU MeshModel without going through
the truck B-rep pipeline:
  • plane-surface faces  → fan-triangulate the coedge-loop polygon
  • cone-surface faces   → parametric grid (handles cylinders and cones)
  • sphere-surface faces → UV sphere grid (GRID_U × GRID_V)
  • torus-surface faces  → UV torus grid

Scene integration:
  • add_entity(): tessellates Solid3D on insert, stores in scene.meshes
  • erase_entities(): removes mesh from scene.meshes on delete
  • populate_meshes_from_document(): rebuilds all meshes on file load
    and undo/redo (called alongside populate_hatches/images)

ROADMAP updated: Solid3D tessellation marked  in sections 2.12, 14.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 19:11:24 +03:00
Hakan Seven
5a682a365a feat: EXTEND and LENGTHEN now support LwPolyline
Both commands detect which terminal segment/vertex is nearest to the
pick point, compute the new endpoint along the segment direction, and
move only that terminal vertex — preserving all other vertices and bulge
values intact.  ROADMAP updated: EXTEND and LENGTHEN marked .

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:05:44 +03:00
Hakan Seven
083eb5cbb5 feat: Spline support for TRIM, EXTEND, OFFSET, BREAK, and LENGTHEN
Add shared spline_ops module with:
- spline_to_bspline / bspline_to_spline: acadrust ↔ truck BSplineCurve conversion
- spline_sample_xy: sample DXF-XY projection at N+1 points with parameters
- spline_nearest_t: nearest-parameter search via coarse+bisection
- spline_pts_wire: world-space wire points for WireModel preview

TRIM: Spline entities can now be used as cutting boundaries (Geo::Spline
sampled into polyline segments) and as entities being trimmed; uses
BSplineCurve::cut() to produce surviving pieces.

EXTEND: extend_spline() shoots a tangent ray from the nearest endpoint
and appends a control point at the first boundary hit.

OFFSET: offset_spline() offsets each sample point along the local
perpendicular normal and rebuilds a new spline from the offset control pts.

BREAK: break_spline() uses spline_nearest_t() + BSplineCurve::cut() to
split the spline at one or two click points.

LENGTHEN: lengthen_spline() uses numerical arc-length integration +
bisection to cut the spline at the parameter corresponding to the new
requested length.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:00:22 +03:00
Hakan Seven
71667cfafe cleanup 2026-04-07 14:43:25 +03:00
Hakan Seven
2c71ad5aeb feat: FILLET now supports LwPolyline segments and corner filleting
- Add LwPolyline helper functions: nearest-segment finder, segment-to-line
  extractor, corner vertex replacer, segment shortener, bulge calculator
- Add FilletEntity::LwPoly variant carrying poly, handle, and segment index
- compute_fillet_entities handles all new combinations: LwPoly×LwPoly
  (same entity corner fillet with bulge encoding), LwPoly×LwPoly (different
  entities), LwPoly×Line, LwPoly×Arc and their symmetric counterparts
- on_entity_pick detects LwPolyline picks and allows same-entity re-pick for
  adjacent-segment corner filleting
- on_hover_entity preview updated to show LwPolyline wire geometry
- entity_pts extended to cover LwPolyline for preview rendering
- Update prompts to mention LwPolyline as a supported entity type

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 14:42:49 +03:00
Hakan Seven
7a07ef8710 feat: EXPLODE now supports Dimension entities
Decomposes Dimension (Linear, Aligned, Radius, Diameter, Angular2Ln,
Angular3Pt, Ordinate) into constituent Lines (extension lines, dimension
line) plus a Text entity for the dimension label value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:29:39 +03:00
Hakan Seven
d3d4ec4a08 feat: STRETCH with proper crossing-window vertex selection
Replaced the simplified MOVE-based STRETCH with a real crossing-window
implementation. Workflow: pick two crossing-window corners, then base+target
points. Only vertices/endpoints inside the window are translated:
- Line: moves start/end independently
- LwPolyline/Polyline: moves individual vertices inside window
- Arc/Circle/Ellipse: moves whole entity if center is inside
- Insert/Text/MText: moves if insertion point is inside

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:25:39 +03:00
Hakan Seven
1ef7bb5131 docs: update ROADMAP priorities — mark completed roadmap items
Mark as done: Named Views, DDEDIT, HATCHEDIT, MASSPROP, FILLET Arc support.
Update priority list to reflect remaining work.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:09:06 +03:00
Hakan Seven
f6d716dfc5 feat: HATCHEDIT command to edit existing hatch pattern, scale, and angle
Add HATCHEDIT (HE alias) command. Works on pre-selected hatch or via
entity pick. Accepts text options: P <pattern>, S <scale>, A <angle>.
Enter applies changes; rebuilds hatch entity and GPU model via add_hatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:08:51 +03:00
Hakan Seven
8078c4c9da feat: DDEDIT command and double-click text editing
Add DDEDIT (ED alias) command that edits Text/MText/Attribute entities
in-place via the command line. Double-clicking a text entity in model space
now auto-launches DDEDIT for that entity. Supports Text, MText,
AttributeDefinition, and AttributeEntity types.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:05:24 +03:00
Hakan Seven
25ec6f66e5 feat: add MASSPROP command — area, perimeter, centroid of selected entities
Computes mass properties for selected entities and prints results to the
command line. Supports: Circle (area+perimeter), Arc (sector area+arc length),
Line (length), LwPolyline (shoelace area+perimeter+centroid), Ellipse
(numerical 256-pt integration for area and arc length).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:00:18 +03:00
Hakan Seven
cfb27d93c3 feat: FILLET now supports Line-Arc, Arc-Line, and Arc-Arc pairs
Extended FilletCommand and ChamferCommand to accept Lines and Arcs as
first/second entity. Added fillet_line_arc() and fillet_arc_arc()
geometry functions that find a tangent fillet circle between the two
entities, trim each to the tangent point, and insert the fillet arc.
r=0 case trims/extends to the nearest intersection without inserting an arc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:58:46 +03:00
Hakan Seven
8e484d55cf docs: update ROADMAP to reflect completed session work
Mark as completed: ARRAY Path, BREAK/TRIM/EXTEND/OFFSET/LENGTHEN Ellipse
support, EXPLODE MLine, command history navigation (↑↓), RECTANG/POLYGON
command aliases. Update priority list accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:54:43 +03:00
Hakan Seven
44af4278f2 feat: EXPLODE MLine support and accurate header documentation
- Add explode_mline() that decomposes each MLine segment into its
  spine Line plus two ±scale/2 offset Lines using per-vertex miter
  directions, matching the visual representation of MLine entities
- Update file header to document all actually-supported entity types
  (LwPolyline, Polyline2D/3D, Polyline, Insert, MLine)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:52:05 +03:00
Hakan Seven
b425c9e790 feat: LENGTHEN support for Ellipse entities
Add lengthen_ellipse() that approximates the arc length via 128-point
numerical integration, then bisects to find the new angular span matching
the requested delta/total/percent, and adjusts the nearer endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:50:52 +03:00
Hakan Seven
eca4c96569 feat: OFFSET support for Ellipse entities
Add offset_ellipse() that scales both semi-axes uniformly by the offset
distance (inside vs outside determined by projecting side_pt onto the
ellipse local frame).  This is the standard CAD approximation; a true
offset of an ellipse is a higher-order Lamé curve.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:49:57 +03:00
Hakan Seven
519b305f0e feat: BREAK support for Ellipse entities
Add break_ellipse() that projects the two break points onto the ellipse
parameter space (eccentric anomaly) and removes the CCW segment between
them, producing a partial Ellipse entity — matching AutoCAD break behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:48:40 +03:00
Hakan Seven
09a6cc3521 feat: TRIM and EXTEND support for Ellipse entities
- Add Ellipse variant to the Geo boundary enum
- Implement algebraic line-ellipse intersection (le()) for fast boundary checks
- Add ellipse_seg_ts() using bisection for all boundary types including
  Arc/Circle/Ellipse boundaries (64-sample sign-change + 32-step bisection)
- Add trim_ellipse() producing partial Ellipse entities with updated parameters
- Add extend_ellipse() to stretch an ellipse arc to the nearest boundary
- Wire Ellipse into TrimCommand and ExtendCommand: on_entity_pick,
  on_entity_replaced, and on_hover_entity (live red/cyan preview)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:47:32 +03:00
Hakan Seven
80ca095121 feat: command history navigation with up/down arrow keys
CommandLine now records every submitted command in a recall list (up to
50 entries).  Pressing ↑ in the command input walks back through the
list, ↓ moves forward, and returning to the newest position restores
the draft text the user had typed before navigating.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 00:04:12 +03:00
Hakan Seven
0868a1719c feat: add RECTANG/REC and POLYGON/POL command aliases
Standard AutoCAD aliases now dispatch to the existing RECT and POLY
commands respectively, so users familiar with AutoCAD naming find
them without modification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 00:02:35 +03:00
Hakan Seven
c184535d5e fix: render wipeout fills after wire pass so they correctly mask wires
Previously wipeout solid fills were part of the hatch pass (pass 1),
drawn before wires (pass 5), so all wires appeared on top of the
wipeout. This fix moves wipeout fills into a dedicated pass 6 that
runs after wires, so the background-colored polygon correctly covers
the lines/text beneath it — matching AutoCAD behaviour.

- Scene.wipeout_models() separated from synced_hatch_models()
- Primitive.wipeout_hatches populated via wipeout_models()
- Pipeline.gpu_wipeouts + upload_wipeouts() + pass 6 after wires

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:44:36 +03:00
Hakan Seven
efc259fdbe feat: per-viewport layer freeze columns in Layer Manager
Add VP freeze/thaw toggle columns to the layer panel when in a paper
space layout. Each viewport gets its own column (VP 1, VP 2, …) showing
a freeze icon per layer. Clicking toggles frozen_layers on the Viewport
entity and syncs back to the panel.

- scene: viewport_list() → [(handle, label, frozen_handles)]
- LayerPanel: VpCol + vp_frozen per layer, sync_with_viewports()
- Message::LayerToggleVpFreeze(layer_idx, vp_col_idx)
- Sync VP columns on layout switch, VPLAYER cmd, undo/redo, layer ops

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:41:39 +03:00
Hakan Seven
c2f1c9078f fix: use file_path as GPU texture debug label to eliminate dead_code warning
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:35:13 +03:00
Hakan Seven
5d0edb3a1f fix: Wipeout fill color respects BACKGROUND command override
Scene now carries bg_color / paper_bg_color fields (defaults match
previous hard-coded values). synced_hatch_models() reads these instead
of hard-coded constants, so Wipeout fills correctly use the custom
background when BACKGROUND <r> <g> <b> has been set.
BACKGROUND command syncs both DocumentTab.bg_color and scene.bg_color.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:32:11 +03:00
Hakan Seven
cc314e75fc feat: Shape entity support (render + grips + props + transform)
- src/entities/shape.rs: diamond marker at insertion point (SHX glyphs
  cannot be rendered without the binary .shx file, so a placeholder is used)
- Grips: single insertion-point grip
- Properties: Name, Style (read-only), Insert X/Y/Z, Size, Rotation
- Transformable: translate, mirror, scale, rotate
- Registered in entities/mod.rs, entities/traits.rs, app/commands.rs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:30:27 +03:00
Hakan Seven
f470f6ebe2 chore: exclude ROADMAP.md from version control
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:28:04 +03:00
Hakan Seven
b3afefc345 docs: ROADMAP §5.2 GDT, §5.3 IMAGE, §2.3 background marked complete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:27:05 +03:00
Hakan Seven
41a5d98b33 feat: per-viewport background color (BACKGROUND command)
- DocumentTab: bg_color / paper_bg_color Optional<[f32;4]> fields
- view.rs: use custom color when set, fall back to defaults
- BACKGROUND <r> <g> <b>: set model or paper-space background (0–255 RGB)
- BACKGROUND RESET: restore default dark grey / paper grey

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:26:26 +03:00
Hakan Seven
4782c3bd96 feat: ImageDefinition object auto-created on RasterImage placement
When add_entity receives a RasterImage without a definition_handle,
create an ImageDefinition object in document.objects and link it.
This ensures DWG/DXF files save the IMAGEDEF section correctly so
other CAD programs can resolve image paths on reload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:24:20 +03:00
Hakan Seven
8404f22292 feat: Tolerance GD&T feature control frame render
Replace raw text dump with proper boxed feature-control frame:
- parse_gdt_rows(): splits %%v cells and ^J row separators
- substitute_gdt_codes(): strips {\Fgdt;X} patterns, maps symbol chars
  to 3-letter ASCII labels (POS, PRP, PAR, SYM, CIR, CYL, …)
- tessellate_tolerance(): outer rectangle, row separators, column
  dividers, and CXF-tessellated cell text — all as Vec<Vec<[f32;2]>>
  (TruckObject::Text polyline path)
- Column widths computed per cell content; text centred in each cell

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:23:06 +03:00
Hakan Seven
4312b6c3a5 feat: raster image render pipeline (IMAGE command + GPU textured quad)
- Add IMAGE / IMAGEATTACH / IM command with async file-picker (rfd)
- src/scene/image_model.rs: ImageModel with RGBA pixel data + quad corners
- src/scene/pipeline/image_gpu.rs: ImageGpu with wgpu texture, sampler, opacity uniform
- src/scene/pipeline/mod.rs: image render pipeline (pass 2, between hatches and meshes)
- src/scene/render.rs: include images in Primitive, call upload_images in prepare
- src/scene/mod.rs: images HashMap, populate_images_from_document, cache on add_entity
- src/modules/home/draw/raster_image.rs: ImageCommand (two-click: origin + width, aspect-correct preview)
- src/io/mod.rs: pick_image_file() async helper (file dialog + dimension decode)
- app: ImagePick / ImagePickResult messages, populate on file open and undo/redo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:19:08 +03:00
Hakan Seven
3d1f355a5c feat: TextStyle font browser (STYLE DIALOG command)
- STYLE DIALOG / TEXTSTYLE DIALOG opens the Text Style Font Browser
- Three-panel dialog: style list | built-in CXF font list | properties
- Properties panel: font file text field, width factor, oblique angle
- Apply button commits edits; Set Current sets the active text style
- Built-in font picker (20 CXF fonts from assets/fonts/) auto-applies
  font to the selected style on click
- Preview pane shows "AaBbCc 0123" sample text

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 15:01:25 +03:00
Hakan Seven
552ab7eb6a feat: TableStyle manager (TABLESTYLE command + dialog)
- TABLESTYLE/TS command: LIST, NEW subcommands for managing table styles
- Table Style Manager dialog: style list with details panel showing
  name, margins, suppression flags, and row styles (data/header/title)
  with text style, height, and alignment per row type
- New / Delete buttons in the dialog

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:57:11 +03:00
Hakan Seven
34076b26bb feat: MLineStyle manager (MLSTYLE command + dialog)
- MLSTYLE command: LIST, NEW, SET, DEL subcommands
- Multiline Style Manager dialog: style list, element details (offset,
  color, linetype), Set Current / New / Delete buttons
- MLINE/ML command now reads document header.multiline_style to apply
  the current style to newly created MLine entities
- MlineCommand.with_style() constructor for style-aware multiline drawing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:54:05 +03:00
Hakan Seven
7e6de57c8d feat: Wipeout solid fill masking
Wipeout entities now render a background-colored solid fill polygon
(via the hatch GPU pipeline) that masks other hatch fills beneath them.
Fills use model space background (0.11 grey) or paper space background
(0.22/0.24/0.28). Polygon and rectangular clip boundaries both supported.
Selected wipeouts use a translucent blue highlight instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:46:47 +03:00