Limit set of active audio cells to only those enabled

main
Elijah Voigt 3 hours ago
parent 2665ffb3c5
commit e89886382d

@ -56,7 +56,6 @@ fn main() {
load_audio_tones,
load_materials,
load_meshes,
spawn_audio_players.after(load_audio_tones),
),
)
.configure_sets(
@ -111,7 +110,14 @@ fn main() {
.add_systems(
Update,
(
control_audio_players.run_if(any_component_changed::<Cell>.or_else(state_changed::<SimulationPlayback>).or_else(state_changed::<AudioPlayback>)).in_set(GameSet::React),
control_audio_players
.run_if(
on_message::<Lifecycle>
.or_else(state_changed::<SimulationPlayback>)
.or_else(state_changed::<AudioPlayback>),
)
.in_set(GameSet::React),
manage_audio_players.run_if(resource_changed::<PitchMap>),
update_pitch_map_resource_ui.run_if(resource_changed::<PitchMap>),
),
)
@ -122,6 +128,7 @@ fn main() {
grid_gizmo,
update_debug_info_coordinates,
(
#[cfg(debug_assertions)]
assert_cell_uniqueness
.run_if(any_with_component::<Cell>)
.after(update_material),
@ -784,6 +791,7 @@ fn is_ui_hovered(hovered: Query<&Hovered>) -> bool {
hovered.iter().any(|Hovered(h)| *h)
}
#[cfg(debug_assertions)]
fn assert_cell_uniqueness(q: Query<(Entity, &Coordinates), With<Cell>>) {
q.iter().for_each(|(e1, c1)| {
q.iter().for_each(|(e2, c2)| {
@ -1231,6 +1239,18 @@ impl PitchMap {
// always ensure the notes list is sorted
self.notes.sort();
}
// Return an iterator over all enabled CellPitch values
fn iter_enabled_cell_pitches(&self) -> impl Iterator<Item = CellPitch> {
self.notes.iter().flat_map(|n| {
(0..=self.octaves)
.map(|o| o as isize)
.map(|o| o - (o / 2))
.map(|o| {
CellPitch { note: n.clone(), octave: o }
})
})
}
}
#[test]
@ -1383,15 +1403,35 @@ fn update_camera_position(mut query: Query<(&Coordinates, &mut Transform), With<
});
}
// Ordering: first, once, after(load_audio_tones)
fn spawn_audio_players(mut commands: Commands, cell_assets: Res<CellAssets>) {
// Run when PitchMap changes to ensure we have just the audio sinks we need
fn manage_audio_players(
mut commands: Commands,
cell_assets: Res<CellAssets>,
pitch_map: Res<PitchMap>,
current: Query<(Entity, &CellPitch), With<AudioSink>>,
mut active: Local<HashSet<CellPitch>>,
) {
*active = pitch_map.iter_enabled_cell_pitches().collect();
CellPitch::iter_all().for_each(|cp| {
let h = cell_assets.pitches.get(&cp).unwrap().clone();
commands.spawn((AudioPlayer(h), cp, PlaybackSettings::default().muted()));
});
// The cell is active, ensure it has an audio entity
if active.contains(&cp) {
if !current.iter().any(|(_this_e, this_cp)| *this_cp == cp) {
let h = cell_assets.pitches.get(&cp).unwrap().clone();
commands.spawn((AudioPlayer(h), cp, PlaybackSettings::default().muted()));
}
}
// The cell is inactive, ensure it does not have an audio entity
else {
if let Some(e) = current
.iter()
.find_map(|(this_e, this_cp)| (*this_cp == cp).then_some(this_e))
{
commands.entity(e).despawn();
}
}
})
}
// Ordering: React
fn control_audio_players(
audio_state: Res<State<AudioPlayback>>,
simulation_state: Res<State<SimulationPlayback>>,

Loading…
Cancel
Save