Expose save slot info (like playtime) in GUI
This commit is contained in:
parent
d1e9a8d57a
commit
dc40526c33
5 changed files with 120 additions and 35 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -620,6 +620,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "5.4.0"
|
||||
|
@ -1565,6 +1574,7 @@ name = "ireko"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"binrw",
|
||||
"chrono",
|
||||
"eframe",
|
||||
"flate2",
|
||||
"paramacro",
|
||||
|
|
|
@ -8,3 +8,4 @@ flate2 = { version = "1.0", features = ["zlib-ng"], default-features = false }
|
|||
binrw = { version = "0.14", features = ["std"], default-features = false }
|
||||
paramacro = { path = "paramacro" }
|
||||
eframe = { version= "0.31" }
|
||||
chrono = { version = "0.4", default-features = false }
|
||||
|
|
115
src/bin/gui.rs
115
src/bin/gui.rs
|
@ -3,7 +3,18 @@ use std::{env, io::Cursor};
|
|||
use binrw::BinRead;
|
||||
use eframe::egui;
|
||||
use ireko::{
|
||||
property::{array_property::ArrayValue, map_property::{MabSubProperty, MapKeyProperty}}, save_object::{generic::Property, LocalProfileObject, PersistentObject}, structure::{DAAssembleIdDataStruct, DABuildDataStruct, DACustomizeAssetIdDataStruct, DAHumanoidColoringDataStruct, DAHumanoidFigureData, DAMachineColoringDataStruct, DAModuleColorStruct, DATriggerDataStruct, DATuningDataStruct, Guid, LinearColorStruct, PrimaryAssetIdStruct, Struct}, CompressedSaveFile
|
||||
CompressedSaveFile,
|
||||
property::{
|
||||
array_property::ArrayValue,
|
||||
map_property::{MabSubProperty, MapKeyProperty},
|
||||
},
|
||||
save_object::{LocalProfileObject, PersistentObject, SlotObject, generic::Property},
|
||||
structure::{
|
||||
DAAssembleIdDataStruct, DABuildDataStruct, DACustomizeAssetIdDataStruct,
|
||||
DAHumanoidColoringDataStruct, DAHumanoidFigureData, DAMachineColoringDataStruct,
|
||||
DAModuleColorStruct, DATriggerDataStruct, DATuningDataStruct, Guid, LinearColorStruct,
|
||||
PrimaryAssetIdStruct, Struct,
|
||||
},
|
||||
};
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
|
@ -39,7 +50,7 @@ fn main() -> eframe::Result {
|
|||
ModuleInventory,
|
||||
PartsInventory,
|
||||
Build,
|
||||
Presets
|
||||
Presets,
|
||||
};
|
||||
let mut tab = Tab::General;
|
||||
|
||||
|
@ -67,7 +78,29 @@ fn main() -> eframe::Result {
|
|||
panic!("Expected a stirng!");
|
||||
};
|
||||
|
||||
if ui.button(&name.value).clicked() {
|
||||
let slot_path = format!("{save_dir}/{}/Slot.sav", id.value);
|
||||
|
||||
let mut slot_data = Cursor::new(std::fs::read(&slot_path).unwrap());
|
||||
|
||||
let slot = CompressedSaveFile::<SlotObject>::read_le(&mut slot_data).unwrap();
|
||||
|
||||
let playtime = chrono::NaiveTime::from_num_seconds_from_midnight_opt(
|
||||
slot.value.objs.playtime.value.round() as u32,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
let last_checkpoint = slot.value.objs.district_tag.value;
|
||||
|
||||
if ui
|
||||
.button(&format!(
|
||||
"{} {} {} {}",
|
||||
name.value,
|
||||
slot.value.objs.slot_info.timestamp.to_datetime(),
|
||||
playtime,
|
||||
last_checkpoint
|
||||
))
|
||||
.clicked()
|
||||
{
|
||||
let persistent_path = format!("{save_dir}/{}/Persistent.sav", id.value);
|
||||
|
||||
let mut persistent_data =
|
||||
|
@ -116,15 +149,20 @@ fn main() -> eframe::Result {
|
|||
ui.checkbox(&mut persistent.demo_version.value, "Demo Version");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(egui::DragValue::new(&mut persistent.money.value).suffix(" cell"));
|
||||
ui.add(
|
||||
egui::DragValue::new(&mut persistent.money.value).suffix(" cell"),
|
||||
);
|
||||
ui.label("Money")
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(egui::DragValue::new(&mut persistent.current_item_slot.value).range(0..=5));
|
||||
ui.add(
|
||||
egui::DragValue::new(&mut persistent.current_item_slot.value)
|
||||
.range(0..=5),
|
||||
);
|
||||
ui.label("Selected Item");
|
||||
});
|
||||
},
|
||||
}
|
||||
Tab::ItemWheel => {
|
||||
for (i, item) in persistent.item_slots.entries.iter_mut().enumerate() {
|
||||
let ArrayValue::Struct { ref mut r#struct } = item.key else {
|
||||
|
@ -140,14 +178,16 @@ fn main() -> eframe::Result {
|
|||
ui.label(format!("{i:02}"));
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
Tab::ItemInventory => {
|
||||
for item in &mut persistent.normal_item_inventory.entries {
|
||||
let MapKeyProperty::StructMaybe(ref key) = item.key else {
|
||||
panic!("Expecting a struct!");
|
||||
};
|
||||
|
||||
let Property::Name(ref name) = **(key.extra_fields[0].key.as_ref().unwrap()) else {
|
||||
let Property::Name(ref name) =
|
||||
**(key.extra_fields[0].key.as_ref().unwrap())
|
||||
else {
|
||||
panic!("Expecting a name property!");
|
||||
};
|
||||
|
||||
|
@ -155,11 +195,15 @@ fn main() -> eframe::Result {
|
|||
panic!("Expecting a struct!");
|
||||
};
|
||||
|
||||
let Property::Int(ref carry_count) = **(value.fields[0].key.as_ref().unwrap()) else {
|
||||
let Property::Int(ref carry_count) =
|
||||
**(value.fields[0].key.as_ref().unwrap())
|
||||
else {
|
||||
panic!("Expecting an int!");
|
||||
};
|
||||
|
||||
let Property::Int(ref store_count) = **(value.fields[1].key.as_ref().unwrap()) else {
|
||||
let Property::Int(ref store_count) =
|
||||
**(value.fields[1].key.as_ref().unwrap())
|
||||
else {
|
||||
panic!("Expecting an int!");
|
||||
};
|
||||
|
||||
|
@ -169,7 +213,7 @@ fn main() -> eframe::Result {
|
|||
ui.label(format!("store: {}", store_count.value));
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
Tab::ModuleInventory => {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Mobility").clicked() {
|
||||
|
@ -208,8 +252,12 @@ fn main() -> eframe::Result {
|
|||
|
||||
let matches = match module {
|
||||
ModuleType::Mobility => key.value == "EDAModuleItemType::Mobility",
|
||||
ModuleType::FrontWeapon => key.value == "EDAModuleItemType::FrontWeapon",
|
||||
ModuleType::RearWeapon => key.value == "EDAModuleItemType::RearWeapon",
|
||||
ModuleType::FrontWeapon => {
|
||||
key.value == "EDAModuleItemType::FrontWeapon"
|
||||
}
|
||||
ModuleType::RearWeapon => {
|
||||
key.value == "EDAModuleItemType::RearWeapon"
|
||||
}
|
||||
ModuleType::Hanger => key.value == "EDAModuleItemType::Hanger",
|
||||
ModuleType::Utility => key.value == "EDAModuleItemType::Utility",
|
||||
ModuleType::Thruster => key.value == "EDAModuleItemType::Thruster",
|
||||
|
@ -221,7 +269,9 @@ fn main() -> eframe::Result {
|
|||
panic!("Expecting struct value!");
|
||||
};
|
||||
|
||||
let Property::Map(ref mut map) = **value.fields[0].key.as_mut().unwrap() else {
|
||||
let Property::Map(ref mut map) =
|
||||
**value.fields[0].key.as_mut().unwrap()
|
||||
else {
|
||||
panic!("Expecting map!");
|
||||
};
|
||||
|
||||
|
@ -236,11 +286,14 @@ fn main() -> eframe::Result {
|
|||
panic!("Expecting struct value!");
|
||||
};
|
||||
|
||||
let Property::Struct(ref asset_id) = **value.fields[0].key.as_mut().unwrap() else {
|
||||
let Property::Struct(ref asset_id) =
|
||||
**value.fields[0].key.as_mut().unwrap()
|
||||
else {
|
||||
panic!("Expecting struct!");
|
||||
};
|
||||
|
||||
let Struct::PrimaryAssetId(ref asset_id) = asset_id.r#struct else {
|
||||
let Struct::PrimaryAssetId(ref asset_id) = asset_id.r#struct
|
||||
else {
|
||||
panic!("Expecting primary asset id!");
|
||||
};
|
||||
|
||||
|
@ -253,23 +306,24 @@ fn main() -> eframe::Result {
|
|||
};*/
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(format!("{:#?} {} level", key, asset_id.primary_asset_name.value));
|
||||
ui.label(format!(
|
||||
"{:#?} {} level",
|
||||
key, asset_id.primary_asset_name.value
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//println!("{:#?}", persistent.module_inventory);
|
||||
},
|
||||
}
|
||||
Tab::PartsInventory => {
|
||||
println!("{:#?}", persistent.parts_inventory);
|
||||
},
|
||||
}
|
||||
Tab::Build => {
|
||||
edit_build_data(ui, &mut persistent.current_build_data);
|
||||
},
|
||||
Tab::Presets => {
|
||||
|
||||
},
|
||||
}
|
||||
Tab::Presets => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -322,8 +376,14 @@ fn edit_customize_data(ui: &mut egui::Ui, customize: &mut DACustomizeAssetIdData
|
|||
edit_humanoid_figure(ui, &mut customize.figure_data);
|
||||
|
||||
ui.checkbox(&mut customize.inverse_face_mesh.value, "Inverse Face");
|
||||
ui.checkbox(&mut customize.inverse_front_hair_mesh.value, "Inverse Front Hair");
|
||||
ui.checkbox(&mut customize.inverse_back_hair_mesh.value, "Inverse Back Hair");
|
||||
ui.checkbox(
|
||||
&mut customize.inverse_front_hair_mesh.value,
|
||||
"Inverse Front Hair",
|
||||
);
|
||||
ui.checkbox(
|
||||
&mut customize.inverse_back_hair_mesh.value,
|
||||
"Inverse Back Hair",
|
||||
);
|
||||
}
|
||||
|
||||
fn edit_humanoid_figure(ui: &mut egui::Ui, figure_data: &mut DAHumanoidFigureData) {
|
||||
|
@ -348,7 +408,10 @@ fn edit_humanoid_figure(ui: &mut egui::Ui, figure_data: &mut DAHumanoidFigureDat
|
|||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(egui::Slider::new(&mut figure_data.waist_up.value, 0.0..=1.0));
|
||||
ui.add(egui::Slider::new(
|
||||
&mut figure_data.waist_up.value,
|
||||
0.0..=1.0,
|
||||
));
|
||||
ui.label("Waist");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,29 +8,29 @@ use crate::{
|
|||
#[derive(Debug)]
|
||||
pub struct SlotObject {
|
||||
#[paramacro::serialized_field = "SavedDataVersion"]
|
||||
version: IntProperty,
|
||||
pub version: IntProperty,
|
||||
|
||||
#[paramacro::serialized_field = "bDemoVersion"]
|
||||
demo: BoolProperty,
|
||||
pub demo: BoolProperty,
|
||||
|
||||
#[paramacro::serialized_field = "CreatedTimeStamp"]
|
||||
created_timestamp: DateTimeStruct,
|
||||
pub created_timestamp: DateTimeStruct,
|
||||
|
||||
#[paramacro::serialized_field = "PlayTime"]
|
||||
playtime: FloatProperty,
|
||||
pub playtime: FloatProperty,
|
||||
|
||||
#[paramacro::serialized_field = "RegisteredName"]
|
||||
name: StrProperty,
|
||||
pub name: StrProperty,
|
||||
|
||||
#[paramacro::serialized_field = "LoadOption"]
|
||||
load_option: DALoadOptionStruct,
|
||||
pub load_option: DALoadOptionStruct,
|
||||
|
||||
#[paramacro::serialized_field = "DistrictTag"]
|
||||
district_tag: NameProperty,
|
||||
pub district_tag: NameProperty,
|
||||
|
||||
#[paramacro::serialized_field = "CycleCount"]
|
||||
cycle_count: IntProperty,
|
||||
pub cycle_count: IntProperty,
|
||||
|
||||
#[paramacro::serialized_field = "SlotInfo"]
|
||||
slot_info: SaveSlotInfoStruct,
|
||||
pub slot_info: SaveSlotInfoStruct,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use binrw::binrw;
|
||||
use chrono::Datelike;
|
||||
|
||||
use crate::property::PropertyBase;
|
||||
|
||||
|
@ -26,3 +27,13 @@ impl PropertyBase for DateTimeStruct {
|
|||
8
|
||||
}
|
||||
}
|
||||
|
||||
impl DateTimeStruct {
|
||||
pub fn to_datetime(&self) -> chrono::NaiveDateTime {
|
||||
let datetime = chrono::NaiveDate::from_ymd_opt(1, 1, 1).unwrap();
|
||||
let datetime = chrono::NaiveDateTime::from(datetime);
|
||||
datetime
|
||||
.checked_add_signed(chrono::TimeDelta::microseconds(self.ticks / 10))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue