From 7e0ac65d5589dbb08f152969b49e0cecc73a866c Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 13 Jul 2026 09:57:54 +0800 Subject: [PATCH] feat: full egui control panel + pointer routing --- src/camera.rs | 11 ++++++++++ src/render/plugin.rs | 1 + src/ui.rs | 51 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/camera.rs b/src/camera.rs index 97df929..0f1b863 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -24,6 +24,10 @@ impl Default for OrbitCamera { } } +/// Set by the UI system each frame; the orbit controller ignores input when true. +#[derive(Resource, Default)] +pub struct WantsPointer(pub bool); + impl OrbitCamera { /// Compute the camera eye position and an orthonormal basis (forward/right/up) /// in Bevy's right-handed Y-up coordinate system. The black hole sits at origin. @@ -50,11 +54,18 @@ impl OrbitCamera { } pub fn orbit_controller( + wants: Res, mut camera: ResMut, mouse: Res>, mut motion: MessageReader, mut wheel: MessageReader, ) { + if wants.0 { + // egui is using the pointer: drain events so they don't pile up, and ignore. + motion.clear(); + wheel.clear(); + return; + } if mouse.pressed(MouseButton::Left) { for ev in motion.read() { camera.yaw -= ev.delta.x * 0.005; diff --git a/src/render/plugin.rs b/src/render/plugin.rs index f8ce3a9..6fef76b 100644 --- a/src/render/plugin.rs +++ b/src/render/plugin.rs @@ -8,6 +8,7 @@ pub struct BlackHolePlugin; impl Plugin for BlackHolePlugin { fn build(&self, app: &mut App) { app.init_resource::() + .init_resource::() .init_resource::() .add_plugins(Material2dPlugin::::default()) .add_plugins(bevy_egui::EguiPlugin::default()) diff --git a/src/ui.rs b/src/ui.rs index 7a74539..24bba71 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -4,14 +4,51 @@ use bevy_egui::egui; pub fn ui_system( mut contexts: bevy_egui::EguiContexts, mut params: ResMut, + mut camera: ResMut, + mut wants: ResMut, ) { if let Ok(ctx) = contexts.ctx_mut() { - egui::Window::new("Controls").show(ctx, |ui| { - ui.add( - egui::Slider::new(&mut params.disk_brightness, 0.0..=3.0) - .text("Disk brightness"), - ); - ui.add(egui::Slider::new(&mut params.steps, 50..=600).text("Steps")); - }); + egui::Window::new("Controls") + .collapsible(true) + .default_pos([16.0, 16.0]) + .show(ctx, |ui| { + egui::CollapsingHeader::new("Camera") + .default_open(true) + .show(ui, |ui| { + ui.add(egui::Slider::new(&mut camera.distance, 3.0..=200.0).text("Distance")); + ui.add(egui::Slider::new(&mut camera.yaw, -3.14..=3.14).text("Yaw")); + ui.add(egui::Slider::new(&mut camera.pitch, 0.05..=3.09).text("Pitch")); + ui.add(egui::Slider::new(&mut camera.fov, 0.3..=2.0).text("FOV")); + }); + egui::CollapsingHeader::new("Accretion Disk") + .default_open(true) + .show(ui, |ui| { + ui.add(egui::Slider::new(&mut params.disk_inner, 1.5..=6.0).text("Inner radius")); + ui.add(egui::Slider::new(&mut params.disk_outer, 6.0..=40.0).text("Outer radius")); + ui.add(egui::Slider::new(&mut params.disk_tilt, 0.0..=3.14).text("Tilt")); + ui.add(egui::Slider::new(&mut params.disk_brightness, 0.0..=3.0).text("Brightness")); + ui.add(egui::Slider::new(&mut params.disk_rotation_speed, 0.0..=3.0).text("Rotation speed")); + }); + egui::CollapsingHeader::new("Doppler").show(ui, |ui| { + ui.checkbox(&mut params.doppler_enabled, "Enabled"); + ui.add_enabled(params.doppler_enabled, egui::Slider::new(&mut params.doppler_strength, 0.0..=3.0).text("Strength")); + }); + egui::CollapsingHeader::new("Renderer").show(ui, |ui| { + ui.add(egui::Slider::new(&mut params.steps, 50..=600).text("Steps")); + ui.add(egui::Slider::new(&mut params.render_scale, 0.5..=1.0).text("Render scale")); + }); + egui::CollapsingHeader::new("Background").show(ui, |ui| { + ui.add(egui::Slider::new(&mut params.star_intensity, 0.0..=3.0).text("Star intensity")); + ui.add(egui::Slider::new(&mut params.skybox_intensity, 0.0..=3.0).text("Skybox intensity")); + }); + egui::CollapsingHeader::new("Grid").show(ui, |ui| { + ui.checkbox(&mut params.grid_enabled, "Enabled"); + ui.add_enabled(params.grid_enabled, egui::Slider::new(&mut params.grid_density, 0.1..=4.0).text("Density")); + }); + }); + // egui captures pointer when the cursor is over a window or being interacted with. + wants.0 = ctx.egui_wants_pointer_input(); + } else { + wants.0 = false; } }