Add replay finished popups
This commit is contained in:
parent
7ebef6172c
commit
c6961134c0
@ -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(),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user