diff --git a/life/assets/return.png b/life/assets/return.png new file mode 100644 index 0000000..15f9625 Binary files /dev/null and b/life/assets/return.png differ diff --git a/life/assets/trashcan.png b/life/assets/trashcan.png new file mode 100644 index 0000000..b674185 Binary files /dev/null and b/life/assets/trashcan.png differ diff --git a/life/assets/trashcanOpen.png b/life/assets/trashcanOpen.png new file mode 100644 index 0000000..39d1260 Binary files /dev/null and b/life/assets/trashcanOpen.png differ diff --git a/life/src/main.rs b/life/src/main.rs index ff1de22..ce923a1 100644 --- a/life/src/main.rs +++ b/life/src/main.rs @@ -2,20 +2,22 @@ // * Debug Panel // * Describe cell I am hovering over (Note, Octave, etc) // * Count # of cells on the board -// * Save board state when playing -// * Restore board state from before playing -// * Wipe board // * Fix tiling repeating // * Negative coordinates should not mirror -// +// * Fix randomly audio not working +// * space -> play/pause sim +// * m -> un/mute audio #![allow(clippy::complexity)] // Only because of FromTemplat macros unfortunately... #![allow(dead_code)] use bevy::{ - feathers::{containers::*, theme::ThemeProps}, ui::{Checked, InteractionDisabled}, ui_widgets::{ - ActivateOnPress, Checkbox, SliderPrecision, SliderStep, ValueChange, checkbox_self_update, slider_self_update - } + feathers::{containers::*, theme::ThemeProps}, + ui::{Checked, InteractionDisabled}, + ui_widgets::{ + ActivateOnPress, Checkbox, SliderPrecision, SliderStep, ValueChange, checkbox_self_update, + slider_self_update, + }, }; use engine::*; @@ -33,6 +35,7 @@ fn main() { .init_resource::() .init_resource::() .init_resource::() + .init_resource::() .insert_resource(ClearColor(WHITE.into())) .insert_resource(UiTheme(create_light_theme())) .init_state::() @@ -107,6 +110,8 @@ enum UiButton { AddLowOctave, SubLowOctave, Note, + Reset, + Wipe, #[default] None, } @@ -127,6 +132,8 @@ impl UiButton { Self::AddLowOctave => "todo.png", Self::SubLowOctave => "todo.png", Self::Note => "todo.png", + Self::Reset => "return.png", + Self::Wipe => "trashcan.png", Self::None => todo!(), } } @@ -246,7 +253,13 @@ fn the_ui() -> impl Scene { }), ui_button(UiButton::Play) SimulationPlayback::Run - on(|_: On, mut next: ResMut>| { + on(| + _: On, + mut next: ResMut>, + mut last_board_state: ResMut, + coordinates: Query<&Coordinates, With> + | { + last_board_state.coordinates = coordinates.iter().cloned().collect(); // Set simulation state next.set(SimulationPlayback::Run); }), @@ -254,6 +267,28 @@ fn the_ui() -> impl Scene { on(|_: On, mut next: ResMut>| { next.set(SimulationPlayback::Step); }), + ui_button(UiButton::Reset) + on(| + _: On, + last_board_state: Res, + mut lifecycle: MessageWriter, + cells: Query>, + mut commands: Commands, + | { + // Todo: reconcile board instead of despawn/spawning the world + cells.iter().for_each(|e| { + commands.entity(e).despawn(); + }); + last_board_state.coordinates.iter().for_each(|c| { + lifecycle.write(Lifecycle::Alive(c.clone())); + }); + }), + ui_button(UiButton::Wipe) + on(|_: On, cells: Query>, mut commands: Commands| { + cells.iter().for_each(|e| { + commands.entity(e).despawn(); + }); + }), ui_button(UiButton::ZoomOut) on(|_: On, mut projection: Query<&mut Projection>| { projection.iter_mut().for_each(|mut p| match *p { @@ -376,6 +411,11 @@ fn the_ui() -> impl Scene { #[derive(Default, Debug, Resource)] struct NextCoordinates(Coordinates); +#[derive(Default, Debug, Resource)] +struct LastBoardState { + coordinates: Vec, +} + #[derive(Debug, Default, Clone, PartialEq, Hash, Eq, Component, FromTemplate)] #[require(Visibility, Transform)] struct Coordinates { @@ -626,7 +666,10 @@ fn new_cell( let cell_pitch = pitch_map.coordinates_cell_pitch(&c); #[derive(Clone, Default, Component)] - enum Foo { #[default]A } + enum Foo { + #[default] + A, + } bsn! { Cell @@ -800,12 +843,12 @@ impl CellPitch { Note::FSharp, Note::G, Note::GSharp, - ].into_iter().flat_map(|note| { - (-5..6).map(move |octave| { - CellPitch { - note: note.clone(), - octave, - } + ] + .into_iter() + .flat_map(|note| { + (-5..6).map(move |octave| CellPitch { + note: note.clone(), + octave, }) }) } @@ -998,7 +1041,7 @@ impl PitchMap { }; let octave: isize = { let num_octaves: usize = self.octaves_up + self.octaves_down + 1; - let y_coord: usize = c.y.strict_abs() as usize; // TODO: shift first or something + let y_coord: usize = c.y.strict_abs() as usize; // TODO: shift first or something debug!("num_octaves: {:?}", num_octaves); debug!("y_coord: {:?}", y_coord); (y_coord % num_octaves) as isize - 5 @@ -1010,10 +1053,7 @@ impl PitchMap { } /// When the pitch map changes, update all cells to use the correct pitch (note + octave) -fn reassign_cell_pitch( - mut query: Query<(&mut CellPitch, &Coordinates)>, - pitch_map: Res, -) { +fn reassign_cell_pitch(mut query: Query<(&mut CellPitch, &Coordinates)>, pitch_map: Res) { info!("query size: {:?}", query.iter().len()); query.iter_mut().for_each(|(mut cell_pitch, c)| { *cell_pitch = pitch_map.coordinates_cell_pitch(c);