use cubik::glium::{self, Display, Frame}; use cubik::fonts::LoadedFont; use cubik::ui::{ImageBackground, TextButton, UIError, TextInput}; use cubik::input::InputListener; use cubik::glium::glutin::event::{VirtualKeyCode, ElementState, MouseButton}; use crate::support::constants::APP_ID; const NORMAL_COLOR: [f32; 4] = [0.94, 0.94, 0.94, 1.]; const HOVER_COLOR: [f32; 4] = [1., 1., 0.2, 1.]; const WHITE: [f32; 4] = [1., 1., 1., 1.]; #[derive(Copy, Clone)] pub enum MainMenuAction { Start, Quit } pub struct MainMenu { pub enabled: bool, buttons: Vec<(MainMenuAction, TextButton)>, btn_font: LoadedFont, bg: ImageBackground, result: Option, start_dialog: StartDialog } impl MainMenu { pub fn new(display: &Display) -> Result { Ok(Self { enabled: false, buttons: vec![ (MainMenuAction::Start, TextButton::new("Start".to_string(), 0.15, (0., -0.3), (0.2, 0.05), NORMAL_COLOR, HOVER_COLOR)), (MainMenuAction::Quit, TextButton::new("Quit".to_string(), 0.15, (0., -0.5), (0.2, 0.05), NORMAL_COLOR, HOVER_COLOR)) ], bg: ImageBackground::new(display, "./textures/mainmenu.jpg", APP_ID, (0., 0.), (3.55, 2.))?, btn_font: LoadedFont::load(display, "./fonts/SourceCodePro-Light.otf", APP_ID, 80.)?, start_dialog: StartDialog::new(display)?, result: None }) } pub fn draw(&mut self, target: &mut Frame, display: &Display, ui_program: &glium::Program) -> Result, UIError> { self.bg.draw(target, ui_program); for (_, button) in &mut self.buttons { button.draw(target, display, ui_program, &self.btn_font)?; } if self.start_dialog.enabled { self.result = self.start_dialog.draw(target, display, ui_program, &self.btn_font)?; } if let Some(result) = self.result { self.result = None; return Ok(Some(result)); } Ok(None) } } impl InputListener for MainMenu { fn handle_key_ev(&mut self, key: Option, pressed: bool) -> bool { if !self.enabled { return false; } self.start_dialog.handle_key_ev(key, pressed) } fn handle_mouse_pos_ev(&mut self, pos: (f32, f32), display: &Display) -> bool { if !self.enabled { return false; } for (_, button) in &mut self.buttons { button.handle_mouse_pos_ev(pos, display); } self.start_dialog.handle_mouse_pos_ev(pos, display); true } fn handle_mouse_ev(&mut self, mouse_button: MouseButton, state: ElementState) -> bool { if !self.enabled { return false; } for (name, button) in &mut self.buttons { if button.handle_mouse_ev(mouse_button, state) { match name { MainMenuAction::Start => self.start_dialog.enabled = true, _ => self.result = Some(*name) }; return true; } } if self.start_dialog.handle_mouse_ev(mouse_button, state) { return true; } false } fn handle_char_ev(&mut self, ch: char) -> bool { if !self.enabled { return false; } self.start_dialog.handle_char_ev(ch) } } struct StartDialog { bg: ImageBackground, ip_input: TextInput, start_btn: TextButton, enabled: bool, result: Option } impl StartDialog { pub fn new(display: &Display) -> Result { Ok(Self { bg: ImageBackground::new(display, "./textures/dialog.png", APP_ID, (0., -0.17), (1.0, 0.7))?, start_btn: TextButton::new("Start".to_string(), 0.08, (0.2, -0.2), (0.2, 0.05), NORMAL_COLOR, HOVER_COLOR), ip_input: TextInput::new((-0.45, -0.15), (0.85, 0.12), WHITE), enabled: false, result: None }) } pub fn draw(&mut self, target: &mut Frame, display: &Display, ui_program: &glium::Program, font: &LoadedFont) -> Result, UIError> { self.bg.draw(target, ui_program); self.ip_input.draw(target, display, ui_program, font)?; self.start_btn.draw(target, display, ui_program, font)?; if let Some(result) = self.result { self.result = None; return Ok(Some(result)); } Ok(None) } } impl InputListener for StartDialog { fn handle_key_ev(&mut self, key: Option, pressed: bool) -> bool { if !self.enabled { return false; } self.ip_input.handle_key_ev(key, pressed) } fn handle_mouse_pos_ev(&mut self, pos: (f32, f32), display: &Display) -> bool { if !self.enabled { return false; } if self.ip_input.handle_mouse_pos_ev(pos, display) { return true; } self.start_btn.handle_mouse_pos_ev(pos, display) } fn handle_mouse_ev(&mut self, mouse_button: MouseButton, state: ElementState) -> bool { if !self.enabled { return false; } if self.ip_input.handle_mouse_ev(mouse_button, state) { return true; } if self.start_btn.handle_mouse_ev(mouse_button, state) { self.result = Some(MainMenuAction::Start); return true; } false } fn handle_char_ev(&mut self, ch: char) -> bool { if !self.enabled { return false; } self.ip_input.handle_char_ev(ch) } }