furmint-runtime 0.1.0

Main package of furmint game engine providing higher level API
Documentation
//! Module for handling events

use specs::{System, WriteExpect};
use std::sync::mpsc::Receiver;

#[non_exhaustive]
/// Enum of possible app events
#[derive(Debug, PartialEq)]
pub enum AppEvent {
    /// An event that should be sent from e.g. SIGINT handler or graphics thread to terminate the
    /// main runtime loop gracefully
    ExitRequested,
}

pub(crate) struct AppEventReceivingSystem {
    receiver: Receiver<AppEvent>,
}

impl AppEventReceivingSystem {
    /// Create a new instance of [`AppEventReceivingSystem`]
    pub fn new(receiver: Receiver<AppEvent>) -> Self {
        Self { receiver }
    }
}

impl<'a> System<'a> for AppEventReceivingSystem {
    type SystemData = WriteExpect<'a, Events<AppEvent>>;

    fn run(&mut self, mut events: Self::SystemData) {
        #[allow(clippy::single_match)] // this match block will grow, so justified ig
        match self.receiver.try_recv() {
            Ok(AppEvent::ExitRequested) => {
                events.send(AppEvent::ExitRequested);
            }
            _ => {}
        }
    }
}

/// Struct representing events
#[derive(Debug)]
pub struct Events<T> {
    current: Vec<T>,
    next: Vec<T>,
}

impl<T> Default for Events<T> {
    fn default() -> Self {
        Self {
            current: Vec::new(),
            next: Vec::new(),
        }
    }
}

impl<T> Events<T> {
    /// Send an event
    pub fn send(&mut self, event: T) {
        self.next.push(event);
    }

    /// Read events from the current frame/batch
    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.current.iter()
    }

    /// Clear current events and swap it with next array of events
    pub(crate) fn update(&mut self) {
        self.current.clear();
        std::mem::swap(&mut self.current, &mut self.next);
    }

    /// Clear all buffered events
    #[allow(unused)]
    pub(crate) fn clear(&mut self) {
        self.current.clear();
        self.next.clear();
    }

    /// Is the current event buffer empty?
    pub fn is_empty(&self) -> bool {
        self.current.is_empty()
    }
}