|
|
|
|
@ -52,6 +52,7 @@ fn main() {
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
(
|
|
|
|
|
default_board.run_if(run_once),
|
|
|
|
|
cell_lifecycle.run_if(on_message::<Lifecycle>),
|
|
|
|
|
update_grid_position.run_if(on_message::<CursorMoved>),
|
|
|
|
|
de_spawn_cells
|
|
|
|
|
@ -587,39 +588,19 @@ impl Coordinates {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// For the purposes of creating assests, what does the given coordinate translate to CellPitch wise
|
|
|
|
|
fn to_cell_pitch(&self) -> CellPitch {
|
|
|
|
|
let Coordinates { x, y } = self.normalized();
|
|
|
|
|
let note = match x {
|
|
|
|
|
0 => Note::A,
|
|
|
|
|
1 => Note::ASharp,
|
|
|
|
|
2 => Note::B,
|
|
|
|
|
3 => Note::C,
|
|
|
|
|
4 => Note::CSharp,
|
|
|
|
|
5 => Note::D,
|
|
|
|
|
6 => Note::DSharp,
|
|
|
|
|
7 => Note::E,
|
|
|
|
|
8 => Note::F,
|
|
|
|
|
9 => Note::FSharp,
|
|
|
|
|
10 => Note::G,
|
|
|
|
|
11 => Note::GSharp,
|
|
|
|
|
_ => panic!("This shouldn't happen!"),
|
|
|
|
|
};
|
|
|
|
|
let octave = y;
|
|
|
|
|
CellPitch { note, octave }
|
|
|
|
|
}
|
|
|
|
|
fn to_cell_pitch(&self, pm: &PitchMap) -> CellPitch {
|
|
|
|
|
let rows = pm.notes.len();
|
|
|
|
|
let cols = pm.octaves_up + pm.octaves_down + 1;
|
|
|
|
|
|
|
|
|
|
// Turn an arbitrary coordinate to a "normalized" coordinate centered on 0,0
|
|
|
|
|
fn normalized(&self) -> Self {
|
|
|
|
|
println!("normalizing {:?}", (self.x, self.y));
|
|
|
|
|
let x = self.x.rem_euclid(12);
|
|
|
|
|
let y = self.y.rem_euclid(11);
|
|
|
|
|
println!("normalized {:?}", (x,y));
|
|
|
|
|
debug_assert!(x >= 0);
|
|
|
|
|
debug_assert!(x <= 12);
|
|
|
|
|
debug_assert!(y >= 0);
|
|
|
|
|
debug_assert!(y <= 11);
|
|
|
|
|
let this_x = self.x.rem_euclid(rows as isize);
|
|
|
|
|
let this_y = self.y.rem_euclid(cols as isize) - (pm.octaves_down as isize);
|
|
|
|
|
|
|
|
|
|
Coordinates { x, y }
|
|
|
|
|
debug_assert!(this_x >= 0);
|
|
|
|
|
|
|
|
|
|
let note = pm.notes.get(this_x as usize).unwrap().clone();
|
|
|
|
|
let octave = this_y;
|
|
|
|
|
|
|
|
|
|
CellPitch { note, octave }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -798,24 +779,21 @@ fn new_cell(
|
|
|
|
|
|
|
|
|
|
let playback_settings = PlaybackSettings::ONCE.with_volume(volume);
|
|
|
|
|
|
|
|
|
|
let cell_pitch = pitch_map.coordinates_cell_pitch(&c);
|
|
|
|
|
let cell_pitch = c.to_cell_pitch(&(*pitch_map));
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Default, Component)]
|
|
|
|
|
enum Foo {
|
|
|
|
|
#[default]
|
|
|
|
|
A,
|
|
|
|
|
}
|
|
|
|
|
debug!("cell pitch: {:#?}", cell_pitch);
|
|
|
|
|
debug!("materials: {:#?}", cell_assets.materials);
|
|
|
|
|
|
|
|
|
|
bsn! {
|
|
|
|
|
Cell
|
|
|
|
|
Coordinates { x, y }
|
|
|
|
|
template_value(cell_pitch)
|
|
|
|
|
template_value(cell_pitch.clone())
|
|
|
|
|
template_value(playback_settings)
|
|
|
|
|
template_value(Transform::from_translation(c.as_translation() + Vec3::new(0.0, 0.0, 1.0)))
|
|
|
|
|
template_value(Mesh2dTemplate(cell_assets.mesh.clone().into()))
|
|
|
|
|
// AudioPlayer added by update_audio
|
|
|
|
|
// MeshMaterial2d added by update_material
|
|
|
|
|
template_value(MeshMaterial2dTemplate(cell_assets.materials.get(&pitch_map.coordinates_cell_pitch(&c)).unwrap().clone().into()))
|
|
|
|
|
template_value(MeshMaterial2dTemplate(cell_assets.materials.get(&cell_pitch).unwrap().clone().into()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -981,7 +959,7 @@ impl CellPitch {
|
|
|
|
|
]
|
|
|
|
|
.into_iter()
|
|
|
|
|
.flat_map(|note| {
|
|
|
|
|
(0..11).map(move |octave| CellPitch {
|
|
|
|
|
(-5..=5).map(move |octave| CellPitch {
|
|
|
|
|
note: note.clone(),
|
|
|
|
|
octave,
|
|
|
|
|
})
|
|
|
|
|
@ -1060,6 +1038,14 @@ fn load_meshes(mut cell_assets: ResMut<CellAssets>, mut meshes: ResMut<Assets<Me
|
|
|
|
|
cell_assets.mesh = meshes.add(Rectangle::new(SCALE, SCALE));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn default_board(mut writer: MessageWriter<Lifecycle>) {
|
|
|
|
|
(-5..=5).for_each(|x| {
|
|
|
|
|
(-5..=5).for_each(|y| {
|
|
|
|
|
writer.write(Lifecycle::Alive(Coordinates { x, y }));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Do not place piece if panning
|
|
|
|
|
// TODO: Tie cursor to real world space, not pixels
|
|
|
|
|
fn mouse_pan(
|
|
|
|
|
@ -1167,23 +1153,6 @@ impl PitchMap {
|
|
|
|
|
// always ensure the notes list is sorted
|
|
|
|
|
self.notes.sort();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given the currently selected notes and octave range selected in the PitchMap convert the given coordinates to a CellPitch
|
|
|
|
|
fn coordinates_cell_pitch(&self, c: &Coordinates) -> CellPitch {
|
|
|
|
|
let Coordinates { x, y } = c.normalized();
|
|
|
|
|
let note: Note = {
|
|
|
|
|
let num_notes = self.notes.len();
|
|
|
|
|
self.notes.get((x % num_notes as isize) as usize).unwrap().clone()
|
|
|
|
|
};
|
|
|
|
|
let octave: isize = {
|
|
|
|
|
let num_octaves = self.octaves_up + self.octaves_down + 1;
|
|
|
|
|
println!("num_octaves: {:?}", num_octaves);
|
|
|
|
|
(y % num_octaves as isize) as isize
|
|
|
|
|
};
|
|
|
|
|
let cp = CellPitch { note, octave };
|
|
|
|
|
println!("Cell Pitch: {:?}", cp);
|
|
|
|
|
cp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
@ -1193,46 +1162,25 @@ fn test_cell_pitch() {
|
|
|
|
|
octaves_up: 1,
|
|
|
|
|
octaves_down: 1,
|
|
|
|
|
};
|
|
|
|
|
{
|
|
|
|
|
let xs = [-6, -3, 0, 3, 6];
|
|
|
|
|
let ys = [-5, -2, 0, 3, 6];
|
|
|
|
|
xs.iter().for_each(|x| {
|
|
|
|
|
ys.iter().for_each(|y| {
|
|
|
|
|
let CellPitch { note, octave } = pm.coordinates_cell_pitch(&Coordinates { x: *x, y: *y });
|
|
|
|
|
debug_assert_eq!(note, Note::A);
|
|
|
|
|
debug_assert_eq!(octave, 0);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
let xs = [-5, -2, 1, 4, 7];
|
|
|
|
|
let ys = [-4, -1, 1, 4, 7];
|
|
|
|
|
xs.iter().for_each(|x| {
|
|
|
|
|
ys.iter().for_each(|y| {
|
|
|
|
|
let CellPitch { note, octave } = pm.coordinates_cell_pitch(&Coordinates { x: *x, y: *y });
|
|
|
|
|
debug_assert_eq!(note, Note::B);
|
|
|
|
|
debug_assert_eq!(octave, 1);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
let xs = [-4, -1, 2, 5, 8];
|
|
|
|
|
let ys = [-3, 0, 2, 5, 8];
|
|
|
|
|
xs.iter().for_each(|x| {
|
|
|
|
|
ys.iter().for_each(|y| {
|
|
|
|
|
let CellPitch { note, octave } = pm.coordinates_cell_pitch(&Coordinates { x: *x, y: *y });
|
|
|
|
|
debug_assert_eq!(note, Note::C);
|
|
|
|
|
debug_assert_eq!(octave, 2);
|
|
|
|
|
});
|
|
|
|
|
let xs = -6..=5;
|
|
|
|
|
let ys = -6..=4;
|
|
|
|
|
xs.enumerate().for_each(|(i, x)| {
|
|
|
|
|
ys.clone().enumerate().for_each(|(j, y)| {
|
|
|
|
|
let c = Coordinates { x, y };
|
|
|
|
|
let n = pm.notes.get(i % 3).unwrap();
|
|
|
|
|
let o = (j as isize % 3) - 1;
|
|
|
|
|
let cp = c.to_cell_pitch(&pm);
|
|
|
|
|
debug_assert_eq!(cp.note, *n);
|
|
|
|
|
debug_assert_eq!(cp.octave, o);
|
|
|
|
|
})
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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>) {
|
|
|
|
|
debug!("query size: {:?}", query.iter().len());
|
|
|
|
|
query.iter_mut().for_each(|(mut cell_pitch, c)| {
|
|
|
|
|
*cell_pitch = pitch_map.coordinates_cell_pitch(c);
|
|
|
|
|
*cell_pitch = c.to_cell_pitch(&(*pitch_map));
|
|
|
|
|
debug!("Updating cell pitch for {:?}", c);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|