Three polyline issues in the FILLET/CHAMFER commands:
- The polyline preview wire ignored bulge, so a filleted corner previewed
as a straight line instead of the arc. lwpoly_pts now tessellates bulge
segments via BulgeArc (same as the entity render).
- Hovering a polyline edge didn't highlight it: the first-pick hover only
handled Line/Arc. Both commands now highlight the nearest polyline
segment on hover.
- CHAMFER didn't work on polylines at all (Line-only). Added a SecondPoly
step + chamfer_lwpoly_corner: pick two adjacent segments of one polyline
to cut the shared corner back by the two distances with a straight edge.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The trim/extend preview wire for an LwPolyline placed each vertex at
[x, elevation, y] (the old Y-up swap), so the highlighted boundary was
drawn in the wrong plane. Use [x, y, elevation] to match the entity
render and the rest of the now-XY commands.
(The remaining axis swaps live in the 3D revolve / truck B-rep pipeline,
which is a separate, internally-consistent Y-up subsystem.)
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The drawing plane is world XY, but break, join, rectangular array, the
stretch/window move, the spline preview wire and several doc comments
still used the stale "Y-up XZ" mapping (world Z = DXF Y). That made
those commands operate against a constant-elevation axis: arc/circle/
line/spline break and join picked the wrong points, rectangular array
stepped rows along the Z (elevation) axis, window-stretch tested the
wrong window bound, and the spline wire drew in the wrong plane.
Map every drawing-plane coordinate through .y (elevation on .z),
matching the entity builders, the inquiry commands and the central
transform. Stale Y-up comments updated to avoid future confusion.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
These commands still read the cursor / entity coordinate with the old
"Y-up XZ" assumption (world Z = DXF Y), which is wrong now that the
drawing plane is world XY: ID/DIST/AREA reported swapped Y↔Z values and
zero-area, and fillet/align/lengthen picked against a constant-elevation
axis. Read the drawing-plane coordinate from .y (elevation stays on .z),
matching the central transform and the entity builders.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The pick/typed point is the world XY plane (z = elevation = 0), but
several entity builders still mapped the screen point as if the world
were Y-up (drawing in XZ), reading the constant elevation as the DXF Y.
That collapsed shapes onto a single line — e.g. a revision cloud always
came out as two horizontal lines regardless of the path drawn.
Map the drawing-plane point straight through (x→x, y→y, z→elevation) in:
revcloud, donut, mline, raster image, wipeout (polygonal + rectangular),
table, attribute definition, and tolerance. Previews already used the
correct pass-through, so they matched the cursor; only the committed
geometry was wrong.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Reworks MLEADER text/leader geometry and grip editing, and aligns LEADER
to MLEADER's conventions (kept as separate entities).
Text & landing (render path):
- Text is side-anchored on the leader-facing edge and reads outward; the
side, alignment and the horizontal landing are recomputed every frame
from the text grip's position relative to the leader, so moving the
arrow or the text re-mirrors the whole layout and the landing stays
attached to the text's near edge.
- Fixes#49: text was centred on the leader endpoint regardless of side.
Grips:
- Text-location grip plus an MTEXT-style triangle wrap-width grip at the
box's far edge; dragging it sets the MText wrap width.
- Multifunction grip menu restored and made functional: leader-line
vertices offer Add Leader / Remove Leader (Add grabs the new arrow so it
follows the cursor — click places, Esc removes it); the text grip offers
Move Independent (text only) and Move with Leader (translates the whole
multileader via a move-all sentinel grip).
Arrows:
- LEADER and MLEADER arrowheads now render at the same size (text height),
matching previews.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Rename the Home tab to "Draw" and add a Model tab beside it with two
groups:
- Model: BOX / CYLINDER / CONE / SPHERE / WEDGE / TORUS, placed with a
footprint + height. Each is built as a real ACIS Solid3D (acadrust
primitive builders) plus a truck B-rep, tessellated into the shaded
mesh pipeline, with edge wires for picking + wireframe.
- Design: UNION / SUBTRACT / INTERSECT via truck-shapeops.
A session-only Scene.model_solids cache holds each solid's truck B-rep
so the boolean tools can combine and chain them. Supersedes the old
command-line BOX/SPHERE/CYLINDER (insert::solid3d_cmds keeps EXTRUDE/
REVOLVE/SWEEP/LOFT).
Known limitations: booleans need solids created this session; curved
ACIS primitives render in-session but not after reload (the SAT
tessellator handles only planar caps); geometry assumes world_offset 0.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Route every text-bearing entity to an in-place editor instead of the
command line: a plain text box for single-line text (Text, attributes,
dimension override, tolerance) and the rich MText editor for MText /
MultiLeader. A Leader resolves to the entity it annotates.
- TEXT places a plain text box at the click; double-click edits in place.
- DDEDIT and double-click on any text entity open the matching editor.
- MLEADER places the leader then opens the MText editor on its content.
- LEADER follows the classic flow: points, Enter, then a linked empty
MText annotation opens in the editor; the leader's annotation_handle
links the pair so they edit/erase as a unit.
Adds shared field read/write helpers and a begin_text_edit router, plus
CommitAndEditText / CommitManyAndEditText results that commit an entity
and open its editor (commit_entity now returns the new handle).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Added SVG icons for text formatting options (bold, italic, underline, overline, strike, uppercase, lowercase).
- Introduced a new `MTextEditorState` struct to manage the state of the MText editor.
- Implemented functionality to open the MText editor from the command line and edit existing MText entities.
- Added message handling for various MText editor actions (formatting, height, style, font, justification, alignment, line spacing).
- Created a dedicated preview area for MText rendering within the editor.
- Updated the command structure to support opening the MText editor and handling text input.
- Refactored existing MText command logic to integrate with the new editor.
DRAWORDER now affects rendering immediately (bump geometry epoch so the
sort cache rebuilds) and front/back anchor to the block's full effective
sort range instead of only existing table entries, so bring-to-front
actually lands on top. The render fallback sorts table-absent entities by
their own handle.
Draw order now applies across entity types, not just within a type. A
per-entity draw-order rank (SortEntitiesTable override or own handle,
ranked per block) is encoded as a small signed clip-z bias in the wire,
hatch, image, and 3DFACE pipelines. The shared LessEqual depth buffer then
orders fills, lines, rasters and 2D solids against each other regardless of
pass order — without touching model coordinates. 3D meshes keep real
geometric depth; wipeouts stay always-on-top.
Adds a Draw Order submenu to the viewport context menu (Bring to Front,
Send to Back, Bring Above/Send Under Object). The above/under items run an
interactive reference-object pick, then reorder the captured selection.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Sağ kenardaki dikey orbit/pan/zoom/zoom-extents araç çubuğu tümüyle
kaldırıldı: viewport render'ı, overlay::nav_toolbar fonksiyonu,
show_navbar state + ToggleNavbar mesajı/handler'ı, NAVBAR komutu, View
şeridindeki "Navigation Bar" aracı ve navbar modülü/ikonu. Aynı
gezinme işlemleri komutlar (3DORBIT, PAN, ZOOM*) ve ViewCube üzerinden
erişilebilir durumda.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
DYN overlay artık ekran-yukarı için world Y'yi (w.y) gösteriyor; eskiden
w.z kullanıldığı için Z-up sahnede top/3D görünümde Y hep 0 görünüyordu
(#27).
Ayrıca overlay etiketi aktif komutun o anki sorusuna göre biçimleniyor:
yeni DynField (Point / Distance / Angle) trait metodu eklendi. CIRCLE
yarıçap adımında 'd=...', ROTATE açı adımında '<...°', diğer nokta
adımlarında koordinat / polar (d + açı) gösteriliyor.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Type-as-you-go suggestion popup above the input that filters known
command names by substring (so `LEADER` surfaces both LEADER and
MLEADER). Up / Down navigates the list, Enter dispatches the
highlighted entry, clicking a row dispatches directly. Esc on a
non-empty input clears the buffer instead of escalating to
command-cancel.
The name corpus comes from `inventory::submit!` blocks placed next
to each `CadCommand` impl rather than a hand-maintained static list.
Adding a new interactive command means dropping one `inventory::submit!`
line in its own module file — the autocomplete picks it up at the
next compile. 98 submissions seeded across 60 module files;
`command::all_registered_command_names()` flattens them at runtime.
One-shot dispatch arms in `app/commands.rs` (NEW, OPEN, SAVE, UNDO,
…) don't have a `CadCommand` impl and are therefore absent from
autocomplete by design.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Two behaviour changes that bring the command line in line with
established CAD workflow:
1. **Always-on keyboard capture.** The input was blurred whenever no
command was running, so typed letters went nowhere until the user
clicked into the field. Replace the blur with a re-focus on every
command lifecycle transition (cmd_result.rs) and on viewport / tab
/ ribbon clicks (update.rs), focus the input at startup, and add
a global key subscription that catches any unhandled character key
or backspace and routes it into the buffer via two new messages
(CommandAppendChar / CommandBackspace) — so the command line keeps
accumulating keystrokes even if focus parks somewhere not
focusable. Removes the unused blur_cmd_input helper.
2. **Space submits.** Typing a space at the end of the input now
submits the buffer the same way Enter does. Only exception: an
active command that's currently collecting free-form prose
(TEXT / MTEXT / DDEDIT body, ATTDEF prompt / default value,
INSERT attribute value, ATTEDIT cell). Those advertise the new
`CadCommand::wants_text_with_spaces()` flag so the Space character
reaches the buffer as a literal.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
The same DXF/DWG bulge → (center, radius, sweep) formula was inlined
in six places (hatch outline, polyline tess + truck path, lwpolyline
×4, scene hatch fill, explode bulge_to_arc) — each with subtly
different sweep-direction handling for the bulge sign.
Add `entities::common::BulgeArc { center, radius, start_angle,
end_angle, sweep }` with one `from_bulge(p0, p1, bulge)` constructor
and a `sample(t)` helper. Callsites collapse to a few lines.
Net: -121 lines, one canonical sweep-direction convention shared by
all consumers.
array.rs (the path-along-curve f32 helper) keeps its inline math —
its sign convention is inverted relative to the others and changing
it without exercising the array-path command risks regressing the
output.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Joining the OpenAEC Foundation (open-aec.com). Crate/struct become
OpenCADStudio, user-facing strings use the spaced "Open CAD Studio"
form, repo URLs point to HakanSeven12/open-cad-studio. Logo (window
icon + assets/logo.svg) redrawn with OCS initials. Drop examples/
binaries — unused.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
A pinned "Start" tab now lives at index 0. It cannot be closed, opens
on launch, and replaces the model-space viewport with a welcome page —
similar to Thunderbird's first-run screen.
- Boot opens with only the Start tab; Drawing1 is no longer auto-spawned.
- The Properties left panel becomes a Recent Documents rail on the
Start tab. Recents persist to disk
(%APPDATA%/H7CAD/recent.txt on Windows, $XDG_CONFIG_HOME/H7CAD/recent.txt
on Linux, ~/Library/Application Support/H7CAD/recent.txt on macOS), up
to 20 entries, saved on every open and rehydrated at boot.
Each row opens or removes the file in place.
- The Support ribbon group (Donate / Report / About / Changelog) is
retired; the same actions surface on the welcome page instead. The
Donate button is the primary call-to-action — solid #B03020 brand
fill with a soft brand-tinted ambient glow halo behind the action row
(Thunderbird-style coloured glow against the neutral page).
- Drawing-only overlays (mouse-area, viewcube, navbar, dynamic input,
selection markers) are suppressed on the Start tab so its clicks
don't trigger CAD commands. OpenFile's "current_is_empty" check
refuses to replace the Start tab, and TabClose ignores requests on
it.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Tessellation and DIMBASELINE pick up the few DimStyle fields that were
still hard-coded or ignored:
- DIMTMOVE = 1 draws a connector segment from the dim-line anchor to the
saved text_middle_point when the text has been moved
- Leader arrows are resolved via the leader's DIMSTYLE → DIMLDRBLK; the
shape (closed-filled / open / dot / tick / …) is drawn through the same
arrow emitter the dim path uses, including fill_tris for filled blocks
- DIMBASELINE picks up DIMDLI from the active DimStyle instead of the
hard-coded 1.5 increment
- DIMTOFL / DIMTIX / DIMATFIT / DIMUPT / DIMTXTDIRECTION are read so the
fields round-trip on save; their effect is at dim creation, not render,
so they're acknowledged with a no-op block
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Two precision problems were producing visibly wrong hatches on UTM-scale
(and similarly-offset) drawings even after world_offset was correct:
1. **Boundary tessellation** — `hatch_model_from_dxf`'s polyline-bulge
arc tessellation ran the whole arc-center computation in f32. With
vertices at WCS magnitude ~1e5 the f32 ULP is ~1 cm, which propagated
into the sampled arc points and showed up as visibly wavy / jagged
hatch boundaries on edges that crossed the long axis of the drawing.
Re-run the full bulge → arc math in f64; only cast at the to_xy
call that feeds the (also f64) boundary buffer.
2. **Pattern phase** — the per-fragment `perp / perp_step` modulo blew
precision when `xz` was at offset-rel WCS magnitude and perp_step
was sub-cm. Move the precision-critical bits out of f32 by keeping
each hatch's anchor in f64 on the model side: `HatchModel` now
carries a `world_origin: [f64; 2]` and the `boundary: [f32; 2]`
vertices are stored as small offsets from it. The GPU vertex shader
adds `origin` back inside the view_proj multiply for clip position
(sub-pixel-lossy at large hatches but invisible); the `xz` varying
that the fragment shader uses for in_polygon + pattern math stays
in hatch-local space at full f32 precision.
For pattern alignment across adjacent hatches with the same family,
the GPU pipeline snaps the anchor to the family's perp/along grid
in f64 before sending it down. Snap uses the same QCAD-PAT
convention (`fam.dy = perp_step`, `fam.dx = along_step`) the
shader's check_family uses — an earlier attempt used the world-frame
`(-dx*sin + dy*cos)` formula, which produced a meaningless grid and
no alignment.
Trade-off: pattern phase is "global modulo per-family-grid" rather
than tied to WCS (0,0). Same hatches still align with each other;
the absolute phase relative to the WCS origin may differ from the
pre-fix behaviour on small drawings.
Consumers that read `model.boundary` directly (hit_test, paper_canvas,
add_hatch round-trip) reconstruct WCS via `boundary[i] + world_origin`.
The hatch wgsl bind-group entry for binding 0 was bumped to
`VERTEX | FRAGMENT` because the vertex shader now reads `h.origin`.
The fragment-shader hatch LOD substitute + sub-pixel skip from e7675be
and the scissor plumbing from fbbac42 still work — those touched
different fields of the same struct.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
* io/xref.rs — replaced the 7-line "BlockRecord::is_loaded turned out to
be unreliable" rationale with a one-liner. The reverted experiment
lives in git history (e88a946, 0996b75).
* refedit::RefEditSession.insert_handle — set at construction but never
read; the "kept for future REFCLOSE DISCARD" TODO can come back via
git history when that feature lands.
* scene::mod — dropped the placeholder MeshModel re-export; nothing
outside `mesh_model` consumes the bare name and MeshLodSet is the
pipeline-facing type now.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
* helpers::wcs_to_ucs — UCS inverse transform with zero call sites.
* scene::Scene::compute_and_set_world_offset — never called; the load
path uses the free function `compute_world_offset` directly.
* tessellate::tessellate_mesh — never called; mesh tessellation goes
through `solid3d_tess`, not the truck Shell/Solid path.
* truck_tess::tess_to_mesh_model — orphaned with tessellate_mesh's
removal.
* MeshModel::WHITE / MeshModel::SELECTED — only used by the removed
tessellate_mesh.
* xattach::Step::FilePath variant — never constructed; XATTACH always
enters through `with_path` after the file picker. Replaced the Step
enum + prefilled_path field with flat `path` / `block_name` fields
and dropped the unreachable text-input flow.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Each item below was gated by #[allow(dead_code)] and has zero callers
across src/ — none of them are part of any public API consumed by
external crates (this is a binary, not a library):
* modules/insert/underlay_frames.rs + edit_aliases.rs — toolbar stubs
whose `tool()` registrars were never wired into the ribbon; the
parent mod.rs inlines its own include_bytes! for the SVGs, so the
files were orphan dead weight.
* ui/snap_popup.rs:snap_marker_color — never called.
* ui/ribbon/mod.rs:last_dropdown_cmd — never called.
* ui/scale_popup.rs:anno_scale_for_label — never called.
* ui/layers.rs:color_name_to_aci — inverse of aci_color_display
with zero call sites.
* linetypes.rs:name_list — never called.
* scene/pipeline/wire_gpu.rs:new_ghost — never called.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Wire pass already uses `WireModel.vp_scissor` to clip viewport-projected
geometry to its paper-space viewport rect; hatch / image / wipeout
passes drew across the whole canvas. When a future paper-space path
projects fills/images into a viewport, they would bleed past the
viewport frame.
Add `vp_scissor: Option<[f32; 4]>` to HatchModel and ImageModel
(mirroring WireModel), forward it through HatchGpu / ImageGpu, and add
per-pass `compute_*_scissors` / `set_scissor_rect` machinery. Factored
the wire-side scissor-projection math into a shared `project_scissor`
helper. Field defaults to None at every constructor site — no producer
sets it yet, so this is plumbing for the paper-viewport fill projection
that Phase 1.4 unblocks without changing current visual output.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Mirrored INSERTs reverse OCS handedness, but acadrust's explode used to
keep the original normal — making CCW-around-normal arcs and ellipses
sweep the wrong way. The fix lives in acadrust 7c711e9, which flips the
new normal when det < 0 and reprojects center/major_axis/angles into the
new OCS. H7CAD's fix_mirrored_arc workaround is no longer needed.
PolyfaceMesh and PolygonMesh were wireframe-only. They now render with
the same flat-color solid fill as Face3D entities.
- Add fill_tris: Vec<[f32;3]> to TruckEntity and WireModel
- PolyfaceMesh: fan-triangulate each face into fill_tris
- PolygonMesh: triangulate each grid quad into fill_tris
- tessellate.rs Lines branch: apply world_offset to fill_tris
- Face3DGpu::from_wires: collect fill_tris from all wires in addition
to Face3D key_vertices quads
- upload_face3d: pass all_wires so fill_tris are batched into one draw call
Viewport-projected wires now clip at pixel level to their viewport boundary.
- WireModel.vp_scissor: Option<[f32; 4]> — paper-space bbox set on projection
- WireGpu.vp_scissor carries it through to the draw loop
- Pipeline.compute_wire_scissors() converts paper→NDC→pixel each frame
- render() calls set_scissor_rect() per wire, reset after viewport group
- INTEGRATION_GAPS.md: Viewport ⚠️ → ✅, all 51 gaps resolved
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
LwPolyline PLINEGEN=0 (DXF default): emit SegmentedLines with NaN
separators between vertex-to-vertex segments; wire_gpu resets
arc-length to 0 after each NaN so linetype pattern restarts per vertex.
PLINEGEN=1: existing Contour path unchanged (continuous pattern).
WireModel gains plinegen field propagated through tessellate pipeline.
Solid3D/Region/Body: call SabReader::read() when parse_sat() returns
None due to binary SAB format (DWG files / newer AutoCAD exports).
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Subtracts the DXF header extents centroid (world_offset) from all coordinates
in f64 BEFORE casting to f32. This eliminates the ~0.5 m ULP error that occurs
at 4,000,000 m UTM coordinates and caused geometry to disappear on zoom-out.
- Scene: adds world_offset field + compute_and_set_world_offset() method
- tessellate.rs: threads world_offset through all f64→f32 conversions
(legacy_geometry, dimension_geometry, solid_wire_fallback, multileader)
- truck_tess.rs: to_local() helper already in place from prior session
- mod.rs: tessellate_entity() and entity_aabb() apply world_offset
- update.rs: compute_and_set_world_offset() called after doc load
- cmd_result.rs / solid3d_cmds.rs: pass correct offset to truck tessellators
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add `aabb: [f32; 4]` field to WireModel (world-space 2-D bounding box).
In tessellate_entity() set each wire's AABB from e.as_entity().bounding_box()
via new entity_aabb() helper; Insert sub-entities each get their own AABB.
Preview/interim wires and any entity returning a zero-extent default box get
UNBOUNDED_AABB so they are never pre-rejected.
Replace the chord-sphere heuristic in Snapper::wire_in_range() with a proper
AABB vs snap-circle overlap test. The new check is four scalar comparisons and
correctly handles closed curves (circles, arcs) which the chord-sphere approach
had to special-case.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Integrate NAVVCUBE, NAVBAR, PROPERTIES, FILETAB, LAYOUTTAB, TOOLPALETTES
and SHEETSET commands to toggle UI widgets at runtime. Add 15 new SVG icons
for view module tools previously using glyph fallbacks. Restyle all SVG
icons to use the established two-color scheme: #e0e0e0 for passive geometry,
#4cc9f0 for active/accent elements.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- REPORT opens GitHub new-issue page
- ABOUT opens a dialog window with version, OS and arch info + Copy Info button
- CHANGELOG opens GitHub releases page
- Fix Windows build: add windows-sys as target-specific dependency for PRINT command
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Arc rendering now respects the normal vector: when normal.z < 0 the
midpoint is placed on the clockwise side so the curve sweeps the right way
- Removed spurious .to_radians() / .to_degrees() round-trips in arc.rs
(angles are already stored in the unit the trig functions expect)
- apply_grip and apply_transform use consistent angle units
- normalize_insert_entity no longer converts arc angles; the old conversion
was only needed by the now-removed .to_radians() call in to_truck
- Added fix_mirrored_arc: swaps arc start/end angles when the INSERT has a
mirrored scale (x_scale * y_scale < 0) so exploded arcs curve correctly
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Redesign Insert ribbon tab with 6 groups matching screenshot layout:
Reference (Attach/Clip/Adjust large + Underlay Layers/Frames/Snap small),
Point Cloud (Attach), Block (Multi-View Block/Insert large + Create/Edit/Base small),
Attributes (Define/Edit large + Manage/Sync small),
Import (Import/Land XML), Content (Content Browser/Design Center)
- Remove Primitives group and dead box_prim/clear/cylinder/sphere modules
- Fix all compiler warnings with #[allow(dead_code)] on unused-but-intentional items
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Redesign View ribbon tab with 8 groups matching AutoCAD layout:
Viewport Tools (UCS Icon, ViewCube, Navigation Bar),
Navigate, Model Viewports (Viewport Configuration, Named, Join, Restore),
Visual Style (dropdown), Projection, Preset,
Palettes (Tool Palettes, Properties, Sheet Set Manager),
Interface (File Tabs, Layout Tabs, Tile Horiz/Vert, Cascade)
- Add Extract Data and Link Data tools to Annotate → Tables group
- Fix tab order to Home → Insert → Annotate → View → Manage via build.rs PRIORITY list
- Add 17 new SVG icons for all new commands
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
New StyleComboGroup RibbonItem renders a dropdown combobox for selecting
text style, dimension style, multileader style, or table style. Ribbon
groups in the Annotate tab now match the reference layout: each group
has a large tool on the left and a style combobox with tool rows on the
right.
Each combobox shows the active style name, opens a scrollable item list
on click, and has an optional "Manage…" row that fires the style manager
command (STYLE / DIMSTYLE / MLEADERSTYLE / TABLESTYLE).
Style state is synced from the document on every layer refresh via
sync_ribbon_styles(). RibbonStyleChanged message propagates selections
back to the acadrust document header and the active_mleader_style field.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
New dimension commands: QDIM, DIMEDIT, DIMTEDIT, DIMBREAK, DIMSPACE,
DIMJOGLINE with full command workflows and SVG icons.
New multileader commands: MLEADERADD, MLEADERREMOVE, MLEADERALIGN,
MLEADERCOLLECT with entity injection pattern for in-place editing.
Updated annotate ribbon: all tools exposed across Text, Dimensions,
Leaders, Tables, Markup, and Annotation Scaling groups. Added STYLE,
FIND, DIMSTYLE shortcut buttons.
Added `inject_picked_entity` to the CadCommand trait for commands that
need a cloned copy of the picked entity to modify (DIMTEDIT, MLEADERADD,
MLEADERREMOVE). Sentinel-based dispatch in cmd_result.rs handles
DIMBREAK, DIMSPACE, DIMJOGLINE, MLEADERALIGN, and MLEADERCOLLECT.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Picks 2+ profile entities (closed or open wires), builds ruled shells
between consecutive pairs via builder::try_wire_homotopy, caps closed
ends with planar faces, and tessellates the result into a Solid3D mesh.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Picks a profile (closed or open 2D entity) then a path entity
(Line or LwPolyline). For Line paths uses tsweep along the line
vector; for Polyline paths uses start→end as translation direction.
Closed profiles produce a capped Solid; open profiles a Shell.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
BOX, SPHERE, and CYLINDER build truck topology solids and tessellate
them into MeshModels stored alongside a Solid3D placeholder entity so
the GPU mesh pipeline renders them immediately.
EXTRUDE picks any closed 2D profile (Circle, LwPolyline, etc.),
attaches a planar face via try_attach_plane, and translational-sweeps
it (tsweep Face → Solid) along Z by the given height.
REVOLVE picks a profile, two axis points, and an angle (default 360°),
then rotational-sweeps the wire (rsweep) around the axis.
Three new CmdResult variants drive the operations:
CommitSolid3D, ExtrudeEntity, RevolveEntity.
Scene::layer_color() added to retrieve the active layer's RGBA color.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
REFEDIT picks an INSERT, extracts the block entities into model space
with the INSERT transform applied (translate + rotate + uniform scale),
and enters an editing session. Any normal modify command works on the
temporary entities.
REFCLOSE SAVE applies the inverse transform, replaces the block
definition, and rebuilds all derived caches (hatch/image/mesh), so
every INSERT of that block reflects the edits immediately.
REFCLOSE DISCARD removes the temp entities without changing the block.
Non-uniform-scale inserts are rejected with an error message.
RefEditSession is stored on DocumentTab; undo snapshots bracket the
begin and close operations.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
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 <[email protected]>
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 <[email protected]>