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); } }