use crate::{settings, actor, audio}; use bevy::prelude::*; use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}; use std::collections::VecDeque; use std::time::SystemTime; const HUD_REFRESH_TIME: f32 = 0.5; const FONT: &str = "tmp/fonts/NotoSansSC-Thin.ttf"; const LOG_MAX: usize = 5; const LOG_MAX_TIME_S: u64 = 10; pub struct HudPlugin; impl Plugin for HudPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, setup); app.add_systems(Update, (update, handle_input)); app.insert_resource(Log { logs: VecDeque::with_capacity(LOG_MAX) }); app.insert_resource(FPSUpdateTimer( Timer::from_seconds(HUD_REFRESH_TIME, TimerMode::Repeating))); } } #[derive(Component)] struct GaugesText; #[derive(Resource)] struct FPSUpdateTimer(Timer); struct Message { text: String, time: u64, } #[derive(Resource)] struct Log { logs: VecDeque, } impl Log { pub fn add(&mut self, message: String) { if self.logs.len() == LOG_MAX { self.logs.pop_front(); } if let Ok(epoch) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { self.logs.push_back(Message { text: message, time: epoch.as_secs(), }); } } pub fn remove_old(&mut self) { if let Some(message) = self.logs.front() { if let Ok(epoch) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { if epoch.as_secs() - message.time > LOG_MAX_TIME_S { self.logs.pop_front(); } } } } } fn setup( mut commands: Commands, settings: Res, asset_server: Res, mut log: ResMut, ) { log.add("Customer wake-up registered.".to_string()); log.add("Systems reactivated.".to_string()); let visibility = if settings.hud_active { Visibility::Inherited } else { Visibility::Hidden }; let mut bundle_fps = TextBundle::from_sections([ TextSection::new( "帧率 ", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() }, ), TextSection::new( "", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() } ), TextSection::new( "\n电量 ", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() }, ), TextSection::new( "", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() } ), TextSection::new( "\n氧 OXYGEN ", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() }, ), TextSection::new( "", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() } ), TextSection::new( "\nAdren水平 ", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() }, ), TextSection::new( "", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() } ), TextSection::new( "\n\n", TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() } ), TextSection::from_style( TextStyle { font: asset_server.load(FONT), font_size: settings.font_size_hud, color: Color::GRAY, ..default() } ), ]).with_style(Style { top: Val::VMin(2.0), left: Val::VMin(3.0), ..default() }); bundle_fps.visibility = visibility; commands.spawn(( bundle_fps, GaugesText, )); } fn update( diagnostics: Res, time: Res