use std::collections::HashMap; use godot::{ classes::{Control, GridContainer, IPanel, Label, LineEdit, Panel, control::SizeFlags}, prelude::*, }; use crate::{game_settings::GameSettingsManager, ui::slider::SliderContainer}; #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Hash)] pub enum Setting { FoV, DefaultName, } impl ToString for Setting { fn to_string(&self) -> String { match self { Setting::FoV => "Field of View", Setting::DefaultName => "Default Name", } .to_string() } } #[derive(Clone)] pub enum SettingValue { SliderNumber(SliderValue), String(String), } #[derive(Clone, Copy)] pub struct SliderValue { min: f64, max: f64, value: f64, } #[derive(GodotClass)] #[class(base=Panel, init)] pub struct SettingsPanel { #[export] settings_grid: Option>, #[export] slider_scene: Option>, settings: HashMap, base: Base, } #[godot_api] impl IPanel 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()), ); if let Some(mut grid) = self.settings_grid.clone() { for (setting, value) in &self.settings { 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::(); 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::() } SettingValue::String(value) => { let mut text_edit = LineEdit::new_alloc(); text_edit.set_custom_minimum_size(Vector2::new(100., -1.)); text_edit.set_text(value); let setting_clone = setting.clone(); text_edit .signals() .text_changed() .connect_other(self, move |s, v| { s.on_change(setting_clone, SettingValue::String(v.to_string())); }); text_edit.upcast() } }; grid.add_child(&node); } } } } } #[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() } _ => {} } } 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); } }