blackout/src/sound/volumetric.rs

80 lines
2.9 KiB
Rust
Raw Normal View History

2024-10-06 16:10:46 +00:00
use avian2d::{parry::query::ClosestPoints, prelude::*};
use bevy::{prelude::*, transform::TransformSystem};
use bevy_synthizer::{Listener, Sound};
2023-04-01 12:20:59 +00:00
use crate::core::GlobalTransformExt;
2022-12-19 20:08:31 +00:00
#[derive(Component, Default, Reflect, Clone, Copy, Debug)]
#[reflect(Component)]
pub struct Volumetric;
fn update(
mut commands: Commands,
listener: Query<(&Collider, &GlobalTransform), With<Listener>>,
mut sounds: Query<(Entity, &Sound, &Parent, Option<&mut Transform>), With<Volumetric>>,
colliders: Query<(&Collider, &GlobalTransform)>,
) {
if let Ok((listener_collider, listener_global_transform)) = listener.get_single() {
for (sound_entity, sound, parent, sound_transform) in &mut sounds {
if sound.paused {
continue;
}
let Ok((sound_collider, sound_global_transform)) = colliders.get(**parent) else {
continue;
};
let closest = listener_global_transform.closest_points(
listener_collider,
sound_global_transform,
sound_collider,
);
if let ClosestPoints::WithinMargin(_p1, p2) = closest {
if let Some(mut sound_transform) = sound_transform {
sound_transform.translation.x = p2.x - sound_global_transform.translation().x;
sound_transform.translation.y = p2.y - sound_global_transform.translation().y;
} else {
let sound_translation = Vec3::new(
p2.x - sound_global_transform.translation().x,
p2.y - sound_global_transform.translation().y,
0.,
);
commands
.entity(sound_entity)
.insert(TransformBundle::from_transform(
Transform::from_translation(sound_translation),
));
}
} else if closest == ClosestPoints::Intersecting && sound_transform.is_some() {
commands
.entity(sound_entity)
.remove::<Transform>()
.remove::<GlobalTransform>();
}
}
}
}
fn removed(
mut commands: Commands,
mut removed: RemovedComponents<Volumetric>,
transforms: Query<Entity, (With<Transform>, With<GlobalTransform>)>,
) {
2024-02-09 20:59:16 +00:00
for entity in removed.read() {
if transforms.get(entity).is_ok() {
commands.entity(entity).insert(TransformBundle::default());
}
}
}
pub struct VolumetricPlugin;
impl Plugin for VolumetricPlugin {
fn build(&self, app: &mut App) {
2022-12-19 20:08:31 +00:00
app.register_type::<Volumetric>()
2023-09-08 21:12:35 +00:00
.add_systems(
PostUpdate,
update.before(TransformSystem::TransformPropagate),
2022-12-19 20:08:31 +00:00
)
2023-09-08 21:12:35 +00:00
.add_systems(PostUpdate, removed);
}
}