Add replay finished screen
This commit is contained in:
parent
6cd8515449
commit
e75cb79c86
@ -1,3 +1,6 @@
|
|||||||
[gd_scene format=3 uid="uid://djmb2jqcpkuep"]
|
[gd_scene format=3 uid="uid://djmb2jqcpkuep"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d3377ecff6nyn" path="res://scenes/replay_finished.tscn" id="1_q5ujf"]
|
||||||
|
|
||||||
[node name="standalone_replay_global" type="StandaloneReplayManager" unique_id=730657724]
|
[node name="standalone_replay_global" type="StandaloneReplayManager" unique_id=730657724]
|
||||||
|
replay_finished_screen = ExtResource("1_q5ujf")
|
||||||
|
|||||||
65
godot/scenes/replay_finished.tscn
Normal file
65
godot/scenes/replay_finished.tscn
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
[gd_scene format=3 uid="uid://d3377ecff6nyn"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://2sfy0vq0fqt3" path="res://scenes/ui/player_listing.tscn" id="1_k8op7"]
|
||||||
|
|
||||||
|
[node name="replay_finished" type="ReplayFinishedScreen" unique_id=291257212 node_paths=PackedStringArray("title_container", "back_button", "player_listings")]
|
||||||
|
title_container = NodePath("title_container")
|
||||||
|
back_button = NodePath("button")
|
||||||
|
player_listings = NodePath("player_listings")
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="title_container" type="HBoxContainer" parent="." unique_id=980404596]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 5
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
offset_left = -168.0
|
||||||
|
offset_top = 55.0
|
||||||
|
offset_right = 168.0
|
||||||
|
offset_bottom = 110.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="button" type="Button" parent="." unique_id=1264024304]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 7
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -40.0
|
||||||
|
offset_top = -87.0
|
||||||
|
offset_right = 42.0
|
||||||
|
offset_bottom = -34.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 0
|
||||||
|
theme_override_font_sizes/font_size = 32
|
||||||
|
text = "Back"
|
||||||
|
|
||||||
|
[node name="player_listings" type="PlayerListings" parent="." unique_id=602626392]
|
||||||
|
player_listing_scene = ExtResource("1_k8op7")
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 5
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
offset_left = -88.0
|
||||||
|
offset_top = 150.0
|
||||||
|
offset_right = 87.5
|
||||||
|
offset_bottom = 167.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="simple_score_view" type="SimpleScoreView" parent="." unique_id=1625972988]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 5
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
offset_left = -20.0
|
||||||
|
offset_top = 93.0
|
||||||
|
offset_right = 20.0
|
||||||
|
offset_bottom = 133.0
|
||||||
|
grow_horizontal = 2
|
||||||
@ -15,6 +15,7 @@ use crate::{
|
|||||||
DamageSource, IPlayer, NetTransform, ball::Ball, remote_player::RemotePlayer,
|
DamageSource, IPlayer, NetTransform, ball::Ball, remote_player::RemotePlayer,
|
||||||
weapon::WeaponType,
|
weapon::WeaponType,
|
||||||
},
|
},
|
||||||
|
team_resource::TeamResource,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const STANDALONE_REPLAY_GLOBAL: &str = "StandaloneReplayGlobal";
|
pub const STANDALONE_REPLAY_GLOBAL: &str = "StandaloneReplayGlobal";
|
||||||
@ -22,9 +23,12 @@ pub const STANDALONE_REPLAY_GLOBAL: &str = "StandaloneReplayGlobal";
|
|||||||
#[derive(GodotClass)]
|
#[derive(GodotClass)]
|
||||||
#[class(base=Node, init)]
|
#[class(base=Node, init)]
|
||||||
pub struct StandaloneReplayManager {
|
pub struct StandaloneReplayManager {
|
||||||
|
#[export]
|
||||||
|
replay_finished_screen: Option<Gd<PackedScene>>,
|
||||||
|
|
||||||
loading_replay: bool,
|
loading_replay: bool,
|
||||||
map: Option<Gd<Map>>,
|
map: Option<Gd<Map>>,
|
||||||
playback: Option<Gd<ReplayPlayback>>,
|
pub playback: Option<Gd<ReplayPlayback>>,
|
||||||
replay: Option<Replay>,
|
replay: Option<Replay>,
|
||||||
|
|
||||||
base: Base<Node>,
|
base: Base<Node>,
|
||||||
@ -63,6 +67,12 @@ impl StandaloneReplayManager {
|
|||||||
|
|
||||||
if let Some(replay) = self.replay.take() {
|
if let Some(replay) = self.replay.take() {
|
||||||
let mut playback = ReplayPlayback::new_alloc();
|
let mut playback = ReplayPlayback::new_alloc();
|
||||||
|
|
||||||
|
playback
|
||||||
|
.signals()
|
||||||
|
.on_finished()
|
||||||
|
.connect_other(self, Self::on_done);
|
||||||
|
|
||||||
playback.bind_mut().replay = replay;
|
playback.bind_mut().replay = replay;
|
||||||
playback.bind_mut().current_map = Some(map);
|
playback.bind_mut().current_map = Some(map);
|
||||||
playback.bind_mut().current_time = 0.;
|
playback.bind_mut().current_time = 0.;
|
||||||
@ -73,6 +83,20 @@ impl StandaloneReplayManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_done(&mut self) {
|
||||||
|
if let Some(scene) = &self.replay_finished_screen {
|
||||||
|
self.base().get_tree().change_scene_to_packed(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.replay.take();
|
||||||
|
self.map.take();
|
||||||
|
if let Some(mut playback) = self.playback.take() {
|
||||||
|
playback.queue_free();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(GodotClass)]
|
#[derive(GodotClass)]
|
||||||
@ -90,12 +114,22 @@ pub struct ReplayPlayback {
|
|||||||
|
|
||||||
pub fast_forwarding: bool,
|
pub fast_forwarding: bool,
|
||||||
|
|
||||||
|
pub finished: bool,
|
||||||
|
|
||||||
base: Base<Node>,
|
base: Base<Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl ReplayPlayback {
|
||||||
|
#[signal]
|
||||||
|
pub fn on_finished();
|
||||||
|
}
|
||||||
|
|
||||||
#[godot_api]
|
#[godot_api]
|
||||||
impl INode for ReplayPlayback {
|
impl INode for ReplayPlayback {
|
||||||
fn ready(&mut self) {}
|
fn ready(&mut self) {
|
||||||
|
self.finished = false;
|
||||||
|
}
|
||||||
|
|
||||||
fn process(&mut self, _: f64) {
|
fn process(&mut self, _: f64) {
|
||||||
if let Some(character) = self.player_characters.get_mut(&self.spectated_player_id) {
|
if let Some(character) = self.player_characters.get_mut(&self.spectated_player_id) {
|
||||||
@ -226,7 +260,8 @@ impl INode for ReplayPlayback {
|
|||||||
|
|
||||||
self.fast_forwarding = false;
|
self.fast_forwarding = false;
|
||||||
|
|
||||||
if self.current_frame_idx >= self.replay.frames.len() {
|
if !self.finished && self.current_frame_idx >= self.replay.frames.len() {
|
||||||
|
self.finished = true;
|
||||||
for (id, mut character) in self.player_characters.clone() {
|
for (id, mut character) in self.player_characters.clone() {
|
||||||
character.queue_free();
|
character.queue_free();
|
||||||
self.player_characters.remove(&id);
|
self.player_characters.remove(&id);
|
||||||
@ -234,6 +269,7 @@ impl INode for ReplayPlayback {
|
|||||||
if let Some(mut ball) = self.ball.take() {
|
if let Some(mut ball) = self.ball.take() {
|
||||||
ball.queue_free();
|
ball.queue_free();
|
||||||
}
|
}
|
||||||
|
self.signals().on_finished().emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,11 +313,21 @@ impl INode for ReplayRecorder {
|
|||||||
id: player.id(),
|
id: player.id(),
|
||||||
name: player.data.name.clone(),
|
name: player.data.name.clone(),
|
||||||
color: team.bind().color.into(),
|
color: team.bind().color.into(),
|
||||||
|
team: player.data.team,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.replay.map_idx = game.bind().selected_map_idx;
|
s.replay.map_idx = game.bind().selected_map_idx;
|
||||||
|
s.replay.teams = game
|
||||||
|
.bind()
|
||||||
|
.get_teams()
|
||||||
|
.iter_shared()
|
||||||
|
.map(|t| ReplayTeam {
|
||||||
|
name: t.bind().name.to_string(),
|
||||||
|
color: t.bind().color.into(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -324,6 +370,8 @@ impl ReplayRecorder {
|
|||||||
|
|
||||||
let mut ball_data = ReplayBall::Held;
|
let mut ball_data = ReplayBall::Held;
|
||||||
|
|
||||||
|
let mut goals = HashMap::new();
|
||||||
|
|
||||||
if let Some(game) = Game::singleton() {
|
if let Some(game) = Game::singleton() {
|
||||||
for player in &game.bind().players {
|
for player in &game.bind().players {
|
||||||
if let Some(state) = player.get_state() {
|
if let Some(state) = player.get_state() {
|
||||||
@ -338,10 +386,15 @@ impl ReplayRecorder {
|
|||||||
} else {
|
} else {
|
||||||
ReplayBall::Held
|
ReplayBall::Held
|
||||||
};
|
};
|
||||||
|
|
||||||
|
goals = game.bind().goals.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.replay.goals = goals.clone();
|
||||||
|
|
||||||
ReplayFrame {
|
ReplayFrame {
|
||||||
time: self.time_elapsed,
|
time: self.time_elapsed,
|
||||||
|
goals,
|
||||||
player_data,
|
player_data,
|
||||||
ball_data,
|
ball_data,
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
@ -352,7 +405,9 @@ impl ReplayRecorder {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Replay {
|
pub struct Replay {
|
||||||
pub map_idx: u8,
|
pub map_idx: u8,
|
||||||
players: HashMap<u16, ReplayPlayer>,
|
pub players: HashMap<u16, ReplayPlayer>,
|
||||||
|
pub teams: Vec<ReplayTeam>,
|
||||||
|
pub goals: HashMap<u8, u16>,
|
||||||
frames: Vec<ReplayFrame>,
|
frames: Vec<ReplayFrame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,16 +416,25 @@ impl Default for Replay {
|
|||||||
Self {
|
Self {
|
||||||
map_idx: Default::default(),
|
map_idx: Default::default(),
|
||||||
players: Default::default(),
|
players: Default::default(),
|
||||||
|
goals: Default::default(),
|
||||||
|
teams: Default::default(),
|
||||||
frames: Default::default(),
|
frames: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ReplayTeam {
|
||||||
|
pub name: String,
|
||||||
|
pub color: ReplayColor,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ReplayPlayer {
|
pub struct ReplayPlayer {
|
||||||
pub id: u16,
|
pub id: u16,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub color: ReplayColor,
|
pub color: ReplayColor,
|
||||||
|
pub team: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -409,6 +473,7 @@ pub struct ReplayFrame {
|
|||||||
player_data: HashMap<u16, ReplayPlayerState>,
|
player_data: HashMap<u16, ReplayPlayerState>,
|
||||||
ball_data: ReplayBall,
|
ball_data: ReplayBall,
|
||||||
events: Vec<ReplayEvent>,
|
events: Vec<ReplayEvent>,
|
||||||
|
goals: HashMap<u8, u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
|||||||
@ -9,6 +9,7 @@ pub mod menu_player;
|
|||||||
pub mod net_stats;
|
pub mod net_stats;
|
||||||
pub mod player_listing;
|
pub mod player_listing;
|
||||||
pub mod player_listings;
|
pub mod player_listings;
|
||||||
|
pub mod replay_finished_screen;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod simple_score_view;
|
pub mod simple_score_view;
|
||||||
pub mod slider;
|
pub mod slider;
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use godot::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::game_manager::Game;
|
use crate::{game_manager::Game, replay::StandaloneReplayManager};
|
||||||
|
|
||||||
#[derive(GodotClass)]
|
#[derive(GodotClass)]
|
||||||
#[class(base=HBoxContainer, init)]
|
#[class(base=HBoxContainer, init)]
|
||||||
@ -53,10 +53,9 @@ impl IHBoxContainer for PlayerListing {
|
|||||||
|
|
||||||
impl PlayerListing {
|
impl PlayerListing {
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
|
if let Some(player_id) = self.player_id {
|
||||||
if let Some(game) = Game::singleton() {
|
if let Some(game) = Game::singleton() {
|
||||||
if let Some(player_id) = self.player_id
|
if let Some(player) = game.bind().find_player(player_id) {
|
||||||
&& let Some(player) = game.bind().find_player(player_id)
|
|
||||||
{
|
|
||||||
if let Some(name_label) = &mut self.name_label {
|
if let Some(name_label) = &mut self.name_label {
|
||||||
name_label.set_text(&player.data.name);
|
name_label.set_text(&player.data.name);
|
||||||
}
|
}
|
||||||
@ -94,6 +93,26 @@ impl PlayerListing {
|
|||||||
ping_label.set_text("Ping");
|
ping_label.set_text("Ping");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let Some(playback) = &StandaloneReplayManager::singleton().bind().playback {
|
||||||
|
if let Some(player) = playback.bind().replay.players.get(&player_id) {
|
||||||
|
if let Some(name_label) = &mut self.name_label {
|
||||||
|
name_label.set_text(&player.name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(name_label) = &mut self.name_label {
|
||||||
|
name_label.set_text("Name");
|
||||||
|
}
|
||||||
|
if let Some(kills_label) = &mut self.kills_label {
|
||||||
|
kills_label.set_text("Kills");
|
||||||
|
}
|
||||||
|
if let Some(deaths_label) = &mut self.deaths_label {
|
||||||
|
deaths_label.set_text("Deaths");
|
||||||
|
}
|
||||||
|
if let Some(ping_label) = &mut self.ping_label {
|
||||||
|
ping_label.set_text("Ping");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,9 @@ use godot::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{game_manager::Game, ui::player_listing::PlayerListing};
|
use crate::{
|
||||||
|
game_manager::Game, replay::StandaloneReplayManager, ui::player_listing::PlayerListing,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(GodotClass)]
|
#[derive(GodotClass)]
|
||||||
#[class(base=HBoxContainer, init)]
|
#[class(base=HBoxContainer, init)]
|
||||||
@ -69,6 +71,40 @@ impl PlayerListings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.base_mut().add_child(&vbox);
|
||||||
|
}
|
||||||
|
} else if let Some(playback) = &StandaloneReplayManager::singleton().bind().playback {
|
||||||
|
let replay = &playback.bind().replay;
|
||||||
|
|
||||||
|
for (id, team) in replay.teams.iter().enumerate() {
|
||||||
|
let mut vbox = VBoxContainer::new_alloc();
|
||||||
|
|
||||||
|
vbox.set_alignment(AlignmentMode::BEGIN);
|
||||||
|
vbox.set_custom_minimum_size(Vector2::new(300., 0.));
|
||||||
|
|
||||||
|
let mut team_label = Label::new_alloc();
|
||||||
|
team_label.set_modulate(team.color.clone().into());
|
||||||
|
team_label.set_text(&team.name);
|
||||||
|
team_label.set_horizontal_alignment(HorizontalAlignment::CENTER);
|
||||||
|
vbox.add_child(&team_label);
|
||||||
|
|
||||||
|
if let Some(listing_scene) = &self.player_listing_scene {
|
||||||
|
let players = replay
|
||||||
|
.players
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, p)| p.team == id as u8)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let header = listing_scene.instantiate_as::<PlayerListing>();
|
||||||
|
vbox.add_child(&header);
|
||||||
|
|
||||||
|
for (_, player) in players {
|
||||||
|
let mut listing = listing_scene.instantiate_as::<PlayerListing>();
|
||||||
|
listing.bind_mut().player_id = Some(player.id);
|
||||||
|
vbox.add_child(&listing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.base_mut().add_child(&vbox);
|
self.base_mut().add_child(&vbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
97
rust/src/ui/replay_finished_screen.rs
Normal file
97
rust/src/ui/replay_finished_screen.rs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
use godot::{
|
||||||
|
classes::{Button, FileDialog, HBoxContainer, IPanel, Label, Panel},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
game_manager::{Game, GameManager},
|
||||||
|
replay::StandaloneReplayManager,
|
||||||
|
ui::player_listings::PlayerListings,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Panel, init)]
|
||||||
|
pub struct ReplayFinishedScreen {
|
||||||
|
#[export]
|
||||||
|
title_container: Option<Gd<HBoxContainer>>,
|
||||||
|
#[export]
|
||||||
|
back_button: Option<Gd<Button>>,
|
||||||
|
#[export]
|
||||||
|
player_listings: Option<Gd<PlayerListings>>,
|
||||||
|
|
||||||
|
base: Base<Panel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IPanel for ReplayFinishedScreen {
|
||||||
|
fn ready(&mut self) {
|
||||||
|
self.produce_title();
|
||||||
|
if let Some(listings) = &mut self.player_listings {
|
||||||
|
listings.bind_mut().update_player_listings();
|
||||||
|
}
|
||||||
|
if let Some(back) = &self.back_button {
|
||||||
|
back.signals().pressed().connect_other(self, |_| {
|
||||||
|
StandaloneReplayManager::singleton().bind_mut().clear();
|
||||||
|
GameManager::singleton().bind().go_to_main_menu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl ReplayFinishedScreen {
|
||||||
|
fn produce_title(&mut self) {
|
||||||
|
if let Some(playback) = &StandaloneReplayManager::singleton().bind().playback {
|
||||||
|
let playback = playback.bind();
|
||||||
|
godot_print!("{:?}", playback.replay.goals);
|
||||||
|
let max_goals = playback
|
||||||
|
.replay
|
||||||
|
.goals
|
||||||
|
.iter()
|
||||||
|
.map(|(_, v)| v)
|
||||||
|
.max()
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0);
|
||||||
|
let winning_team_ids = playback
|
||||||
|
.replay
|
||||||
|
.goals
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, goals)| **goals == max_goals)
|
||||||
|
.map(|(team, _)| *team)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let winning_teams = playback
|
||||||
|
.replay
|
||||||
|
.teams
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(id, _)| winning_team_ids.contains(&((*id) as u8)))
|
||||||
|
.map(|(_, team)| team)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if let Some(container) = &mut self.title_container {
|
||||||
|
for (idx, team) in winning_teams.iter().enumerate() {
|
||||||
|
let mut label = Label::new_alloc();
|
||||||
|
label.set_text(&team.name);
|
||||||
|
label.set_modulate(team.color.clone().into());
|
||||||
|
if idx > 0 {
|
||||||
|
let mut and_label = Label::new_alloc();
|
||||||
|
and_label.set_text(" and ");
|
||||||
|
container.add_child(&and_label);
|
||||||
|
}
|
||||||
|
container.add_child(&label);
|
||||||
|
}
|
||||||
|
let mut end = Label::new_alloc();
|
||||||
|
end.set_text(" victory!");
|
||||||
|
container.add_child(&end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_replay(&mut self, path: GString) {
|
||||||
|
if let Some(game) = &Game::singleton()
|
||||||
|
&& let Some(recorder) = &game.bind().replay_recorder
|
||||||
|
{
|
||||||
|
recorder.bind().save_to(&path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user