From 38a84588e56a965661d6df0280c2406ef5304aad Mon Sep 17 00:00:00 2001 From: Sofia Date: Mon, 3 Aug 2026 21:26:35 +0300 Subject: [PATCH] Add initial team settings to lobby as well --- godot/scenes/lobby.tscn | 50 ++++++------ rust/src/ui/lobby.rs | 175 +++++++++++++++++++++++++++++----------- 2 files changed, 151 insertions(+), 74 deletions(-) diff --git a/godot/scenes/lobby.tscn b/godot/scenes/lobby.tscn index 4aa56d7..df0884a 100644 --- a/godot/scenes/lobby.tscn +++ b/godot/scenes/lobby.tscn @@ -17,21 +17,19 @@ bg_color = Color(0.06469653, 0.064696535, 0.06469648, 0.34901962) [sub_resource type="LabelSettings" id="LabelSettings_1cgct"] font_size = 32 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jbm04"] -bg_color = Color(0.30692267, 0.3069227, 0.30692264, 1) - [node name="lobby_world" type="LobbyWorld" unique_id=129662054 node_paths=PackedStringArray("lobby")] menu_player_scene = ExtResource("3_q60fs") lobby = NodePath("lobby") -[node name="lobby" type="LobbyPanel" parent="." unique_id=915192272 node_paths=PackedStringArray("players_list", "name_field", "ready_button", "map_selection", "options_panel", "options_grid", "alt_colors")] +[node name="lobby" type="LobbyPanel" parent="." unique_id=915192272 node_paths=PackedStringArray("players_list", "name_field", "ready_button", "map_selection", "options_panel", "options_grid", "options_tabs", "alt_colors")] players_list = NodePath("v_box_container/players_list") name_field = NodePath("v_box_container/h_box_container/text_edit") player_listing_prefab = ExtResource("1_o1atq") ready_button = NodePath("v_box_container3/ready_button") map_selection = NodePath("v_box_container2/option_button") options_panel = NodePath("options_panel") -options_grid = NodePath("options_panel/h_box_container/options_grid") +options_grid = NodePath("options_panel/h_box_container/tab_container/general") +options_tabs = NodePath("options_panel/h_box_container/tab_container") alt_colors = NodePath("v_box_container/h_box_container/check_box") start_game_icon = ExtResource("3_oipnb") ready_icon = ExtResource("4_yad6j") @@ -107,7 +105,6 @@ theme_override_constants/icon_max_width = 100 metadata/_edit_lock_ = true [node name="options_panel" type="Panel" parent="lobby" unique_id=1194589850] -visible = false layout_mode = 1 anchors_preset = 8 anchor_left = 0.5 @@ -120,35 +117,36 @@ offset_right = 291.5 offset_bottom = 213.5 grow_horizontal = 2 grow_vertical = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_jbm04") - -[node name="options_close" type="Button" parent="lobby/options_panel" unique_id=2115857774] -layout_mode = 1 -anchors_preset = 1 -anchor_left = 1.0 -anchor_right = 1.0 -offset_left = -33.5 -offset_bottom = 31.0 -grow_horizontal = 0 -text = "X" [node name="h_box_container" type="VBoxContainer" parent="lobby/options_panel" unique_id=1163233032] -layout_mode = 0 -offset_left = 0.5 -offset_top = 3.5 -offset_right = 115.5 -offset_bottom = 43.5 +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 -[node name="label" type="Label" parent="lobby/options_panel/h_box_container" unique_id=1002581329] +[node name="h_box_container" type="HBoxContainer" parent="lobby/options_panel/h_box_container" unique_id=1966956919] layout_mode = 2 + +[node name="label" type="Label" parent="lobby/options_panel/h_box_container/h_box_container" unique_id=1002581329] +layout_mode = 2 +size_flags_horizontal = 3 text = "Game Options" -[node name="v_box_container" type="HBoxContainer" parent="lobby/options_panel/h_box_container" unique_id=1445409921] +[node name="options_close" type="Button" parent="lobby/options_panel/h_box_container/h_box_container" unique_id=2115857774] layout_mode = 2 +text = "X" -[node name="options_grid" type="GridContainer" parent="lobby/options_panel/h_box_container" unique_id=504671462] +[node name="tab_container" type="TabContainer" parent="lobby/options_panel/h_box_container" unique_id=1185146072] +layout_mode = 2 +size_flags_vertical = 3 +current_tab = 0 + +[node name="general" type="GridContainer" parent="lobby/options_panel/h_box_container/tab_container" unique_id=504671462] layout_mode = 2 columns = 2 +metadata/_tab_index = 0 [node name="chat_box" parent="lobby" unique_id=1125601400 instance=ExtResource("2_5gu6x")] custom_minimum_size = Vector2(400, 300) @@ -229,7 +227,7 @@ current = true [node name="two_towers_static" parent="background" unique_id=86902040 instance=ExtResource("6_apkv3")] transform = Transform3D(-0.1736482, 0, -0.9848077, 0, 1, 0, 0.9848077, 0, -0.1736482, -15.664, -7, -7.637) -[connection signal="pressed" from="lobby/options_panel/options_close" to="lobby" method="close_options"] +[connection signal="pressed" from="lobby/options_panel/h_box_container/h_box_container/options_close" to="lobby" method="close_options"] [connection signal="pressed" from="lobby/v_box_container3/h_box_container/exit_button" to="lobby" method="exit"] [connection signal="pressed" from="lobby/v_box_container3/h_box_container/options_button" to="lobby" method="open_options"] [connection signal="pressed" from="lobby/v_box_container3/h_box_container/settings_button" to="lobby/settings" method="open"] diff --git a/rust/src/ui/lobby.rs b/rust/src/ui/lobby.rs index 43456f0..af1dcff 100644 --- a/rust/src/ui/lobby.rs +++ b/rust/src/ui/lobby.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use godot::{ classes::{ Button, CheckBox, CompressedTexture2D, Control, GridContainer, IPanel, Label, LineEdit, - OptionButton, Panel, SpinBox, VBoxContainer, + OptionButton, Panel, SpinBox, TabContainer, VBoxContainer, }, prelude::*, }; @@ -37,9 +37,13 @@ pub struct LobbyPanel { #[export] options_grid: Option>, #[export] + options_tabs: Option>, + #[export] alt_colors: Option>, option_nodes: HashMap>, + team_grids: HashMap>, + team_option_nodes: HashMap>>, #[export] start_game_icon: Option>, @@ -112,6 +116,11 @@ impl IPanel for LobbyPanel { } }); }); + game.signals().on_map_changed().connect_other(self, |s, _| { + s.run_deferred(|s| { + s.generate_team_options(); + }); + }); let is_host = if let Some(peer) = &NetworkManager::singleton().bind().peer { peer.is_host() @@ -186,53 +195,11 @@ impl IPanel for LobbyPanel { self.update_ready_button(); - let mut nodes = Vec::new(); - if let Some(game) = Game::singleton() { - for (option, value) in &game.bind().opts.values { - let mut label = Label::new_alloc(); - label.set_text(&format!("{}:", option.to_string())); - nodes.push(label.upcast()); - - let value_node = match value { - GameOptionValue::Boolean(value) => { - let mut checkbox = CheckBox::new_alloc(); - checkbox.set_pressed(*value); - checkbox.set_disabled(!NetworkManager::singleton().bind().is_host()); - - let checkbox_clone = checkbox.clone(); - let option = option.clone(); - checkbox.signals().pressed().connect_other(self, move |s| { - s.option_changed( - option, - GameOptionValue::Boolean(checkbox_clone.is_pressed()), - ); - }); - - self.option_nodes.insert(option, checkbox.clone().upcast()); - - checkbox.upcast::() - } - GameOptionValue::Number(value) => { - let mut spinbox = SpinBox::new_alloc(); - spinbox.set_value(*value); - spinbox.set_editable(NetworkManager::singleton().bind().is_host()); - - let option = option.clone(); - spinbox.signals().value_changed().connect_other( - self, - move |s, new_value| { - s.option_changed(option, GameOptionValue::Number(new_value)); - }, - ); - - self.option_nodes.insert(option, spinbox.clone().upcast()); - - spinbox.upcast() - } - }; - nodes.push(value_node); - } - } + let nodes = if let Some(game) = Game::singleton() { + self.generate_options(&game.bind().opts.values, None) + } else { + Vec::new() + }; if let Some(grid) = &mut self.options_grid { for node in nodes { @@ -240,6 +207,8 @@ impl IPanel for LobbyPanel { } } + self.generate_team_options(); + MusicManager::singleton() .bind_mut() .play(Some(Music::MainMenu), false); @@ -283,6 +252,12 @@ impl LobbyPanel { } } + fn team_option_changed(&mut self, team: u8, key: GameOption, value: GameOptionValue) { + if let Some(game) = &mut Game::singleton() { + game.bind_mut().change_team_option(team, key, value); + } + } + fn on_game_opts_update(&mut self, opts: &GameOptions, is_host: bool) { if let Some(selection) = &mut self.map_selection { selection.set_disabled(!is_host && !opts.is_true(GameOption::AllowAnyMap)); @@ -440,4 +415,108 @@ impl LobbyPanel { } idx } + + fn generate_team_options(&mut self) { + if let Some(mut tabs) = self.options_tabs.clone() { + for (_, grid) in self.team_grids.clone() { + tabs.remove_child(&grid); + } + self.team_grids.clear(); + self.team_option_nodes.clear(); + + if let Some(game) = Game::singleton() { + for (id, team) in game.bind().get_teams().iter_shared().enumerate() { + let mut grid = GridContainer::new_alloc(); + grid.set_name(&team.bind().name.to_string()); + grid.set_columns(2); + + if let Some(opts) = game.bind().get_team_opts(id as u8) { + let nodes = self.generate_options(&opts.values, Some(id as u8)); + for node in nodes { + grid.add_child(&node); + } + } + tabs.add_child(&grid); + self.team_grids.insert(id as u8, grid); + } + } + } + } + + fn generate_options( + &mut self, + opts: &HashMap, + team: Option, + ) -> Vec> { + let mut nodes = Vec::new(); + for (option, value) in opts { + let mut label = Label::new_alloc(); + label.set_text(&format!("{}:", option.to_string())); + nodes.push(label.upcast()); + + let value_node = match value { + GameOptionValue::Boolean(value) => { + let mut checkbox = CheckBox::new_alloc(); + checkbox.set_pressed(*value); + checkbox.set_disabled(!NetworkManager::singleton().bind().is_host()); + + let checkbox_clone = checkbox.clone(); + let option = option.clone(); + checkbox.signals().pressed().connect_other(self, move |s| { + if let Some(team) = team { + s.team_option_changed( + team, + option, + GameOptionValue::Boolean(checkbox_clone.is_pressed()), + ); + } else { + s.option_changed( + option, + GameOptionValue::Boolean(checkbox_clone.is_pressed()), + ); + } + }); + + checkbox.upcast::() + } + GameOptionValue::Number(value) => { + let mut spinbox = SpinBox::new_alloc(); + spinbox.set_value(*value); + spinbox.set_editable(NetworkManager::singleton().bind().is_host()); + + let option = option.clone(); + spinbox + .signals() + .value_changed() + .connect_other(self, move |s, new_value| { + if let Some(team) = team { + s.team_option_changed( + team, + option, + GameOptionValue::Number(new_value), + ); + } else { + s.option_changed(option, GameOptionValue::Number(new_value)); + } + }); + + spinbox.upcast() + } + }; + if let Some(team) = team { + if let Some(nodes) = self.team_option_nodes.get_mut(&team) { + nodes.insert(option.clone(), value_node.clone()); + } else { + let mut nodes = HashMap::new(); + nodes.insert(option.clone(), value_node.clone()); + self.team_option_nodes.insert(team, nodes); + } + } else { + self.option_nodes.insert(option.clone(), value_node.clone()); + } + + nodes.push(value_node); + } + nodes + } }