blackout/src/sound/volumetric.rs

60 lines
2.3 KiB
Rust
Raw Normal View History

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(
listener: Query<(&Collider, &GlobalTransform), With<Listener>>,
mut sounds: Query<(&Sound, &Parent, &mut Transform), With<Volumetric>>,
colliders: Query<(&Collider, &GlobalTransform)>,
) {
if let Ok((listener_collider, listener_global_transform)) = listener.get_single() {
for (sound, parent, mut sound_transform) in &mut sounds {
if sound.paused {
continue;
}
if let Ok((sound_collider, sound_global_transform)) = colliders.get(**parent) {
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.);
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 {
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<Volumetric>) {
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);
}
}