use crate::{
prelude::*,
renderer::{Rendering, WindowRenderer},
};
use std::time::{Duration, Instant};
use time::OffsetDateTime;
const ONE_SECOND: Duration = Duration::from_secs(1);
#[derive(Debug, Clone)]
pub(crate) struct Environment {
focused_window: Option<WindowId>,
delta_time: Duration,
start: Instant,
frame_rate: f32,
frame_count: usize,
run_count: usize,
quit: bool,
last_frame_time: Instant,
frame_timer: Duration,
}
impl Default for Environment {
fn default() -> Self {
Self {
focused_window: None,
delta_time: Duration::default(),
start: Instant::now(),
frame_rate: 0.0,
frame_count: 0,
run_count: 0,
quit: false,
last_frame_time: Instant::now(),
frame_timer: Duration::default(),
}
}
}
impl PixState {
#[inline]
pub fn present(&mut self) {
self.renderer.present();
}
#[inline]
#[must_use]
pub fn focused(&self) -> bool {
self.env
.focused_window
.map(|focused_window| focused_window == self.renderer.window_id())
.unwrap_or_default()
}
#[inline]
#[must_use]
pub fn focused_window(&self, window_id: WindowId) -> bool {
matches!(self.env.focused_window, Some(id) if id == window_id)
}
#[inline]
#[must_use]
pub const fn delta_time(&self) -> Duration {
self.env.delta_time
}
#[inline]
#[must_use]
pub fn elapsed(&self) -> Duration {
self.env.start.elapsed()
}
#[inline]
#[must_use]
pub const fn frame_count(&self) -> usize {
self.env.frame_count
}
#[inline]
pub fn redraw(&mut self) {
self.env.run_count = 1;
}
#[inline]
pub fn run_times(&mut self, n: usize) {
self.env.run_count = n;
}
#[inline]
#[must_use]
pub const fn avg_frame_rate(&self) -> f32 {
self.env.frame_rate
}
#[inline]
pub fn quit(&mut self) {
self.env.quit = true;
}
#[inline]
pub fn abort_quit(&mut self) {
self.env.quit = false;
}
#[inline]
#[must_use]
pub fn day() -> u32 {
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.day() as u32
}
#[inline]
#[must_use]
pub fn month() -> u32 {
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.month() as u32
}
#[inline]
#[must_use]
pub fn year() -> i32 {
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.year()
}
#[inline]
#[must_use]
pub fn hour() -> u32 {
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.hour() as u32
}
#[inline]
#[must_use]
pub fn minute() -> u32 {
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.minute() as u32
}
#[inline]
#[must_use]
pub fn second() -> u32 {
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.second() as u32
}
}
impl PixState {
#[inline]
pub(crate) const fn last_frame_time(&self) -> Instant {
self.env.last_frame_time
}
#[inline]
pub(crate) fn set_delta_time(&mut self, now: Instant, time_since_last: Duration) {
self.env.delta_time = time_since_last;
self.env.last_frame_time = now;
}
#[inline]
pub(crate) const fn is_running(&self) -> bool {
self.settings.running || self.env.run_count > 0
}
#[inline]
pub(crate) const fn should_quit(&self) -> bool {
self.env.quit
}
#[inline]
pub(crate) fn increment_frame(&mut self, time_since_last: Duration) -> PixResult<()> {
let s = &self.settings;
let env = &mut self.env;
if env.run_count > 0 {
env.run_count -= 1;
}
env.frame_count += 1;
if s.running && s.show_frame_rate {
env.frame_timer += time_since_last;
if env.frame_timer >= ONE_SECOND {
env.frame_rate = env.frame_count as f32 / env.frame_timer.as_secs_f32();
env.frame_timer -= ONE_SECOND;
env.frame_count = 0;
self.renderer.set_fps(env.frame_rate)?;
}
}
Ok(())
}
pub(crate) fn focus_window(&mut self, id: Option<WindowId>) {
self.env.focused_window = id;
}
}