Add replay finished popups

This commit is contained in:
Sofia 2026-08-03 17:34:58 +03:00
parent 7ebef6172c
commit c6961134c0
3 changed files with 95 additions and 16 deletions

View File

@ -1,4 +1,10 @@
use std::{collections::HashMap, fs, io::Cursor, thread};
use std::{
collections::HashMap,
fs,
io::Cursor,
sync::mpsc::{Receiver, channel},
thread,
};
use flate2::{Compression, bufread::GzDecoder, write::GzEncoder};
use godot::{
@ -484,6 +490,11 @@ impl ReplayPlayback {
}
}
pub enum ReplaySaveEvent {
Error(String),
Done,
}
#[derive(GodotClass)]
#[class(base=Node, init)]
pub struct ReplayRecorder {
@ -494,6 +505,8 @@ pub struct ReplayRecorder {
recording: bool,
pub recv: Option<Receiver<ReplaySaveEvent>>,
base: Base<Node>,
}
@ -546,17 +559,42 @@ impl INode for ReplayRecorder {
self.current_frame = self.record_frame();
}
}
fn process(&mut self, _: f64) {
if let Some(recv) = &self.recv {
if let Ok(data) = recv.recv() {
match data {
ReplaySaveEvent::Error(err) => self.signals().on_saved().emit(&err),
ReplaySaveEvent::Done => self.signals().on_saved().emit(&String::new()),
}
self.recv.take();
}
}
}
}
#[godot_api]
impl ReplayRecorder {
pub fn save_to(&self, path: &GString) {
#[signal]
pub fn on_saved(error: GString);
pub fn save_to(&mut self, path: &GString) {
let path = path.to_string();
let replay = self.replay.clone();
let (send, recv) = channel();
self.recv = Some(recv);
thread::spawn(move || {
let mut bytes = Vec::new();
let encoder = GzEncoder::new(&mut bytes, Compression::default());
ciborium::into_writer(&replay, encoder).ok();
fs::write(path, bytes).ok();
match ciborium::into_writer(&replay, encoder) {
Ok(_) => match fs::write(path, bytes) {
Ok(_) => send.send(ReplaySaveEvent::Done).ok(),
Err(e) => send.send(ReplaySaveEvent::Error(e.to_string())).ok(),
},
Err(e) => send.send(ReplaySaveEvent::Error(e.to_string())).ok(),
}
});
}

View File

@ -1,5 +1,8 @@
use godot::{
classes::{Button, FileDialog, HBoxContainer, IPanel, Label, Panel},
classes::{
AcceptDialog, Button, FileDialog, HBoxContainer, IPanel, Label, Panel, PopupPanel,
window::WindowInitialPosition,
},
prelude::*,
};
@ -21,6 +24,9 @@ pub struct GameFinishedScreen {
#[export]
save_file_dialog: Option<Gd<FileDialog>>,
saving_replay_popup: Option<Gd<PopupPanel>>,
saving_replay_accept_dialog: Option<Gd<AcceptDialog>>,
base: Base<Panel>,
}
@ -45,6 +51,15 @@ impl IPanel for GameFinishedScreen {
.file_selected()
.connect_other(self, Self::save_replay);
}
if let Some(game) = &mut Game::singleton()
&& let Some(recorder) = &mut game.bind_mut().replay_recorder
{
recorder
.signals()
.on_saved()
.connect_other(self, Self::on_replay_saved);
}
}
}
@ -103,10 +118,44 @@ impl GameFinishedScreen {
}
pub fn save_replay(&mut self, path: GString) {
if let Some(game) = &Game::singleton()
&& let Some(recorder) = &game.bind().replay_recorder
if let Some(game) = &mut Game::singleton()
&& let Some(recorder) = &mut game.bind_mut().replay_recorder
{
recorder.bind().save_to(&path);
let mut popup = PopupPanel::new_alloc();
popup.set_initial_position(WindowInitialPosition::CENTER_MAIN_WINDOW_SCREEN);
popup.set_title("Saving replay");
let mut label = Label::new_alloc();
label.set_text("Saving replay");
popup.add_child(&label);
self.base_mut().add_child(&popup);
popup.show();
self.saving_replay_popup = Some(popup);
recorder.bind_mut().save_to(&path);
}
}
fn on_replay_saved(&mut self, err: GString) {
if let Some(popup) = self.saving_replay_popup.clone() {
self.base_mut().remove_child(&popup);
}
let mut popup = AcceptDialog::new_alloc();
popup.set_initial_position(WindowInitialPosition::CENTER_MAIN_WINDOW_SCREEN);
popup.set_title("Save Finished");
let mut label = Label::new_alloc();
let text: GString = if err.is_empty() {
"Replay Saved!".into()
} else {
(&format!("Error: {}", err)).into()
};
label.set_text(&text);
popup.add_child(&label);
popup.show();
self.base_mut().add_child(&popup);
}
}

View File

@ -85,12 +85,4 @@ impl ReplayFinishedScreen {
}
}
}
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);
}
}
}