use std::collections::VecDeque;
use puffin::GlobalFrameView;
use web_time::Instant;
use crate::system::{SystemSample, sample_now};
pub struct PanelState {
pub(super) view: GlobalFrameView,
pub(super) pinned: Option<usize>,
pub(super) system: VecDeque<SystemSample>,
pub(super) last_tick: Option<Instant>,
pub(super) config: PanelConfig,
pub(super) flame_view: FlameView,
pub(super) selection: Option<(usize, usize)>,
pub(super) last_tick_ns: u64,
pub(super) profiler_load_ns: f64,
pub(super) show_profiler_load: bool,
}
#[derive(Clone, Copy)]
pub(super) struct FlameView {
pub start: f32,
pub end: f32,
}
impl FlameView {
pub(super) const FULL: Self = Self {
start: 0.0,
end: 1.0,
};
pub(super) fn width(self) -> f32 {
self.end - self.start
}
}
impl PanelState {
pub fn new(config: PanelConfig) -> Self {
crate::gpu::ensure_collector();
Self {
view: GlobalFrameView::default(),
pinned: None,
system: VecDeque::with_capacity(config.history_capacity),
last_tick: None,
config,
flame_view: FlameView::FULL,
selection: None,
last_tick_ns: 0,
profiler_load_ns: 0.0,
show_profiler_load: false,
}
}
pub fn tick(&mut self) {
let started = Instant::now();
puffin::GlobalProfiler::lock().new_frame();
let s = sample_now(&mut self.last_tick);
if self.system.len() >= self.config.history_capacity {
self.system.pop_front();
}
self.system.push_back(s);
self.last_tick_ns = started.elapsed().as_nanos() as u64;
}
pub(super) fn record_render_ns(&mut self, render_ns: u64) {
let load = (self.last_tick_ns + render_ns) as f64;
self.profiler_load_ns = if self.profiler_load_ns == 0.0 {
load
} else {
0.9 * self.profiler_load_ns + 0.1 * load
};
}
pub const fn toggle_profiler_load(&mut self) {
self.show_profiler_load = !self.show_profiler_load;
}
pub const fn pinned(&self) -> Option<usize> {
self.pinned
}
pub const fn is_paused(&self) -> bool {
self.pinned.is_some()
}
pub fn pin_latest(&mut self) {
if !self.system.is_empty() {
self.pinned = Some(self.system.len() - 1);
}
}
pub const fn unpin(&mut self) {
self.pinned = None;
self.selection = None;
}
pub const fn selection(&self) -> Option<(usize, usize)> {
self.selection
}
pub fn toggle_pause(&mut self) {
if self.pinned.is_some() {
self.unpin();
} else {
self.pin_latest();
}
}
pub const fn reset_flame_zoom(&mut self) {
self.flame_view = FlameView::FULL;
}
}
#[derive(Clone)]
pub struct PanelConfig {
pub history_capacity: usize,
pub bar_good_threshold: f64,
pub bar_warn_threshold: f64,
}
impl PanelConfig {
pub const FRAME_MS: Self = Self {
history_capacity: 256,
bar_good_threshold: 16.667,
bar_warn_threshold: 33.333,
};
}