Commit Graph
263 Commits
Author SHA1 Message Date
Hakan SevenandClaude Opus 5 188d1a9ccb fix(dim): draw a dimension from the picture it carries
A DIMENSION references the block "that contains the entities that make up
the dimension picture", and that block is the picture: AutoCAD requires
it and draws it, BricsCAD draws it when present and only renders from the
dimension variables when it is missing. OCS re-derived the picture from
DIMVARS every time and ignored the block entirely.

That works while a style agrees with what the drawing actually drew. A
Revit-exported schedule here does not: its style stores DIMTXT already in
drawing units beside a DIMSCALE meant to scale it, so the text came out
three hundred times too tall, and each dimension carries a DIMFXL
override that is likewise already in drawing units, so the extension
lines ran nearly a million units past the points they measure.

Neither is guesswork about units now. The block holds the geometry the
drawing was authored with, so it is drawn: the contents are already in
world space and the block's base point is the origin, and the identity
instance that carries them exists only to reuse the scene graph's
ByBlock / layer-0 colour resolution. Every wire answers to the dimension,
so a pick still selects the dimension rather than one of its pieces.
Re-deriving stays as the fallback for a dimension with no block.

Annotative dimensions keep the old path: their several representations
are separate blocks and choosing between them is what the annotation
machinery already does, while the doctrine above assumes one picture.

A picture is only good while its inputs hold, so it is dropped when they
change: editing a dimension's properties, and saving the dimension style
it is drawn with. Entity edits already dropped it.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-08 02:44:30 +03:00
Hakan SevenandClaude Opus 5 523b85f42b fix(units): make the units selector reach what it names
The status-bar units button wrote INSUNITS, which nothing on screen reads.
INSUNITS only tells the drawing how to scale content arriving from
elsewhere, so picking a unit relabelled the drawing and changed nothing
visible — the selector looked broken because the variable it moved was
invisible.

Point the button at LUNITS instead, the setting that decides how every
coordinate and distance is written, and give the three questions the word
"units" runs together a place each:

- The button offers the five length formats, each shown beside a sample of
  itself, so Engineering and Architectural are told apart by sight.
- UNITS / DDUNITS opens a real dialog: length and angle format and
  precision, the direction angle zero points, whether positive angles run
  clockwise, and the insertion unit. Its sample comes from the same
  formatters the drawing uses, so it cannot drift from the readout.
- DWGUNITS converts. Model geometry, viewport framing, the header's length
  defaults and each dimension style's scale all move together in one undo
  step; paper space is left alone, since the sheet is still the same sheet.
  Locked layers are converted too — a half-converted drawing would be at
  two scales at once.

The coordinate readout formatted at four decimal places whatever the
drawing asked for; it now goes through the same format_length the
properties panel uses. That made the angle formats reachable in turn, so
degrees-minutes-seconds now carries the d/'/" marks that say which
convention it is, and surveyor's units are written at all.

Typed input is still plain decimal: a length the readout writes as
5'-6 1/2" cannot yet be typed back. ANGBASE and ANGDIR are stored but not
yet applied to displayed directions.

Closes #668

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 19:59:09 +03:00
Hakan SevenandClaude Opus 5 26b4f29a13 feat(options): offer the file association in Options
Registering as the .dwg/.dxf handler was reachable only by typing
FILEASSOC, which is also the only thing that installs the icons the
desktop shows — so a user with no reason to know the command had no way
to arrive at either.

The checkbox makes the same two calls the command does, so the stored
setting and the actual registration cannot drift apart. A registration
the system refuses puts the checkbox back rather than leaving it showing
a state that is not true.

The line under it says the icons come with it, since that is what sends
people looking for this in the first place.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 17:51:06 +03:00
Hakan SevenandClaude Opus 5 36e328f7d7 feat(layers): add LAYTRANS to translate layers onto a standard
Drawings arrive from elsewhere carrying someone else's layer names, and
folding them into a set of house layers meant renaming and merging by
hand, one layer at a time.

LAYTRANS reads a layer set out of another drawing and moves this one onto
it. Given a file it maps every name the two already share and translates
at once, which is all most incoming drawings need. Bare, it opens a
translator: the drawing's layers on one side, the loaded set on the
other, mappings built up between them and applied only on Translate, so a
mapping can be reconsidered and the whole translation is a single undo
step. Mappings can be saved and read back, objects can be forced to
ByLayer so the target layer's properties are what actually shows, and the
result can be written out as a log.

The move itself is the one LAYMRG already made for a single pair, so
LAYMRG now goes through it too rather than keeping its own copy.

Three things fell out for free or nearly so. A standards file is a
drawing, so .dws and .dwt need nothing but a place in the file filter.
The entity list is flat and holds block definitions, so objects inside
blocks travel with everything else instead of being stranded on a layer
that no longer exists. And a target layer that this drawing already has
is left alone: the drawing has an opinion about it, and restyling it
would reach past what was asked for -- only newly created targets take
the standard's properties.

Mappings are saved beside the drawing rather than inside a DWS. That is
where AutoCAD keeps them, but putting them there would mean inventing a
place in the drawing that nothing else reads back.

Closes #624

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 16:51:15 +03:00
Hakan SevenandClaude Opus 5 f7590b1aa8 feat(plugin-api): let add-ons ask for a visual style by name
Removing the binary wireframe event left add-ons with no way to set a
visual style except by spelling out a command string. Give them the
intent back, in the vocabulary everything else now speaks.

The name is carried as text rather than the render-mode type: this crate
is dependency-free by default and only pulls acadrust in behind the host
feature, which is not a weight to add to the manifest contract for one
enum. The host resolves it against the same list its ribbon, its picker
and its commands read, so an add-on can offer exactly the styles the
application does and no others. An unknown name says so and lists the
ones that exist, from that same list.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 14:29:01 +03:00
Hakan SevenandClaude Opus 5 b5a1146966 feat(view): one list of visual styles behind every way of choosing one
The ribbon offered four styles and dispatched each one's id as a command.
Two of those ids were not visual-style commands: "Shaded" carried SOLID,
which draws a 2D filled polygon, so choosing it started a draw command;
"Hidden" carried HIDDEN, which matched nothing at all, so it did nothing.
The intent had been for the button to fire its tool's event, but the
dropdown never reads one -- it dispatches the id.

Behind that sat two generations of the same feature. The render-mode
picker offered the seven styles a viewport can actually be drawn in;
everything else -- the ribbon, VSCURRENT, SHADEMODE, VISUALSTYLES and a
handful of bare verbs -- went through a binary wireframe-or-shaded flag
that could only approximate them, reporting "Hidden (shown shaded)" and
"X-Ray (shown as wireframe)" when asked for something it had no way to
draw. Four descriptions of one choice, each drifting on its own.

There is one list now. Each style names itself once -- mode, label, icon,
and the command that applies it -- and the ribbon, the picker, the
VISUALSTYLES verb and the interactive prompt all read from it, down to
the line that lists the choices, so what is offered cannot disagree with
what works. Keywords are the render modes' own names, since there is one
set of styles left to name.

The binary path is gone rather than kept alongside: its message, its
module event, the tool definitions that produced it, the ribbon's
special-cased highlight arms, the bare style verbs and the older keyword
spellings. X-Ray goes with it -- no render mode draws one, and it was
already coming out as a plain wireframe. Three files that had been left
holding a single icon constant each fold into the list.

Note: ModuleEvent::SetWireframe leaves the plugin API with it.

Closes #621

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 14:15:59 +03:00
Hakan SevenandClaude Opus 5 5c5c7606a1 feat(select): offer the selection modes at "Select objects"
Only Previous and Last were on offer, so Window, Crossing, Fence, the two
polygons and All could not be reached at all -- and with no keyboard to
type them into, the buttons were the only way in.

Window and Crossing fix the sense of the next box. Dragging derives that
from the direction the corner travels and would overwrite it the moment
the corner moved, so the derivation stands down while a keyword holds it.
Add and Remove decide what a pick does for the rest of the round: Remove
subtracts the way Shift already does, rather than through PICKADD, which
decides whether a pick *replaces* the set and so would have wiped
everything gathered so far. Both are dropped when the next command
starts, since neither outlives the selection that asked for them.

Fence and the polygons are picked point by point, which TRIM and EXTEND
already ask for. That gesture -- the points, the rubber-banded dashed
preview, whether the path closes -- moves into one place both bind to,
and the two preview builders duplicated in trim.rs go with it.

A fence is not the polygon test with crossing set: that closes the point
list and counts whatever lies inside, so a line drawn past a row of
objects would take everything behind it too. It gets a hit test that only
counts a real intersection, and skips the area-based geometry entirely.

The lasso gathered its hits from wires, hatches, block hatches, meshes and
block meshes inline; the new modes need the same list, and a second copy
would drift. Both now come through `Scene::path_hit_handles`.

Closes #596

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 13:32:11 +03:00
Hakan SevenandClaude Opus 5 0af6b470ed refactor(snap): measure typed distance along the guide that is drawn
Extension answered "which acquired ray is this snap on?" twice, from two
different tests: the overlay picked its guide by off-ray distance in
screen pixels, while typed-distance entry re-searched the tracking set in
world space. Two tests can disagree, and the ways they disagree are both
bad -- a guide on screen that typing ignores, or a distance running off
along a ray the user cannot see. The second search could also come up
empty on its own, since only four acquisitions are kept and the oldest is
dropped as new ones arrive.

Ask once. The search that draws the guide now also reports the endpoint it
drew from, the snap carries it, and typed distance reads the ray straight
off that -- the direction is just the way from the endpoint to the snap,
which sits beyond it by construction. The screen-space test stays the only
one, which is what the guide wanted anyway: it stays scale-independent
where a world test would not.

Also correct the tracking-point doc: it claims XZ with Y=0, but
`edge_dirs_at` builds every direction from X/Y with Z zeroed and the rays
follow it.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 11:29:15 +03:00
Hakan SevenandClaude Opus 5 b8f9727a27 fix(grip): stop double-offsetting the UCS grip snap marker
The extension anchors needed the same pane-to-canvas lift the snap
marker already got, but the block that added it was placed next to the
one that was already there rather than merged into it, so `screen` took
the tile origin twice. A single full-canvas tile has no origin to add, so
it only shows once the viewport is split. Fold the anchors into the
existing block.

Also require the ray to pass through the snapped point before offering it
as a distance reference. Only four acquisitions are kept and the oldest is
dropped as new ones arrive, so the ray that produced a snap can be gone by
the time a distance is typed; picking the nearest survivor unconditionally
sent the point off along an unrelated ray instead of falling back to plain
point input. `extension_snap` projects onto the ray in exact f64, so the
tolerance only has to clear rounding, scaled with the coordinate to hold at
UTM magnitudes.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-07 11:22:04 +03:00
gianlucafiore 62457be90e Support tracking and direct distance input for grip editing 2026-08-06 23:35:58 -03:00
Karim Jerbi 8f009d0058 feat(insert): add docked block palette
Add a searchable block palette with previews, file import, collision-safe nested definitions, and dependency/table-record import. Keep palette thumbnails current across drawing switches and block-definition edits.
2026-08-06 11:02:52 +03:00
Hakan Seven 67a767e23b fix(view): pause hover during navigation 2026-08-06 00:21:44 +03:00
Hakan Seven afc94dce13 feat(qselect): expand filter workflow
Refs #511
2026-08-05 13:40:53 +03:00
Hakan Seven e07f4f959b fix(view): preserve projection framing
Use full 3D bounds to derive a safe perspective eye distance without changing the camera target, orientation, or field of view.

Refs #502
2026-08-05 12:47:46 +03:00
Hakan Seven deaecdfb1e fix(ribbon): mask tools on start
Refs #494

Refs #507
2026-08-05 00:52:52 +03:00
Hakan Seven b92b8df997 fix(trim): handle lasso and box selection
Keep selection gestures in the active trim flow so crossed segments are modified instead of selected.\n\nRefs #487
2026-08-05 00:26:29 +03:00
Hakan Seven 474bfcc7db fix(input): restore arrow key navigation
Route editor and command-line arrows by active context and recall successfully dispatched commands.\n\nRefs #485
2026-08-05 00:08:35 +03:00
Hakan Seven 657d023fb7 feat(ucs): integrate coordinate systems
Route coordinate input, geometry creation, transforms, properties,\nviews, and viewport persistence through a shared working plane.\n\nRefs #484
2026-08-04 23:17:54 +03:00
Hakan Seven b1d55c6a7e feat(view): add visual style previews
- preview render modes on hover without committing
- distinguish 2D and 3D wireframe fill and depth behavior

Refs #483
2026-08-04 21:23:25 +03:00
Hakan Seven 7c893d8f5f feat(ui): refine drawing tabs
Use theme-driven active and hover states, integrate close controls, and keep tab spacing stable across drawing states.

Refs #481
2026-08-04 19:04:59 +03:00
Hakan Seven 9cf0c9f945 fix(ui): refine command line and clipboard
- preserve command history colors after reopening
- remove collapsed command bar residue and split the unsaved prompt
- read system text when the drawing clipboard is empty

Refs #467
Refs #468
Refs #470
2026-08-04 18:53:08 +03:00
Hakan Seven d1f9055901 feat(ui): refine ribbon and view navigation 2026-08-04 18:21:52 +03:00
Hakan Seven 675538eb8d fix(layers): disable redundant set current
Refs #459
2026-08-04 17:37:19 +03:00
Hakan Seven c9550b48f9 feat(properties): refine quick properties
- Keep the floating panel near the selection and inside the viewport
- Persist the toggle and hide the panel without a selection
- Show only Material in 3D Visualization
2026-08-04 17:32:06 +03:00
Hakan Seven b0806679c9 feat(command-line): resize history panel
Refs #456
2026-08-04 16:54:59 +03:00
Hakan Seven 539d83de47 feat(grips): improve direct editing
Refit arcs from fixed control points and highlight hovered grips.
Let Lengthen preview from the cursor or accept a typed distance.
2026-08-04 16:27:03 +03:00
Hakan Seven b744d4bf2d fix(viewport): align picks in oblique views
Project cursor rays directly onto the active drawing plane so previews
and committed points remain under the pointer.

Refs #429
Refs #452
2026-08-04 15:58:53 +03:00
Hakan Seven 429d2eb06b feat(ui): refine about dialog
Use intrinsic modal sizing and present platform details in a balanced layout.\n\nRefs #450
2026-08-04 15:53:34 +03:00
Hakan Seven 2f86bfde8e feat(input): add editable shortcut table
Persist all active bindings and route keyboard events through the configured table.\n\nRefs #449
2026-08-04 15:35:06 +03:00
Hakan Seven 4be8d9735c feat(ui): add dockable properties panel
Preserve panel width across left/right docking and persist resize, position, and auto-collapse preferences.

Refs #348
Refs #650
2026-08-04 13:46:02 +03:00
Hakan Seven f6b9d6514e feat(plot): add Print All workflow 2026-08-04 11:29:11 +03:00
Hakan Seven 5662e07303 feat(area): support multi-object selection 2026-08-04 00:01:12 +03:00
Hakan Seven 48332ee807 feat(area): add object and aggregate modes
Mesh-backed measurements need cached surface metrics. Keep shared loop collection available in web builds.
2026-08-03 22:31:20 +03:00
Hakan Seven 53cf31f33d feat(web): unify fonts and refine viewcube
Preload one language-aware font resource across the interface, drawing text, and navigation labels.\n\nRender the navigation cube, ring, outlines, and labels through a 4x MSAA target.
2026-08-03 15:28:51 +03:00
Hakan Seven 9e90e50662 feat(io): add user-approved recovery 2026-08-03 12:47:48 +03:00
Hakan Seven 25515fa33c feat(styles): overhaul style managers
Unify editor layouts, live previews, comparisons, read-only behavior, and localized controls across all named style managers.

Refs #629
2026-08-03 02:01:47 +03:00
Hakan Seven d06a1022f2 fix(input): handle @/# coordinate modes 2026-08-02 23:32:54 +03:00
Hakan Seven 3e6693b93f feat(locale): localize full interface 2026-08-02 22:09:25 +03:00
Hakan Seven b90b3e3ecf feat(locale): add Fluent translations
Default to the platform language with persisted overrides across native and web builds.

Refs #630
2026-08-02 18:53:38 +03:00
Hakan Seven f3f1cb4a0f fix(grip): honor drafting constraints
Refs #620
2026-08-02 16:15:35 +03:00
Hakan Seven e03e091b3c feat(annotation): integrate object contexts 2026-08-02 12:00:15 +03:00
Hakan Seven 6c62daf260 fix(plot): match PDF output to viewport
Refs #618
2026-08-01 20:05:38 +03:00
Hakan Seven 90a5495601 Merge branch 'codex/issue-618-plot-parity' 2026-08-01 19:35:15 +03:00
Hakan Seven 380cc4c9a8 fix(plot): align layout output with viewport
Keep nested model hatches, PAT origins and dots, and Layout lineweight scaling consistent across screen and vector output.\n\nRefs #618
2026-08-01 19:29:57 +03:00
Hakan Seven dccaf95f49 feat(draw): continue paths on initial Enter
Start LINE, PLINE, ARC, and SPLINE from the latest path endpoint when Enter accepts the first point. Fall back to the active UCS origin.\n\nRefs #610
2026-08-01 19:09:19 +03:00
Hakan Seven 796d7d91d0 fix(ui): auto-size modal dialogs
Measure dialog content before fill layout so fields stay visible.\nKeep the MText preview width tied to its toolbar width.\n\nRefs #608
2026-08-01 18:24:05 +03:00
Hakan Seven 1cf2b700ce fix(polyline): place added vertices live
Keep new vertices in grip placement until click and restore the original entity on Escape. Correct reverse direction and segment metadata across polyline variants.\n\nRefs #610
2026-07-31 23:36:07 +03:00
Hakan Seven f0c1be0db1 fix(plot): correct layout hatch output
Keep Layout output on the selected physical sheet and preserve hatch lineweights and plot styles through paper, viewport, and nested block paths.\n\nRefs #607
2026-07-31 23:08:41 +03:00
Hakan Seven a66940a3f0 feat(grip): support multi-grip editing
Refs #606
2026-07-31 22:05:30 +03:00
Hakan Seven a418710cbd fix(plot): align direct output with preview
Refs #607
2026-07-31 22:05:26 +03:00