life: user defined notes and octaves; saving my place

main
Elijah Voigt 4 weeks ago
parent 1ac628a503
commit 6b492c9a62

@ -14,56 +14,46 @@ fn main() {
.init_resource::<NextCoordinates>() .init_resource::<NextCoordinates>()
.init_resource::<CellAssets>() .init_resource::<CellAssets>()
.init_resource::<Panning>() .init_resource::<Panning>()
.init_resource::<PitchMap>()
.insert_resource(ClearColor(WHITE.into())) .insert_resource(ClearColor(WHITE.into()))
.insert_resource(UiTheme(create_light_theme())) .insert_resource(UiTheme(create_light_theme()))
.init_state::<SimulationPlayback>() .init_state::<SimulationPlayback>()
.init_state::<AudioPlayback>() .init_state::<AudioPlayback>()
.add_message::<Lifecycle>() .add_message::<Lifecycle>()
.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( .add_systems(
Update, Startup,
update_grid_position.run_if(on_message::<CursorMoved>), (
) the_camera.spawn(),
.add_systems( the_ui.spawn(),
Update, load_audio_tones,
// Run if any component added/removed: AudioSink load_materials,
// Run if state changed: AudioPlayback load_meshes,
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::<Cell>),
)
.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)),
) )
.add_systems( .add_systems(
Update, Update,
simulation_step.run_if(state_changed::<SimulationPlayback>), (
update_grid_position.run_if(on_message::<CursorMoved>),
// 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::<Cell>),
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::<SimulationPlayback>),
grid_gizmo,
// TODO: Visualize audio play/mute buttons enable/disable
toggle_interactive::<SimulationPlayback>,
// TODO Visualize simulation run/pause buttons enable/disable
toggle_interactive::<AudioPlayback>,
),
) )
// TODO: Visualize audio play/mute buttons enable/disable
.add_systems(Update, toggle_interactive::<SimulationPlayback>)
.add_systems(Update, toggle_interactive::<AudioPlayback>)
// TODO Visualize simulation run/pause buttons enable/disable
.add_systems(Update, cell_lifecycle.run_if(on_message::<Lifecycle>)) .add_systems(Update, cell_lifecycle.run_if(on_message::<Lifecycle>))
.add_systems(Update, mouse_pan.run_if(on_message::<MouseMotion>)) .add_systems(Update, mouse_pan.run_if(on_message::<MouseMotion>))
.add_systems(Update, set_pan_state) .add_systems(Update, set_pan_state)
@ -94,6 +84,7 @@ enum UiButton {
SubHighOctave, SubHighOctave,
AddLowOctave, AddLowOctave,
SubLowOctave, SubLowOctave,
Note,
#[default] #[default]
None, None,
} }
@ -113,6 +104,7 @@ impl UiButton {
Self::SubHighOctave => "todo.png", Self::SubHighOctave => "todo.png",
Self::AddLowOctave => "todo.png", Self::AddLowOctave => "todo.png",
Self::SubLowOctave => "todo.png", Self::SubLowOctave => "todo.png",
Self::Note => "todo.png",
Self::None => todo!(), Self::None => todo!(),
} }
} }
@ -207,6 +199,66 @@ fn the_ui() -> impl Scene {
on(|_: On<Activate>, mut next: ResMut<NextState<AudioPlayback>>| { on(|_: On<Activate>, mut next: ResMut<NextState<AudioPlayback>>| {
next.set(AudioPlayback::Play); next.set(AudioPlayback::Play);
}), }),
ui_button(UiButton::Note)
Note::A
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::ASharp
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::B
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::C
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::CSharp
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::D
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::DSharp
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::E
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::F
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::FSharp
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::G
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::Note)
Note::GSharp
on(|_: On<Activate>, pitch_map: ResMut<PitchMap>| {
warn!("TODO")
}),
ui_button(UiButton::AddLowOctave) ui_button(UiButton::AddLowOctave)
on(|_: On<Activate>| { on(|_: On<Activate>| {
warn!("TODO") warn!("TODO")
@ -564,29 +616,40 @@ struct CellAssets {
mesh: Handle<Mesh>, mesh: Handle<Mesh>,
} }
#[derive(Hash, PartialEq, Eq, Debug, Clone)] // TODO: Impl Ord to sort Notes
#[derive(Hash, PartialEq, Eq, Debug, Clone, Component, Default, FromTemplate)]
enum Note { enum Note {
#[default]
A, A,
ASharp,
B, B,
C,
CSharp, CSharp,
D,
DSharp,
E, E,
F,
FSharp, FSharp,
G,
GSharp,
} }
impl Note { impl Note {
/// Pitches: /// Pitches: https://en.wikipedia.org/wiki/Piano_key_frequencies
/// A -440 Hz
/// B - 493.88 Hz
/// C# - 554.37 Hz
/// E - 659.25 Hz
/// F# - 698.46 Hz
fn as_frequency(&self) -> f32 { fn as_frequency(&self) -> f32 {
match self { match self {
Note::A => 440.0, Self::A => 440.0,
Note::B => 493.88, Self::ASharp => todo!(),
Note::CSharp => 553.37, Self::B => todo!(),
Note::E => 659.25, Self::C => todo!(),
Note::FSharp => 698.46, 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<Panning>) -> bool {
panning.0 panning.0
} }
// TODO: Do not spawn cell when clicking UI
// This may or may not be an eye sore // This may or may not be an eye sore
fn create_light_theme() -> ThemeProps { fn create_light_theme() -> ThemeProps {
ThemeProps { ThemeProps {
@ -779,3 +840,20 @@ fn toggle_interactive<T: Component + States + PartialEq>(
} }
}) })
} }
#[derive(Resource)]
struct PitchMap {
notes: Vec<Note>,
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,
}
}
}

Loading…
Cancel
Save