2024-03-17 22:49:50 +00:00
|
|
|
use crate::{settings, actor};
|
2024-03-17 14:23:22 +00:00
|
|
|
use bevy::prelude::*;
|
|
|
|
use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
|
2024-03-17 23:36:56 +00:00
|
|
|
use std::collections::VecDeque;
|
2024-03-17 14:23:22 +00:00
|
|
|
|
2024-03-17 20:57:30 +00:00
|
|
|
const HUD_REFRESH_TIME: f32 = 0.5;
|
|
|
|
const FONT: &str = "tmp/fonts/NotoSansSC-Thin.ttf";
|
2024-03-17 23:36:56 +00:00
|
|
|
const LOG_MAX: usize = 5;
|
2024-03-17 20:57:30 +00:00
|
|
|
|
2024-03-17 22:49:50 +00:00
|
|
|
pub struct HudPlugin;
|
|
|
|
impl Plugin for HudPlugin {
|
2024-03-17 14:23:22 +00:00
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.add_systems(Startup, setup);
|
2024-03-17 18:03:02 +00:00
|
|
|
app.add_systems(Update, (update, handle_input));
|
2024-03-17 23:36:56 +00:00
|
|
|
app.insert_resource(Log { logs: VecDeque::with_capacity(LOG_MAX) });
|
2024-03-17 20:57:30 +00:00
|
|
|
app.insert_resource(FPSUpdateTimer(
|
|
|
|
Timer::from_seconds(HUD_REFRESH_TIME, TimerMode::Repeating)));
|
2024-03-17 14:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Component)]
|
2024-03-17 20:29:27 +00:00
|
|
|
struct GaugesText;
|
2024-03-17 14:23:22 +00:00
|
|
|
|
|
|
|
#[derive(Resource)]
|
|
|
|
struct FPSUpdateTimer(Timer);
|
|
|
|
|
2024-03-17 23:36:56 +00:00
|
|
|
#[derive(Resource)]
|
|
|
|
struct Log {
|
|
|
|
logs: VecDeque<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Log {
|
|
|
|
pub fn add(&mut self, message: String) {
|
|
|
|
if self.logs.len() == LOG_MAX {
|
|
|
|
self.logs.pop_front();
|
|
|
|
}
|
|
|
|
self.logs.push_back(message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-17 14:23:22 +00:00
|
|
|
fn setup(
|
|
|
|
mut commands: Commands,
|
2024-03-17 18:03:02 +00:00
|
|
|
settings: Res<settings::Settings>,
|
2024-03-17 19:04:16 +00:00
|
|
|
asset_server: Res<AssetServer>,
|
2024-03-17 23:36:56 +00:00
|
|
|
mut log: ResMut<Log>,
|
2024-03-17 14:23:22 +00:00
|
|
|
) {
|
2024-03-17 23:36:56 +00:00
|
|
|
log.add("Customer wake-up registered.".to_string());
|
|
|
|
log.add("Systems reactivated.".to_string());
|
2024-03-17 21:28:10 +00:00
|
|
|
let visibility = if settings.hud_active {
|
2024-03-17 18:03:02 +00:00
|
|
|
Visibility::Inherited
|
|
|
|
} else {
|
|
|
|
Visibility::Hidden
|
|
|
|
};
|
|
|
|
let mut bundle_fps = TextBundle::from_sections([
|
|
|
|
TextSection::new(
|
2024-03-17 19:31:16 +00:00
|
|
|
" 帧率 ",
|
2024-03-17 18:03:02 +00:00
|
|
|
TextStyle {
|
2024-03-17 19:28:45 +00:00
|
|
|
font: asset_server.load(FONT),
|
2024-03-17 19:31:16 +00:00
|
|
|
font_size: settings.font_size_hud,
|
2024-03-17 19:04:16 +00:00
|
|
|
color: Color::GRAY,
|
2024-03-17 18:03:02 +00:00
|
|
|
..default()
|
|
|
|
},
|
|
|
|
),
|
2024-03-17 19:04:16 +00:00
|
|
|
TextSection::new(
|
|
|
|
"",
|
2024-03-17 18:03:02 +00:00
|
|
|
TextStyle {
|
2024-03-17 19:28:45 +00:00
|
|
|
font: asset_server.load(FONT),
|
2024-03-17 19:31:16 +00:00
|
|
|
font_size: settings.font_size_hud,
|
2024-03-17 19:04:16 +00:00
|
|
|
color: Color::GRAY,
|
2024-03-17 18:03:02 +00:00
|
|
|
..default()
|
|
|
|
}
|
2024-03-17 19:04:16 +00:00
|
|
|
),
|
2024-03-17 20:29:27 +00:00
|
|
|
TextSection::new(
|
2024-03-17 21:28:10 +00:00
|
|
|
"\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 ",
|
2024-03-17 20:29:27 +00:00
|
|
|
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 Adren水平 ",
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
),
|
2024-03-17 23:36:56 +00:00
|
|
|
TextSection::new(
|
|
|
|
"\n\n",
|
|
|
|
TextStyle {
|
|
|
|
font: asset_server.load(FONT),
|
|
|
|
font_size: settings.font_size_hud,
|
|
|
|
color: Color::GRAY,
|
|
|
|
..default()
|
|
|
|
}
|
|
|
|
),
|
|
|
|
TextSection::new(
|
|
|
|
"<log>",
|
|
|
|
TextStyle {
|
|
|
|
font: asset_server.load(FONT),
|
|
|
|
font_size: settings.font_size_hud,
|
|
|
|
color: Color::GRAY,
|
|
|
|
..default()
|
|
|
|
}
|
|
|
|
),
|
2024-03-17 18:03:02 +00:00
|
|
|
]);
|
|
|
|
bundle_fps.visibility = visibility;
|
2024-03-17 14:23:22 +00:00
|
|
|
commands.spawn((
|
2024-03-17 18:03:02 +00:00
|
|
|
bundle_fps,
|
2024-03-17 20:29:27 +00:00
|
|
|
GaugesText,
|
2024-03-17 14:23:22 +00:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update(
|
|
|
|
diagnostics: Res<DiagnosticsStore>,
|
2024-03-17 22:49:50 +00:00
|
|
|
time: Res<Time>,
|
2024-03-17 23:36:56 +00:00
|
|
|
log: Res<Log>,
|
2024-03-17 22:49:50 +00:00
|
|
|
player: Query<(&actor::Suit, &actor::LifeForm), With<actor::Player>>,
|
2024-03-17 14:23:22 +00:00
|
|
|
mut timer: ResMut<FPSUpdateTimer>,
|
2024-03-17 20:29:27 +00:00
|
|
|
mut query: Query<&mut Text, With<GaugesText>>,
|
2024-03-17 14:23:22 +00:00
|
|
|
) {
|
|
|
|
if timer.0.tick(time.delta()).just_finished() {
|
2024-03-17 22:49:50 +00:00
|
|
|
let player = player.get_single();
|
|
|
|
if player.is_ok() {
|
|
|
|
let (suit, lifeform) = player.unwrap();
|
|
|
|
for mut text in &mut query {
|
|
|
|
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
|
|
|
|
if let Some(value) = fps.smoothed() {
|
|
|
|
// Update the value of the second section
|
|
|
|
text.sections[1].value = format!("{value:.0}");
|
|
|
|
}
|
2024-03-17 14:23:22 +00:00
|
|
|
}
|
2024-03-17 22:49:50 +00:00
|
|
|
let power = suit.power;
|
|
|
|
text.sections[3].value = format!("{power:}Wh");
|
|
|
|
let oxy_percent = suit.oxygen / suit.oxygen_max * 100.0;
|
|
|
|
let oxy_total = suit.oxygen * 1e6;
|
|
|
|
text.sections[5].value = format!("{oxy_percent:.1}% [{oxy_total:.0}mg]");
|
|
|
|
let adrenaline = lifeform.adrenaline * 990.0 + 10.0;
|
|
|
|
text.sections[7].value = format!("{adrenaline:.0}pg/mL");
|
2024-03-17 14:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-17 23:36:56 +00:00
|
|
|
for mut text in &mut query {
|
|
|
|
let logs_vec: Vec<&str> = log.logs.iter().map(|s| s.as_str()).collect();
|
|
|
|
text.sections[9].value = logs_vec.join("\n");
|
|
|
|
}
|
2024-03-17 14:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-17 18:03:02 +00:00
|
|
|
|
|
|
|
fn handle_input(
|
|
|
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
|
|
|
settings: Res<settings::Settings>,
|
2024-03-17 20:29:27 +00:00
|
|
|
mut query: Query<&mut Visibility, With<GaugesText>>,
|
2024-03-17 18:03:02 +00:00
|
|
|
) {
|
|
|
|
if keyboard_input.just_pressed(settings.key_togglehud) {
|
|
|
|
for mut vis in &mut query {
|
|
|
|
if *vis == Visibility::Inherited {
|
|
|
|
*vis = Visibility::Hidden;
|
|
|
|
} else {
|
|
|
|
*vis = Visibility::Inherited;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|