Files
rdl/src/main.rs
Arthur Roberts 6004df73f7 Fixed the flag/command line stuff
Also added it all into the command_manager thing so the App struct
doesn't look quite so busy
2023-07-04 23:34:34 +01:00

449 lines
18 KiB
Rust

use config::{default_save_filename, load_config, save_config, Config};
use eframe::egui;
use eframe::egui::Color32;
use infos::{
CommandErrors, CommandManager, Difficulty, LauncherInfo, MultiManager, SingleManager, WadInfo,
};
use native_dialog::{MessageDialog, MessageType};
use std::path::PathBuf;
use std::process::Command;
pub mod config;
pub mod infos;
pub mod wad;
fn main() -> Result<(), eframe::Error> {
let gui_options = eframe::NativeOptions {
..Default::default()
};
eframe::run_native(
"Rust Doom Launcher",
gui_options,
Box::new(|_cc| Box::<RustDoomLauncher>::default()),
)
}
#[derive(PartialEq)]
enum FileType {
Iwad,
Pwad,
Launcher,
}
struct RustDoomLauncher {
launcher_manager: SingleManager<LauncherInfo>,
iwad_manager: SingleManager<WadInfo>,
pwad_manager: MultiManager<WadInfo>,
add_name: String,
config_filename: PathBuf,
config_file_loaded: bool,
command_manager: CommandManager,
display_command: bool,
add_stuff_window_displayed: bool,
selected_file_type: FileType,
selected_file_path: PathBuf,
}
impl Default for RustDoomLauncher {
fn default() -> Self {
Self {
launcher_manager: SingleManager::new(),
iwad_manager: SingleManager::new(),
pwad_manager: MultiManager::new(),
command_manager: CommandManager::new(),
add_name: "".to_string(),
config_filename: default_save_filename(),
config_file_loaded: false,
display_command: false,
add_stuff_window_displayed: false,
selected_file_type: FileType::Pwad,
selected_file_path: PathBuf::new(),
}
}
}
impl RustDoomLauncher {
// There must be a better way than this - maybe for the RustDoomLauncher to
// have a config thing
fn get_config_file_stuff(&mut self) {
let config = load_config(&self.config_filename).unwrap();
if let Some(iwads) = config.iwads {
for iwad in iwads {
self.iwad_manager.add(&iwad);
}
}
if let Some(pwads) = config.pwads {
for pwad in pwads {
self.pwad_manager.add(&pwad.clone());
}
}
if let Some(launchers) = config.launchers {
for launcher in launchers {
self.launcher_manager.add(&launcher);
}
}
}
fn launch_doom(&self) {
match self.command_manager.generate_command() {
Err(e) => {
let text = match e {
CommandErrors::NoIwad => "an IWAD",
CommandErrors::NoLauncher => "a launcher",
};
MessageDialog::new()
.set_type(MessageType::Error)
.set_title("I can't let you do that")
.set_text(&format!("You didn't pick {}!\nPlease do that", text))
.show_alert()
.unwrap();
}
Ok((launcher, command)) => {
// Note to self, don't hit launch button when running from emacs
let result = Command::new(launcher).args(command).spawn();
match result {
Err(e) => panic!("{}", e),
Ok(_o) => (),
}
}
}
}
fn launcher_and_iwad(&self) -> Result<(&LauncherInfo, &WadInfo), CommandErrors> {
let launcher = match self.launcher_manager.get_current() {
Some(l) => l,
None => {
return Err(CommandErrors::NoLauncher);
}
};
let iwad = match self.iwad_manager.get_current() {
Some(iwad) => iwad,
None => {
return Err(CommandErrors::NoIwad);
}
};
Ok((launcher, iwad))
}
}
impl eframe::App for RustDoomLauncher {
fn on_close_event(&mut self) -> bool {
let config = Config {
iwads: Some(self.iwad_manager.selectable.clone()),
pwads: Some(self.pwad_manager.selectable.clone()),
launchers: Some(self.launcher_manager.selectable.clone()),
};
save_config(&self.config_filename, &config).unwrap();
true
}
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
if !self.config_file_loaded {
self.get_config_file_stuff();
self.config_file_loaded = true;
}
egui::containers::panel::CentralPanel::default().show(ctx, |ui| {
ui.horizontal(|ui| {
ui.heading("RustDoomLauncher");
let button = match self.launcher_and_iwad() {
Err(_) => egui::Button::new("PLAY SOME DOOM!"),
Ok((_, _)) => egui::Button::new("PLAY SOME DOOM!").fill(Color32::DARK_GREEN),
};
if ui.add(button).clicked() {
self.launch_doom();
}
if ui.button("Add WAD or Launcher").clicked() {
self.add_stuff_window_displayed = true;
}
});
ui.horizontal(|ui| {
ui.vertical(|ui| {
ui.set_max_width(100.0);
ui.label("Launchers");
let mut remove_pos: Option<usize> = None;
let mut add_pos: Option<usize> = None;
for (launcher, pos, selected) in self
.launcher_manager
.iter_selectable_with_pos_and_selected()
{
ui.horizontal(|ui| {
if ui
.add(egui::SelectableLabel::new(selected, &launcher.name))
.clicked()
{
add_pos = Some(pos);
}
if ui.button("").clicked() {
remove_pos = Some(pos);
}
});
}
// I'm unsure whether there's a better way to do this.
// The iterator call is a mutable borrow - thus compiler doesn't let me
// do a mutable thing in the middle of that, which I guess is fair enough,
// but I would like to break out of the loop as soon as that occurs...
// Completely unsure
if let Some(rp) = remove_pos {
self.launcher_manager.remove_selectable(rp);
if self.launcher_manager.get_current().is_none() {
self.command_manager.remove_launcher();
}
}
if let Some(ap) = add_pos {
self.launcher_manager.set_current(ap);
self.command_manager
.add_launcher(self.launcher_manager.get_current().unwrap())
}
ui.separator();
ui.label("IWADs");
let mut remove_pos: Option<usize> = None;
let mut add_pos: Option<usize> = None;
for (launcher, pos, selected) in
self.iwad_manager.iter_selectable_with_pos_and_selected()
{
ui.horizontal(|ui| {
if ui
.add(egui::SelectableLabel::new(selected, &launcher.name))
.clicked()
{
add_pos = Some(pos);
}
if ui.button("").clicked() {
remove_pos = Some(pos);
}
});
}
if let Some(rp) = remove_pos {
self.iwad_manager.remove_selectable(rp);
if self.launcher_manager.get_current().is_none() {
self.command_manager.remove_launcher();
}
}
if let Some(ap) = add_pos {
self.iwad_manager.set_current(ap);
self.command_manager
.add_iwad(self.iwad_manager.get_current().unwrap());
}
});
ui.separator();
ui.vertical(|ui| {
ui.set_min_width(100.0);
ui.label("PWADs");
let mut remove_pos: Option<usize> = None;
let mut add_pos: Option<usize> = None;
for (pwad, pos, selected) in
self.pwad_manager.iter_selectable_with_pos_and_selected()
{
ui.horizontal(|ui| {
if ui
.add(egui::SelectableLabel::new(selected, &pwad.name))
.clicked()
{
add_pos = Some(pos);
}
if ui.button("").clicked() {
remove_pos = Some(pos);
}
});
}
if let Some(rp) = remove_pos {
self.pwad_manager.remove_selectable(rp);
self.command_manager
.add_pwads(&self.pwad_manager.get_current())
}
if let Some(ap) = add_pos {
self.pwad_manager.set_current(ap);
self.command_manager
.add_pwads(&self.pwad_manager.get_current())
}
});
let mut text = "Placeholder for WAD info stuffs";
let window_size = frame.info().window_info.size;
ui.add(
egui::TextEdit::multiline(&mut text)
.desired_width(window_size[0] / 1.6)
.desired_rows(20),
);
});
ui.separator();
ui.horizontal_wrapped(|ui| {
ui.horizontal(|ui| {
ui.set_max_width(180.0);
let warp_label = ui.label("warp");
let r = ui.text_edit_singleline(&mut self.command_manager.warp)
.labelled_by(warp_label.id);
if r.changed() {
let _ = self.command_manager.generate_command_str();
}
});
ui.separator();
ui.horizontal(|ui| {
ui.horizontal(|ui| {
ui.label("difficulty");
ui.set_max_width(180.0);
eframe::egui::ComboBox::new("difficulty", "")
.selected_text(format!("{}", self.command_manager.difficulty))
.show_ui(ui, |ui| {
for diff in Difficulty::iterator() {
let r = ui.selectable_value(
&mut self.command_manager.difficulty,
*diff,
diff.to_string(),
);
if r.clicked() {
let _ = self.command_manager.generate_command_str();
}
}
});
});
ui.separator();
ui.horizontal(|ui| {
ui.label("fast");
let r = ui.add(egui::Checkbox::without_text(&mut self.command_manager.fast_monsters));
if r.clicked() {
let _ = self.command_manager.generate_command_str();
}
});
ui.separator();
ui.horizontal(|ui| {
ui.label("respawn");
let r = ui.add(egui::Checkbox::without_text(&mut self.command_manager.respawning_monsters));
if r.clicked() {
let _ = self.command_manager.generate_command_str();
}
});
});
});
ui.separator();
ui.horizontal(|ui| {
ui.label("Command");
ui.add(egui::Checkbox::without_text(&mut self.display_command));
});
ui.horizontal_wrapped(|ui| {
if let Some(l) = self.launcher_manager.get_current() {
if ui.add(egui::SelectableLabel::new(false, &l.name)).clicked() {
self.launcher_manager.remove_current();
self.command_manager.remove_launcher();
}
} else {
ui.label("Select a launcher plz");
}
if let Some(iwad) = self.iwad_manager.get_current() {
if ui
.add(egui::SelectableLabel::new(false, &iwad.name))
.clicked()
{
self.iwad_manager.remove_current();
self.command_manager.remove_iwad();
}
} else {
ui.label("Select an iwad plz");
}
let mut remove: Option<usize> = None;
for (pos, pwad) in self.pwad_manager.get_current().iter().enumerate() {
if ui
.add(egui::SelectableLabel::new(false, &pwad.name))
.clicked()
{
remove = Some(pos);
break;
}
}
if let Some(r) = remove {
self.pwad_manager.remove_current(r);
self.command_manager
.add_pwads(&self.pwad_manager.get_current())
}
});
if self.display_command {
ui.horizontal(|ui| {
let mut text = self.command_manager.command_string.clone();
let window_size = frame.info().window_info.size;
ui.add(egui::TextEdit::multiline(&mut text).desired_width(window_size[0]));
});
}
});
egui::Window::new("Add WAD or Launcher")
.open(&mut self.add_stuff_window_displayed)
.show(ctx, |ui| {
ui.horizontal(|ui| {
let name_label = ui.label("Name");
ui.text_edit_singleline(&mut self.add_name)
.labelled_by(name_label.id);
});
ui.horizontal(|ui| {
ui.label("Path");
ui.label(
self.selected_file_path
.clone()
.into_os_string()
.into_string()
.unwrap(),
);
if ui.button("Find").clicked() {
if let Some(path) = rfd::FileDialog::new().pick_file() {
self.selected_file_path = path;
}
}
});
ui.horizontal(|ui| {
ui.label("What sort of file is it?");
if ui
.add(egui::SelectableLabel::new(
self.selected_file_type == FileType::Launcher,
"Launcher",
))
.clicked()
{
self.selected_file_type = FileType::Launcher
}
if ui
.add(egui::SelectableLabel::new(
self.selected_file_type == FileType::Iwad,
"IWAD",
))
.clicked()
{
self.selected_file_type = FileType::Iwad
}
if ui
.add(egui::SelectableLabel::new(
self.selected_file_type == FileType::Pwad,
"PWAD",
))
.clicked()
{
self.selected_file_type = FileType::Pwad
}
});
if ui.button("Add!").clicked() {
if self.add_name.is_empty() || self.selected_file_path.as_os_str().is_empty() {
return;
}
match self.selected_file_type {
FileType::Iwad => {
self.iwad_manager.add(&WadInfo {
name: self.add_name.clone(),
path: self.selected_file_path.clone(),
});
}
FileType::Pwad => {
self.pwad_manager.add(&WadInfo {
name: self.add_name.clone(),
path: self.selected_file_path.clone(),
});
}
FileType::Launcher => {
self.launcher_manager.add(&LauncherInfo {
name: self.add_name.clone(),
path: self.selected_file_path.clone(),
});
}
}
}
});
}
}