Port to Synthizer.

This commit is contained in:
Nolan Darilek 2022-05-23 13:35:25 -05:00
parent 1022037efe
commit 29405c7307
7 changed files with 192 additions and 67 deletions

View File

@ -25,8 +25,8 @@ features = [
[dependencies] [dependencies]
backtrace = "0.3" backtrace = "0.3"
bevy_input_actionmap = { git = "https://github.com/lightsoutgames/bevy_input_actionmap" } bevy_input_actionmap = { git = "https://github.com/lightsoutgames/bevy_input_actionmap" }
bevy_openal = { git = "https://github.com/lightsoutgames/bevy_openal" }
bevy_rapier2d = "0.13" bevy_rapier2d = "0.13"
bevy_synthizer = { git = "https://labs.lightsout.games/projects/bevy_synthizer" }
bevy_tts = { git = "https://github.com/lightsoutgames/bevy_tts", default-features = false, features = ["tolk"] } bevy_tts = { git = "https://github.com/lightsoutgames/bevy_tts", default-features = false, features = ["tolk"] }
coord_2d = "0.3" coord_2d = "0.3"
futures-lite = "1" futures-lite = "1"
@ -36,6 +36,6 @@ maze_generator = "2"
once_cell = "1" once_cell = "1"
pathfinding = "3" pathfinding = "3"
rand = "0.8" rand = "0.8"
sentry = "0.25" sentry = "0.26"
serde = "1" serde = "1"
shadowcast = "0.8" shadowcast = "0.8"

View File

@ -586,7 +586,7 @@ impl<RapierUserData: 'static + WorldQuery + Send + Sync> PluginGroup
fn build(&mut self, group: &mut bevy::app::PluginGroupBuilder) { fn build(&mut self, group: &mut bevy::app::PluginGroupBuilder) {
group group
.add(crate::bevy_tts::TtsPlugin) .add(crate::bevy_tts::TtsPlugin)
.add(crate::bevy_openal::OpenAlPlugin) .add(crate::bevy_synthizer::SynthizerPlugin)
.add(CorePlugin::<RapierUserData>::default()); .add(CorePlugin::<RapierUserData>::default());
} }
} }

View File

@ -3,7 +3,7 @@
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
pub use bevy_input_actionmap; pub use bevy_input_actionmap;
pub use bevy_openal; pub use bevy_synthizer;
pub use bevy_rapier2d; pub use bevy_rapier2d;
pub use bevy_tts; pub use bevy_tts;
pub mod commands; pub mod commands;

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use bevy::prelude::*; use bevy::prelude::*;
use crate::{ use crate::{
bevy_openal::{Listener, Sound}, bevy_synthizer::{Listener, Sound},
commands::RunIfExistsExt, commands::RunIfExistsExt,
sound::SoundIcon, sound::SoundIcon,
}; };
@ -14,7 +14,7 @@ struct Behind;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct PitchShiftConfig { pub struct PitchShiftConfig {
pub downshift_behind: bool, pub downshift_behind: bool,
pub downshift: f32, pub downshift: f64,
} }
impl Default for PitchShiftConfig { impl Default for PitchShiftConfig {
@ -64,10 +64,10 @@ fn tag_behind(
} }
#[derive(Clone, Debug, Default, Deref, DerefMut)] #[derive(Clone, Debug, Default, Deref, DerefMut)]
struct LastIconPitch(HashMap<Entity, f32>); struct LastIconPitch(HashMap<Entity, f64>);
#[derive(Clone, Debug, Default, Deref, DerefMut)] #[derive(Clone, Debug, Default, Deref, DerefMut)]
struct LastSoundPitch(HashMap<Entity, f32>); struct LastSoundPitch(HashMap<Entity, f64>);
fn behind_added( fn behind_added(
config: Res<PitchShiftConfig>, config: Res<PitchShiftConfig>,

View File

@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use bevy::{asset::HandleId, prelude::*, transform::TransformSystem}; use bevy::{asset::HandleId, prelude::*, transform::TransformSystem};
use bevy_openal::{Buffer, Sound, SoundState}; use bevy_synthizer::{DistanceMax, DistanceRef, Rolloff, Sound};
use rand::random; use rand::random;
use crate::{commands::RunIfExistsExt, core::PointLike}; use crate::{commands::RunIfExistsExt, core::PointLike};
@ -11,12 +11,12 @@ use crate::{commands::RunIfExistsExt, core::PointLike};
pub struct Footstep { pub struct Footstep {
pub sound: HandleId, pub sound: HandleId,
pub step_length: f32, pub step_length: f32,
pub gain: f32, pub gain: f64,
pub reference_distance: f32, pub reference_distance: Option<f64>,
pub max_distance: f32, pub max_distance: Option<f64>,
pub rolloff_factor: f32, pub rolloff: Option<f64>,
pub pitch: f32, pub pitch: Option<f64>,
pub pitch_variation: Option<f32>, pub pitch_variation: Option<f64>,
} }
impl Default for Footstep { impl Default for Footstep {
@ -25,10 +25,10 @@ impl Default for Footstep {
sound: "".into(), sound: "".into(),
step_length: 0.8, step_length: 0.8,
gain: 1., gain: 1.,
reference_distance: 1., reference_distance: None,
max_distance: f32::MAX, max_distance: None,
rolloff_factor: 1., rolloff: None,
pitch: 1., pitch: None,
pitch_variation: Some(0.15), pitch_variation: Some(0.15),
} }
} }
@ -43,15 +43,15 @@ pub struct FootstepBundle {
fn added( fn added(
mut commands: Commands, mut commands: Commands,
asset_server: Res<AssetServer>,
footsteps: Query<(Entity, &Footstep), Added<Footstep>>, footsteps: Query<(Entity, &Footstep), Added<Footstep>>,
assets: Res<Assets<Buffer>>,
) { ) {
for (entity, footstep) in footsteps.iter() { for (entity, footstep) in footsteps.iter() {
let buffer = assets.get_handle(footstep.sound); let buffer = asset_server.get_handle(footstep.sound);
commands.run_if_exists(entity, move |mut entity| { commands.run_if_exists(entity, move |mut entity| {
entity.insert(Sound { entity.insert(Sound {
buffer, buffer,
state: SoundState::Stopped, paused: true,
..default() ..default()
}); });
}); });
@ -59,27 +59,87 @@ fn added(
} }
fn update( fn update(
mut commands: Commands,
mut last_step_distance: Local<HashMap<Entity, (f32, Transform)>>, mut last_step_distance: Local<HashMap<Entity, (f32, Transform)>>,
mut footsteps: Query<(Entity, &Footstep, &Parent, &mut Sound), Changed<GlobalTransform>>, mut footsteps: Query<
(
Entity,
&Footstep,
&Parent,
&mut Sound,
Option<&DistanceRef>,
Option<&DistanceMax>,
Option<&Rolloff>,
),
Changed<GlobalTransform>,
>,
transforms_storage: Query<&Transform>, transforms_storage: Query<&Transform>,
) { ) {
for (entity, footstep, parent, mut sound) in footsteps.iter_mut() { for (entity, footstep, parent, mut sound, reference_distance, max_distance, rolloff) in
footsteps.iter_mut()
{
let coordinates = transforms_storage.get(**parent).unwrap(); let coordinates = transforms_storage.get(**parent).unwrap();
if let Some(last) = last_step_distance.get(&entity) { if let Some(last) = last_step_distance.get(&entity) {
let distance = last.0 + (last.1.distance(coordinates)); let distance = last.0 + (last.1.distance(coordinates));
if distance >= footstep.step_length { if distance >= footstep.step_length {
last_step_distance.insert(entity, (0., *coordinates)); last_step_distance.insert(entity, (0., *coordinates));
sound.gain = footstep.gain; sound.gain = footstep.gain;
sound.reference_distance = footstep.reference_distance; if let Some(v) = footstep.reference_distance {
sound.max_distance = footstep.max_distance; let insert = if let Some(v2) = reference_distance {
sound.rolloff_factor = footstep.rolloff_factor; v != **v2
sound.pitch = footstep.pitch; } else {
true
};
if insert {
commands.run_if_exists(entity, move |mut entity| {
entity.insert(DistanceRef(v));
})
}
} else if reference_distance.is_some() {
commands.run_if_exists(entity, |mut entity| {
entity.remove::<DistanceRef>();
});
}
if let Some(v) = footstep.max_distance {
let insert = if let Some(v2) = max_distance {
v != **v2
} else {
true
};
if insert {
commands.run_if_exists(entity, move |mut entity| {
entity.insert(DistanceMax(v));
})
}
} else if max_distance.is_some() {
commands.run_if_exists(entity, |mut entity| {
entity.remove::<DistanceMax>();
});
}
if let Some(v) = footstep.rolloff {
let insert = if let Some(v2) = rolloff {
v != **v2
} else {
true
};
if insert {
commands.run_if_exists(entity, move |mut entity| {
entity.insert(Rolloff(v));
})
}
} else if rolloff.is_some() {
commands.run_if_exists(entity, |mut entity| {
entity.remove::<Rolloff>();
});
}
sound.pitch = footstep.pitch.unwrap_or(1.);
if let Some(pitch_variation) = footstep.pitch_variation { if let Some(pitch_variation) = footstep.pitch_variation {
let mut pitch = footstep.pitch - pitch_variation / 2.; let mut pitch = sound.pitch - pitch_variation / 2.;
pitch += random::<f32>() * pitch_variation; pitch += random::<f64>() * pitch_variation;
sound.pitch = pitch; sound.pitch = pitch;
} }
sound.play(); sound.paused = false;
sound.restart = true;
} else if last.1 != *coordinates { } else if last.1 != *coordinates {
last_step_distance.insert(entity, (distance, *coordinates)); last_step_distance.insert(entity, (distance, *coordinates));
} }

View File

@ -1,7 +1,7 @@
use std::{fmt::Debug, hash::Hash, time::Duration}; use std::{fmt::Debug, hash::Hash, time::Duration};
use bevy::{asset::HandleId, prelude::*, transform::TransformSystem}; use bevy::{asset::HandleId, prelude::*, transform::TransformSystem};
use bevy_openal::{Buffer, Sound, SoundState}; use bevy_synthizer::{DistanceMax, DistanceRef, Rolloff, Sound};
use rand::random; use rand::random;
@ -15,11 +15,11 @@ use crate::{
#[derive(Component, Clone, Debug)] #[derive(Component, Clone, Debug)]
pub struct SoundIcon { pub struct SoundIcon {
pub sound: HandleId, pub sound: HandleId,
pub gain: f32, pub gain: f64,
pub pitch: f32, pub pitch: f64,
pub reference_distance: f32, pub reference_distance: Option<f64>,
pub max_distance: f32, pub max_distance: Option<f64>,
pub rolloff_factor: f32, pub rolloff: Option<f64>,
pub interval: Option<Timer>, pub interval: Option<Timer>,
} }
@ -30,9 +30,9 @@ impl Default for SoundIcon {
sound: "".into(), sound: "".into(),
gain: 0.3, gain: 0.3,
pitch: 1., pitch: 1.,
reference_distance: 1., reference_distance: None,
max_distance: f32::MAX, max_distance: None,
rolloff_factor: 1., rolloff: None,
interval: Some(Timer::from_seconds(seconds, true)), interval: Some(Timer::from_seconds(seconds, true)),
}; };
if let Some(ref mut interval) = icon.interval { if let Some(ref mut interval) = icon.interval {
@ -50,36 +50,43 @@ pub struct SoundIconBundle {
pub global_transform: GlobalTransform, pub global_transform: GlobalTransform,
} }
fn add_sound_icon_sounds( fn added(
mut commands: Commands, mut commands: Commands,
asset_server: Res<AssetServer>,
icons: Query<(Entity, &SoundIcon), Added<SoundIcon>>, icons: Query<(Entity, &SoundIcon), Added<SoundIcon>>,
assets: Res<Assets<Buffer>>,
) { ) {
for (entity, icon) in icons.iter() { for (entity, icon) in icons.iter() {
let buffer = assets.get_handle(icon.sound); let buffer = asset_server.get_handle(icon.sound);
let gain = icon.gain; let gain = icon.gain;
let pitch = icon.pitch; let pitch = icon.pitch;
let looping = icon.interval.is_none(); let looping = icon.interval.is_none();
let reference_distance = icon.reference_distance; let reference_distance = icon.reference_distance;
let max_distance = icon.max_distance; let max_distance = icon.max_distance;
let rolloff_factor = icon.rolloff_factor; let rolloff = icon.rolloff;
commands.run_if_exists(entity, move |mut entity| { commands.run_if_exists(entity, move |mut entity| {
entity.insert(Sound { entity.insert(Sound {
buffer, buffer,
gain, gain,
pitch, pitch,
looping, looping,
state: SoundState::Stopped, paused: true,
reference_distance,
max_distance,
rolloff_factor,
..default() ..default()
}); });
if let Some(v) = reference_distance {
entity.insert(DistanceRef(v));
}
if let Some(v) = max_distance {
entity.insert(DistanceMax(v));
}
if let Some(v) = rolloff {
entity.insert(Rolloff(v));
}
}); });
} }
} }
fn update<S>( fn update<S>(
mut commands: Commands,
config: Res<SoundIconConfig<S>>, config: Res<SoundIconConfig<S>>,
state: Res<State<S>>, state: Res<State<S>>,
time: Res<Time>, time: Res<Time>,
@ -90,8 +97,11 @@ fn update<S>(
Option<&Visible>, Option<&Visible>,
Option<&Parent>, Option<&Parent>,
&mut Sound, &mut Sound,
Option<&DistanceRef>,
Option<&DistanceMax>,
Option<&Rolloff>,
)>, )>,
buffers: Res<Assets<Buffer>>, asset_server: Res<AssetServer>,
) where ) where
S: 'static + Clone + Debug + Eq + Hash + Send + Sync, S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
{ {
@ -99,7 +109,17 @@ fn update<S>(
return; return;
} }
for visible in viewers.iter() { for visible in viewers.iter() {
for (icon_entity, mut icon, visibility, parent, mut sound) in icons.iter_mut() { for (
icon_entity,
mut icon,
visibility,
parent,
mut sound,
distance_ref,
distance_max,
rolloff,
) in icons.iter_mut()
{
let entity = if visibility.is_some() { let entity = if visibility.is_some() {
icon_entity icon_entity
} else { } else {
@ -108,26 +128,72 @@ fn update<S>(
if visible.contains(&entity) { if visible.contains(&entity) {
let looping = sound.looping; let looping = sound.looping;
if looping { if looping {
sound.state = SoundState::Playing; sound.paused = false;
} else if let Some(interval) = icon.interval.as_mut() { } else if let Some(interval) = icon.interval.as_mut() {
interval.tick(time.delta()); interval.tick(time.delta());
if interval.finished() { if interval.finished() {
sound.state = SoundState::Playing; sound.paused = false;
sound.restart = true;
interval.reset(); interval.reset();
} }
} }
let buffer = buffers.get_handle(icon.sound); let buffer = asset_server.get_handle(icon.sound);
sound.looping = icon.interval.is_none(); sound.looping = icon.interval.is_none();
if sound.buffer != buffer { if sound.buffer != buffer {
sound.buffer = buffer; sound.buffer = buffer;
} }
sound.gain = icon.gain; sound.gain = icon.gain;
sound.pitch = icon.pitch; sound.pitch = icon.pitch;
sound.reference_distance = icon.reference_distance; if let Some(v) = icon.reference_distance {
sound.max_distance = icon.max_distance; let insert = if let Some(v2) = distance_ref {
sound.rolloff_factor = icon.rolloff_factor; v != **v2
} else { } else {
sound.state = SoundState::Stopped; true
};
if insert {
commands.run_if_exists(icon_entity, move |mut entity| {
entity.insert(DistanceRef(v));
})
}
} else if distance_ref.is_some() {
commands.run_if_exists(icon_entity, |mut entity| {
entity.remove::<DistanceRef>();
});
}
if let Some(v) = icon.max_distance {
let insert = if let Some(v2) = distance_max {
v != **v2
} else {
true
};
if insert {
commands.run_if_exists(icon_entity, move |mut entity| {
entity.insert(DistanceMax(v));
})
}
} else if distance_max.is_some() {
commands.run_if_exists(icon_entity, |mut entity| {
entity.remove::<DistanceMax>();
});
}
if let Some(v) = icon.rolloff {
let insert = if let Some(v2) = rolloff {
v != **v2
} else {
true
};
if insert {
commands.run_if_exists(icon_entity, move |mut entity| {
entity.insert(Rolloff(v));
})
}
} else if rolloff.is_some() {
commands.run_if_exists(icon_entity, |mut entity| {
entity.remove::<Rolloff>();
});
}
} else {
sound.paused = true;
} }
} }
} }
@ -137,7 +203,7 @@ fn exploration_focus_changed(
mut focused: Query<(Entity, Option<&Children>), Changed<ExplorationFocused>>, mut focused: Query<(Entity, Option<&Children>), Changed<ExplorationFocused>>,
mut icons: Query<&mut SoundIcon>, mut icons: Query<&mut SoundIcon>,
) { ) {
const ICON_GAIN: f32 = 3.; const ICON_GAIN: f64 = 3.;
for (entity, children) in focused.iter_mut() { for (entity, children) in focused.iter_mut() {
if let Ok(mut icon) = icons.get_mut(entity) { if let Ok(mut icon) = icons.get_mut(entity) {
icon.gain *= ICON_GAIN; icon.gain *= ICON_GAIN;
@ -157,7 +223,7 @@ fn exploration_focus_removed(
mut query: Query<&mut SoundIcon>, mut query: Query<&mut SoundIcon>,
children: Query<&Children>, children: Query<&Children>,
) { ) {
const ICON_GAIN: f32 = 3.; const ICON_GAIN: f64 = 3.;
for entity in removed.iter() { for entity in removed.iter() {
if let Ok(mut icon) = query.get_mut(entity) { if let Ok(mut icon) = query.get_mut(entity) {
icon.gain /= ICON_GAIN; icon.gain /= ICON_GAIN;
@ -191,7 +257,7 @@ where
'a: 'static, 'a: 'static,
{ {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_system(add_sound_icon_sounds) app.add_system(added)
.add_system_to_stage( .add_system_to_stage(
CoreStage::PostUpdate, CoreStage::PostUpdate,
update::<S>.after(TransformSystem::TransformPropagate), update::<S>.after(TransformSystem::TransformPropagate),

View File

@ -1,7 +1,6 @@
use std::{fmt::Debug, hash::Hash}; use std::{fmt::Debug, hash::Hash};
use bevy::prelude::*; use bevy::prelude::*;
use bevy_openal::{Context, Sound};
use crate::core::CoreConfig; use crate::core::CoreConfig;
@ -11,7 +10,7 @@ pub mod icon;
pub use footstep::{Footstep, FootstepBundle}; pub use footstep::{Footstep, FootstepBundle};
pub use icon::{SoundIcon, SoundIconBundle}; pub use icon::{SoundIcon, SoundIconBundle};
fn scale_sounds(config: Res<CoreConfig>, mut sounds: Query<&mut Sound>) { /*fn scale_sounds(config: Res<CoreConfig>, mut sounds: Query<&mut Sound>) {
let pixels_per_unit = config.pixels_per_unit as f32; let pixels_per_unit = config.pixels_per_unit as f32;
for mut sound in sounds.iter_mut() { for mut sound in sounds.iter_mut() {
sound.reference_distance *= pixels_per_unit; sound.reference_distance *= pixels_per_unit;
@ -19,7 +18,7 @@ fn scale_sounds(config: Res<CoreConfig>, mut sounds: Query<&mut Sound>) {
sound.max_distance *= pixels_per_unit; sound.max_distance *= pixels_per_unit;
} }
} }
} }*/
pub struct SoundPlugin<'a, S>(std::marker::PhantomData<&'a S>); pub struct SoundPlugin<'a, S>(std::marker::PhantomData<&'a S>);
@ -36,13 +35,13 @@ where
{ {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
let core_config = *app.world.get_resource::<CoreConfig>().unwrap(); let core_config = *app.world.get_resource::<CoreConfig>().unwrap();
if let Some(context) = app.world.get_resource::<Context>() { /*if let Some(context) = app.world.get_resource::<Context>() {
context context
.set_meters_per_unit(1. / core_config.pixels_per_unit as f32) .set_meters_per_unit(1. / core_config.pixels_per_unit as f32)
.unwrap(); .unwrap();
} }*/
app.add_plugin(footstep::FootstepPlugin) app.add_plugin(footstep::FootstepPlugin)
.add_plugin(icon::SoundIconPlugin::<S>::default()) .add_plugin(icon::SoundIconPlugin::<S>::default());
.add_system(scale_sounds); // .add_system(scale_sounds);
} }
} }