use std::collections::VecDeque;
use crate::prelude::*;
pub struct EventLogEntry {
pub time: f32,
pub message: String,
pub category: String,
}
pub struct EventLog {
entries: VecDeque<EventLogEntry>,
max_entries: usize,
elapsed_time: f32,
}
impl EventLog {
pub fn new(max_entries: usize) -> Self {
Self {
entries: VecDeque::new(),
max_entries,
elapsed_time: 0.0,
}
}
pub fn log(&mut self, category: impl Into<String>, message: impl Into<String>) {
self.entries.push_back(EventLogEntry {
time: self.elapsed_time,
message: message.into(),
category: category.into(),
});
if self.entries.len() > self.max_entries {
self.entries.pop_front();
}
}
pub fn tick(&mut self, delta_time: f32) {
self.elapsed_time += delta_time;
}
pub fn elapsed_time(&self) -> f32 {
self.elapsed_time
}
pub fn entries(&self) -> &VecDeque<EventLogEntry> {
&self.entries
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn clear(&mut self) {
self.entries.clear();
}
pub fn render(&self, ui: &mut egui::Ui, category_color: impl Fn(&str) -> egui::Color32) {
ui.vertical(|ui| {
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.strong("Event Log");
ui.label(format!("({})", self.entries.len()));
});
ui.separator();
egui::ScrollArea::vertical()
.stick_to_bottom(true)
.show(ui, |ui| {
if self.entries.is_empty() {
ui.label("No events recorded");
return;
}
for entry in &self.entries {
let total_seconds = entry.time as u64;
let minutes = total_seconds / 60;
let seconds = total_seconds % 60;
let tenths = ((entry.time - entry.time.floor()) * 10.0) as u32;
let timestamp = format!("{:02}:{:02}.{}", minutes, seconds, tenths);
let color = category_color(&entry.category);
ui.horizontal(|ui| {
ui.monospace(
egui::RichText::new(format!("[{}]", timestamp))
.color(egui::Color32::from_rgb(120, 120, 120)),
);
ui.monospace(egui::RichText::new(&entry.category).color(color));
ui.label(&entry.message);
});
}
});
});
}
}