use std::{
any::TypeId,
sync::Arc,
thread,
time::{Duration, Instant},
};
use parking_lot::{Mutex, RwLock};
use super::{
interactor::Interactor,
message::{Content, Message, Participant, Sender},
renderer::Renderer,
ICmdWindow,
};
#[derive(Debug)]
pub struct Looper {
pub window: Arc<RwLock<ICmdWindow>>,
pub fps: u16,
renderer_ready: Mutex<bool>,
interactor_ready: Mutex<bool>,
}
impl Looper {
pub fn new(window: Arc<RwLock<ICmdWindow>>, fps: u16) -> Self {
Looper {
window,
fps,
renderer_ready: false.into(),
interactor_ready: false.into(),
}
}
pub fn launch(&self) {
self.send(Message {
from: self.get_id(),
to: TypeId::of::<Renderer>(),
content: Content::IsReady,
});
let mut last_exec = Instant::now();
let interval = Duration::from_micros((1000 / self.fps).into());
loop {
if !self.update(()) {
break;
}
if *self.renderer_ready.lock() {
if last_exec.elapsed() >= interval {
self.send(Message {
from: self.get_id(),
to: TypeId::of::<Renderer>(),
content: Content::Update,
});
last_exec = Instant::now();
}
}
thread::sleep(Duration::from_millis(1));
}
}
}
impl Sender for Looper {
fn get_window(&self) -> Arc<RwLock<ICmdWindow>> {
self.window.clone()
}
}
impl Participant for Looper {
type Params = ();
fn resolve(&self, msg: Message, _: Self::Params) -> bool {
match msg.content {
Content::Ready => {
if msg.from == TypeId::of::<Renderer>() {
*self.renderer_ready.lock() = true;
};
if msg.from == TypeId::of::<Interactor>() {
*self.interactor_ready.lock() = true;
};
true
}
Content::IsReady => {
self.send(Message {
from: self.get_id(),
to: msg.from,
content: Content::Ready,
});
true
}
Content::Quit => false,
_ => true,
}
}
}