use crate::{
Alignment, EngineStats, GameCommand, GameCommandsArg, Identity, IntCoords2d, Query,
QueryResultList, Rgb, System, SystemsGenerator, Text, Timer, UiAnchor, EVENT_BEFORE_UPDATE,
EVENT_INIT, EVENT_UPDATE,
};
pub const FPS_TRACKER_ID: &str = "thomas_fps_tracking_tag";
pub struct EngineAnalysisOptions {
pub include_tracking_ui: bool,
}
pub struct EngineAnalysisSystemsGenerator {
options: EngineAnalysisOptions,
}
impl EngineAnalysisSystemsGenerator {
pub fn new(options: EngineAnalysisOptions) -> Self {
Self { options }
}
}
impl SystemsGenerator for EngineAnalysisSystemsGenerator {
fn generate(&self) -> Vec<(&'static str, System)> {
let mut systems = vec![
(
EVENT_INIT,
System::new(vec![], |_, commands| {
commands
.borrow_mut()
.issue(GameCommand::AddEntity(vec![Box::new(EngineStats {
fps: 0,
frame_timer: Timer::new(),
frame_counter: 0,
})]));
}),
),
(
EVENT_BEFORE_UPDATE,
System::new(vec![Query::new().has::<EngineStats>()], gather_stats),
),
];
if self.options.include_tracking_ui {
systems.append(&mut vec![
(
EVENT_INIT,
System::new(vec![], |_, commands| {
commands.borrow_mut().issue(GameCommand::AddEntity(vec![
Box::new(Text {
anchor: UiAnchor::TopLeft,
justification: Alignment::Left,
offset: IntCoords2d::zero(),
value: String::from(""),
foreground_color: Some(Rgb::magenta()),
background_color: None,
}),
Box::new(Identity {
id: String::from(FPS_TRACKER_ID),
name: String::from("FPS Tracking Tag"),
}),
]));
}),
),
(
EVENT_UPDATE,
System::new(
vec![
Query::new()
.has::<Text>()
.has_where::<Identity>(|id| id.id == FPS_TRACKER_ID),
Query::new().has::<EngineStats>(),
],
update_tracking_ui,
),
),
])
}
systems
}
}
fn gather_stats(results: Vec<QueryResultList>, _: GameCommandsArg) {
if let [engine_stats_results, ..] = &results[..] {
let mut engine_stats = engine_stats_results.get_only_mut::<EngineStats>();
engine_stats.frame_counter += 1;
if !engine_stats.frame_timer.is_running() {
engine_stats.frame_timer.start();
}
if engine_stats.frame_timer.elapsed_millis() >= 1000 {
engine_stats.fps = engine_stats.frame_counter;
engine_stats.frame_counter = 0;
engine_stats.frame_timer.restart();
}
}
}
fn update_tracking_ui(results: Vec<QueryResultList>, _: GameCommandsArg) {
if let [fps_tag_results, engine_stats_results, ..] = &results[..] {
let mut fps_tag = fps_tag_results.get_only_mut::<Text>();
let stats = engine_stats_results.get_only::<EngineStats>();
fps_tag.value = format!("FPS: {}", stats.fps);
}
}