layer-system 0.3.1

A system for handling different kinds of events
Documentation

Layer system

This is a simple system for managing programs with multiple different parts. It's inspired by State in Amethyst, but aims to be simpler, more flexible and more general.

Example Usage

enum Event {
    Fixed,           // generated at fixed times
    Click(u16, u16), // generated by click
    Quit,            // genreated by try to close window
}

use self::Event::*;

struct State; // a global state

type LayerManager = layer_system::LayerManager<State, Event>; // the layer manager

use layer_system::{Change, Layer}; // other imports from layer System

struct World; // layer for the game world

impl Layer<State, Event> for World {
    fn passive_update(&mut self, _state: &mut State, event: &Event) {
        match event {
            Fixed => { /* render here */ }
            _ => (),
        }
    }

    fn update(&mut self, _state: &mut State, event: &Event) -> Change<State, Event> {
        match event {
            Fixed => { /* world physics update */ }
            _ => (),
        }
        Change::none()
    }
}

struct Interface;

enum ClickEvent {
    Action,
    Pause,
    Exit,
    Nothing,
}

impl Interface {
    fn click(&self, x: u16, y: u16) -> ClickEvent {
        use self::ClickEvent::*;
        if y < 16 {
            if x < 64 {
                Action
            } else if x < 128 {
                Pause
            } else if x < 192 {
                Exit
            } else {
                Nothing
            }
        } else {
            Nothing
        }
    }
}

impl Layer<State, Event> for Interface {
    fn passive_update(&mut self, _state: &mut State, event: &Event) {
        match event {
            Fixed => { /* render here */ }
            _ => (),
        }
    }

    fn update(&mut self, _state: &mut State, event: &Event) -> Change<State, Event> {
        match event {
            Click(x, y) => match self.click(*x, *y) {
                // execute some action when clicking "Action"
                ClickEvent::Action => {
                    /* execute action */
                    Change::none()
                }
                // pause when clicking "Pause"
                ClickEvent::Pause => Change::add(vec![Box::new(Pause)]),
                // remove all layers when clicking "Exit"
                ClickEvent::Exit => Change::close(),
                // nothing was clicked, so in case the world supports a click event, just defer it
                ClickEvent::Nothing => Change::pass(),
            },
            // when trying to quit the game, pause it first
            Quit => Change::add(vec![Box::new(Pause)]),
            // Defer all other events, so World will handle everything else
            _ => Change::pass(),
        }
    }
}

struct Pause;

impl Layer<State, Event> for Pause {
    fn passive_update(&mut self, _state: &mut State, event: &Event) {
        match event {
            Fixed => { /* render here */ }
            _ => (),
        }
    }

    fn update(&mut self, _state: &mut State, event: &Event) -> Change<State, Event> {
        match event {
            // do not defer `Fixed`, so world physics won't be updated anymore
            Fixed => Change::none(),
            // end pause by clicking somewhere
            Click(_, _) => Change::remove(),
            // when trying to quit the game again, quit it
            Quit => Change::close(),
        }
    }
}

fn main() {
    let mut manager = LayerManager::new(vec![Box::new(World), Box::new(Interface)]);

    let mut state = State;

    while manager.is_active() {
        manager.update(&mut state, Fixed);
        /* handle other events in events loop */
        // if click event:
        manager.update(&mut state, Click(0, 0));
        // if quit event:
        manager.update(&mut state, Quit);
        /* wait for a fixed time */
    }
}