|
|
|
|
@ -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::<CellAssets>()
|
|
|
|
|
.init_resource::<Panning>()
|
|
|
|
|
.init_resource::<PitchMap>()
|
|
|
|
|
.init_resource::<LastBoardState>()
|
|
|
|
|
.insert_resource(ClearColor(WHITE.into()))
|
|
|
|
|
.insert_resource(UiTheme(create_light_theme()))
|
|
|
|
|
.init_state::<SimulationPlayback>()
|
|
|
|
|
@ -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<Activate>, mut next: ResMut<NextState<SimulationPlayback>>| {
|
|
|
|
|
on(|
|
|
|
|
|
_: On<Activate>,
|
|
|
|
|
mut next: ResMut<NextState<SimulationPlayback>>,
|
|
|
|
|
mut last_board_state: ResMut<LastBoardState>,
|
|
|
|
|
coordinates: Query<&Coordinates, With<Cell>>
|
|
|
|
|
| {
|
|
|
|
|
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<Activate>, mut next: ResMut<NextState<SimulationPlayback>>| {
|
|
|
|
|
next.set(SimulationPlayback::Step);
|
|
|
|
|
}),
|
|
|
|
|
ui_button(UiButton::Reset)
|
|
|
|
|
on(|
|
|
|
|
|
_: On<Activate>,
|
|
|
|
|
last_board_state: Res<LastBoardState>,
|
|
|
|
|
mut lifecycle: MessageWriter<Lifecycle>,
|
|
|
|
|
cells: Query<Entity, With<Cell>>,
|
|
|
|
|
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<Activate>, cells: Query<Entity, With<Cell>>, mut commands: Commands| {
|
|
|
|
|
cells.iter().for_each(|e| {
|
|
|
|
|
commands.entity(e).despawn();
|
|
|
|
|
});
|
|
|
|
|
}),
|
|
|
|
|
ui_button(UiButton::ZoomOut)
|
|
|
|
|
on(|_: On<Activate>, 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<Coordinates>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[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 {
|
|
|
|
|
]
|
|
|
|
|
.into_iter()
|
|
|
|
|
.flat_map(|note| {
|
|
|
|
|
(-5..6).map(move |octave| CellPitch {
|
|
|
|
|
note: note.clone(),
|
|
|
|
|
octave,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
@ -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<PitchMap>,
|
|
|
|
|
) {
|
|
|
|
|
fn reassign_cell_pitch(mut query: Query<(&mut CellPitch, &Coordinates)>, pitch_map: Res<PitchMap>) {
|
|
|
|
|
info!("query size: {:?}", query.iter().len());
|
|
|
|
|
query.iter_mut().for_each(|(mut cell_pitch, c)| {
|
|
|
|
|
*cell_pitch = pitch_map.coordinates_cell_pitch(c);
|
|
|
|
|
|