Save appearance settings separately, so it's harder to reset it accidentally. Closes #120.

This commit is contained in:
IQuant 2024-08-18 11:27:33 +03:00
parent a9de876274
commit d8dbd5d44c
3 changed files with 69 additions and 41 deletions

View file

@ -121,6 +121,25 @@ enum AppState {
AskSavestateReset, AskSavestateReset,
} }
#[derive(Debug, Serialize, Deserialize)]
struct PlayerAppearance {
player_color: PlayerColor,
player_picker: PlayerPicker,
hue: f32,
cosmetics: (bool, bool, bool),
}
impl Default for PlayerAppearance {
fn default() -> Self {
Self {
player_color: PlayerColor::default(),
player_picker: PlayerPicker::None,
hue: 0.0,
cosmetics: (true, true, true),
}
}
}
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct AppSavedState { struct AppSavedState {
addr: String, addr: String,
@ -134,10 +153,6 @@ struct AppSavedState {
show_extra_debug_stuff: bool, show_extra_debug_stuff: bool,
#[serde(default)] #[serde(default)]
record_all: bool, record_all: bool,
player_color: PlayerColor,
player_picker: PlayerPicker,
hue: f32,
cosmetics: (bool, bool, bool),
} }
impl Default for AppSavedState { impl Default for AppSavedState {
@ -151,10 +166,6 @@ impl Default for AppSavedState {
start_game_automatically: false, start_game_automatically: false,
show_extra_debug_stuff: false, show_extra_debug_stuff: false,
record_all: false, record_all: false,
player_color: PlayerColor::default(),
player_picker: PlayerPicker::None,
hue: 0.0,
cosmetics: (true, true, true),
} }
} }
} }
@ -209,9 +220,11 @@ pub struct App {
can_start_automatically: bool, can_start_automatically: bool,
player_image: RgbaImage, player_image: RgbaImage,
end_run_confirmation: bool, end_run_confirmation: bool,
appearance: PlayerAppearance,
} }
const MODMANAGER: &str = "modman"; const MODMANAGER: &str = "modman";
const APPEARANCE: &str = "appearance";
fn filled_group<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> { fn filled_group<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
let style = ui.style(); let style = ui.style();
@ -247,6 +260,20 @@ impl App {
.storage .storage
.and_then(|storage| eframe::get_value(storage, MODMANAGER)) .and_then(|storage| eframe::get_value(storage, MODMANAGER))
.unwrap_or_default(); .unwrap_or_default();
let appearance: PlayerAppearance = cc
.storage
.and_then(|storage| {
eframe::get_value(storage, APPEARANCE).inspect(|x| info!("Loaded appearance {x:?}"))
})
.unwrap_or_else(|| {
// Fallback to loading from the old location
cc.storage
.and_then(|storage| {
eframe::get_value(storage, eframe::APP_KEY)
.inspect(|x| info!("Loaded appearance from fallback: {x:?}"))
})
.unwrap_or_default()
});
saved_state.times_started += 1; saved_state.times_started += 1;
Self::set_fonts(&cc.egui_ctx); Self::set_fonts(&cc.egui_ctx);
@ -291,6 +318,7 @@ impl App {
run_save_state, run_save_state,
player_image, player_image,
end_run_confirmation: false, end_run_confirmation: false,
appearance,
} }
} }
@ -302,7 +330,7 @@ impl App {
}; };
let my_nickname = self.app_saved_state.nickname.clone().or(steam_nickname); let my_nickname = self.app_saved_state.nickname.clone().or(steam_nickname);
let mod_path = self.modmanager_settings.mod_path(); let mod_path = self.modmanager_settings.mod_path();
let mut cosmetics = self.app_saved_state.cosmetics; let mut cosmetics = self.appearance.cosmetics;
if let Some(path) = &self.modmanager_settings.game_save_path { if let Some(path) = &self.modmanager_settings.game_save_path {
let flags = path.join("save00/persistent/flags"); let flags = path.join("save00/persistent/flags");
let hat = flags.join("secret_hat").exists(); let hat = flags.join("secret_hat").exists();
@ -321,7 +349,7 @@ impl App {
NetManagerInit { NetManagerInit {
my_nickname, my_nickname,
save_state: self.run_save_state.clone(), save_state: self.run_save_state.clone(),
player_color: self.app_saved_state.player_color, player_color: self.appearance.player_color,
cosmetics, cosmetics,
mod_path, mod_path,
player_path: player_path(self.modmanager_settings.mod_path()), player_path: player_path(self.modmanager_settings.mod_path()),
@ -615,32 +643,29 @@ impl App {
.crop(1, 1, 8, 18) .crop(1, 1, 8, 18)
.into_rgba8(); .into_rgba8();
} }
let old_hue = self.app_saved_state.hue; let old_hue = self.appearance.hue;
ui.add(Slider::new(&mut self.app_saved_state.hue, 0.0..=360.0).text("Shift hue")); ui.add(Slider::new(&mut self.appearance.hue, 0.0..=360.0).text("Shift hue"));
if old_hue != self.app_saved_state.hue { if old_hue != self.appearance.hue {
let diff = self.app_saved_state.hue - old_hue; let diff = self.appearance.hue - old_hue;
shift_hue(diff, &mut self.app_saved_state.player_color.player_main); shift_hue(diff, &mut self.appearance.player_color.player_main);
shift_hue(diff, &mut self.app_saved_state.player_color.player_alt); shift_hue(diff, &mut self.appearance.player_color.player_alt);
shift_hue(diff, &mut self.app_saved_state.player_color.player_arm); shift_hue(diff, &mut self.appearance.player_color.player_arm);
shift_hue(diff, &mut self.app_saved_state.player_color.player_forearm); shift_hue(diff, &mut self.appearance.player_color.player_forearm);
shift_hue(diff, &mut self.app_saved_state.player_color.player_cape); shift_hue(diff, &mut self.appearance.player_color.player_cape);
shift_hue( shift_hue(diff, &mut self.appearance.player_color.player_cape_edge);
diff,
&mut self.app_saved_state.player_color.player_cape_edge,
);
} }
ui.horizontal(|ui| { ui.horizontal(|ui| {
display_player_skin(ui, self); display_player_skin(ui, self);
player_select_current_color_slot(ui, self); player_select_current_color_slot(ui, self);
player_skin_display_color_picker( player_skin_display_color_picker(
ui, ui,
&mut self.app_saved_state.player_color, &mut self.appearance.player_color,
&self.app_saved_state.player_picker, &self.appearance.player_picker,
); );
}); });
if ui.button("Reset colors to default").clicked() { if ui.button("Reset colors to default").clicked() {
self.app_saved_state.player_color = PlayerColor::default(); self.appearance.player_color = PlayerColor::default();
self.app_saved_state.hue = 0.0 self.appearance.hue = 0.0
} }
} }
} }
@ -974,6 +999,7 @@ impl eframe::App for App {
fn save(&mut self, storage: &mut dyn eframe::Storage) { fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, eframe::APP_KEY, &self.app_saved_state); eframe::set_value(storage, eframe::APP_KEY, &self.app_saved_state);
eframe::set_value(storage, MODMANAGER, &self.modmanager_settings); eframe::set_value(storage, MODMANAGER, &self.modmanager_settings);
eframe::set_value(storage, APPEARANCE, &self.appearance);
} }
} }

View file

@ -244,6 +244,8 @@ impl Connections {
*state.key() *state.key()
); );
self.connect(*state.key()); self.connect(*state.key());
// TODO: signal that reconnect happened.
// Several things should be reset on it, as we certainly lost several messages during it.
all_connected = false; all_connected = false;
} }
} }

View file

@ -135,33 +135,33 @@ pub fn color_picker(ui: &mut Ui, color: &mut [u8; 4]) {
pub fn player_select_current_color_slot(ui: &mut Ui, app: &mut App) { pub fn player_select_current_color_slot(ui: &mut Ui, app: &mut App) {
let mut clicked = false; let mut clicked = false;
let last = app.app_saved_state.player_picker.clone(); let last = app.appearance.player_picker.clone();
ui.scope(|ui| { ui.scope(|ui| {
ui.set_max_width(100.0); ui.set_max_width(100.0);
ui.vertical_centered_justified(|ui| { ui.vertical_centered_justified(|ui| {
if ui.button("Main color").clicked() { if ui.button("Main color").clicked() {
clicked = true; clicked = true;
app.app_saved_state.player_picker = PlayerPicker::PlayerMain app.appearance.player_picker = PlayerPicker::PlayerMain
} }
if ui.button("Alt color").clicked() { if ui.button("Alt color").clicked() {
clicked = true; clicked = true;
app.app_saved_state.player_picker = PlayerPicker::PlayerAlt app.appearance.player_picker = PlayerPicker::PlayerAlt
} }
if ui.button("Arm color").clicked() { if ui.button("Arm color").clicked() {
clicked = true; clicked = true;
app.app_saved_state.player_picker = PlayerPicker::PlayerArm app.appearance.player_picker = PlayerPicker::PlayerArm
} }
if ui.button("Forearm color").clicked() { if ui.button("Forearm color").clicked() {
clicked = true; clicked = true;
app.app_saved_state.player_picker = PlayerPicker::PlayerForearm app.appearance.player_picker = PlayerPicker::PlayerForearm
} }
if ui.button("Cape color").clicked() { if ui.button("Cape color").clicked() {
clicked = true; clicked = true;
app.app_saved_state.player_picker = PlayerPicker::PlayerCape app.appearance.player_picker = PlayerPicker::PlayerCape
} }
if ui.button("Cape edge color").clicked() { if ui.button("Cape edge color").clicked() {
clicked = true; clicked = true;
app.app_saved_state.player_picker = PlayerPicker::PlayerCapeEdge app.appearance.player_picker = PlayerPicker::PlayerCapeEdge
} }
if let Some(path) = &app.modmanager_settings.game_save_path { if let Some(path) = &app.modmanager_settings.game_save_path {
let flags = path.join("save00/persistent/flags"); let flags = path.join("save00/persistent/flags");
@ -169,19 +169,19 @@ pub fn player_select_current_color_slot(ui: &mut Ui, app: &mut App) {
let amulet = flags.join("secret_amulet").exists(); let amulet = flags.join("secret_amulet").exists();
let gem = flags.join("secret_amulet_gem").exists(); let gem = flags.join("secret_amulet_gem").exists();
if hat { if hat {
ui.checkbox(&mut app.app_saved_state.cosmetics.0, "Crown"); ui.checkbox(&mut app.appearance.cosmetics.0, "Crown");
} }
if amulet { if amulet {
ui.checkbox(&mut app.app_saved_state.cosmetics.1, "Amulet"); ui.checkbox(&mut app.appearance.cosmetics.1, "Amulet");
} }
if gem { if gem {
ui.checkbox(&mut app.app_saved_state.cosmetics.2, "Gem"); ui.checkbox(&mut app.appearance.cosmetics.2, "Gem");
} }
} }
}); });
}); });
if clicked && last == app.app_saved_state.player_picker { if clicked && last == app.appearance.player_picker {
app.app_saved_state.player_picker = PlayerPicker::None app.appearance.player_picker = PlayerPicker::None
} }
} }
@ -190,9 +190,9 @@ pub fn display_player_skin(ui: &mut Ui, app: &App) {
add_cosmetics( add_cosmetics(
&mut img, &mut img,
app.modmanager_settings.game_save_path.clone(), app.modmanager_settings.game_save_path.clone(),
app.app_saved_state.cosmetics, app.appearance.cosmetics,
); );
make_player_image(&mut img, app.app_saved_state.player_color); make_player_image(&mut img, app.appearance.player_color);
let texture: TextureHandle = ui.ctx().load_texture( let texture: TextureHandle = ui.ctx().load_texture(
"player", "player",
egui::ColorImage::from_rgba_unmultiplied([8, 18], &img.into_raw()), egui::ColorImage::from_rgba_unmultiplied([8, 18], &img.into_raw()),