fix(scene): correct view_world_aabb space + guard initial render

Two bugs in the new frustum culler that left the GUI rendering nothing
on file open:

1. `cam.target` is already in **local** f32 space — `fit_to_bounds`
   populates it from local wire coords — so subtracting `world_offset`
   again pushed the view rect to the negated centroid, with the actual
   geometry far outside.
2. The first call to `entity_wires()` after open comes from `fit_all()`
   itself, while `camera_generation` is still 0 and the camera is at
   its default origin. Culling against that rect discarded every wire
   → fit_all saw an empty list → camera never moved → the user-visible
   render stayed empty forever.

`view_world_aabb` now returns `None` until `camera_generation > 0`
(letting fit_all collect a real extent), then derives the view rect
directly from `cam.target` in local space.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
HakanandClaude Opus 4.7 committed 2026-05-14 14:02:48 +03:00
1 parent 78cbb5570e
commit 8d5ecdef51
1 file changed
+12 -5
+12 -5
View File
@@ -343,16 +343,23 @@ impl Scene {
// top-level paper canvas is small enough not to need it.
return None;
}
// Until the first explicit camera move (typically `fit_all()` after
// file open), the camera sits at the default origin while geometry
// lives at large local offsets — culling against the default rect
// would discard everything and starve fit_all of points to fit to.
if self.camera_generation == 0 {
return None;
}
let cam = self.camera.borrow();
let aspect = self.last_render_aspect.get().max(0.01);
let h = cam.ortho_size();
let w = h * aspect;
// Generous margin: in 3D / perspective the projection actually covers
// more than the orthographic-equivalent rect, and pan inertia briefly
// moves geometry past the visible edge before camera_generation bumps.
let margin = 1.25_f32;
let cx = (cam.target.x - self.world_offset[0] as f32) as f32;
let cy = (cam.target.y - self.world_offset[1] as f32) as f32;
// `cam.target` is in the same local f32 space as emitted wire points
// (fit_to_bounds populates it from local wire coords). No further
// `world_offset` subtraction is needed.
let cx = cam.target.x;
let cy = cam.target.y;
Some([
cx - w * margin,
cy - h * margin,