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}