Skip to content

Commit

Permalink
Remove the ability to ignore global volume (#11092)
Browse files Browse the repository at this point in the history
# Objective

The ability to ignore the global volume doesn't seem desirable and
complicates the API.

#7706 added global volume and the ability to ignore it, but there was no
further discussion about whether that's useful. Feel free to discuss
here :)

## Solution

Replace the `Volume` type's functionality with the `VolumeLevel`. Remove
`VolumeLevel`.

I also removed `DerefMut` derive that effectively made the volume `pub`
and actually ensured that the volume isn't set below `0` even in release
builds.

## Migration Guide

The option to ignore the global volume using `Volume::Absolute` has been
removed and `Volume` now stores the volume level directly, removing the
need for the `VolumeLevel` struct.
  • Loading branch information
tim-blackbird authored Jan 15, 2024
1 parent 8c6d9b8 commit c29a972
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 61 deletions.
63 changes: 14 additions & 49 deletions crates/bevy_audio/src/audio.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,33 @@
use crate::{AudioSource, Decodable};
use bevy_asset::{Asset, Handle};
use bevy_derive::{Deref, DerefMut};
use bevy_derive::Deref;
use bevy_ecs::prelude::*;
use bevy_math::Vec3;
use bevy_reflect::prelude::*;

/// Defines the volume to play an audio source at.
#[derive(Clone, Copy, Debug, Reflect)]
pub enum Volume {
/// A volume level relative to the global volume.
Relative(VolumeLevel),
/// A volume level that ignores the global volume.
Absolute(VolumeLevel),
}

impl Default for Volume {
fn default() -> Self {
Self::Relative(VolumeLevel::default())
}
}

impl Volume {
/// Create a new volume level relative to the global volume.
pub fn new_relative(volume: f32) -> Self {
Self::Relative(VolumeLevel::new(volume))
}
/// Create a new volume level that ignores the global volume.
pub fn new_absolute(volume: f32) -> Self {
Self::Absolute(VolumeLevel::new(volume))
}
}

/// A volume level equivalent to a non-negative float.
#[derive(Clone, Copy, Deref, DerefMut, Debug, Reflect)]
pub struct VolumeLevel(pub(crate) f32);
#[derive(Clone, Copy, Deref, Debug, Reflect)]
pub struct Volume(pub(crate) f32);

impl Default for VolumeLevel {
impl Default for Volume {
fn default() -> Self {
Self(1.0)
}
}

impl VolumeLevel {
impl Volume {
/// Create a new volume level.
pub fn new(volume: f32) -> Self {
debug_assert!(volume >= 0.0);
Self(volume)
Self(f32::max(volume, 0.))
}
/// Get the value of the volume level.
pub fn get(&self) -> f32 {
self.0
}

/// Zero (silent) volume level
pub const ZERO: Self = VolumeLevel(0.0);
pub const ZERO: Self = Volume(0.0);
}

/// The way Bevy manages the sound playback.
Expand Down Expand Up @@ -106,7 +80,7 @@ impl PlaybackSettings {
/// Will play the associated audio source once.
pub const ONCE: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Once,
volume: Volume::Relative(VolumeLevel(1.0)),
volume: Volume(1.0),
speed: 1.0,
paused: false,
spatial: false,
Expand All @@ -115,28 +89,19 @@ impl PlaybackSettings {
/// Will play the associated audio source in a loop.
pub const LOOP: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Loop,
volume: Volume::Relative(VolumeLevel(1.0)),
speed: 1.0,
paused: false,
spatial: false,
..PlaybackSettings::ONCE
};

/// Will play the associated audio source once and despawn the entity afterwards.
pub const DESPAWN: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Despawn,
volume: Volume::Relative(VolumeLevel(1.0)),
speed: 1.0,
paused: false,
spatial: false,
..PlaybackSettings::ONCE
};

/// Will play the associated audio source once and remove the audio components afterwards.
pub const REMOVE: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Remove,
volume: Volume::Relative(VolumeLevel(1.0)),
speed: 1.0,
paused: false,
spatial: false,
..PlaybackSettings::ONCE
};

/// Helper to start in a paused state.
Expand Down Expand Up @@ -196,21 +161,21 @@ impl SpatialListener {
}
}

/// Use this [`Resource`] to control the global volume of all audio with a [`Volume::Relative`] volume.
/// Use this [`Resource`] to control the global volume of all audio.
///
/// Note: changing this value will not affect already playing audio.
#[derive(Resource, Default, Clone, Copy, Reflect)]
#[reflect(Resource)]
pub struct GlobalVolume {
/// The global volume of all audio.
pub volume: VolumeLevel,
pub volume: Volume,
}

impl GlobalVolume {
/// Create a new [`GlobalVolume`] with the given volume.
pub fn new(volume: f32) -> Self {
Self {
volume: VolumeLevel::new(volume),
volume: Volume::new(volume),
}
}
}
Expand Down
12 changes: 3 additions & 9 deletions crates/bevy_audio/src/audio_output.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
AudioSourceBundle, Decodable, GlobalVolume, PlaybackMode, PlaybackSettings, SpatialAudioSink,
SpatialListener, SpatialScale, Volume,
SpatialListener, SpatialScale,
};
use bevy_asset::{Asset, Assets, Handle};
use bevy_ecs::{prelude::*, system::SystemParam};
Expand Down Expand Up @@ -159,10 +159,7 @@ pub(crate) fn play_queued_audio_system<Source: Asset + Decodable>(
};

sink.set_speed(settings.speed);
match settings.volume {
Volume::Relative(vol) => sink.set_volume(vol.0 * global_volume.volume.0),
Volume::Absolute(vol) => sink.set_volume(vol.0),
}
sink.set_volume(settings.volume.0 * global_volume.volume.0);

if settings.paused {
sink.pause();
Expand Down Expand Up @@ -202,10 +199,7 @@ pub(crate) fn play_queued_audio_system<Source: Asset + Decodable>(
};

sink.set_speed(settings.speed);
match settings.volume {
Volume::Relative(vol) => sink.set_volume(vol.0 * global_volume.volume.0),
Volume::Absolute(vol) => sink.set_volume(vol.0),
}
sink.set_volume(settings.volume.0 * global_volume.volume.0);

if settings.paused {
sink.pause();
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_audio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct AudioPlaySet;
/// Insert an [`AudioBundle`] onto your entities to play audio.
#[derive(Default)]
pub struct AudioPlugin {
/// The global volume for all audio entities with a [`Volume::Relative`] volume.
/// The global volume for all audio entities.
pub global_volume: GlobalVolume,
/// The scale factor applied to the positions of audio sources and listeners for
/// spatial audio.
Expand All @@ -72,12 +72,11 @@ pub struct AudioPlugin {

impl Plugin for AudioPlugin {
fn build(&self, app: &mut App) {
app.register_type::<VolumeLevel>()
app.register_type::<Volume>()
.register_type::<GlobalVolume>()
.register_type::<SpatialListener>()
.register_type::<SpatialScale>()
.register_type::<PlaybackMode>()
.register_type::<Volume>()
.register_type::<PlaybackSettings>()
.insert_resource(self.global_volume)
.insert_resource(self.spatial_scale)
Expand Down

0 comments on commit c29a972

Please sign in to comment.