diff --git a/src/sound/mod.rs b/src/sound/mod.rs index 110029d..fab4918 100644 --- a/src/sound/mod.rs +++ b/src/sound/mod.rs @@ -6,9 +6,11 @@ use crate::core::CoreConfig; pub mod footstep; pub mod icon; +pub mod volumetric; pub use footstep::Footstep; pub use icon::SoundIcon; +pub use volumetric::Volumetric; /*fn scale_sounds(config: Res, mut sounds: Query<&mut Sound>) { let pixels_per_unit = config.pixels_per_unit as f32; @@ -40,7 +42,8 @@ where .unwrap(); }*/ app.add_plugin(footstep::FootstepPlugin) - .add_plugin(icon::SoundIconPlugin::::default()); + .add_plugin(icon::SoundIconPlugin::::default()) + .add_plugin(volumetric::VolumetricPlugin); // .add_system(scale_sounds); } } diff --git a/src/sound/volumetric.rs b/src/sound/volumetric.rs new file mode 100644 index 0000000..bcc73fc --- /dev/null +++ b/src/sound/volumetric.rs @@ -0,0 +1,85 @@ +use bevy::{prelude::*, transform::TransformSystem}; +use bevy_rapier2d::{parry::query::ClosestPoints, prelude::*}; +use bevy_synthizer::{Listener, Sound}; + +use crate::{commands::RunIfExistsExt, core::GlobalTransformExt}; + +#[derive(Component, Clone, Copy, Debug)] +pub struct Volumetric; + +fn update( + mut commands: Commands, + listener: Query<(&Collider, &GlobalTransform), With>, + mut sounds: Query< + ( + Entity, + Option<&Collider>, + Option<&Parent>, + &mut Transform, + &GlobalTransform, + ), + With, + >, + colliders: Query<&Collider>, +) { + if let Ok((listener_collider, listener_global_transform)) = listener.get_single() { + for (sound_entity, sound_collider, parent, mut sound_transform, sound_global_transform) in + &mut sounds + { + let sound_collider = if sound_collider.is_some() { + sound_collider + } else if let Some(parent) = parent { + colliders.get(**parent).ok() + } else { + None + }; + if let Some(sound_collider) = sound_collider { + let closest = listener_global_transform.closest_points( + listener_collider, + sound_global_transform, + sound_collider, + ); + if let ClosestPoints::WithinMargin(_p1, p2) = closest { + let p2 = Vec3::new(p2.x, p2.y, 0.); + if p2.distance(sound_global_transform.translation()) >= 1. { + sound_transform.translation.x = + p2.x - sound_global_transform.translation().x; + sound_transform.translation.y = + p2.y - sound_global_transform.translation().y; + } + } else if closest == ClosestPoints::Intersecting { + if sound_global_transform + .translation() + .distance(listener_global_transform.translation()) + >= 1. + { + sound_transform.translation.x = listener_global_transform.translation().x + - sound_global_transform.translation().x; + sound_transform.translation.y = listener_global_transform.translation().y + - sound_global_transform.translation().y; + } + } + } + } + } +} + +fn removed(mut commands: Commands, removed: RemovedComponents) { + for entity in removed.iter() { + commands.run_if_exists(entity, |mut entity| { + entity.insert_bundle(TransformBundle::default()); + }); + } +} + +pub struct VolumetricPlugin; + +impl Plugin for VolumetricPlugin { + fn build(&self, app: &mut App) { + app.add_system_to_stage( + CoreStage::PostUpdate, + update.before(TransformSystem::TransformPropagate), + ) + .add_system_to_stage(CoreStage::PostUpdate, removed); + } +}