466 lines
16 KiB
Rust
466 lines
16 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use godot::{
|
|
classes::{
|
|
Button, Control, GridContainer, IPanelContainer, InputEvent, Label, LineEdit,
|
|
PanelContainer,
|
|
control::{FocusBehaviorRecursive, SizeFlags},
|
|
},
|
|
prelude::*,
|
|
};
|
|
|
|
use crate::{
|
|
game_settings::{GameSettings, GameSettingsManager, Keybind},
|
|
ui::slider::SliderContainer,
|
|
};
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
|
pub enum Setting {
|
|
// General settings
|
|
FoV,
|
|
DefaultName,
|
|
ReplayFPS,
|
|
|
|
// Volume settings
|
|
MasterVolume,
|
|
SfxVolume,
|
|
MusicVolume,
|
|
AnnouncerVolume,
|
|
|
|
// Keybinds
|
|
MoveLeft,
|
|
MoveForward,
|
|
MoveRight,
|
|
MoveBackward,
|
|
Shoot,
|
|
Melee,
|
|
Jump,
|
|
SelectRaygun,
|
|
SelectShotgun,
|
|
ThrowTelegrenade,
|
|
}
|
|
|
|
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::ReplayFPS => "Replay FPS",
|
|
|
|
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",
|
|
Setting::ThrowTelegrenade => "Throw Telegrenade",
|
|
}
|
|
.to_string()
|
|
}
|
|
}
|
|
|
|
impl Setting {
|
|
pub fn tab(&self) -> SettingsTab {
|
|
match self {
|
|
Setting::FoV => SettingsTab::General,
|
|
Setting::DefaultName => SettingsTab::General,
|
|
Setting::ReplayFPS => SettingsTab::General,
|
|
|
|
Setting::MasterVolume => SettingsTab::Volume,
|
|
Setting::SfxVolume => SettingsTab::Volume,
|
|
Setting::MusicVolume => SettingsTab::Volume,
|
|
Setting::AnnouncerVolume => SettingsTab::Volume,
|
|
|
|
_ => SettingsTab::Keybinds,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
|
pub enum SettingValue {
|
|
SliderNumber(SliderValue),
|
|
String(String),
|
|
Keybind(Keybind),
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
|
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>>,
|
|
#[export]
|
|
reset_button: Option<Gd<PackedScene>>,
|
|
|
|
settings: HashMap<Setting, SettingValue>,
|
|
default_settings: HashMap<Setting, SettingValue>,
|
|
|
|
keybind_button: Option<(Setting, Gd<Button>)>,
|
|
|
|
values: HashMap<Setting, Gd<Control>>,
|
|
reset_buttons: HashMap<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;
|
|
let default_settings = GameSettings::default();
|
|
settings_from(&mut self.settings, settings);
|
|
settings_from(&mut self.default_settings, &default_settings);
|
|
|
|
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 default_value = self.default_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(reset_btn) = &self.reset_button {
|
|
let mut button = reset_btn.instantiate_as::<Button>();
|
|
button.set_disabled(value == default_value);
|
|
|
|
let setting_clone = setting.clone();
|
|
let default_value_clone = default_value.clone();
|
|
button.signals().pressed().connect_other(self, move |s| {
|
|
s.change_value(setting_clone, default_value_clone.clone());
|
|
});
|
|
|
|
grid.add_child(&button);
|
|
self.reset_buttons.insert(*setting, button);
|
|
}
|
|
|
|
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()
|
|
}
|
|
};
|
|
|
|
self.values.insert(*setting, node.clone());
|
|
|
|
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 change_value(&mut self, setting: Setting, new_value: SettingValue) {
|
|
if let Some(control) = self.values.get(&setting).cloned() {
|
|
match new_value.clone() {
|
|
SettingValue::SliderNumber(slider_value) => {
|
|
if let Ok(mut slider) = control.try_cast::<SliderContainer>() {
|
|
slider.bind_mut().value = slider_value.value;
|
|
}
|
|
}
|
|
SettingValue::String(text) => {
|
|
if let Ok(mut edit) = control.try_cast::<LineEdit>() {
|
|
edit.set_text(&text);
|
|
self.on_change(setting, new_value);
|
|
}
|
|
}
|
|
SettingValue::Keybind(keybind) => {
|
|
if let Ok(mut button) = control.try_cast::<Button>() {
|
|
button.set_text(&keybind.to_string());
|
|
self.on_change(setting, new_value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn on_change(&mut self, setting: Setting, new_value: SettingValue) {
|
|
if let Some(reset_btn) = self.reset_buttons.get_mut(&setting)
|
|
&& let Some(default_value) = self.default_settings.get(&setting)
|
|
{
|
|
reset_btn.set_disabled(new_value == *default_value);
|
|
}
|
|
|
|
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::ReplayFPS, SettingValue::SliderNumber(value)) => {
|
|
new_settings.replay_fps = value.value as u8;
|
|
}
|
|
|
|
(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_shotgun = *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;
|
|
}
|
|
(Setting::ThrowTelegrenade, SettingValue::Keybind(keybind)) => {
|
|
new_settings.keybinds.telegrenade = *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);
|
|
}
|
|
}
|
|
|
|
fn settings_from(map: &mut HashMap<Setting, SettingValue>, settings: &GameSettings) {
|
|
map.insert(
|
|
Setting::FoV,
|
|
SettingValue::SliderNumber(SliderValue {
|
|
min: 60.,
|
|
max: 120.,
|
|
value: settings.fov,
|
|
}),
|
|
);
|
|
map.insert(
|
|
Setting::DefaultName,
|
|
SettingValue::String(settings.default_name.clone()),
|
|
);
|
|
map.insert(
|
|
Setting::ReplayFPS,
|
|
SettingValue::SliderNumber(SliderValue {
|
|
min: 1.,
|
|
max: 240.,
|
|
value: 60.,
|
|
}),
|
|
);
|
|
map.insert(
|
|
Setting::MasterVolume,
|
|
SettingValue::SliderNumber(SliderValue {
|
|
min: 0.,
|
|
max: 100.,
|
|
value: settings.volume.master_volume,
|
|
}),
|
|
);
|
|
map.insert(
|
|
Setting::SfxVolume,
|
|
SettingValue::SliderNumber(SliderValue {
|
|
min: 0.,
|
|
max: 100.,
|
|
value: settings.volume.sfx_volume,
|
|
}),
|
|
);
|
|
map.insert(
|
|
Setting::MusicVolume,
|
|
SettingValue::SliderNumber(SliderValue {
|
|
min: 0.,
|
|
max: 100.,
|
|
value: settings.volume.music_volume,
|
|
}),
|
|
);
|
|
map.insert(
|
|
Setting::AnnouncerVolume,
|
|
SettingValue::SliderNumber(SliderValue {
|
|
min: 0.,
|
|
max: 100.,
|
|
value: settings.volume.announcer_volume,
|
|
}),
|
|
);
|
|
|
|
map.insert(
|
|
Setting::MoveForward,
|
|
SettingValue::Keybind(settings.keybinds.move_forward),
|
|
);
|
|
map.insert(
|
|
Setting::MoveBackward,
|
|
SettingValue::Keybind(settings.keybinds.move_backward),
|
|
);
|
|
map.insert(
|
|
Setting::MoveLeft,
|
|
SettingValue::Keybind(settings.keybinds.move_left),
|
|
);
|
|
map.insert(
|
|
Setting::MoveRight,
|
|
SettingValue::Keybind(settings.keybinds.move_right),
|
|
);
|
|
map.insert(
|
|
Setting::SelectRaygun,
|
|
SettingValue::Keybind(settings.keybinds.select_raygun),
|
|
);
|
|
map.insert(
|
|
Setting::SelectShotgun,
|
|
SettingValue::Keybind(settings.keybinds.select_shotgun),
|
|
);
|
|
map.insert(
|
|
Setting::Shoot,
|
|
SettingValue::Keybind(settings.keybinds.shoot),
|
|
);
|
|
map.insert(
|
|
Setting::Melee,
|
|
SettingValue::Keybind(settings.keybinds.melee),
|
|
);
|
|
map.insert(Setting::Jump, SettingValue::Keybind(settings.keybinds.jump));
|
|
map.insert(
|
|
Setting::ThrowTelegrenade,
|
|
SettingValue::Keybind(settings.keybinds.telegrenade),
|
|
);
|
|
}
|