mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-04 00:21:57 +00:00
Finished initial implementation of DiffScreen.
This commit is contained in:
parent
67c3b57851
commit
c36e8faeb0
@ -29,6 +29,7 @@ either = "1.6.1"
|
||||
ref-cast = "1.0.6"
|
||||
derive_more = "0.99.13"
|
||||
strum = { version = "0.20.0", features = ["derive"] }
|
||||
size_format = "1.0.2"
|
||||
|
||||
# Serde
|
||||
serde_yaml = "0.8.17"
|
||||
@ -1,23 +1,319 @@
|
||||
//! Diff screen
|
||||
|
||||
// Imports
|
||||
use eframe::egui;
|
||||
use crate::loaded_game::LoadedGame;
|
||||
use anyhow::Context;
|
||||
use dcb::card::{
|
||||
property::{ArrowColor, CrossMoveEffect, Effect, EffectCondition},
|
||||
Card,
|
||||
};
|
||||
use dcb_util::{btree_map_par_iter::ParIterValue, BTreeMapParIter, StrContainsCaseInsensitive};
|
||||
use eframe::egui::{self, Color32};
|
||||
use std::{collections::BTreeMap, path::PathBuf};
|
||||
|
||||
/// Diff screen
|
||||
pub struct DiffScreen {}
|
||||
pub struct DiffScreen {
|
||||
/// Other loaded game we're diffing against
|
||||
other_loaded_game: LoadedGame,
|
||||
|
||||
/// Search
|
||||
search: String,
|
||||
}
|
||||
|
||||
impl DiffScreen {
|
||||
/// Creates a new diff screen
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
pub fn new(other_file_path: PathBuf) -> Result<Self, anyhow::Error> {
|
||||
// Load the other loaded game
|
||||
let other_loaded_game = LoadedGame::load(other_file_path).context("Unable to load other game")?;
|
||||
|
||||
Ok(Self {
|
||||
other_loaded_game,
|
||||
search: String::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Displays this diff screen
|
||||
pub fn display(&mut self, ui: &mut egui::Ui) {
|
||||
let Self {} = &*self;
|
||||
pub fn display(&mut self, ui: &mut egui::Ui, loaded_game: &LoadedGame) {
|
||||
let lhs = &loaded_game.card_table;
|
||||
let rhs = &self.other_loaded_game.card_table;
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Diff");
|
||||
// If the card table of both are equal, return
|
||||
if lhs == rhs {
|
||||
return;
|
||||
}
|
||||
|
||||
// Else display the search
|
||||
let search = &mut self.search;
|
||||
ui.vertical(|ui| {
|
||||
ui.label("Search");
|
||||
ui.text_edit_singleline(search);
|
||||
});
|
||||
ui.separator();
|
||||
|
||||
// Then get the cards by their names on each loaded game
|
||||
let lhs_names = lhs
|
||||
.cards
|
||||
.iter()
|
||||
.map(|card| (card.name(), card))
|
||||
.filter(|(name, _)| name.as_str().contains_case_insensitive(&*search))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
let rhs_names = rhs
|
||||
.cards
|
||||
.iter()
|
||||
.map(|card| (card.name(), card))
|
||||
.filter(|(name, _)| name.as_str().contains_case_insensitive(&*search))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
|
||||
// Then display all differences
|
||||
egui::ScrollArea::auto_sized().show(ui, |ui| {
|
||||
egui::Grid::new("my_grid").striped(false).show(ui, |ui| {
|
||||
// Header
|
||||
ui.colored_label(Color32::from_rgb(255, 0, 0), "Loaded game");
|
||||
ui.colored_label(Color32::from_rgb(255, 0, 0), "Other game");
|
||||
ui.end_row();
|
||||
|
||||
for (name, cards) in BTreeMapParIter::new(&lhs_names, &rhs_names) {
|
||||
match cards {
|
||||
ParIterValue::Both(lhs, rhs) => {
|
||||
// If they're equal, skip
|
||||
if lhs == rhs {
|
||||
continue;
|
||||
}
|
||||
ui.heading(name.as_str());
|
||||
ui.heading(name.as_str());
|
||||
ui.end_row();
|
||||
|
||||
// Check every property
|
||||
match (lhs, rhs) {
|
||||
(Card::Digimon(lhs), Card::Digimon(rhs)) => {
|
||||
if lhs.speciality != rhs.speciality {
|
||||
ui.label(format!("Speciality: {}", lhs.speciality.as_str()));
|
||||
ui.label(format!("Speciality: {}", rhs.speciality.as_str()));
|
||||
ui.end_row();
|
||||
}
|
||||
if lhs.level != rhs.level {
|
||||
ui.label(format!("Level: {}", lhs.level.as_str()));
|
||||
ui.label(format!("Level: {}", rhs.level.as_str()));
|
||||
ui.end_row();
|
||||
}
|
||||
if lhs.hp != rhs.hp {
|
||||
ui.label(format!("Hp: {}", lhs.hp));
|
||||
ui.label(format!("Hp: {}", rhs.hp));
|
||||
ui.end_row();
|
||||
}
|
||||
if lhs.dp_cost != rhs.dp_cost {
|
||||
ui.label(format!("DP: {}", lhs.dp_cost));
|
||||
ui.label(format!("DP: {}", rhs.dp_cost));
|
||||
ui.end_row();
|
||||
}
|
||||
if lhs.dp_give != rhs.dp_give {
|
||||
ui.label(format!("+P: {}", lhs.dp_give));
|
||||
ui.label(format!("+P: {}", rhs.dp_give));
|
||||
ui.end_row();
|
||||
}
|
||||
for (mv_name, lhs_mv, rhs_mv) in std::array::IntoIter::new([
|
||||
("Circle", &lhs.move_circle, &rhs.move_circle),
|
||||
("Triangle", &lhs.move_triangle, &rhs.move_triangle),
|
||||
("Cross", &lhs.move_cross, &rhs.move_cross),
|
||||
]) {
|
||||
if lhs_mv.name != rhs_mv.name {
|
||||
ui.label(format!("{} move name: {}", mv_name, lhs_mv.name));
|
||||
ui.label(format!("{} move name: {}", mv_name, rhs_mv.name));
|
||||
ui.end_row();
|
||||
}
|
||||
if lhs_mv.power != rhs_mv.power {
|
||||
ui.label(format!("{} move power: {}", mv_name, lhs_mv.power));
|
||||
ui.label(format!("{} move power: {}", mv_name, rhs_mv.power));
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
if lhs.cross_move_effect != rhs.cross_move_effect {
|
||||
self::display_cross_move_effect_opt(ui, &lhs.cross_move_effect);
|
||||
self::display_cross_move_effect_opt(ui, &rhs.cross_move_effect);
|
||||
ui.end_row();
|
||||
}
|
||||
if lhs.effect_description != rhs.effect_description {
|
||||
ui.label("Effect description");
|
||||
ui.label("Effect description");
|
||||
ui.end_row();
|
||||
|
||||
for (idx, (lhs_desc, rhs_desc)) in
|
||||
(lhs.effect_description.zip(rhs.effect_description)).iter().enumerate()
|
||||
{
|
||||
if lhs_desc == rhs_desc {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui.label(format!("\t#{}: {}", idx + 1, lhs_desc.as_str()));
|
||||
ui.label(format!("\t#{}: {}", idx + 1, rhs_desc.as_str()));
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
if lhs.effect_arrow_color != rhs.effect_arrow_color {
|
||||
ui.label(format!(
|
||||
"Effect arrow color: {}",
|
||||
lhs.effect_arrow_color.map_or("None", ArrowColor::as_str)
|
||||
));
|
||||
ui.label(format!(
|
||||
"Effect arrow color: {}",
|
||||
rhs.effect_arrow_color.map_or("None", ArrowColor::as_str)
|
||||
));
|
||||
ui.end_row();
|
||||
}
|
||||
for (idx, (lhs_cond, rhs_cond)) in
|
||||
(lhs.effect_conditions.zip(rhs.effect_conditions)).iter().enumerate()
|
||||
{
|
||||
if lhs_cond != rhs_cond {
|
||||
self::display_effect_condition_opt(ui, idx, &lhs_cond);
|
||||
self::display_effect_condition_opt(ui, idx, &rhs_cond);
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
for (idx, (lhs_effect, rhs_effect)) in
|
||||
(lhs.effects.zip(rhs.effects)).iter().enumerate()
|
||||
{
|
||||
if lhs_effect != rhs_effect {
|
||||
self::display_effect_opt(ui, idx, &lhs_effect);
|
||||
self::display_effect_opt(ui, idx, &rhs_effect);
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
},
|
||||
(Card::Item(lhs), Card::Item(rhs)) => {
|
||||
if lhs.effect_description != rhs.effect_description {
|
||||
ui.label("Effect description");
|
||||
ui.label("Effect description");
|
||||
ui.end_row();
|
||||
|
||||
for (idx, (lhs_desc, rhs_desc)) in
|
||||
(lhs.effect_description.zip(rhs.effect_description)).iter().enumerate()
|
||||
{
|
||||
if lhs_desc == rhs_desc {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui.label(format!("\t#{}: {}", idx + 1, lhs_desc.as_str()));
|
||||
ui.label(format!("\t#{}: {}", idx + 1, rhs_desc.as_str()));
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
if lhs.effect_arrow_color != rhs.effect_arrow_color {
|
||||
ui.label(format!(
|
||||
"Effect arrow color: {}",
|
||||
lhs.effect_arrow_color.map_or("None", ArrowColor::as_str)
|
||||
));
|
||||
ui.label(format!(
|
||||
"Effect arrow color: {}",
|
||||
rhs.effect_arrow_color.map_or("None", ArrowColor::as_str)
|
||||
));
|
||||
ui.end_row();
|
||||
}
|
||||
for (idx, (lhs_cond, rhs_cond)) in
|
||||
(lhs.effect_conditions.zip(rhs.effect_conditions)).iter().enumerate()
|
||||
{
|
||||
if lhs_cond != rhs_cond {
|
||||
self::display_effect_condition_opt(ui, idx, &lhs_cond);
|
||||
self::display_effect_condition_opt(ui, idx, &rhs_cond);
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
for (idx, (lhs_effect, rhs_effect)) in
|
||||
(lhs.effects.zip(rhs.effects)).iter().enumerate()
|
||||
{
|
||||
if lhs_effect != rhs_effect {
|
||||
self::display_effect_opt(ui, idx, &lhs_effect);
|
||||
self::display_effect_opt(ui, idx, &rhs_effect);
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
},
|
||||
(Card::Digivolve(lhs), Card::Digivolve(rhs)) => {
|
||||
if lhs.effect_description != rhs.effect_description {
|
||||
ui.label("Effect description");
|
||||
ui.label("Effect description");
|
||||
ui.end_row();
|
||||
|
||||
for (idx, (lhs_desc, rhs_desc)) in
|
||||
(lhs.effect_description.zip(rhs.effect_description)).iter().enumerate()
|
||||
{
|
||||
if lhs_desc == rhs_desc {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui.label(format!("\t#{}: {}", idx + 1, lhs_desc.as_str()));
|
||||
ui.label(format!("\t#{}: {}", idx + 1, rhs_desc.as_str()));
|
||||
ui.end_row();
|
||||
}
|
||||
}
|
||||
if lhs.effect != rhs.effect {
|
||||
ui.label(format!("Effect: {}", lhs.effect));
|
||||
ui.label(format!("Effect: {}", rhs.effect));
|
||||
ui.end_row();
|
||||
}
|
||||
},
|
||||
// If they're different card types, simply emit their card types
|
||||
_ => {
|
||||
ui.label(lhs.ty().as_str());
|
||||
ui.label(rhs.ty().as_str());
|
||||
ui.end_row();
|
||||
},
|
||||
}
|
||||
},
|
||||
ParIterValue::Left(_) => {
|
||||
ui.heading(name.as_str());
|
||||
ui.heading("❌");
|
||||
ui.end_row();
|
||||
},
|
||||
ParIterValue::Right(_) => {
|
||||
ui.heading("❌");
|
||||
ui.heading(name.as_str());
|
||||
ui.end_row();
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: Better way of doing a big separator?
|
||||
ui.separator();
|
||||
ui.separator();
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Displays an optional cross move effect
|
||||
fn display_cross_move_effect_opt(ui: &mut egui::Ui, effect: &Option<CrossMoveEffect>) {
|
||||
ui.label(format!(
|
||||
"Cross move effect: {}",
|
||||
dcb_util::DisplayWrapper::new(|f| match effect {
|
||||
Some(effect) => write!(f, "{effect}"),
|
||||
None => write!(f, "None"),
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
/// Displays an optional effect condition
|
||||
fn display_effect_condition_opt(ui: &mut egui::Ui, idx: usize, cond: &Option<EffectCondition>) {
|
||||
ui.label(format!(
|
||||
"Cross move effect #{}: {}",
|
||||
idx + 1,
|
||||
dcb_util::DisplayWrapper::new(|f| match cond {
|
||||
// TODO: Properly display it
|
||||
Some(cond) => write!(f, "{cond:#?}"),
|
||||
None => write!(f, "None"),
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
/// Displays an optional effect
|
||||
fn display_effect_opt(ui: &mut egui::Ui, idx: usize, effect: &Option<Effect>) {
|
||||
ui.label(format!(
|
||||
"Cross move effect #{}: {}",
|
||||
idx + 1,
|
||||
dcb_util::DisplayWrapper::new(|f| match effect {
|
||||
// TODO: Properly display it
|
||||
Some(effect) => write!(f, "{effect:#?}"),
|
||||
None => write!(f, "None"),
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
once_cell,
|
||||
never_type,
|
||||
seek_stream_len,
|
||||
try_blocks
|
||||
try_blocks,
|
||||
array_zip
|
||||
)]
|
||||
|
||||
// Modules
|
||||
@ -140,7 +141,9 @@ impl epi::App for CardEditor {
|
||||
|
||||
if let Some(_loaded_game) = loaded_game {
|
||||
if ui.button("Diff").clicked() {
|
||||
*diff_screen = Some(DiffScreen::new());
|
||||
if let Err(err) = self::on_diff(diff_screen) {
|
||||
alert::error!("Unable to diff with game: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -173,11 +176,11 @@ impl epi::App for CardEditor {
|
||||
}
|
||||
|
||||
// Draw diff screen
|
||||
if let (Some(screen), Some(_loaded_game)) = (diff_screen.as_mut(), loaded_game.as_mut()) {
|
||||
if let (Some(screen), Some(loaded_game)) = (diff_screen.as_mut(), loaded_game.as_ref()) {
|
||||
let mut is_open = true;
|
||||
egui::Window::new("Diff screen")
|
||||
.open(&mut is_open)
|
||||
.show(ctx, |ui| screen.display(ui));
|
||||
.show(ctx, |ui| screen.display(ui, loaded_game));
|
||||
|
||||
// If the window closed, destroy it
|
||||
if !is_open {
|
||||
@ -1012,6 +1015,21 @@ fn on_open(loaded_game: &mut Option<LoadedGame>) -> Result<(), anyhow::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// On 'View > Diff'.
|
||||
fn on_diff(diff_screen: &mut Option<DiffScreen>) -> Result<(), anyhow::Error> {
|
||||
// Ask for the file path
|
||||
let other_file_path = match self::ask_game_file_path() {
|
||||
Some(path) => path,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
// Try to create the screen
|
||||
let screen = DiffScreen::new(other_file_path).context("Unable to create diff screen")?;
|
||||
*diff_screen = Some(screen);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Asks the user for the game file path
|
||||
fn ask_game_file_path() -> Option<std::path::PathBuf> {
|
||||
let cur_dir_path = std::env::current_dir().expect("Unable to get current directory path");
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
// Imports
|
||||
use super::{AttackType, Speciality};
|
||||
use std::fmt;
|
||||
|
||||
/// A digimon's cross move effect
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
|
||||
@ -121,3 +122,14 @@ impl ::dcb_bytes::Bytes for CrossMoveEffect {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CrossMoveEffect {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
CrossMoveEffect::AttackToZero(attack) => write!(f, "{attack} to zero"),
|
||||
CrossMoveEffect::Counter(attack) => write!(f, "{attack} Counter"),
|
||||
CrossMoveEffect::TripleAgainst(speciality) => write!(f, "Triple against {speciality}"),
|
||||
_ => write!(f, "{}", self.as_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user