Improve the selection-cycling list box so overlapping objects can be
identified at a glance:
- Add a color swatch per row showing the object's effective drawn color
- Show the layer name right-aligned next to the element type
- Size the popup to fit its content with consistent padding
Widen render_style_for_viewport visibility from scene-internal to
crate-wide so the view layer resolves the same color the renderer uses.
Persist camera, render state, and solid fallback geometry across saves. Generate previews from a clean live viewport and refresh recent-file thumbnails immediately.
Keep all solid geometry GPU-resident during navigation. Use vertex-rate instancing, compact untextured vertices, vertex-cache ordering, and cached silhouette sources without culling geometry.
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.
Share source buffers across block placements and render nested content with GPU instance transforms.\n\nChunk silhouettes and compact mesh material data so large drawings stay under device buffer limits and remain responsive.
A paper layout painted its whole canvas in the page colour, so the sheet
had no visible edge — zooming out never reached one, because the surround
was the same colour as the page. Floating viewports then painted
themselves black over it.
Both come from the same idea, that a viewport's canvas is a colour it can
be handed. What lies behind a viewport depends on what the viewport is:
- The full-canvas sheet shows the desk. `paper_bg_color` is the page, and
the page is a bounded rectangle `paper_sheet_fill` already draws; using
it for the canvas too erased the boundary between them. The desk is now
its own colour, defined once in the scene and read by both the widget
and the renderer, so the two cannot drift apart.
- A floating viewport sits on that sheet and must paint no canvas at all.
Handing it a transparent one does not work: the background shader
returns an opaque colour whatever alpha it is given, so alpha zero came
out black. Skipping the pass is the only way to ask for see-through, so
`skip_background` now suppresses both the clear and the pass. It is part
of the frame signature too — without that, a cached frame would keep
showing the canvas the flag was just turned off for.
Shading and fog still blend toward what is behind a floating viewport,
which is the page, so the uniform keeps that colour even though nothing
paints it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Keep storage fast paths on capable adapters and use packed or texture fallbacks only when device limits require them.\n\nCompact mesh-edge varyings to avoid WebGL shader rejection.
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
Avoid full document, cache, and GPU rebuilds for entity deltas so add, delete, history, selection, and live polyline edits stay responsive on large drawings.
Keep resident wires, draw depths, GPU slabs, and edit history incremental across entity changes. Defer rollover work to avoid cursor jumps on dense drawings.
Replace full-document snapshots with Arc first-touch deltas and batch cache invalidation. Reuse interaction and GPU category caches across unrelated edits.
entity_wires() returns the memoized Arc instead of a per-call deep copy;
MESH entities over 50k vertices ship no per-vertex snap/key tables
(matching PolyfaceMesh/PolygonMesh); the Face3D/other render split
caches a None marker and uses the base set directly when there is no
Face3D wire; test fix for the depth-map BlockCache::build signature.
Reviewed: correctness sound — wire AABB comes from entity_aabb (not
key_vertices) so large meshes stay selectable; snap consumers are
empty-guarded; the Arc/strong_count reasoning for try_resident_patch
holds. One consistent pre-existing quirk noted (auto_fit_viewport
centroid excludes tableless meshes, as Poly*Mesh already do).
Fill triangles (DIMTFILL backgrounds, MLEADER masks, hatches) carry the
entity's draw-order rank, but SDF glyph quads were pushed at neutral 0.0
— any entity in the front half of the draw order had its own background
fill painted over its text. gather_text_verts now adds the host wire's
wire_draw_depth to each glyph: a text background lands at the same
biased depth (glyphs draw after fills and win the LessEqual test), and
text respects draw order against other entities' fills too.
The #403 glyph-reuse fast path gains a rank-stability gate: adding or
removing an entity shifts every sibling's bias (the rank denominator
changes), so reuse is only safe across all-Modified edits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The per-epoch Face3D/other split cloned every wire into two owned lists
even when the face3d list came out empty — for pure 2-D drawings and
mesh imports (#358) the 'other' list was a wire-for-wire copy of the
entire base set, held resident in split_cache alongside the original.
Cache None as an 'everything is other' marker and hand the render the
base set itself for that frame. The base Arc is deliberately not stored
in the cache: try_resident_patch can only apply an incremental patch
while the resident Arc is uniquely held, so pinning it there would
silently degrade every edit to a full rebuild.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paper layouts gather glyphs for the sheet and each content viewport in
one frame; the single-slot last_sdf_text handed the first source's
glyphs to the rest, hiding every model-space text entity inside
viewports (regression in aea1fd2). Key the reuse by render source, and
invalidate on Tolerance/ATTDEF edits and complex-linetype hosts too.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>