My personal project and infrastructure archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nomicon/games/rstnode/rst-client/src/event.rs

169 lines
4.6 KiB

use ggez::{
event::{EventHandler, KeyCode, KeyMods, MouseButton},
graphics, Context, GameResult,
};
use std::collections::BTreeMap;
use std::sync::{
atomic::{AtomicUsize, Ordering},
mpsc::{channel, Receiver, Sender},
};
static ID_CTR: AtomicUsize = AtomicUsize::new(0);
static mut tx: Option<Sender<HandlerDiff>> = None;
static mut rx: Option<Receiver<HandlerDiff>> = None;
#[inline(always)]
pub fn get_tx() -> Sender<HandlerDiff> {
unsafe { tx.as_ref() }.expect("Call event::setup() first!").clone()
}
/// Must absolutely call this function before using the event system!
pub fn setup() {
let (tx_, rx_) = channel();
unsafe { tx = Some(tx_) };
unsafe { rx = Some(rx_) };
}
pub type EventId = usize;
pub fn new_id() -> EventId {
ID_CTR.fetch_add(1, Ordering::Relaxed)
}
pub type BoxedHandler = Box<dyn EventHandler + 'static>;
pub enum HandlerDiff {
Add { id: usize, inner: BoxedHandler },
Remove(usize),
}
impl HandlerDiff {
pub fn add(inner: impl EventHandler + 'static) -> (usize, Self) {
let id = new_id();
(
id,
Self::Add {
id,
inner: Box::new(inner),
},
)
}
pub fn remove(id: usize) -> Self {
Self::Remove(id)
}
}
pub struct EventLayer<L> {
layers: BTreeMap<usize, BoxedHandler>,
layer_rx: Receiver<HandlerDiff>,
render: L,
}
impl<L: EventHandler> EventLayer<L> {
pub fn new(render: L) -> Self {
let layer_rx = unsafe { rx.take().expect("Call event::setup() first!") };
Self {
layers: BTreeMap::new(),
layer_rx,
render,
}
}
}
impl<L: EventHandler> EventHandler for EventLayer<L> {
fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
// Add all new layers to the update stack
while let Ok(l) = self.layer_rx.try_recv() {
match l {
HandlerDiff::Add { id, inner } => {
self.layers.insert(id, inner);
}
HandlerDiff::Remove(ref id) => {
self.layers.remove(id);
}
}
}
// Then update all the layers
self.layers
.iter_mut()
.map(|(_, l)| l.update(ctx))
.collect::<GameResult<Vec<()>>>()?;
// Update the renderer last
self.render.update(ctx)?;
Ok(())
}
fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
graphics::clear(ctx, graphics::Color::from_rgb(15, 15, 15));
self.render.draw(ctx)?;
self.layers
.iter_mut()
.map(|(_, l)| l.draw(ctx))
.collect::<Vec<_>>();
graphics::present(ctx)
}
fn mouse_button_down_event(&mut self, ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
self.layers
.iter_mut()
.map(|(_, l)| l.mouse_button_down_event(ctx, button, x, y))
.collect::<Vec<_>>();
}
fn mouse_button_up_event(&mut self, ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
self.layers
.iter_mut()
.map(|(_, l)| l.mouse_button_up_event(ctx, button, x, y))
.collect::<Vec<_>>();
}
fn mouse_motion_event(&mut self, ctx: &mut Context, x: f32, y: f32, dx: f32, dy: f32) {
self.layers
.iter_mut()
.map(|(_, l)| l.mouse_motion_event(ctx, x, y, dx, dy))
.collect::<Vec<_>>();
}
/// A keyboard button was pressed.
///
/// The default implementation of this will call `ggez::event::quit()`
/// when the escape key is pressed. If you override this with
/// your own event handler you have to re-implment that
/// functionality yourself.
fn key_down_event(
&mut self,
ctx: &mut Context,
keycode: KeyCode,
keymods: KeyMods,
repeat: bool,
) {
self.layers
.iter_mut()
.map(|(_, l)| l.key_down_event(ctx, keycode, keymods, repeat))
.collect::<Vec<_>>();
}
/// A keyboard button was released.
fn key_up_event(&mut self, ctx: &mut Context, keycode: KeyCode, keymods: KeyMods) {
self.layers
.iter_mut()
.map(|(_, l)| l.key_up_event(ctx, keycode, keymods))
.collect::<Vec<_>>();
}
/// A unicode character was received, usually from keyboard input.
/// This is the intended way of facilitating text input.
fn text_input_event(&mut self, ctx: &mut Context, character: char) {
self.layers
.iter_mut()
.map(|(_, l)| l.text_input_event(ctx, character))
.collect::<Vec<_>>();
}
}