Minesweeper-rs/src/gui/settings_menu.rs
Alexander Bass 86dfecb4b3 init
2023-04-22 18:10:47 -04:00

230 lines
6.3 KiB
Rust

use crate::logic::game_board::ModifyMode;
use super::{
texture_store::TextureStore,
ui_event::{GUIEvent, GUIEvents},
Language, UIState,
};
use macroquad::{
hash,
prelude::*,
ui::{root_ui, widgets, Skin, Ui},
};
pub struct SettingsMenu {
mines: usize,
width: usize,
height: usize,
board_modify_mode: ModifyMode,
}
impl Default for SettingsMenu {
fn default() -> Self {
Self {
mines: 99,
width: 30,
height: 16,
board_modify_mode: ModifyMode::Flag,
}
}
}
impl SettingsMenu {
pub fn render(
&mut self,
ui_state: &UIState,
event_handler: &mut GUIEvents,
textures: &TextureStore,
skin: &Skin,
exit_button_skin: &Skin,
) {
let screen_width = screen_width();
let screen_height = screen_height();
let background_color = Color::from_rgba(192, 192, 192, 255);
root_ui().window(hash!(), vec2(0., 0.), vec2(screen_width, screen_height), |ui| {
draw_rectangle(0f32, 0f32, screen_width, screen_height, background_color);
ui.push_skin(&exit_button_skin);
if widgets::Button::new("").size(vec2(50.0, 50.0)).position(vec2(0f32, 0f32)).ui(ui) {
event_handler.add(GUIEvent::CloseSettings)
}
ui.pop_skin();
ui.push_skin(&skin);
let half_screen_width = screen_width * 0.5;
const MIN_MINEFIELD_WIDTH: usize = 5;
const MAX_MINEFIELD_WIDTH: usize = 100;
const MIN_MINEFIELD_HEIGHT: usize = 5;
const MAX_MINEFIELD_HEIGHT: usize = 100;
render_counter(
&mut self.width,
ui,
&textures,
vec2(half_screen_width, 100f32),
String::from("Minefield Width"),
MIN_MINEFIELD_WIDTH,
MAX_MINEFIELD_WIDTH,
);
render_counter(
&mut self.height,
ui,
&textures,
vec2(half_screen_width, 200f32),
String::from("Minefield Height"),
MIN_MINEFIELD_WIDTH,
MIN_MINEFIELD_HEIGHT,
);
render_counter(
&mut self.mines,
ui,
&textures,
vec2(half_screen_width, 300f32),
String::from("Mines"),
1,
self.width * self.height - 10,
);
const NEW_GAME_HEIGHT: f32 = 40f32;
const NEW_GAME_WIDTH: f32 = 250f32;
if widgets::Button::new("New Game")
.size(vec2(NEW_GAME_WIDTH, NEW_GAME_HEIGHT))
.position(vec2((screen_width - NEW_GAME_WIDTH) * 0.5, 0.0))
.ui(ui)
{
event_handler.add(GUIEvent::CreateNewGame(self.width, self.height, self.mines));
event_handler.add(GUIEvent::CloseSettings);
}
const BUTTON_MENU_WIDTH: f32 = 250f32;
let language_button_x = (screen_width - BUTTON_MENU_WIDTH) * 0.5;
const BUTTON_SIZE: f32 = 100f32;
const BUTTON_MENU_Y: f32 = 400f32;
let question_button_x = (screen_width - BUTTON_MENU_WIDTH) * 0.5 + (BUTTON_MENU_WIDTH - BUTTON_SIZE);
const BUTTON_MENU_LABEL_HEIGHT: f32 = 20f32;
widgets::Label::new("Language")
.position(vec2(language_button_x, BUTTON_MENU_Y - BUTTON_MENU_LABEL_HEIGHT))
.size(vec2(BUTTON_SIZE, BUTTON_MENU_LABEL_HEIGHT))
.ui(ui);
widgets::Label::new("Question Marking")
.position(vec2(question_button_x, BUTTON_MENU_Y - BUTTON_MENU_LABEL_HEIGHT))
.size(vec2(BUTTON_SIZE, BUTTON_MENU_LABEL_HEIGHT))
.ui(ui);
if let Language::English = ui_state.language {
if widgets::Button::new("English")
.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
.position(vec2(language_button_x, BUTTON_MENU_Y))
.ui(ui)
{
event_handler.add(GUIEvent::SwitchLanguage(Language::Japanese));
}
} else {
if widgets::Button::new("Japanese")
.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
.position(vec2(language_button_x, BUTTON_MENU_Y))
.ui(ui)
{
event_handler.add(GUIEvent::SwitchLanguage(Language::English));
}
}
if let ModifyMode::Question = self.board_modify_mode {
if widgets::Button::new("ON")
.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
.position(vec2(question_button_x, BUTTON_MENU_Y))
.ui(ui)
{
self.board_modify_mode = ModifyMode::Flag;
event_handler.add(GUIEvent::SetQuestionMode(ModifyMode::Flag));
}
} else {
if widgets::Button::new("OFF")
.size(vec2(BUTTON_SIZE, BUTTON_SIZE))
.position(vec2(question_button_x, BUTTON_MENU_Y))
.ui(ui)
{
self.board_modify_mode = ModifyMode::Question;
event_handler.add(GUIEvent::SetQuestionMode(ModifyMode::Question));
}
}
});
}
}
fn render_counter(
count: &mut usize,
ui: &mut Ui,
textures: &TextureStore,
position: Vec2,
title: String,
min: usize,
max: usize,
) {
let digits: Vec<usize> = {
let digits = count.to_string();
let digits = format!("{:0>3}", digits);
digits.chars().map(|i| (i.to_digit(10u32).unwrap_or(0)) as usize).collect()
};
const COUNTER_DIGIT_WIDTH: f32 = 13f32 * 2.0;
const COUNTER_DIGIT_HEIGHT: f32 = 23f32 * 2.0;
const COUNTER_BUTTON_HEIGHT: f32 = 30f32;
const COUNTER_BUTTON_MARGIN: f32 = 10f32;
const BUTTON_OFFSET_HEIGHT: f32 = (COUNTER_DIGIT_HEIGHT - COUNTER_BUTTON_HEIGHT) * 0.5;
let counter_width = digits.len() as f32 * COUNTER_DIGIT_WIDTH;
let position = position - vec2(counter_width * 0.5, 0.0);
for (x, digit) in digits.iter().enumerate() {
let position = vec2(COUNTER_DIGIT_WIDTH * x as f32, 0f32) + position;
widgets::Texture::new(textures.numbers[*digit])
.size(COUNTER_DIGIT_WIDTH, COUNTER_DIGIT_HEIGHT)
.position(position)
.ui(ui);
}
if widgets::Button::new("+")
.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
.position(position + vec2(counter_width + COUNTER_BUTTON_MARGIN, BUTTON_OFFSET_HEIGHT))
.ui(ui)
{
*count += 1;
}
if widgets::Button::new("-")
.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
.position(position - vec2(COUNTER_BUTTON_HEIGHT + COUNTER_BUTTON_MARGIN, -BUTTON_OFFSET_HEIGHT))
.ui(ui)
{
if *count > min {
*count -= 1;
}
}
if widgets::Button::new("++")
.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
.position(
position
+ vec2(
counter_width + COUNTER_BUTTON_MARGIN * 2.0 + COUNTER_BUTTON_HEIGHT,
BUTTON_OFFSET_HEIGHT,
),
)
.ui(ui)
{
*count += 10;
}
if widgets::Button::new("--")
.size(vec2(COUNTER_BUTTON_HEIGHT, COUNTER_BUTTON_HEIGHT))
.position(position - vec2((COUNTER_BUTTON_HEIGHT + COUNTER_BUTTON_MARGIN) * 2.0, -BUTTON_OFFSET_HEIGHT))
.ui(ui)
{
if *count as isize - 10 > min as isize {
*count -= 10;
} else {
*count = min;
}
}
if *count > max {
*count = max;
}
if *count < min {
*count = min;
}
let label_height = 20f32;
widgets::Label::new(title)
.position(position - vec2(0f32, label_height))
.size(vec2(counter_width, label_height))
.ui(ui);
}