Move hud stuff to hud

This commit is contained in:
Sofia 2026-07-27 02:11:54 +03:00
parent 6992bc5eff
commit 2384eb90ba
7 changed files with 300 additions and 185 deletions

View File

@ -2,21 +2,13 @@
[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/effects.tscn" id="2_ywmwa"]
[ext_resource type="PackedScene" uid="uid://n3u0jr4wiib1" path="res://scenes/ui/settings.tscn" id="3_beej8"]
[ext_resource type="PackedScene" uid="uid://2sfy0vq0fqt3" path="res://scenes/ui/player_listing.tscn" id="4_okac2"]
[ext_resource type="PackedScene" uid="uid://ffh5txda3j1" path="res://scenes/ui/chat_box.tscn" id="5_cv68x"]
[ext_resource type="PackedScene" uid="uid://c1gs6cqek1qlq" path="res://scenes/ui/hud.tscn" id="5_cv68x"]
[ext_resource type="Texture2D" uid="uid://bdfqu6p74pfwe" path="res://raw_assets/crosshair/Crosshair 1.png" id="6_7awel"]
[ext_resource type="AudioStream" uid="uid://bfg31e3s4jv8c" path="res://raw_assets/sfx/Hit.mp3" id="7_dguuj"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_oh8vq"]
[sub_resource type="LabelSettings" id="LabelSettings_7awel"]
font_size = 32
font_color = Color(1, 0, 0, 1)
outline_size = 10
outline_color = Color(0, 0, 0, 1)
[node name="player" type="LocalPlayer" unique_id=863055906 node_paths=PackedStringArray("camera", "soldier_mesh", "collider", "effects", "dead_cam_target", "respawn_label", "camera_origin", "weapon_node", "pause_panel", "exit_to_lobby", "settings_panel", "scoreboard", "chatbox", "health_label", "hit_sound")]
[node name="player" type="LocalPlayer" unique_id=863055906 node_paths=PackedStringArray("camera", "soldier_mesh", "collider", "effects", "dead_cam_target", "respawn_label", "camera_origin", "weapon_node", "hud", "hit_sound")]
look_sensitivity = 1.5
camera = NodePath("camera_3d")
move_speed = 7.0
@ -27,12 +19,7 @@ dead_cam_target = NodePath("dead_camera_target")
respawn_label = NodePath("respawn_label")
camera_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")
scoreboard = NodePath("scoreboard")
chatbox = NodePath("chat_box")
health_label = NodePath("health_label")
hud = NodePath("hud")
hit_sound = NodePath("hit_sound")
health = 100
punch_cooldown = 1.0
@ -91,99 +78,11 @@ grow_horizontal = 2
grow_vertical = 2
horizontal_alignment = 1
[node name="score_view" type="SimpleScoreView" parent="." unique_id=1128041371]
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -20.0
offset_top = 18.0
offset_right = 20.0
offset_bottom = 58.0
grow_horizontal = 2
alignment = 1
[node name="pause_menu" type="Panel" parent="." unique_id=1542204162]
visible = false
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -67.75
offset_top = -101.25
offset_right = 67.75
offset_bottom = 101.25
grow_horizontal = 2
grow_vertical = 2
[node name="v_box_container" type="VBoxContainer" parent="pause_menu" unique_id=839758321]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
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"
[node name="exit" type="Button" parent="pause_menu/v_box_container" unique_id=641638697]
layout_mode = 2
text = "Exit"
[node name="settings" parent="." unique_id=999912383 instance=ExtResource("3_beej8")]
visible = false
[node name="scoreboard" type="PanelContainer" parent="." unique_id=1276565374]
custom_minimum_size = Vector2(0, -1)
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -76.0
offset_top = 58.0
offset_right = 77.0
offset_bottom = 100.0
grow_horizontal = 2
size_flags_vertical = 3
[node name="h_box_container" type="PlayerListings" parent="scoreboard" unique_id=256898638]
player_listing_scene = ExtResource("4_okac2")
layout_mode = 2
alignment = 1
metadata/_edit_lock_ = true
[node name="chat_box" parent="." unique_id=1125601400 instance=ExtResource("5_cv68x")]
in_game = true
[node name="health_label" type="Label" parent="." unique_id=651212450]
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 34.0
offset_top = -45.0
offset_right = 74.0
offset_bottom = -22.0
grow_vertical = 0
text = "100"
label_settings = SubResource("LabelSettings_7awel")
vertical_alignment = 2
[node name="hit_sound" type="AudioStreamPlayer" parent="." unique_id=1224745673]
stream = ExtResource("7_dguuj")
bus = &"SFX"
[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"]
[node name="hud" parent="." unique_id=2049159590 instance=ExtResource("5_cv68x")]
[connection signal="on_exit" from="hud" to="." method="exit"]
[connection signal="on_exit_to_lobby" from="hud" to="." method="exit_to_lobby"]

121
godot/scenes/ui/hud.tscn Normal file
View File

@ -0,0 +1,121 @@
[gd_scene format=3 uid="uid://c1gs6cqek1qlq"]
[ext_resource type="PackedScene" uid="uid://n3u0jr4wiib1" path="res://scenes/ui/settings.tscn" id="1_bo48s"]
[ext_resource type="PackedScene" uid="uid://2sfy0vq0fqt3" path="res://scenes/ui/player_listing.tscn" id="2_8qguk"]
[ext_resource type="PackedScene" uid="uid://ffh5txda3j1" path="res://scenes/ui/chat_box.tscn" id="3_136eg"]
[sub_resource type="LabelSettings" id="LabelSettings_oj5la"]
font_size = 32
font_color = Color(1, 0, 0, 1)
outline_size = 10
outline_color = Color(0, 0, 0, 1)
[node name="hud" type="Hud" unique_id=1365644678 node_paths=PackedStringArray("pause_panel", "settings_button", "exit_to_lobby", "exit", "settings_panel", "scoreboard", "chatbox", "health_label")]
pause_panel = NodePath("pause_menu")
settings_button = NodePath("pause_menu/v_box_container/settings")
exit_to_lobby = NodePath("pause_menu/v_box_container/exit_to_lobby")
exit = NodePath("pause_menu/v_box_container/exit")
settings_panel = NodePath("settings")
scoreboard = NodePath("scoreboard")
chatbox = NodePath("chat_box")
health_label = NodePath("health_label")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="score_view" type="SimpleScoreView" parent="." unique_id=981879809]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -20.0
offset_top = 18.0
offset_right = 20.0
offset_bottom = 58.0
grow_horizontal = 2
alignment = 1
[node name="pause_menu" type="Panel" parent="." unique_id=990293559]
visible = false
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -67.75
offset_top = -101.25
offset_right = 67.75
offset_bottom = 101.25
grow_horizontal = 2
grow_vertical = 2
[node name="v_box_container" type="VBoxContainer" parent="pause_menu" unique_id=1801932370]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
grow_horizontal = 2
grow_vertical = 2
alignment = 1
[node name="settings" type="Button" parent="pause_menu/v_box_container" unique_id=1671674264]
layout_mode = 2
text = "Settings"
[node name="exit_to_lobby" type="Button" parent="pause_menu/v_box_container" unique_id=313653211]
layout_mode = 2
text = "Exit to Lobby"
[node name="exit" type="Button" parent="pause_menu/v_box_container" unique_id=1097485912]
layout_mode = 2
text = "Exit"
[node name="settings" parent="." unique_id=999912383 instance=ExtResource("1_bo48s")]
visible = false
layout_mode = 1
[node name="scoreboard" type="PanelContainer" parent="." unique_id=99762392]
custom_minimum_size = Vector2(0, -1)
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -76.0
offset_top = 58.0
offset_right = 77.0
offset_bottom = 100.0
grow_horizontal = 2
size_flags_vertical = 3
[node name="h_box_container" type="PlayerListings" parent="scoreboard" unique_id=43264288]
player_listing_scene = ExtResource("2_8qguk")
layout_mode = 2
alignment = 1
metadata/_edit_lock_ = true
[node name="chat_box" parent="." unique_id=1125601400 instance=ExtResource("3_136eg")]
in_game = true
layout_mode = 0
[node name="health_label" type="Label" parent="." unique_id=676741647]
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 34.0
offset_top = -45.0
offset_right = 74.0
offset_bottom = -22.0
grow_vertical = 0
text = "100"
label_settings = SubResource("LabelSettings_oj5la")
vertical_alignment = 2

View File

@ -2,8 +2,8 @@ use std::{f32::consts::PI, ops::Neg};
use godot::{
classes::{
AudioStreamPlayer, Button, Camera3D, CharacterBody3D, CollisionShape3D, ICharacterBody3D,
Input, InputEvent, InputEventMouseMotion, Label, Panel, PanelContainer, input::MouseMode,
AudioStreamPlayer, Camera3D, CharacterBody3D, CollisionShape3D, ICharacterBody3D, Input,
InputEvent, InputEventMouseMotion, Label, input::MouseMode,
},
obj::WithBaseField,
prelude::*,
@ -30,7 +30,7 @@ use crate::{
weapon::{BallWeapon, Raygun, Shotgun, Weapon, WeaponType},
},
replay::ReplayEvent,
ui::{chatbox::ChatBox, cli::CommandLinePanel, settings::SettingsPanel},
ui::{cli::CommandLinePanel, hud::Hud},
};
#[derive(GodotClass)]
@ -56,18 +56,10 @@ pub struct LocalPlayer {
camera_origin: Option<Gd<Node3D>>,
#[export]
weapon_node: Option<Gd<Node3D>>,
#[export]
pause_panel: Option<Gd<Panel>>,
#[export]
exit_to_lobby: Option<Gd<Button>>,
#[export]
settings_panel: Option<Gd<SettingsPanel>>,
#[export]
scoreboard: Option<Gd<PanelContainer>>,
#[export]
chatbox: Option<Gd<ChatBox>>,
#[export]
health_label: Option<Gd<Label>>,
hud: Option<Gd<Hud>>,
#[export]
hit_sound: Option<Gd<AudioStreamPlayer>>,
#[export]
@ -223,9 +215,6 @@ impl IPlayer for LocalPlayer {
s.kill(source);
}
}
if let Some(health_label) = &mut s.health_label {
health_label.set_text(&s.health.max(0).to_string());
}
});
}
@ -305,6 +294,10 @@ impl IPlayer for LocalPlayer {
fn is_replay_mode(&self) -> bool {
false
}
fn get_health(&self) -> i32 {
self.health
}
}
#[godot_api]
@ -323,28 +316,6 @@ impl ICharacterBody3D for LocalPlayer {
self.set_lock(true);
}
CommandLinePanel::singleton()
.signals()
.on_open()
.connect_other(self, |s| s.update_lock());
CommandLinePanel::singleton()
.signals()
.on_close()
.connect_other(self, |s| {
s.update_lock();
});
if let Some(chatbox) = self.chatbox.clone() {
chatbox
.signals()
.on_opened()
.connect_other(self, |s| s.update_lock());
chatbox
.signals()
.on_closed()
.connect_other(self, |s| s.update_lock());
}
self.swap_weapon(WeaponType::Raygun, false);
if let Some(camera) = &mut self.camera {
@ -357,11 +328,13 @@ impl ICharacterBody3D for LocalPlayer {
remover.bind_mut().active = true;
}
self.run_deferred(|s| {
if let Some(exit_to_lobby) = &mut s.exit_to_lobby {
exit_to_lobby.set_visible(NetworkManager::singleton().bind().is_host());
if let Some(mut hud) = self.hud.clone() {
hud.bind_mut().player_id = self.player_id.unwrap_or(0);
hud.bind_mut()
.signals()
.on_lock_changed()
.connect_other(self, |s, lock| s.set_lock(lock));
}
});
}
fn process(&mut self, delta: f64) {
@ -436,10 +409,6 @@ impl ICharacterBody3D for LocalPlayer {
camera.set_global_position(new_pos);
}
if let Some(scoreboard) = &mut self.scoreboard {
scoreboard.set_visible(Input::singleton().is_action_pressed("scoreboard"));
}
if self.movement_dir.length_squared() > 0. && self.base().is_on_floor() && !self.is_dead {
if let Some(effects) = &mut self.effects {
effects.bind_mut().walk();
@ -478,19 +447,6 @@ impl ICharacterBody3D for LocalPlayer {
}
fn input(&mut self, event: Gd<InputEvent>) {
if event.is_action_pressed("pause") {
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();
}
}
if self.locked {
if event.is_action_pressed("shoot") {
if let Some(pos) = self.raycast_from_camera() {
@ -637,22 +593,6 @@ impl LocalPlayer {
damage: i32,
);
fn update_lock(&mut self) {
self.run_deferred(|s| {
let paused = if let Some(panel) = &s.pause_panel {
panel.is_visible()
} else {
false
};
let chat_visible = if let Some(chat) = &s.chatbox {
chat.bind().is_editing()
} else {
false
};
s.set_lock(!CommandLinePanel::singleton().bind().opened && !paused && !chat_visible);
});
}
fn set_lock(&mut self, locked: bool) {
self.locked = locked;
if self.locked {

View File

@ -57,6 +57,7 @@ pub trait IPlayer {
fn drop_ball(&mut self, with_velocity: bool) -> bool;
fn get_camera_origin(&self) -> Option<Gd<Node3D>>;
fn is_replay_mode(&self) -> bool;
fn get_health(&self) -> i32;
}
pub trait PlayerCommon {

View File

@ -230,6 +230,10 @@ impl IPlayer for RemotePlayer {
fn is_replay_mode(&self) -> bool {
self.replay_mode
}
fn get_health(&self) -> i32 {
self.health
}
}
#[godot_api]

149
rust/src/ui/hud.rs Normal file
View File

@ -0,0 +1,149 @@
use godot::{
classes::{Button, Control, IControl, Input, InputEvent, Label, Panel, PanelContainer},
prelude::*,
};
use crate::{
game_manager::Game,
net::network_manager::NetworkManager,
ui::{chatbox::ChatBox, cli::CommandLinePanel, settings::SettingsPanel},
};
#[derive(GodotClass)]
#[class(base=Control, init)]
pub struct Hud {
pub player_id: u16,
#[export]
pause_panel: Option<Gd<Panel>>,
#[export]
settings_button: Option<Gd<Button>>,
#[export]
exit_to_lobby: Option<Gd<Button>>,
#[export]
exit: Option<Gd<Button>>,
#[export]
settings_panel: Option<Gd<SettingsPanel>>,
#[export]
scoreboard: Option<Gd<PanelContainer>>,
#[export]
chatbox: Option<Gd<ChatBox>>,
#[export]
health_label: Option<Gd<Label>>,
lock: bool,
base: Base<Control>,
}
#[godot_api]
impl IControl for Hud {
fn ready(&mut self) {
self.run_deferred(|s| {
if let Some(exit_to_lobby) = &mut s.exit_to_lobby {
exit_to_lobby.set_visible(NetworkManager::singleton().bind().is_host());
}
});
CommandLinePanel::singleton()
.signals()
.on_open()
.connect_other(self, |s| s.update_lock());
CommandLinePanel::singleton()
.signals()
.on_close()
.connect_other(self, |s| {
s.update_lock();
});
if let Some(chatbox) = self.chatbox.clone() {
chatbox
.signals()
.on_opened()
.connect_other(self, |s| s.update_lock());
chatbox
.signals()
.on_closed()
.connect_other(self, |s| s.update_lock());
}
if let Some(exit_to_lobby) = &self.exit_to_lobby {
exit_to_lobby
.signals()
.pressed()
.connect_other(self, |s| s.signals().on_exit_to_lobby().emit());
}
if let Some(exit) = &self.exit {
exit.signals()
.pressed()
.connect_other(self, |s| s.signals().on_exit().emit());
}
if let Some(settings_btn) = &self.settings_button {
settings_btn.signals().pressed().connect_other(self, |s| {
if let Some(settings) = &mut s.settings_panel {
settings.set_visible(true);
}
});
}
self.update_lock();
}
fn process(&mut self, _: f64) {
if let Some(scoreboard) = &mut self.scoreboard {
scoreboard.set_visible(Input::singleton().is_action_pressed("scoreboard"));
}
if let Some(game) = Game::singleton()
&& let Some(player) = game.bind().find_player(self.player_id)
&& let Some(character) = &player.character
&& let Some(health_label) = &mut self.health_label
{
health_label.set_text(&character.dyn_bind().get_health().to_string());
}
}
fn input(&mut self, event: Gd<InputEvent>) {
if event.is_action_pressed("pause") {
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();
}
}
}
}
#[godot_api]
impl Hud {
#[signal]
pub fn on_lock_changed(lock: bool);
#[signal]
pub fn on_exit_to_lobby();
#[signal]
pub fn on_exit();
pub fn update_lock(&mut self) {
let paused = if let Some(panel) = &self.pause_panel {
panel.is_visible()
} else {
false
};
let chat_visible = if let Some(chat) = &self.chatbox {
chat.bind().is_editing()
} else {
false
};
let prev_lock = self.lock;
self.lock = !CommandLinePanel::singleton().bind().opened && !paused && !chat_visible;
if prev_lock != self.lock {
let lock = self.lock;
self.signals().on_lock_changed().emit(lock);
}
}
}

View File

@ -2,6 +2,7 @@ pub mod chatbox;
pub mod cli;
pub mod credits;
pub mod game_finished_screen;
pub mod hud;
pub mod lobby;
pub mod lobby_player_listing;
pub mod main_menu;