Fix awkward mouse conflict issues between egui and the engine

This commit is contained in:
reo 2025-12-13 18:23:52 +03:00
parent f5a16213fa
commit 8041c7e01d
6 changed files with 53 additions and 4 deletions

View file

@ -106,6 +106,11 @@ impl System for MainSystem {
character_pos = tr.translation; character_pos = tr.translation;
} }
egui_queue.queue(move |egui_ctx| { egui_queue.queue(move |egui_ctx| {
// disable text selection on all labels.
egui_ctx.style_mut(|style| {
style.interaction.selectable_labels = false;
});
egui::Window::new("Debug").show(egui_ctx, |ui| { egui::Window::new("Debug").show(egui_ctx, |ui| {
ui.label("Hello World!"); ui.label("Hello World!");
ui.label(format!("Frame Delta: {:.3}", time_ctx.frame_dt)); ui.label(format!("Frame Delta: {:.3}", time_ctx.frame_dt));

View file

@ -42,6 +42,7 @@ impl System for MenuSystem {
}); });
} }
fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) {
// The menu is toggled by pressing the escape key // The menu is toggled by pressing the escape key
let input = res.get::<InputState>().unwrap(); let input = res.get::<InputState>().unwrap();
@ -63,18 +64,21 @@ impl MenuSystem {
.next() .next()
.unwrap(); .unwrap();
let window = res.get::<PlatformContext>().unwrap().window.lock().unwrap(); let pctx = res.get::<PlatformContext>().unwrap();
let window = pctx.window.lock().unwrap();
match *menu_state { match *menu_state {
MenuState::Open => { MenuState::Open => {
*menu_state = MenuState::Closed; *menu_state = MenuState::Closed;
window.set_cursor_grab(CursorGrabMode::Confined).or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)); window.set_cursor_grab(CursorGrabMode::Confined).or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked));
window.set_cursor_visible(false); window.set_cursor_visible(false);
pctx.should_egui_receive_input_events.set(false);
}, },
MenuState::Closed => { MenuState::Closed => {
*menu_state = MenuState::Open; *menu_state = MenuState::Open;
window.set_cursor_grab(CursorGrabMode::None); window.set_cursor_grab(CursorGrabMode::None);
window.set_cursor_visible(true); window.set_cursor_visible(true);
pctx.should_egui_receive_input_events.set(true);
}, },
} }
} }

View file

@ -1,4 +1,4 @@
use std::cell::RefCell; use std::cell::{RefCell, Cell};
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use raidillon_platform::{Platform, PlatformContext, TimeContext}; use raidillon_platform::{Platform, PlatformContext, TimeContext};
@ -31,6 +31,8 @@ pub struct GliumPlatform<E: EngineTrait<PlatformCtx = PlatformContext>> {
time: time::Time, time: time::Time,
egui_queue: Rc<RefCell<EguiQueue>>, egui_queue: Rc<RefCell<EguiQueue>>,
settings: Arc<RwLock<Settings>>, settings: Arc<RwLock<Settings>>,
/// Used for [`raidillon_platform::context::PlatformContext::should_egui_receive_input_events`]
should_egui_receive_input_events: Rc<Cell<bool>>,
} }
impl<E: EngineTrait<PlatformCtx = PlatformContext>> Platform<E> for GliumPlatform<E> { impl<E: EngineTrait<PlatformCtx = PlatformContext>> Platform<E> for GliumPlatform<E> {
@ -64,6 +66,7 @@ impl<E: EngineTrait<PlatformCtx = PlatformContext>> Platform<E> for GliumPlatfor
Settings::load_or_default(default_config_path()).unwrap() Settings::load_or_default(default_config_path()).unwrap()
) )
); );
let should_egui_receive_input_events = Rc::new(Cell::new(false));
Self { Self {
event_loop, event_loop,
@ -75,6 +78,7 @@ impl<E: EngineTrait<PlatformCtx = PlatformContext>> Platform<E> for GliumPlatfor
time, time,
egui_queue, egui_queue,
settings, settings,
should_egui_receive_input_events,
} }
} }
@ -92,6 +96,7 @@ impl<E: EngineTrait<PlatformCtx = PlatformContext>> Platform<E> for GliumPlatfor
window: self.window.clone(), window: self.window.clone(),
egui_queue: self.egui_queue.clone(), egui_queue: self.egui_queue.clone(),
settings: self.settings.clone(), settings: self.settings.clone(),
should_egui_receive_input_events: self.should_egui_receive_input_events.clone(),
}; };
self.engine.initialize(ctx.clone()); self.engine.initialize(ctx.clone());
self.settings.read().unwrap().display_settings.apply(&*self.window.lock().unwrap()); self.settings.read().unwrap().display_settings.apply(&*self.window.lock().unwrap());
@ -136,6 +141,7 @@ impl<E: EngineTrait<PlatformCtx = PlatformContext>> Platform<E> for GliumPlatfor
window: self.window.clone(), window: self.window.clone(),
egui_queue: self.egui_queue.clone(), egui_queue: self.egui_queue.clone(),
env_light_dir: Vec3::new(0.0, -1.0, 0.0), env_light_dir: Vec3::new(0.0, -1.0, 0.0),
should_egui_receive_input_events: self.should_egui_receive_input_events.clone(),
}; };
self.rendering_system_manager self.rendering_system_manager

View file

@ -8,9 +8,12 @@ use crate::system::RenderingContext;
use egui_glium::EguiGlium; use egui_glium::EguiGlium;
use winit::event::{Event, WindowEvent}; use winit::event::{Event, WindowEvent};
use winit::event_loop::EventLoop; use winit::event_loop::EventLoop;
use std::cell::Cell;
use std::rc::Rc;
pub struct EguiRenderer { pub struct EguiRenderer {
egui_glium: EguiGlium, egui_glium: EguiGlium,
should_egui_receive_input_events: Option<Rc<Cell<bool>>>,
} }
impl RenderingSystem for EguiRenderer { impl RenderingSystem for EguiRenderer {
@ -21,10 +24,14 @@ impl RenderingSystem for EguiRenderer {
let window = window.lock().unwrap(); let window = window.lock().unwrap();
let egui_glium = EguiGlium::new(ViewportId::ROOT, &display, &window, &event_loop); let egui_glium = EguiGlium::new(ViewportId::ROOT, &display, &window, &event_loop);
Self { egui_glium } Self { egui_glium: egui_glium, should_egui_receive_input_events: None }
} }
fn render(&mut self, ctx: &mut RenderingContext) { fn render(&mut self, ctx: &mut RenderingContext) {
if self.should_egui_receive_input_events.is_none() {
self.should_egui_receive_input_events = Some(ctx.should_egui_receive_input_events.clone());
}
let window = ctx.window.lock().unwrap(); let window = ctx.window.lock().unwrap();
self.egui_glium.run(&window, |egui_ctx| { self.egui_glium.run(&window, |egui_ctx| {
@ -38,8 +45,29 @@ impl RenderingSystem for EguiRenderer {
let window = window.lock().unwrap(); let window = window.lock().unwrap();
match event { match event {
Event::WindowEvent { event, .. } => { Event::WindowEvent { event, .. } => {
let should_egui_receive_input_events = match self.should_egui_receive_input_events.as_ref() {
Some(v) => v.get(),
None => true,
};
let should_send_event = if should_egui_receive_input_events {
true
} else {
!matches!(event,
WindowEvent::KeyboardInput { .. } |
WindowEvent::ModifiersChanged(_) |
WindowEvent::CursorMoved { .. } |
WindowEvent::MouseInput { .. } |
WindowEvent::MouseWheel { .. } |
WindowEvent::Touch(_) |
WindowEvent::Ime(_)
)
};
if should_send_event {
let _ = self.egui_glium.on_event(&window, &event); let _ = self.egui_glium.on_event(&window, &event);
} }
}
_ => {}, _ => {},
} }
} }

View file

@ -10,6 +10,7 @@ use raidillon_core::{define_typemap, EguiQueue};
use raidillon_core::scene::Scene; use raidillon_core::scene::Scene;
use glam::Vec3; use glam::Vec3;
use winit::event_loop::EventLoop; use winit::event_loop::EventLoop;
use std::cell::Cell;
pub struct RenderingContext<'a> { pub struct RenderingContext<'a> {
pub scene: &'a Scene, pub scene: &'a Scene,
@ -19,6 +20,7 @@ pub struct RenderingContext<'a> {
pub asset_manager: ModelManagerRef, pub asset_manager: ModelManagerRef,
pub egui_queue: Rc<RefCell<EguiQueue>>, pub egui_queue: Rc<RefCell<EguiQueue>>,
pub env_light_dir: Vec3, pub env_light_dir: Vec3,
pub should_egui_receive_input_events: Rc<Cell<bool>>
} }
/// The internal "rendering system" trait of glium_platform. /// The internal "rendering system" trait of glium_platform.

View file

@ -1,3 +1,4 @@
use std::cell::Cell;
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use winit::event::Event; use winit::event::Event;
@ -15,6 +16,9 @@ pub struct PlatformContext {
pub window: Arc<Mutex<winit::window::Window>>, pub window: Arc<Mutex<winit::window::Window>>,
pub egui_queue: Rc<RefCell<EguiQueue>>, pub egui_queue: Rc<RefCell<EguiQueue>>,
pub settings: Arc<RwLock<Settings>>, pub settings: Arc<RwLock<Settings>>,
/// Sets whether or not egui will receive input events.
/// Added to prevent the mouse state conflict between the engine and egui.
pub should_egui_receive_input_events: Rc<Cell<bool>>,
} }
#[derive(Clone)] #[derive(Clone)]