statez 0.1.2

Basic state management for the ggez game framework.
extern crate ggez;
extern crate statez;

use ggez::{conf, event, graphics, Context, GameResult};
use statez::{State, StateManager, StateTransition};

#[derive(Clone)]
enum Color {
    Red,
    Orange,
    Yellow,
    Green,
    Blue,
    Purple,
    Magenta,
}

impl Color {
    fn next_color(current_color: &Color) -> Color {
        match current_color {
            Color::Red => Color::Orange,
            Color::Orange => Color::Yellow,
            Color::Yellow => Color::Green,
            Color::Green => Color::Blue,
            Color::Blue => Color::Purple,
            Color::Purple => Color::Magenta,
            Color::Magenta => Color::Red,
        }
    }
}

impl Into<graphics::Color> for Color {
    fn into(self) -> graphics::Color {
        match self {
            Color::Red => graphics::Color::new(1.0, 0.0, 0.0, 1.0),
            Color::Orange => graphics::Color::new(1.0, 0.5, 0.0, 1.0),
            Color::Yellow => graphics::Color::new(1.0, 1.0, 0.0, 1.0),
            Color::Green => graphics::Color::new(0.0, 1.0, 0.0, 1.0),
            Color::Blue => graphics::Color::new(0.0, 0.0, 1.0, 1.0),
            Color::Purple => graphics::Color::new(0.5, 0.0, 1.0, 1.0),
            Color::Magenta => graphics::Color::new(1.0, 0.0, 0.5, 1.0),
        }
    }
}

struct SharedData {
    rect_color: Color,
}

#[derive(Default)]
struct BaseState {
    overlay_visible: bool,
}

#[derive(Default)]
struct OverlayState {
    return_to_previous: bool,
}

impl State<SharedData> for BaseState {
    fn start(&mut self, _shared_data: &mut SharedData, ctx: &mut Context) {
        graphics::set_background_color(ctx, graphics::WHITE);
    }

    fn resume(&mut self, _shared_data: &mut SharedData, _ctx: &mut Context) {
        self.overlay_visible = false
    }

    fn update(
        &mut self,
        _shared_data: &mut SharedData,
        _ctx: &mut Context,
    ) -> GameResult<StateTransition<SharedData>> {
        if self.overlay_visible {
            Ok(StateTransition::Push(Box::new(OverlayState::default())))
        } else {
            Ok(StateTransition::None)
        }
    }

    fn draw(&mut self, shared_data: &mut SharedData, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);
        graphics::set_color(ctx, shared_data.rect_color.clone().into())?;

        graphics::rectangle(
            ctx,
            graphics::DrawMode::Fill,
            graphics::Rect::new(50.0, 50.0, 250.0, 300.0),
        )?;

        if !self.overlay_visible {
            graphics::present(ctx);
        }

        Ok(())
    }

    fn key_up_event(
        &mut self,
        _shared_data: &mut SharedData,
        _ctx: &mut Context,
        keycode: event::Keycode,
        _keymod: event::Mod,
        _repeat: bool,
    ) {
        if keycode == event::Keycode::Space {
            self.overlay_visible = true;
        }
    }
}

impl State<SharedData> for OverlayState {
    fn stop(&mut self, shared_data: &mut SharedData, _ctx: &mut Context) {
        shared_data.rect_color = Color::next_color(&shared_data.rect_color);
    }

    fn update(
        &mut self,
        _shared_data: &mut SharedData,
        _ctx: &mut Context,
    ) -> GameResult<StateTransition<SharedData>> {
        if self.return_to_previous {
            Ok(StateTransition::Pop)
        } else {
            Ok(StateTransition::None)
        }
    }

    fn draw(&mut self, shared_data: &mut SharedData, ctx: &mut Context) -> GameResult<()> {
        // Shade the layers beneath
        let (width, height) = graphics::get_size(ctx);
        graphics::set_color(ctx, graphics::Color::new(0.0, 0.0, 0.0, 0.8))?;
        graphics::rectangle(
            ctx,
            graphics::DrawMode::Fill,
            graphics::Rect::new(0.0, 0.0, width as f32, height as f32),
        )?;

        // Draw filled circle
        graphics::set_color(ctx, shared_data.rect_color.clone().into())?;
        graphics::circle(
            ctx,
            graphics::DrawMode::Fill,
            graphics::Point2::new(350.0, 200.0),
            125.0,
            0.1,
        )?;

        // Draw outline
        graphics::set_color(ctx, graphics::BLACK)?;
        graphics::circle(
            ctx,
            graphics::DrawMode::Line(2.0),
            graphics::Point2::new(350.0, 200.0),
            125.0,
            0.1,
        )?;

        graphics::present(ctx);

        Ok(())
    }

    fn draw_previous_state(&mut self, _shared_data: &mut SharedData, _ctx: &mut Context) -> bool {
        true
    }

    fn key_up_event(
        &mut self,
        _shared_data: &mut SharedData,
        _ctx: &mut Context,
        keycode: event::Keycode,
        _keymod: event::Mod,
        _repeat: bool,
    ) {
        if keycode == event::Keycode::Space {
            self.return_to_previous = true;
        }
    }
}

fn main() {
    let mut conf = conf::Conf::new();
    conf.window_mode = conf::WindowMode::default().dimensions(600, 400);
    conf.window_setup = conf::WindowSetup::default()
        .title("statez - using_shared_data - press space to toggle overlay")
        .samples(4)
        .unwrap();
    let ctx = &mut Context::load_from_conf("using_shared_data", "statez", conf)
        .expect("Unable to create context");

    let shared_data = SharedData {
        rect_color: Color::Red,
    };

    let state_manager = &mut StateManager::new(shared_data, Box::new(BaseState::default()));

    event::run(ctx, state_manager).expect("Fatal error");

    println!("Terminated successfully.");
}