rough/ui/
mod.rs

1use cubik::glium::{self, Display, Frame};
2use cubik::fonts::LoadedFont;
3use cubik::ui::{ImageBackground, TextButton, UIError, TextInput};
4use cubik::input::InputListener;
5use cubik::glium::glutin::event::{VirtualKeyCode, ElementState, MouseButton};
6use crate::support::constants::APP_ID;
7
8const NORMAL_COLOR: [f32; 4] = [0.94, 0.94, 0.94, 1.];
9const HOVER_COLOR: [f32; 4] = [1., 1., 0.2, 1.];
10const WHITE: [f32; 4] = [1., 1., 1., 1.];
11
12#[derive(Copy, Clone)]
13pub enum MainMenuAction {
14	Start,
15	Quit
16}
17
18pub struct MainMenu {
19	pub enabled: bool,
20	buttons: Vec<(MainMenuAction, TextButton)>,
21	btn_font: LoadedFont,
22	bg: ImageBackground,
23	result: Option<MainMenuAction>,
24	start_dialog: StartDialog
25}
26
27impl MainMenu {
28	pub fn new(display: &Display) -> Result<Self, UIError> {
29		Ok(Self {
30			enabled: false,
31			buttons: vec![
32				(MainMenuAction::Start,
33				 	TextButton::new("Start".to_string(), 0.15, (0., -0.3), (0.2, 0.05), NORMAL_COLOR, HOVER_COLOR)),
34				(MainMenuAction::Quit,
35				 	TextButton::new("Quit".to_string(), 0.15, (0., -0.5), (0.2, 0.05), NORMAL_COLOR, HOVER_COLOR))
36			],
37			bg: ImageBackground::new(display, "./textures/mainmenu.jpg", APP_ID, (0., 0.), (3.55, 2.))?,
38			btn_font: LoadedFont::load(display, "./fonts/SourceCodePro-Light.otf", APP_ID, 80.)?,
39			start_dialog: StartDialog::new(display)?,
40			result: None
41		})
42	}
43
44	pub fn draw(&mut self, target: &mut Frame, display: &Display, ui_program: &glium::Program) -> Result<Option<MainMenuAction>, UIError> {
45		self.bg.draw(target, ui_program);
46		for (_, button) in &mut self.buttons {
47			button.draw(target, display, ui_program, &self.btn_font)?;
48		}
49		if self.start_dialog.enabled { self.result = self.start_dialog.draw(target, display, ui_program, &self.btn_font)?; }
50		
51		if let Some(result) = self.result {
52			self.result = None;
53			return Ok(Some(result));
54		}
55		Ok(None)
56	}
57}
58
59impl InputListener for MainMenu {
60	fn handle_key_ev(&mut self, key: Option<VirtualKeyCode>, pressed: bool) -> bool {
61		if !self.enabled { return false; }
62		self.start_dialog.handle_key_ev(key, pressed)
63	}
64
65	fn handle_mouse_pos_ev(&mut self, pos: (f32, f32), display: &Display) -> bool {
66		if !self.enabled { return false; }
67		for (_, button) in &mut self.buttons {
68			button.handle_mouse_pos_ev(pos, display);
69		}
70		self.start_dialog.handle_mouse_pos_ev(pos, display);
71		true
72	}
73
74	fn handle_mouse_ev(&mut self, mouse_button: MouseButton, state: ElementState) -> bool {
75		if !self.enabled { return false; }
76		for (name, button) in &mut self.buttons {
77			if button.handle_mouse_ev(mouse_button, state) {
78				match name {
79					MainMenuAction::Start => self.start_dialog.enabled = true,
80					_ => self.result = Some(*name)
81				};
82				return true;
83			}
84		}
85		if self.start_dialog.handle_mouse_ev(mouse_button, state) { return true; }
86		false
87	}
88
89	fn handle_char_ev(&mut self, ch: char) -> bool {
90		if !self.enabled { return false; }
91		self.start_dialog.handle_char_ev(ch)
92	}
93}
94
95struct StartDialog {
96	bg: ImageBackground,
97	ip_input: TextInput,
98	start_btn: TextButton,
99	enabled: bool,
100	result: Option<MainMenuAction>
101}
102
103impl StartDialog {
104	pub fn new(display: &Display) -> Result<Self, UIError> {
105		Ok(Self {
106			bg: ImageBackground::new(display, "./textures/dialog.png", APP_ID, (0., -0.17), (1.0, 0.7))?,
107			start_btn: TextButton::new("Start".to_string(), 0.08, (0.2, -0.2), (0.2, 0.05), NORMAL_COLOR, HOVER_COLOR),
108			ip_input: TextInput::new((-0.45, -0.15), (0.85, 0.12), WHITE),
109			enabled: false,
110			result: None
111		})
112	}
113
114	pub fn draw(&mut self, target: &mut Frame, display: &Display, ui_program: &glium::Program, font: &LoadedFont) -> Result<Option<MainMenuAction>, UIError> {
115		self.bg.draw(target, ui_program);
116		self.ip_input.draw(target, display, ui_program, font)?;
117		self.start_btn.draw(target, display, ui_program, font)?;
118		if let Some(result) = self.result {
119			self.result = None;
120			return Ok(Some(result));
121		}
122		Ok(None)
123	}
124}
125
126impl InputListener for StartDialog {
127	fn handle_key_ev(&mut self, key: Option<VirtualKeyCode>, pressed: bool) -> bool {
128		if !self.enabled { return false; }
129		self.ip_input.handle_key_ev(key, pressed)
130	}
131
132	fn handle_mouse_pos_ev(&mut self, pos: (f32, f32), display: &Display) -> bool {
133		if !self.enabled { return false; }
134		if self.ip_input.handle_mouse_pos_ev(pos, display) { return true; }
135		self.start_btn.handle_mouse_pos_ev(pos, display)
136	}
137
138	fn handle_mouse_ev(&mut self, mouse_button: MouseButton, state: ElementState) -> bool {
139		if !self.enabled { return false; }
140		if self.ip_input.handle_mouse_ev(mouse_button, state) { return true; }
141		if self.start_btn.handle_mouse_ev(mouse_button, state) {
142			self.result = Some(MainMenuAction::Start);
143			return true;
144		}
145		false
146	}
147
148	fn handle_char_ev(&mut self, ch: char) -> bool {
149		if !self.enabled { return false; }
150		self.ip_input.handle_char_ev(ch)
151	}
152}