diff --git a/src/render/plugin.rs b/src/render/plugin.rs index 1938029..453c685 100644 --- a/src/render/plugin.rs +++ b/src/render/plugin.rs @@ -131,7 +131,12 @@ impl Plugin for BlackHolePlugin { .add_systems(Update, rebuild_bloom) // bevy_egui 0.41 requires UI systems to run inside the egui context // pass (fonts/ctx are initialized there); placing them in Update panics. - .add_systems(bevy_egui::EguiPrimaryContextPass, crate::ui::ui_system); + // setup_egui_style is a one-shot (Local guard): retries until the + // context exists, applies the theme once, never runs again. + .add_systems( + bevy_egui::EguiPrimaryContextPass, + (crate::ui::setup_egui_style, crate::ui::ui_system).chain(), + ); } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 546f3e6..a4cd4c2 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -4,6 +4,23 @@ pub mod preset; use bevy::prelude::*; use bevy_egui::egui; +/// One-shot egui styling. Registered in `EguiPrimaryContextPass` with a +/// `Local` guard so it retries until `ctx_mut()` first succeeds, then +/// runs exactly once. Per-frame set_style/set_visuals would dirty layout +/// caches every frame; this avoids that. +pub fn setup_egui_style( + mut contexts: bevy_egui::EguiContexts, + mut done: Local, +) { + if *done { + return; + } + if let Ok(ctx) = contexts.ctx_mut() { + crate::ui::style::setup(&ctx); + *done = true; + } +} + pub fn ui_system( mut contexts: bevy_egui::EguiContexts, mut params: ResMut,