From 6b492c9a6212a744bfc826bff843b3b8672e488c Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Wed, 24 Jun 2026 00:00:52 -0700 Subject: [PATCH] life: user defined notes and octaves; saving my place --- life/src/main.rs | 186 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 132 insertions(+), 54 deletions(-) diff --git a/life/src/main.rs b/life/src/main.rs index 85085d8..a399929 100644 --- a/life/src/main.rs +++ b/life/src/main.rs @@ -14,56 +14,46 @@ fn main() { .init_resource::() .init_resource::() .init_resource::() + .init_resource::() .insert_resource(ClearColor(WHITE.into())) .insert_resource(UiTheme(create_light_theme())) .init_state::() .init_state::() .add_message::() - .add_systems(Startup, the_camera.spawn()) - .add_systems(Startup, the_ui.spawn()) - .add_systems(Startup, load_audio_tones) - .add_systems(Startup, load_materials) - .add_systems(Startup, load_meshes) .add_systems( - Update, - update_grid_position.run_if(on_message::), - ) - .add_systems( - Update, - // Run if any component added/removed: AudioSink - // Run if state changed: AudioPlayback - control_volume, - ) - .add_systems(Update, grid_gizmo) - .add_systems( - Update, - de_spawn_cells - .run_if(not(is_ui_hovered)) - .run_if(not(is_panning)) - .run_if(input_just_released(MouseButton::Left)), - ) - .add_systems( - Update, - assert_cell_uniqueness.run_if(any_with_component::), - ) - .add_systems( - Update, - simulation_step.run_if(input_just_pressed(KeyCode::ArrowRight)), - ) - .add_systems( - Update, - simulation_step - .run_if(in_state(SimulationPlayback::Run)) - .run_if(cooldown_secs(SIM_FRAME_DURATION)), + Startup, + ( + the_camera.spawn(), + the_ui.spawn(), + load_audio_tones, + load_materials, + load_meshes, + ), ) .add_systems( Update, - simulation_step.run_if(state_changed::), + ( + update_grid_position.run_if(on_message::), + // Run if any component added/removed: AudioSink + // Run if state changed: AudioPlayback + control_volume, + de_spawn_cells + .run_if(not(is_ui_hovered)) + .run_if(not(is_panning)) + .run_if(input_just_released(MouseButton::Left)), + assert_cell_uniqueness.run_if(any_with_component::), + simulation_step.run_if(input_just_pressed(KeyCode::ArrowRight)), + simulation_step + .run_if(in_state(SimulationPlayback::Run)) + .run_if(cooldown_secs(SIM_FRAME_DURATION)), + simulation_step.run_if(state_changed::), + grid_gizmo, + // TODO: Visualize audio play/mute buttons enable/disable + toggle_interactive::, + // TODO Visualize simulation run/pause buttons enable/disable + toggle_interactive::, + ), ) - // TODO: Visualize audio play/mute buttons enable/disable - .add_systems(Update, toggle_interactive::) - .add_systems(Update, toggle_interactive::) - // TODO Visualize simulation run/pause buttons enable/disable .add_systems(Update, cell_lifecycle.run_if(on_message::)) .add_systems(Update, mouse_pan.run_if(on_message::)) .add_systems(Update, set_pan_state) @@ -94,6 +84,7 @@ enum UiButton { SubHighOctave, AddLowOctave, SubLowOctave, + Note, #[default] None, } @@ -113,6 +104,7 @@ impl UiButton { Self::SubHighOctave => "todo.png", Self::AddLowOctave => "todo.png", Self::SubLowOctave => "todo.png", + Self::Note => "todo.png", Self::None => todo!(), } } @@ -207,6 +199,66 @@ fn the_ui() -> impl Scene { on(|_: On, mut next: ResMut>| { next.set(AudioPlayback::Play); }), + ui_button(UiButton::Note) + Note::A + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::ASharp + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::B + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::C + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::CSharp + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::D + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::DSharp + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::E + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::F + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::FSharp + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::G + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), + ui_button(UiButton::Note) + Note::GSharp + on(|_: On, pitch_map: ResMut| { + warn!("TODO") + }), ui_button(UiButton::AddLowOctave) on(|_: On| { warn!("TODO") @@ -564,29 +616,40 @@ struct CellAssets { mesh: Handle, } -#[derive(Hash, PartialEq, Eq, Debug, Clone)] +// TODO: Impl Ord to sort Notes +#[derive(Hash, PartialEq, Eq, Debug, Clone, Component, Default, FromTemplate)] enum Note { + #[default] A, + ASharp, B, + C, CSharp, + D, + DSharp, E, + F, FSharp, + G, + GSharp, } impl Note { - /// Pitches: - /// A -440 Hz - /// B - 493.88 Hz - /// C# - 554.37 Hz - /// E - 659.25 Hz - /// F# - 698.46 Hz + /// Pitches: https://en.wikipedia.org/wiki/Piano_key_frequencies fn as_frequency(&self) -> f32 { match self { - Note::A => 440.0, - Note::B => 493.88, - Note::CSharp => 553.37, - Note::E => 659.25, - Note::FSharp => 698.46, + Self::A => 440.0, + Self::ASharp => todo!(), + Self::B => todo!(), + Self::C => todo!(), + Self::CSharp => todo!(), + Self::D => todo!(), + Self::DSharp => todo!(), + Self::E => todo!(), + Self::F => todo!(), + Self::FSharp => todo!(), + Self::G => todo!(), + Self::GSharp => todo!(), } } } @@ -741,8 +804,6 @@ fn is_panning(panning: Res) -> bool { panning.0 } -// TODO: Do not spawn cell when clicking UI - // This may or may not be an eye sore fn create_light_theme() -> ThemeProps { ThemeProps { @@ -779,3 +840,20 @@ fn toggle_interactive( } }) } + +#[derive(Resource)] +struct PitchMap { + notes: Vec, + octaves_up: usize, + octaves_down: usize, +} + +impl Default for PitchMap { + fn default() -> Self { + Self { + notes: vec![Note::A, Note::B, Note::CSharp, Note::E, Note::FSharp], + octaves_up: 3, + octaves_down: 3, + } + } +}