//! Example showing typical usage of `PrefsPlugin`. use bevy::{color::palettes::tailwind, ecs::system::EntityCommands, log::LogPlugin, prelude::*}; use bevy_simple_prefs::{Prefs, PrefsPlugin}; // All `Prefs` must also be `Reflect` and `Default`. #[derive(Prefs, Reflect, Default)] struct ExamplePrefs { // Each field of the `Prefs` will be inserted into the `App` as a separate `Resource`. volume: Volume, difficulty: Difficulty, } // All `Prefs` fields must be `Resource`, `Reflect`, and `Clone`. #[derive(Resource, Reflect, Clone, Eq, PartialEq, Debug)] struct Volume(pub u32); #[derive(Resource, Reflect, Clone, Eq, PartialEq, Debug, Default)] enum Difficulty { Easy, #[default] Normal, Hard, } fn main() { App::new() .add_plugins(DefaultPlugins.set(LogPlugin { filter: "prefs=debug,bevy_simple_prefs=debug".into(), ..default() })) // `PrefsPlugin` is generic, add as many different types of // prefs as you want. Make sure to set a unique filename for // each. .add_plugins(PrefsPlugin::::default()) .add_systems(Startup, setup) .add_systems( Update, ( volume_buttons, volume_label.run_if(resource_changed::), difficulty_buttons, difficulty_label.run_if(resource_changed::), button_style, ), ) .run(); } const TEXT_SIZE: f32 = 40.; const TEXT_COLOR: Srgba = tailwind::EMERALD_50; const BUTTON_TEXT_COLOR: Srgba = tailwind::EMERALD_50; const LABEL_BACKGROUND: Srgba = tailwind::EMERALD_800; const NORMAL_BUTTON: Srgba = tailwind::EMERALD_500; const HOVERED_BUTTON: Srgba = tailwind::EMERALD_600; const PRESSED_BUTTON: Srgba = tailwind::EMERALD_700; #[derive(Component)] struct VolumeUpButton; #[derive(Component)] struct VolumeDownButton; #[derive(Component)] struct VolumeLabel; #[derive(Component)] struct DifficultyUpButton; #[derive(Component)] struct DifficultyDownButton; #[derive(Component)] struct DifficultyLabel; fn volume_buttons( up_query: Query<&Interaction, (Changed, With)>, down_query: Query<&Interaction, (Changed, With)>, mut volume: ResMut, ) { // Prefs are persisted when the individual resources are changed. // Be careful when mutably dereferencing, as this can trigger unnecessary IO. let current = volume.bypass_change_detection().0; for _ in up_query.iter().filter(|i| **i == Interaction::Pressed) { let new = (current + 10).min(100); volume.set_if_neq(Volume(new)); } for _ in down_query.iter().filter(|i| **i == Interaction::Pressed) { let new = current.saturating_sub(10); volume.set_if_neq(Volume(new)); } } fn volume_label(volume: Res, mut text_query: Query<&mut Text, With>) { for mut text in &mut text_query { text.sections[0].value.clone_from(&format!("{}", volume.0)); } } fn difficulty_buttons( up_query: Query<&Interaction, (Changed, With)>, down_query: Query<&Interaction, (Changed, With)>, mut difficulty: ResMut, ) { for _ in up_query.iter().filter(|i| **i == Interaction::Pressed) { let next = difficulty.bypass_change_detection().next(); difficulty.set_if_neq(next); } for _ in down_query.iter().filter(|i| **i == Interaction::Pressed) { let prev = difficulty.bypass_change_detection().prev(); difficulty.set_if_neq(prev); } } fn difficulty_label( difficulty: Res, mut text_query: Query<&mut Text, With>, ) { for mut text in &mut text_query { text.sections[0] .value .clone_from(&format!("{:?}", *difficulty)); } } fn button_style( mut interaction_query: Query< (&Interaction, &mut BackgroundColor), (Changed, With