forked from 1b-agent/opencadstudio-upstream
fix(hover): drop the geometry-only pick cache — it served stale culled wires
hit_test_wires got a cache keyed on geometry_epoch alone (462d9b4), but
the underlying wire set IS view-culled (wires_for_block culls to
view_world_aabb). After zoom-in + edit, the cache pinned the set culled
to that close-up view; zooming back out, blocks that had been off-screen
were missing from the pick set, so hover/selection stopped working on
them until the next geometry change.
Revert to the camera-keyed entity_wires_arc for picking — it re-culls
when the view changes. The actual 0.5.1 hover regression fix (hatch
rebuild/re-upload on rollover) stays.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
462d9b4b66
commit
ed29933d87
1 file changed
+4
-25
+4
-25
@@ -633,13 +633,6 @@ pub struct Scene {
|
|||||||
/// invalidates the cull-dependent wire list as well as a geometry change.
|
/// invalidates the cull-dependent wire list as well as a geometry change.
|
||||||
/// Uses `Arc` so `build_primitive()` avoids a full Vec clone during navigation.
|
/// Uses `Arc` so `build_primitive()` avoids a full Vec clone during navigation.
|
||||||
wire_cache: RefCell<Option<((u64, u64), Arc<Vec<WireModel>>)>>,
|
wire_cache: RefCell<Option<((u64, u64), Arc<Vec<WireModel>>)>>,
|
||||||
/// Camera-invariant full wire set for **picking** (Model layout), keyed on
|
|
||||||
/// `geometry_epoch` alone. The wires are world-space, so a pan/zoom must not
|
|
||||||
/// re-tessellate the whole un-culled model just to hit-test the next mouse
|
|
||||||
/// move (seconds on a 100k-entity drawing). Built once per geometry change
|
|
||||||
/// and reused across every camera move; a slightly stale curve tol is
|
|
||||||
/// harmless for an 8 px pick threshold.
|
|
||||||
hit_wire_cache: RefCell<Option<(u64, Arc<Vec<WireModel>>)>>,
|
|
||||||
/// Per-Model-tile cached tessellation. Each tile has its own camera
|
/// Per-Model-tile cached tessellation. Each tile has its own camera
|
||||||
/// (live for the active tile, stored snapshot for the others), so
|
/// (live for the active tile, stored snapshot for the others), so
|
||||||
/// LOD / frustum culling has to run independently — the shared
|
/// LOD / frustum culling has to run independently — the shared
|
||||||
@@ -827,7 +820,6 @@ impl Scene {
|
|||||||
block_epoch: GEOMETRY_EPOCH.fetch_add(1, Ordering::Relaxed),
|
block_epoch: GEOMETRY_EPOCH.fetch_add(1, Ordering::Relaxed),
|
||||||
selection_generation: 0,
|
selection_generation: 0,
|
||||||
wire_cache: RefCell::new(None),
|
wire_cache: RefCell::new(None),
|
||||||
hit_wire_cache: RefCell::new(None),
|
|
||||||
model_tile_wire_cache: RefCell::new(HashMap::default()),
|
model_tile_wire_cache: RefCell::new(HashMap::default()),
|
||||||
sort_cache: RefCell::new(None),
|
sort_cache: RefCell::new(None),
|
||||||
draw_depth_cache: RefCell::new(None),
|
draw_depth_cache: RefCell::new(None),
|
||||||
@@ -2091,23 +2083,10 @@ impl Scene {
|
|||||||
/// only — paper-space entities are NOT interactive.
|
/// only — paper-space entities are NOT interactive.
|
||||||
pub fn hit_test_wires(&self) -> Arc<Vec<WireModel>> {
|
pub fn hit_test_wires(&self) -> Arc<Vec<WireModel>> {
|
||||||
if self.current_layout == "Model" {
|
if self.current_layout == "Model" {
|
||||||
// Camera-invariant pick cache: reuse the full wire set across pan /
|
// entity_wires_arc is culled to the current view and keyed on the
|
||||||
// zoom (world-space wires don't change), rebuilding only when the
|
// camera, so it re-culls when the view changes — picking must reach
|
||||||
// geometry changes. `entity_wires_arc` itself keys on the camera,
|
// entities that scroll into view after a pan/zoom.
|
||||||
// so calling it on every mouse move after a navigate would
|
return self.entity_wires_arc();
|
||||||
// re-tessellate the whole un-culled model — the large-file hover
|
|
||||||
// stutter. Gate on `geometry_epoch` here instead.
|
|
||||||
{
|
|
||||||
let c = self.hit_wire_cache.borrow();
|
|
||||||
if let Some((g, ref arc)) = *c {
|
|
||||||
if g == self.geometry_epoch {
|
|
||||||
return Arc::clone(arc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let arc = self.entity_wires_arc();
|
|
||||||
*self.hit_wire_cache.borrow_mut() = Some((self.geometry_epoch, Arc::clone(&arc)));
|
|
||||||
return arc;
|
|
||||||
}
|
}
|
||||||
let layout_block = self.current_layout_block_handle();
|
let layout_block = self.current_layout_block_handle();
|
||||||
match self.active_viewport {
|
match self.active_viewport {
|
||||||
|
|||||||
Reference in new issue
Block a user