diff --git a/godot/project.godot b/godot/project.godot index 4494731..ac04df6 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -21,6 +21,7 @@ NetworkManagerGlob="*uid://cxuy526twid8s" CommandLinePanelGlobal="*uid://bsb6asp5o35w3" GameManagerGlobal="*uid://bii6018k3ip3t" CliParserGlobal="*uid://c52o7xa0fnr53" +GameSettingsGlobal="*uid://bjr15hjiojecw" [display] diff --git a/godot/scenes/misc/game_settings.tscn b/godot/scenes/misc/game_settings.tscn new file mode 100644 index 0000000..890472f --- /dev/null +++ b/godot/scenes/misc/game_settings.tscn @@ -0,0 +1,3 @@ +[gd_scene format=3 uid="uid://bjr15hjiojecw"] + +[node name="game_settings" type="GameSettingsManager" unique_id=893289518] diff --git a/godot/scenes/player/local_player.tscn b/godot/scenes/player/local_player.tscn index 83c4222..7d20893 100644 --- a/godot/scenes/player/local_player.tscn +++ b/godot/scenes/player/local_player.tscn @@ -2,13 +2,14 @@ [ext_resource type="PackedScene" uid="uid://bod6b3befmyt5" path="res://scenes/player/soldier_m.tscn" id="1_jd651"] [ext_resource type="PackedScene" uid="uid://cl66unms2gim0" path="res://scenes/player/splorch.tscn" id="2_ywmwa"] +[ext_resource type="PackedScene" uid="uid://n3u0jr4wiib1" path="res://scenes/ui/settings.tscn" id="3_beej8"] [sub_resource type="Environment" id="Environment_3nx84"] glow_enabled = true [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_oh8vq"] -[node name="player" type="LocalPlayer" unique_id=863055906 node_paths=PackedStringArray("camera", "soldier_mesh", "collider", "splorch", "dead_cam_target", "respawn_label", "ball_origin", "weapon_node", "pause_panel", "exit_to_lobby")] +[node name="player" type="LocalPlayer" unique_id=863055906 node_paths=PackedStringArray("camera", "soldier_mesh", "collider", "splorch", "dead_cam_target", "respawn_label", "ball_origin", "weapon_node", "pause_panel", "exit_to_lobby", "settings_panel")] look_sensitivity = 1.5 camera = NodePath("camera_3d") move_speed = 5.0 @@ -21,6 +22,7 @@ ball_origin = NodePath("camera_3d") weapon_node = NodePath("camera_3d/weapon_node") pause_panel = NodePath("pause_menu") exit_to_lobby = NodePath("pause_menu/v_box_container/exit_to_lobby") +settings_panel = NodePath("settings") health = 100 collision_mask = 4 @@ -100,6 +102,10 @@ grow_horizontal = 2 grow_vertical = 2 alignment = 1 +[node name="settings" type="Button" parent="pause_menu/v_box_container" unique_id=676182211] +layout_mode = 2 +text = "Settings" + [node name="exit_to_lobby" type="Button" parent="pause_menu/v_box_container" unique_id=1816170399] layout_mode = 2 text = "Exit to Lobby" @@ -108,5 +114,9 @@ text = "Exit to Lobby" layout_mode = 2 text = "Exit" +[node name="settings" parent="." unique_id=999912383 instance=ExtResource("3_beej8")] +visible = false + +[connection signal="pressed" from="pause_menu/v_box_container/settings" to="settings" method="open"] [connection signal="pressed" from="pause_menu/v_box_container/exit_to_lobby" to="." method="exit_to_lobby"] [connection signal="pressed" from="pause_menu/v_box_container/exit" to="." method="exit"] diff --git a/rust/src/game_settings.rs b/rust/src/game_settings.rs index 84aeaa5..64da392 100644 --- a/rust/src/game_settings.rs +++ b/rust/src/game_settings.rs @@ -1,9 +1,12 @@ use godot::{ classes::{FileAccess, file_access::ModeFlags}, prelude::*, + tools::get_autoload_by_name, }; use serde::{Deserialize, Serialize}; +pub const NETWORK_SINGLETON_NAME: &str = "GameSettingsGlobal"; + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GameSettings { pub fov: f64, @@ -16,7 +19,7 @@ impl Default for GameSettings { } #[derive(GodotClass)] -#[class(base=Node, singleton)] +#[class(base=Node)] pub struct GameSettingsManager { pub settings: GameSettings, base: Base, @@ -35,7 +38,15 @@ impl INode for GameSettingsManager { } } +#[godot_api] impl GameSettingsManager { + #[signal] + pub fn on_settings_changed(); + + pub fn singleton() -> Gd { + get_autoload_by_name::(NETWORK_SINGLETON_NAME) + } + pub fn update_settings(&mut self, settings: GameSettings) { self.settings = settings; if let Some(mut file) = FileAccess::open("user://config.toml", ModeFlags::WRITE) { @@ -43,5 +54,6 @@ impl GameSettingsManager { file.store_string(&serialized); } } + self.run_deferred(|s| s.signals().on_settings_changed().emit()); } } diff --git a/rust/src/player.rs b/rust/src/player.rs index 274cca5..29a7feb 100644 --- a/rust/src/player.rs +++ b/rust/src/player.rs @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize}; use crate::{ game_manager::{Game, GameManager, GameOption}, + game_settings::{GameSettings, GameSettingsManager}, net::{ network_manager::{ NetworkManager, @@ -21,7 +22,7 @@ use crate::{ util::{NetVector3, cast_ray}, }, soldier_mesh::SoldierMesh, - ui::cli::CommandLinePanel, + ui::{cli::CommandLinePanel, settings::SettingsPanel}, weapon::{BallWeapon, Raygun, Weapon, WeaponType}, }; @@ -195,6 +196,8 @@ pub struct LocalPlayer { #[export] exit_to_lobby: Option>, #[export] + settings_panel: Option>, + #[export] health: i32, pub player_id: Option, @@ -375,6 +378,15 @@ impl IPlayer for LocalPlayer { #[godot_api] impl ICharacterBody3D for LocalPlayer { fn ready(&mut self) { + self.update_settings(&GameSettingsManager::singleton().bind().settings); + GameSettingsManager::singleton() + .bind_mut() + .signals() + .on_settings_changed() + .connect_other(self, |s| { + s.update_settings(&GameSettingsManager::singleton().bind().settings) + }); + if !CommandLinePanel::singleton().bind().opened { self.set_lock(true); } @@ -486,6 +498,11 @@ impl ICharacterBody3D for LocalPlayer { if let Some(pause_panel) = &mut self.pause_panel { let is_visible = pause_panel.is_visible(); pause_panel.set_visible(!is_visible); + if !pause_panel.is_visible() { + if let Some(settings_panel) = &mut self.settings_panel { + settings_panel.set_visible(false); + } + } self.update_lock(); } } @@ -611,6 +628,12 @@ impl LocalPlayer { GameManager::singleton().bind_mut().exit_game(); NetworkManager::singleton().bind_mut().disconnect(); } + + pub fn update_settings(&mut self, settings: &GameSettings) { + if let Some(camera) = &mut self.camera { + camera.set_fov(settings.fov as f32); + } + } } #[derive(GodotClass)]