Commit Graph
23 Commits
Author SHA1 Message Date
Hakan Seven e94cbedaa2 fix(save): preserve 3D view and thumbnails
Persist camera, render state, and solid fallback geometry across saves. Generate previews from a clean live viewport and refresh recent-file thumbnails immediately.
2026-08-23 17:59:12 +03:00
Hakan Seven 15ab027d70 fix(scene): preserve viewport settings
Reuse full VPort records during camera and tile synchronization so
navigation cannot replace file-defined display state with defaults.

Honor image, ground, IBL, and sun-backed sky parameters in
background rendering.
2026-08-12 13:11:12 +03:00
Hakan Seven adb8ced8b5 feat(view): complete ZOOM options
Add command-line navigation modes and persistent wheel controls.\n\nRefs #412
2026-08-08 20:37:53 +03:00
Hakan Seven c45daeffb6 feat(render): add scene environment pipeline 2026-08-05 23:42:18 +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 e03e091b3c feat(annotation): integrate object contexts 2026-08-02 12:00:15 +03:00
Hakan Seven c9aab122f0 feat(find): add find and replace
Closes #583
2026-07-30 17:56:54 +03:00
Hakan Seven 3897fb2661 fix(viewports): fit extents per pane
Closes #554
2026-07-29 23:03:06 +03:00
Hakan Seven 00cc17ea55 fix(scene): isolate drawing-space state
Cancel stale interaction state across space changes and keep live previews and zoom extents in their active paper/model context.\n\nRefs #539\nRefs #540\nRefs #541
2026-07-28 18:51:20 +03:00
Hakan Seven 731df4a725 feat(cad): integrate standard codec coverage
Render, edit, query, select, and explode newly decoded standard entity variants. Pin acadifc de8d6b5 and preserve None color semantics.
2026-07-26 19:30:43 +03:00
Hakan Seven 12bf126646 perf: remove large drawing stalls
Keep resident geometry and GPU resources stable across edits, MSPACE zoom, and Model/Paper switches. Add unified PERF output for tracing remaining costs.
2026-07-25 13:34:48 +03:00
Hakan SevenandClaude Opus 4.8 2ff37b088b fix(camera): re-derive ortho near/far per frame so orbit never clips
The orthographic depth half-range was frozen at fit time and measured along
the fit-time eye direction. A 3-D drawing fitted straight-down (top view) got
a shallow depth span; orbiting only rotated the camera, never resized the
span, so the drawing's width loaded onto the eye axis and overran near/far —
clipping the model the moment it was tilted off top (#473).

Cache the model AABB on the camera and recompute the near/far depth from it
for the live eye direction every frame. This tracks orbit, viewcube snaps,
roll and restored views uniformly, and keeps the same tight, zoom-independent
depth precision (coincident solids / meshes / wires keep their draw order).
Falls back to the scalar half-range / distance-scaled span when no AABB is set.

Closes #473

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-24 14:57:16 +03:00
Hakan SevenandClaude Fable 5 ea860cab72 fix(view): ZOOM Extents fills the window at the real aspect (#364)
fit_to_bounds fitted the bounding box's circumscribed DIAGONAL into the
viewport height regardless of shape, so a wide drawing filled only a
small central patch. Fit against the actual viewport aspect instead —
required half-height = max(|y|, |x|/aspect) over the view-space corners
— and trim the border margin from 20% to 10%. ZOOM EXTENTS/ALL and
ZOOM WINDOW both pass the live pane aspect.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-21 23:09:37 +03:00
Hakan SevenandClaude Opus 4.8 251ad436d7 fix(viewport): frame model-documentation drawing views correctly
A floating viewport with a real saved view — a non-zero view target, as a model
documentation drawing view or a detail/section viewport carries — now uses that
view directly instead of running the median-cluster overlap test. That test
measured against the densest sub-cluster (a big symbol library beside the small
view geometry) and wrongly auto-fit these viewports onto the library. A fully
uninitialised view (target AND centre both zero) frames its saved origin and
stays empty rather than auto-fitting the whole model in; the auto-fit rescue is
kept only for a stale target=(0,0,0) paired with a non-zero pre-georeference
centre.

Also widen the restored-view ortho depth half-range (view_height ×4 → ×64): a
thin projection such as a section/side view has content far deeper than its
visible height (its cut plane sits ~half an object-depth from the view target),
so the tighter range clipped the view outline behind the far plane. Orthographic
depth precision is linear, so the wider range costs no z-fighting.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-20 21:11:30 +03:00
Hakan SevenandClaude Opus 4.8 b30f9b9741 feat(scene): draw nonprint light, camera and geo-location glyphs
Lights, camera views and the geographic-location marker had no on-screen
representation. Add display glyphs for all three:

- Lights render through a new EntityType::Light: a cone/flashlight for spot
  lights, a wire sphere for point lights, a sun for distant lights, sized in
  screen space (fixed-world fallback).
- Camera views (perspective VIEW records) and the GEODATA "daisy" marker are
  synthesized into the model-space resident wire set from the document, since
  they are not entities.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-19 22:15:40 +03:00
Hakan SevenandClaude Opus 4.8 1b60924bbe fix(view): show geometry far off the drawing plane
A benchmark drawing carrying a circle and an ellipse 800 km below its own
plane showed neither, and ZOOM Extents zoomed out to 800 km to find them.
Both come from sizing the view off the wrong axis.

Zoom and clipping answer to different extents and are now measured that
way: the zoom frames what the view actually shows, the extent across the
screen plane, while near/far span what lies along the eye direction.
Sizing both from the 3-D diagonal let one far-off Z drag the horizontal
zoom out with it. The two agree on a flat drawing, which is why it went
unnoticed.

A camera restored from a file's saved view keeps its pose, but nothing
had sized its near/far, so the projection fell back to a guess scaled
from the zoom distance — far too narrow when geometry reaches off the
plane, and the geometry was silently clipped away. It now takes the
drawing's own recorded extent.

$EXTMIN/$EXTMAX is untrustworthy for positioning — stale after an edit,
or the sentinel when the writer never computed it — which is why fit_all
scans entities instead. It is the right input here: too wide only costs a
little depth precision, too narrow deletes geometry, so the drawing's own
claim errs in the safe direction. It also costs nothing on open.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-15 22:21:38 +03:00
Hakan SevenandClaude Opus 4.8 9838cd6d83 fix(dxf): stop writing a duplicate *Active viewport (#319)
Opening a DXF whose active viewport is stored uppercase (*ACTIVE),
editing and re-saving produced a file with two full-window model-space
viewports — the file's own *ACTIVE plus a fresh *Active we add on save.
The reserved viewport name is case-insensitive, so the two didn't
collapse and other CAD apps drew them one on top of the other, which
read as the copied objects being linked / "reacting as one".

save_model_tiles_to_vports dropped existing active viewports with a
case-sensitive `name != "*Active"` filter, so an uppercase *ACTIVE
survived and sat next to the new entry. Route every *Active comparison
(save filter + camera/tile restore) through a case-insensitive
is_active_vport_name helper so the file's record is recognised and
replaced instead of duplicated.

Also bumps acadrust to #99f75fe (merged PR #1): the ASCII DXF writer now
emits shortest round-trippable floats instead of the full 16-digit
expansion, halving the round-tripped file size.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-09 22:36:00 +03:00
Hakan SevenandClaude Opus 4.8 b50921923f chore: post-merge cleanup for #287/#289
- Reword the two new explanatory comments to describe the behaviour on its
  own instead of citing another product.
- window_to_sheet: drop the unused window_min parameter (the caller already
  derives its coordinate offset from the returned min-corner position) and fix
  the doc comment to match what the function returns.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-06 01:22:10 +03:00
Kevin GriffinandClaude Fable 5 a3107d95e4 fix(view): exclude XLine/Ray display segments from ZOOM Extents (#284)
XLine/Ray tessellate as +/-1e6 display segments (entities/ray.rs), and
both fit_all outlier defenses miss them: the IQR reject passes because a
construction line through the drawing has its centroid at its base
point, inside the consensus cluster; and the per-point lim filter passes
because local_extent_max is computed once at document load and stays at
the 1e9 default for drawings created fresh in-app. The far endpoints
then poison the bounds and the view fits +/-1e6, shrinking real
geometry to a dot.

Exclude XLine/Ray wires from the extents up front (AutoCAD likewise
ignores infinite lines in ZOOM Extents), falling back to fitting their
base points when the drawing holds nothing else.

Regression tests verified to fail without the fix (camera distance
3,000,000) and pass with it.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-05 14:08:43 -07:00
Hakan SevenandClaude Opus 4.8 572e9aca01 fix(camera): keep ortho depth precision constant across zoom
The orthographic near/far span was ±1000x the camera distance, so
zooming out ballooned the depth range and collapsed z-buffer precision:
coincident solids, meshes and wires then flipped draw order (meshes drew
in front of solids only when zoomed out, correct order when zoomed in).

Size the depth half-range from the drawing's extent instead — the bbox
diagonal on fit_to_bounds, the view height on a restored saved view —
and hold it constant as the camera zooms, so precision no longer depends
on distance. Falls back to the old distance-scaled range when unset.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-02 01:23:27 +03:00
Hakan SevenandClaude Opus 4.8 ddf576765b fix(view): drop non-standard camera View record; restore from VPORT
OCS wrote an app-specific "OpenCADStudio_Camera_Model" entry to the VIEW
table and preferred it when restoring the model view. That record polluted
the file for other CAD programs and its DXF round-trip was broken, so a
drawing saved in TOP reopened from DXF at an isometric-ish angle.

The model view now persists and restores entirely via the standard *Active
VPORT entry (view direction / target / twist), which round-trips natively in
both DWG and DXF. The custom View record is no longer written; existing ones
in older files are left untouched. Paper space already used the standard
sheet viewport and keeps a read-only fallback for very old files.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-27 19:27:23 +03:00
Hakan SevenandClaude Opus 4.8 495b13ec4f refactor(viewport): migrate model-space tiling to iced pane_grid
Replace the custom model_tiles tiling with iced 0.14 pane_grid as the layout
source of truth, while paper-space floating viewports are left untouched (they
overlap/free-place, which pane_grid cannot model).

Each Model pane is its own shader widget rendering its camera into the pane
bounds; the renderer Primitive carries a base_slot so several shader widgets
share the type-keyed MultiPipeline storage on disjoint slots. A second pane_grid
of transparent mouse_areas (plus on_resize) layers above the crosshair overlay
to receive input — the overlay's Hidden cursor interaction otherwise levitates
the cursor and starves any layer beneath it. The active pane follows the cursor
(hover-activate), and grid / crosshair / UCS icon render per pane while the
ViewCube and render-mode picker stay on the active pane only.

Split / close / VPORTS presets and the VPort table round-trip now drive
pane_grid (guillotine reconstruction on load). Adds drag-to-swap via a controls
bar handle with a ghost-card preview, visible pane dividers from the pane_grid
split regions, a default model background of RGB(33,40,48), and removes all the
superseded custom-tile code.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-27 11:50:11 +03:00
Hakan SevenandClaude Opus 4.8 9b8ee94c0c refactor: rename mislabeled scene files to match contents
Two names collided with the pick subsystem and misdescribed their files:

- scene/hittest.rs -> scene/camera_ops.rs. Its contents are camera/view
  operations (zoom, fit-all, named-view restore, camera<->document sync,
  per-tile grid/snap), not hit-testing — the real screen-space hit-test
  lives in scene/pick/hit_test.rs.
- scene/pick/selection.rs -> scene/pick/selection_state.rs. It holds only
  the SelectionState struct; the name clashed with scene/selection.rs
  (the Scene selection operations).

Callers are unaffected (the crate::scene::SelectionState re-export path is
unchanged). No behavior change.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-26 23:45:16 +03:00