skullball/rust/src/ui/settings.rs

385 lines
13 KiB
Rust

use std::collections::HashMap;
use godot::{
classes::{
Button, Control, GridContainer, IPanelContainer, InputEvent, InputEventKey,
InputEventMouseButton, InputMap, Label, LineEdit, PanelContainer,
control::{FocusBehaviorRecursive, FocusMode, SizeFlags},
},
prelude::*,
};
use crate::{
game_settings::{GameSettingsManager, Keybind},
ui::slider::SliderContainer,
};
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum Setting {
// General settings
FoV,
DefaultName,
// Volume settings
MasterVolume,
SfxVolume,
MusicVolume,
AnnouncerVolume,
// Keybinds
MoveLeft,
MoveForward,
MoveRight,
MoveBackward,
Shoot,
Melee,
Jump,
SelectRaygun,
SelectShotgun,
}
pub enum SettingsTab {
General,
Volume,
Keybinds,
}
impl ToString for Setting {
fn to_string(&self) -> String {
match self {
Setting::FoV => "Field of View",
Setting::DefaultName => "Default Name",
Setting::MasterVolume => "Master volume",
Setting::SfxVolume => "Sfx Volume",
Setting::MusicVolume => "Music Volume",
Setting::AnnouncerVolume => "Announcer Volume",
Setting::MoveLeft => "Move left",
Setting::MoveRight => "Move right",
Setting::MoveForward => "Move forward",
Setting::MoveBackward => "Move backward",
Setting::SelectRaygun => "Select Raygun",
Setting::SelectShotgun => "Select Shotgun",
Setting::Shoot => "Shoot",
Setting::Melee => "Melee",
Setting::Jump => "Jump",
}
.to_string()
}
}
impl Setting {
pub fn tab(&self) -> SettingsTab {
match self {
Setting::FoV => SettingsTab::General,
Setting::DefaultName => SettingsTab::General,
Setting::MasterVolume => SettingsTab::Volume,
Setting::SfxVolume => SettingsTab::Volume,
Setting::MusicVolume => SettingsTab::Volume,
Setting::AnnouncerVolume => SettingsTab::Volume,
_ => SettingsTab::Keybinds,
}
}
}
#[derive(Clone)]
pub enum SettingValue {
SliderNumber(SliderValue),
String(String),
Keybind(Keybind),
}
#[derive(Clone, Copy)]
pub struct SliderValue {
min: f64,
max: f64,
value: f64,
}
#[derive(GodotClass)]
#[class(base=PanelContainer, init)]
pub struct SettingsPanel {
#[export]
general_grid: Option<Gd<GridContainer>>,
#[export]
volume_grid: Option<Gd<GridContainer>>,
#[export]
keybinds_grid: Option<Gd<GridContainer>>,
#[export]
slider_scene: Option<Gd<PackedScene>>,
settings: HashMap<Setting, SettingValue>,
keybind_button: Option<(Setting, Gd<Button>)>,
base: Base<PanelContainer>,
}
#[godot_api]
impl IPanelContainer for SettingsPanel {
fn ready(&mut self) {
let singleton = GameSettingsManager::singleton();
let settings = &singleton.bind().settings;
self.settings.insert(
Setting::FoV,
SettingValue::SliderNumber(SliderValue {
min: 60.,
max: 120.,
value: settings.fov,
}),
);
self.settings.insert(
Setting::DefaultName,
SettingValue::String(settings.default_name.clone()),
);
self.settings.insert(
Setting::MasterVolume,
SettingValue::SliderNumber(SliderValue {
min: 0.,
max: 100.,
value: settings.volume.master_volume,
}),
);
self.settings.insert(
Setting::SfxVolume,
SettingValue::SliderNumber(SliderValue {
min: 0.,
max: 100.,
value: settings.volume.sfx_volume,
}),
);
self.settings.insert(
Setting::MusicVolume,
SettingValue::SliderNumber(SliderValue {
min: 0.,
max: 100.,
value: settings.volume.music_volume,
}),
);
self.settings.insert(
Setting::AnnouncerVolume,
SettingValue::SliderNumber(SliderValue {
min: 0.,
max: 100.,
value: settings.volume.announcer_volume,
}),
);
self.settings.insert(
Setting::MoveForward,
SettingValue::Keybind(settings.keybinds.move_forward),
);
self.settings.insert(
Setting::MoveBackward,
SettingValue::Keybind(settings.keybinds.move_backward),
);
self.settings.insert(
Setting::MoveLeft,
SettingValue::Keybind(settings.keybinds.move_left),
);
self.settings.insert(
Setting::MoveRight,
SettingValue::Keybind(settings.keybinds.move_right),
);
self.settings.insert(
Setting::SelectRaygun,
SettingValue::Keybind(settings.keybinds.select_raygun),
);
self.settings.insert(
Setting::SelectShotgun,
SettingValue::Keybind(settings.keybinds.select_shotgun),
);
self.settings.insert(
Setting::Shoot,
SettingValue::Keybind(settings.keybinds.shoot),
);
self.settings.insert(
Setting::Melee,
SettingValue::Keybind(settings.keybinds.melee),
);
self.settings
.insert(Setting::Jump, SettingValue::Keybind(settings.keybinds.jump));
let mut keys = self.settings.keys().collect::<Vec<_>>();
keys.sort();
for setting in keys.into_iter() {
let value = self.settings.get(setting).unwrap().clone();
let grid = match setting.tab() {
SettingsTab::General => self.general_grid.clone(),
SettingsTab::Volume => self.volume_grid.clone(),
SettingsTab::Keybinds => self.keybinds_grid.clone(),
};
if let Some(mut grid) = grid {
let mut label = Label::new_alloc();
label.set_text(&setting.to_string());
label.set_h_size_flags(SizeFlags::EXPAND | SizeFlags::SHRINK_BEGIN);
grid.add_child(&label);
if let Some(scene) = self.slider_scene.clone() {
let node = match value {
SettingValue::SliderNumber(slider_value) => {
let mut slider = scene.instantiate_as::<SliderContainer>();
slider.bind_mut().min = slider_value.min;
slider.bind_mut().max = slider_value.max;
slider.bind_mut().value = slider_value.value;
let setting_clone = setting.clone();
let value_clone = slider_value.clone();
slider.bind_mut().signals().on_change().connect_other(
self,
move |s, new_value| {
s.run_deferred(move |s| {
s.on_change(
setting_clone,
SettingValue::SliderNumber(SliderValue {
value: new_value,
..value_clone
}),
)
})
},
);
slider.upcast::<Control>()
}
SettingValue::String(value) => {
let mut line_edit = LineEdit::new_alloc();
line_edit.set_custom_minimum_size(Vector2::new(100., -1.));
line_edit.set_text(&value);
line_edit.set_max_length(20);
let setting_clone = setting.clone();
line_edit
.signals()
.text_changed()
.connect_other(self, move |s, v| {
s.on_change(setting_clone, SettingValue::String(v.to_string()));
});
line_edit.upcast()
}
SettingValue::Keybind(value) => {
let mut toggle_button = Button::new_alloc();
toggle_button.set_text(&value.to_string());
toggle_button.set_toggle_mode(true);
let setting_clone = setting.clone();
let button_clone = toggle_button.clone();
toggle_button
.signals()
.pressed()
.connect_other(self, move |s| {
if let Some((_, mut button)) = s.keybind_button.take() {
button.set_pressed(false);
}
s.base_mut().set_focus_behavior_recursive(
FocusBehaviorRecursive::DISABLED,
);
s.keybind_button = Some((setting_clone, button_clone.clone()))
});
toggle_button.upcast()
}
};
grid.add_child(&node);
}
}
}
}
fn input(&mut self, event: Gd<InputEvent>) {
if let Some((setting, mut button)) = self.keybind_button.clone()
&& let Some(keybind) = Keybind::from_event(event)
{
self.keybind_button.take();
self.on_change(setting.clone(), SettingValue::Keybind(keybind));
button.set_text(&keybind.to_string());
button.set_pressed(false);
self.base_mut()
.set_focus_behavior_recursive(FocusBehaviorRecursive::INHERITED);
}
}
}
#[godot_api]
impl SettingsPanel {
pub fn on_change(&mut self, setting: Setting, new_value: SettingValue) {
self.settings.insert(setting, new_value);
let mut new_settings = GameSettingsManager::singleton().bind().settings.clone();
for (setting, value) in &self.settings {
match (setting, value) {
(Setting::FoV, SettingValue::SliderNumber(value)) => {
new_settings.fov = value.value;
}
(Setting::DefaultName, SettingValue::String(value)) => {
new_settings.default_name = value.clone()
}
(Setting::MasterVolume, SettingValue::SliderNumber(value)) => {
new_settings.volume.master_volume = value.value;
}
(Setting::SfxVolume, SettingValue::SliderNumber(value)) => {
new_settings.volume.sfx_volume = value.value;
}
(Setting::MusicVolume, SettingValue::SliderNumber(value)) => {
new_settings.volume.music_volume = value.value;
}
(Setting::AnnouncerVolume, SettingValue::SliderNumber(value)) => {
new_settings.volume.announcer_volume = value.value;
}
(Setting::MoveRight, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.move_right = *keybind;
}
(Setting::MoveLeft, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.move_left = *keybind;
}
(Setting::MoveForward, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.move_forward = *keybind;
}
(Setting::MoveBackward, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.move_backward = *keybind;
}
(Setting::SelectRaygun, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.select_raygun = *keybind;
}
(Setting::SelectShotgun, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.select_raygun = *keybind;
}
(Setting::Shoot, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.shoot = *keybind;
}
(Setting::Melee, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.melee = *keybind;
}
(Setting::Jump, SettingValue::Keybind(keybind)) => {
new_settings.keybinds.jump = *keybind;
}
_ => {}
}
}
GameSettingsManager::singleton()
.bind_mut()
.update_settings(new_settings);
}
#[func]
pub fn open(&mut self) {
self.base_mut().set_visible(true);
}
#[func]
pub fn close(&mut self) {
self.base_mut().set_visible(false);
}
}