use std::{collections::VecDeque, rc::Rc};
use crate::prelude::*;
pub struct TriggerArgs<'a, W> {
pub w: &'a mut W,
pub t: &'a mut Trigger<W>,
}
pub type TriggerFunc<W> = Rc<dyn Fn(TriggerArgs<W>) -> Result<()>>;
pub struct Trigger<W> {
pub timer: f32,
pub delay: f32,
pub done: bool,
pub repeat: bool,
pub func: TriggerFunc<W>,
}
impl<W> Trigger<W> {
pub fn played(&self) -> f32 {
self.timer - self.delay
}
pub fn with_func<F: Fn(TriggerArgs<W>) -> Result<()> + 'static>(mut self, func: F) -> Self {
self.func = Rc::new(func);
self
}
pub fn with_delay(mut self, delay: f32) -> Self {
self.delay = delay;
self
}
pub fn with_repeat(mut self, repeat: bool) -> Self {
self.repeat = repeat;
self
}
}
impl<W> Default for Trigger<W> {
fn default() -> Self {
Self {
timer: 0.0,
delay: 0.0,
done: false,
repeat: false,
func: Rc::new(|_| Ok(())),
}
}
}
#[derive(Default)]
pub struct TriggerManager<W> {
queue: VecDeque<Trigger<W>>,
}
impl<W> TriggerManager<W> {
pub fn new() -> Self {
Self {
queue: VecDeque::new(),
}
}
pub fn add(&mut self, trigger: Trigger<W>) {
self.queue.push_back(trigger);
}
pub fn take_queue(&mut self) -> VecDeque<Trigger<W>> {
std::mem::take(&mut self.queue)
}
pub fn prepend_queue(&mut self, mut queue: VecDeque<Trigger<W>>) {
if !queue.is_empty() {
std::mem::swap(&mut self.queue, &mut queue);
self.queue.extend(queue);
}
}
pub fn update(w: &mut W, tick: f32, mut queue: VecDeque<Trigger<W>>) -> VecDeque<Trigger<W>> {
let mut remove_triggers = false;
for t in queue.iter_mut() {
if t.done {
continue;
}
t.timer += tick;
if t.timer < t.delay {
continue;
}
let func = t.func.clone();
let args = TriggerArgs { w, t };
if let Err(err) = func(args) {
log::error!("Trigger: {err:?}");
t.done = true;
}
if !t.repeat {
t.done = true;
}
if t.done {
remove_triggers = true;
}
}
if remove_triggers {
queue.retain(|trigger| !trigger.done);
}
queue
}
}