fix(ui): block scroll-wheel passthrough to orbit camera over the panel
Wheel-scrolling over the right-side egui panel was zooming the orbit camera instead of scrolling the panel. Root cause: ui_system set WantsPointer from ctx.egui_wants_pointer_input(), which delegates to is_pointer_over_egui() -> layer_id_at(). That lookup only walks egui's `areas` table. But this SidePanel is shown on the background layer of a hand-rolled root `Ui` (the bevy_egui 0.41 single-context SidePanel pattern) and never registers an Area, so layer_id_at() returns None over the panel and egui_wants_pointer_input() returns false even with the cursor squarely over it. WantsPointer stayed false, so orbit_controller let every MouseWheel event through. Confirmed via diagnostics: `over=false` on every frame while hovering the panel. First attempt — claiming the panel interior with ui.interact(Sense::hover()) — failed: interact registers a *widget*, not an *area*, so layer_id_at() still found nothing (verified: over stayed false). Fix: bypass egui's area heuristic entirely. Capture the SidePanel's InnerResponse and test the pointer position against its response.rect directly (a deterministic geometric check). Keep egui_is_using_pointer() so an in-progress slider/resize drag still claims the pointer even if the cursor momentarily exits the rect. wants.0 = pointer_in(panel_rect) || egui_is_using_pointer()
This commit is contained in:
parent
e779ad7bb7
commit
0a03c3a718
@ -180,7 +180,7 @@ pub fn ui_system(
|
||||
.layer_id(LayerId::background())
|
||||
.max_rect(ctx.viewport_rect()),
|
||||
);
|
||||
egui::Panel::right("controls")
|
||||
let panel_response = egui::Panel::right("controls")
|
||||
.default_size(300.0)
|
||||
.size_range(260.0..=400.0)
|
||||
.resizable(true)
|
||||
@ -253,7 +253,19 @@ pub fn ui_system(
|
||||
});
|
||||
});
|
||||
|
||||
// egui captures pointer when the cursor is over a window or being
|
||||
// interacted with. MUST stay last — load-bearing for orbit camera.
|
||||
wants.0 = ctx.egui_wants_pointer_input();
|
||||
// Decide whether egui should own the pointer this frame, so the orbit
|
||||
// camera can stand down. We can't rely on `ctx.egui_wants_pointer_input()`:
|
||||
// this SidePanel is rendered on the background layer of a hand-rolled root
|
||||
// `Ui` (the bevy_egui 0.41 single-context pattern) and never registers an
|
||||
// `Area`, so egui's `is_pointer_over_egui()` / `layer_id_at()` return `false`
|
||||
// even while the cursor is squarely over the panel — wheel scroll then leaks
|
||||
// straight through to the camera. Instead we test the pointer against the
|
||||
// panel's own response rect (a deterministic geometric check), and keep
|
||||
// `egui_is_using_pointer()` so dragging a slider/resize-handle still claims
|
||||
// the pointer even if the cursor momentarily leaves the rect.
|
||||
let panel_rect = panel_response.response.rect;
|
||||
let pointer_pos = ctx.input(|i| i.pointer.interact_pos());
|
||||
let over_panel = pointer_pos.is_some_and(|p| panel_rect.contains(p));
|
||||
let using = ctx.egui_is_using_pointer();
|
||||
wants.0 = over_panel || using;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user