blackout/src/sound/icon.rs

181 lines
5.1 KiB
Rust
Raw Normal View History

use bevy::prelude::*;
use bevy_synthizer::{Audio, Sound};
2021-05-13 17:25:45 +00:00
use rand::random;
use crate::{
core::Player,
2021-05-13 17:25:45 +00:00
exploration::ExplorationFocused,
visibility::{Visible, VisibleEntities},
2021-05-13 17:25:45 +00:00
};
#[derive(Component, Clone, Debug)]
2021-05-13 17:25:45 +00:00
pub struct SoundIcon {
pub audio: Audio,
2022-05-23 18:35:25 +00:00
pub gain: f64,
pub pitch: f64,
2021-05-13 17:25:45 +00:00
pub interval: Option<Timer>,
}
impl Default for SoundIcon {
fn default() -> Self {
let seconds = random::<f32>() + 4.5;
Self {
audio: default(),
2022-05-31 15:59:25 +00:00
gain: 1.,
2021-05-13 17:25:45 +00:00
pitch: 1.,
interval: Some(Timer::from_seconds(seconds, TimerMode::Once)),
2021-05-13 17:25:45 +00:00
}
}
}
2022-08-03 14:43:07 +00:00
fn added(mut commands: Commands, icons: Query<(Entity, &SoundIcon), Added<SoundIcon>>) {
2023-03-28 17:13:23 +00:00
for (entity, icon) in &icons {
let buffer = icon.audio.clone();
let gain = icon.gain;
let pitch = icon.pitch;
2021-05-24 20:34:38 +00:00
let looping = icon.interval.is_none();
2023-04-01 12:20:59 +00:00
commands.entity(entity).insert(Sound {
2023-09-08 21:12:35 +00:00
audio: buffer,
2023-04-01 12:20:59 +00:00
gain,
pitch,
looping,
paused: true,
..default()
2021-05-24 20:34:38 +00:00
});
}
}
fn update<S>(
config: Res<SoundIconPlugin<S>>,
2021-05-13 17:25:45 +00:00
state: Res<State<S>>,
time: Res<Time>,
viewers: Query<&VisibleEntities, With<Player>>,
2021-05-13 17:25:45 +00:00
mut icons: Query<(
Entity,
2021-05-13 17:25:45 +00:00
&mut SoundIcon,
Option<&Visible>,
2021-05-13 17:25:45 +00:00
Option<&Parent>,
2021-05-24 20:34:38 +00:00
&mut Sound,
2021-05-13 17:25:45 +00:00
)>,
) where
2023-03-28 16:57:37 +00:00
S: States,
2021-05-13 17:25:45 +00:00
{
2023-09-08 21:12:35 +00:00
if !config.states.is_empty() && !config.states.contains(state.get()) {
2021-06-09 19:53:48 +00:00
return;
2021-05-13 17:25:45 +00:00
}
2023-03-28 17:13:23 +00:00
for visible in &viewers {
for (icon_entity, mut icon, visibility, parent, mut sound) in &mut icons {
let entity = if visibility.is_some() {
2022-05-31 15:17:16 +00:00
Some(icon_entity)
} else if parent.is_some() {
Some(**parent.unwrap())
2021-05-13 17:25:45 +00:00
} else {
2022-05-31 15:17:16 +00:00
None
2021-05-13 17:25:45 +00:00
};
2022-05-31 15:17:16 +00:00
if let Some(entity) = entity {
if visible.contains(&entity) {
if let Some(interval) = icon.interval.as_mut() {
2022-05-31 15:17:16 +00:00
if interval.finished() {
interval.reset();
continue;
} else if interval.percent() == 0. {
sound.generator = None;
2022-05-31 15:17:16 +00:00
}
interval.tick(time.delta());
}
if sound.audio != icon.audio {
sound.audio = icon.audio.clone();
}
if sound.gain != icon.gain {
sound.gain = icon.gain;
}
if sound.pitch != icon.pitch {
sound.pitch = icon.pitch;
2021-05-13 17:25:45 +00:00
}
let looping = icon.interval.is_none();
if sound.looping != looping {
sound.looping = looping;
}
if sound.paused {
sound.paused = false;
sound.generator = None;
2022-05-23 18:35:25 +00:00
}
} else if !sound.paused {
sound.paused = true;
if let Some(interval) = icon.interval.as_mut() {
interval.reset();
}
2022-05-23 18:35:25 +00:00
}
} else {
panic!("Should not happen");
2021-05-13 17:25:45 +00:00
}
}
}
}
fn exploration_focus_changed(
mut focused: Query<(Entity, Option<&Children>), Changed<ExplorationFocused>>,
mut icons: Query<&mut SoundIcon>,
2021-05-13 17:25:45 +00:00
) {
2022-05-23 18:35:25 +00:00
const ICON_GAIN: f64 = 3.;
2023-03-28 17:13:23 +00:00
for (entity, children) in &mut focused {
if let Ok(mut icon) = icons.get_mut(entity) {
icon.gain *= ICON_GAIN;
}
if let Some(children) = children {
for child in children.iter() {
if let Ok(mut icon) = icons.get_mut(*child) {
icon.gain *= ICON_GAIN;
}
}
2021-05-13 17:25:45 +00:00
}
}
}
fn exploration_focus_removed(
2023-03-28 16:57:37 +00:00
mut removed: RemovedComponents<ExplorationFocused>,
mut query: Query<&mut SoundIcon>,
children: Query<&Children>,
2021-05-13 17:25:45 +00:00
) {
2022-05-23 18:35:25 +00:00
const ICON_GAIN: f64 = 3.;
2023-03-28 16:57:37 +00:00
for entity in &mut removed {
if let Ok(mut icon) = query.get_mut(entity) {
icon.gain /= ICON_GAIN;
}
if let Ok(children) = children.get(entity) {
for child in children.iter() {
if let Ok(mut icon) = query.get_mut(*child) {
2022-05-18 15:27:42 +00:00
icon.gain /= ICON_GAIN;
}
}
2021-05-13 17:25:45 +00:00
}
}
}
#[derive(Resource, Clone)]
pub struct SoundIconPlugin<S> {
pub states: Vec<S>,
2021-05-13 17:25:45 +00:00
}
impl<S> Default for SoundIconPlugin<S> {
2021-05-13 17:25:45 +00:00
fn default() -> Self {
Self { states: default() }
2021-05-13 17:25:45 +00:00
}
}
impl<S> Plugin for SoundIconPlugin<S>
2021-05-13 17:25:45 +00:00
where
2023-03-28 16:57:37 +00:00
S: States,
2021-05-13 17:25:45 +00:00
{
2022-01-10 19:50:52 +00:00
fn build(&self, app: &mut App) {
app.insert_resource(self.clone())
.add_systems(PreUpdate, added)
2023-09-08 21:12:35 +00:00
.add_systems(PreUpdate, (exploration_focus_changed, update::<S>).chain())
2023-04-01 03:40:12 +00:00
.add_systems(
2023-09-08 21:12:35 +00:00
PostUpdate,
exploration_focus_removed.after(exploration_focus_changed),
2023-04-01 15:37:49 +00:00
);
2021-05-13 17:25:45 +00:00
}
}