some more UI

This commit is contained in:
Rph :3
2025-04-18 00:15:28 +02:00
parent 165a9fc139
commit 4d6e23980e
8 changed files with 413 additions and 25 deletions

View File

@@ -1,16 +1,18 @@
mod omori_locator;
mod app_logic;
mod config;
mod mod_builder;
use std::{sync::Arc, thread, time::{Duration, SystemTime}};
use std::{process::exit, sync::Arc, thread, time::SystemTime, default::Default};
use app_logic::{AppThread, UiEvent, UiState, UiStateHolder};
use crossbeam_channel::{Receiver, Sender};
use eframe::egui;
use egui::{mutex::{Mutex, RwLock}, Align, Layout, RichText, ThemePreference};
use egui_alignments::{center_horizontal, center_vertical, top_horizontal, Aligner};
use egui::{mutex::Mutex, Align, Layout, RichText, TextStyle, ThemePreference};
use egui_alignments::{center_vertical, top_horizontal};
use egui_extras::{Column, TableBuilder};
use egui_modal::Modal;
use mod_builder::ModConfiguration;
use sha2::Digest;
fn main() -> anyhow::Result<()> {
@@ -30,6 +32,7 @@ fn main() -> anyhow::Result<()> {
viewport: egui::ViewportBuilder::default()
.with_min_inner_size([640.0, 480.0]),
..Default::default()
};
let app_state = UiStateHolder {
@@ -60,7 +63,9 @@ fn main() -> anyhow::Result<()> {
struct Application {
state: UiStateHolder,
sender: Sender<UiEvent>,
key_input: String
key_input: String,
configuration: ModConfiguration,
did_fill_configuration: bool
}
impl Application {
@@ -68,7 +73,9 @@ impl Application {
Application {
sender,
state,
key_input: "".to_string()
key_input: "".to_string(),
configuration: Default::default(),
did_fill_configuration: false
}
}
}
@@ -76,10 +83,15 @@ impl Application {
const GAME_KEY_HASH: &[u8; 32] = include_bytes!("keyhash");
impl eframe::App for Application {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) {
exit(0); // TODO: Prompt the user to maybe please consider not actually exiting the app while it's working
}
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let state = self.state.state.lock();
let state = state.clone();
ctx.request_repaint_after_secs(10.0);
match state {
UiState::Loading => {
egui::CentralPanel::default().show(ctx, |ui| {
@@ -154,7 +166,7 @@ impl eframe::App for Application {
invalid_path_modal.button(ui, "OK");
});
});
egui::TopBottomPanel::top("key_prompt_title_bar").show(ctx, |ui| {
egui::TopBottomPanel::top("game_prompt_title_bar").show(ctx, |ui| {
ui.with_layout(Layout::top_down(Align::Center), |ui| {
ui.label(RichText::new("Select your base game").size(32.0));
});
@@ -200,7 +212,8 @@ impl eframe::App for Application {
TableBuilder::new(ui)
.striped(true)
.column(Column::remainder())
.column(Column::auto())
.column(Column::auto().at_least(100.0))
.sense(egui::Sense::hover() | egui::Sense::click())
.body(|body| {
body.rows(20.0, others.len(), |mut row| {
let item = &others[row.index()];
@@ -211,12 +224,25 @@ impl eframe::App for Application {
let dt = chrono::Duration::from(chrono::TimeDelta::seconds(dt as i64));
row.col(|ui| {
ui.label(format!("{}", item.0.display()));
ui.with_layout(Layout::right_to_left(Align::Center).with_main_align(Align::Min).with_main_justify(true), |ui| {
ui.label(format!("{}", item.0.display()));
});
});
row.col(|ui| {
ui.label(format!("{}", chrono_humanize::HumanTime::from(dt)));
ui.with_layout(Layout::right_to_left(Align::Center).with_main_align(Align::Max), |ui| {
ui.label(format!("{}", chrono_humanize::HumanTime::from(dt)));
});
});
if row.response().clicked() {
if omori_locator::validate_omori_installation(&item.0) {
self.sender.send(UiEvent::UsePath(item.0.clone())).expect("Failed to send");
} else {
invalid_path_modal.open();
}
}
if row.response().hovered() {
ctx.set_cursor_icon(egui::CursorIcon::PointingHand);
}
});
});
@@ -226,7 +252,144 @@ impl eframe::App for Application {
});
});
});
},
UiState::PickPlaytest(playtest_history) => {
let invalid_path_modal = Modal::new(ctx, "invalid_playtest_modal");
invalid_path_modal.show(|ui| {
invalid_path_modal.title(ui, "Invalid path");
invalid_path_modal.frame(ui, |ui| {
invalid_path_modal.body(ui, "Please pick a valid, Oneloader-generated playtest.");
});
invalid_path_modal.buttons(ui, |ui| {
invalid_path_modal.button(ui, "OK");
});
});
egui::TopBottomPanel::top("playtest_prompt_title_bar").show(ctx, |ui| {
ui.with_layout(Layout::top_down(Align::Center), |ui| {
ui.label(RichText::new("Select your playtest").size(32.0));
});
});
egui::CentralPanel::default().show(ctx, |ui| {
ui.with_layout(Layout::right_to_left(Align::Min).with_main_justify(true).with_main_align(Align::Center), |ui| {
if ui.button(RichText::new("Pick playtest").size(16.0)).clicked() {
match rfd::FileDialog::new().pick_folder() {
Some(path) => {
if omori_locator::validate_playtest(&path) {
self.sender.send(UiEvent::UsePath(path)).expect("Failed to send");
} else {
invalid_path_modal.open();
}
},
None => {}
}
}
});
if playtest_history.len() > 0 {
ui.label("History of playtests");
ui.separator();
TableBuilder::new(ui)
.striped(true)
.column(Column::remainder())
.column(Column::auto().at_least(100.0))
.sense(egui::Sense::hover() | egui::Sense::click())
.body(|body| {
body.rows(20.0, playtest_history.len(), |mut row| {
let item = &playtest_history[row.index()];
let dt =
(item.1 as i64) -
(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).expect("Failed to get the time").as_secs() as i64);
let dt = chrono::Duration::from(chrono::TimeDelta::seconds(dt as i64));
row.col(|ui| {
ui.with_layout(Layout::right_to_left(Align::Center).with_main_align(Align::Min).with_main_justify(true), |ui| {
ui.label(format!("{}", item.0.display()));
});
});
row.col(|ui| {
ui.with_layout(Layout::right_to_left(Align::Center).with_main_align(Align::Max), |ui| {
ui.label(format!("{}", chrono_humanize::HumanTime::from(dt)));
});
});
if row.response().clicked() {
if omori_locator::validate_playtest(&item.0) {
self.sender.send(UiEvent::UsePath(item.0.clone())).expect("Failed to send");
} else {
invalid_path_modal.open();
}
}
if row.response().hovered() {
ctx.set_cursor_icon(egui::CursorIcon::PointingHand);
}
});
});
} else {
ui.label("Any playtests you've used before will be remembered here.");
}
});
},
UiState::Configure(initial_configuration) => {
if !self.did_fill_configuration {
self.did_fill_configuration = true;
self.configuration = initial_configuration;
}
let mut font = TextStyle::Body.resolve(&ctx.style());
font.size = 16.0;
egui::TopBottomPanel::top("configure_title_bar").show(ctx, |ui| {
ui.with_layout(Layout::top_down(Align::Center), |ui| {
ui.label(RichText::new("Configure your mod").size(32.0));
});
});
egui::CentralPanel::default().show(ctx, |ui| {
top_horizontal(ui, |ui| {
TableBuilder::new(ui)
.column(Column::auto().at_least(100.0))
.column(Column::exact(300.0))
.body(|mut body| {
body.row(24.0, |mut row| {
row.col(|ui| {
ui.label(RichText::new("Mod ID").size(16.0));
});
row.col(|ui| {
ui.add(egui::TextEdit::singleline(&mut self.configuration.mod_id).font(font.clone()));
});
});
body.row(24.0, |mut row| {
row.col(|ui| {
ui.label(RichText::new("Mod Name").size(16.0));
});
row.col(|ui| {
ui.add(egui::TextEdit::singleline(&mut self.configuration.mod_name).font(font.clone()));
});
});
body.row(24.0, |mut row| {
row.col(|ui| {
ui.label(RichText::new("Mod Description").size(16.0));
});
row.col(|ui| {
ui.add(egui::TextEdit::singleline(&mut self.configuration.mod_description).font(font.clone()));
});
});
body.row(24.0, |mut row| {
row.col(|ui| {
ui.label(RichText::new("Mod Version").size(16.0));
});
row.col(|ui| {
ui.add(egui::TextEdit::singleline(&mut self.configuration.mod_version).font(font.clone()));
});
});
});
});
ui.separator();
});
}
}
}
}
}