Skip to content

Commit

Permalink
Changing the default PlaybackMode to PlaybackMode::Remove
Browse files Browse the repository at this point in the history
Adding `PlaybackMode` to `AudioPlayer`
Adding convience methods to `AudioPlayer` to create with different `PlaybackMode`s
  • Loading branch information
seivan committed Dec 2, 2024
1 parent 56d5591 commit 42ffd89
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 58 deletions.
70 changes: 33 additions & 37 deletions crates/bevy_audio/src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Volume {
}

/// The way Bevy manages the sound playback.
#[derive(Debug, Clone, Copy, Reflect)]
#[derive(Debug, Clone, Copy, Reflect, Default)]
pub enum PlaybackMode {
/// Play the sound once. Do nothing when it ends.
Once,
Expand All @@ -42,6 +42,7 @@ pub enum PlaybackMode {
/// Despawn the entity and its children when the sound finishes playing.
Despawn,
/// Remove the audio components from the entity, when the sound finishes playing.
#[default]
Remove,
}

Expand All @@ -53,8 +54,6 @@ pub enum PlaybackMode {
#[derive(Component, Clone, Copy, Debug, Reflect)]
#[reflect(Default, Component, Debug)]
pub struct PlaybackSettings {
/// The desired playback behavior.
pub mode: PlaybackMode,
/// Volume to play at.
pub volume: Volume,
/// Speed to play at.
Expand All @@ -77,40 +76,17 @@ pub struct PlaybackSettings {

impl Default for PlaybackSettings {
fn default() -> Self {
// TODO: what should the default be: ONCE/DESPAWN/REMOVE?
Self::ONCE
Self {
volume: Volume(1.0),
speed: 1.0,
paused: false,
spatial: false,
spatial_scale: None,
}
}
}

impl PlaybackSettings {
/// Will play the associated audio source once.
pub const ONCE: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Once,
volume: Volume(1.0),
speed: 1.0,
paused: false,
spatial: false,
spatial_scale: None,
};

/// Will play the associated audio source in a loop.
pub const LOOP: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Loop,
..PlaybackSettings::ONCE
};

/// Will play the associated audio source once and despawn the entity afterwards.
pub const DESPAWN: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Despawn,
..PlaybackSettings::ONCE
};

/// Will play the associated audio source once and remove the audio components afterwards.
pub const REMOVE: PlaybackSettings = PlaybackSettings {
mode: PlaybackMode::Remove,
..PlaybackSettings::ONCE
};

/// Helper to start in a paused state.
pub const fn paused(mut self) -> Self {
self.paused = true;
Expand Down Expand Up @@ -251,7 +227,7 @@ pub type AudioBundle = AudioSourceBundle<AudioSource>;
#[derive(Component, Reflect)]
#[reflect(Component)]
#[require(PlaybackSettings)]
pub struct AudioPlayer<Source = AudioSource>(pub Handle<Source>)
pub struct AudioPlayer<Source = AudioSource>(pub Handle<Source>, pub PlaybackMode)
where
Source: Asset + Decodable;

Expand All @@ -260,7 +236,7 @@ where
Source: Asset + Decodable,
{
fn clone(&self) -> Self {
Self(self.0.clone())
Self(self.0.clone(), self.1)
}
}

Expand All @@ -271,7 +247,27 @@ impl AudioPlayer<AudioSource> {
/// initialize an [`AudioPlayer`] with a different type, just initialize it directly using normal
/// tuple struct syntax.
pub fn new(source: Handle<AudioSource>) -> Self {
Self(source)
Self(source, PlaybackMode::default())
}

/// Creates a new [`AudioPlayer`] that plays the sound once.
pub fn with_once(source: Handle<AudioSource>) -> Self {
Self(source, PlaybackMode::Once)
}

/// Creates a new [`AudioPlayer`] that loops the sound forever.
pub fn with_loop(source: Handle<AudioSource>) -> Self {
Self(source, PlaybackMode::Loop)
}

/// Creates a new [`AudioPlayer`] that despawns the entity when the sound finishes playing.
pub fn with_despawn(source: Handle<AudioSource>) -> Self {
Self(source, PlaybackMode::Despawn)
}

/// Creates a new [`AudioPlayer`] that removes the audio component from the entity when the sound finishes playing.
pub fn with_remove(source: Handle<AudioSource>) -> Self {
Self(source, PlaybackMode::Remove)
}
}

Expand Down Expand Up @@ -314,7 +310,7 @@ impl<T: Asset + Decodable> Clone for AudioSourceBundle<T> {
impl<T: Decodable + Asset> Default for AudioSourceBundle<T> {
fn default() -> Self {
Self {
source: AudioPlayer(Handle::default()),
source: AudioPlayer(Handle::default(), PlaybackMode::Once),
settings: Default::default(),
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_audio/src/audio_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ pub(crate) fn play_queued_audio_system<Source: Asset + Decodable>(
sink.pause();
}

match settings.mode {
match source_handle.1 {
PlaybackMode::Loop => {
sink.append(audio_source.decoder().repeat_infinite());
commands.entity(entity).insert(SpatialAudioSink { sink });
Expand Down Expand Up @@ -204,7 +204,7 @@ pub(crate) fn play_queued_audio_system<Source: Asset + Decodable>(
sink.pause();
}

match settings.mode {
match source_handle.1 {
PlaybackMode::Loop => {
sink.append(audio_source.decoder().repeat_infinite());
commands.entity(entity).insert(AudioSink { sink });
Expand Down
2 changes: 1 addition & 1 deletion examples/audio/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
}

fn setup(asset_server: Res<AssetServer>, mut commands: Commands) {
commands.spawn(AudioPlayer::new(
commands.spawn(AudioPlayer::with_once(
asset_server.load("sounds/Windless Slopes.ogg"),
));
}
4 changes: 2 additions & 2 deletions examples/audio/decodable.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Shows how to create a custom [`Decodable`] type by implementing a Sine wave.
use bevy::{
audio::{AddAudioSource, AudioPlugin, Source},
audio::{AddAudioSource, AudioPlugin, PlaybackMode, Source},
math::ops,
prelude::*,
reflect::TypePath,
Expand Down Expand Up @@ -99,5 +99,5 @@ fn setup(mut assets: ResMut<Assets<SineAudio>>, mut commands: Commands) {
let audio_handle = assets.add(SineAudio {
frequency: 440., // this is the frequency of A4
});
commands.spawn(AudioPlayer(audio_handle));
commands.spawn(AudioPlayer(audio_handle, PlaybackMode::Once));
}
8 changes: 4 additions & 4 deletions examples/audio/pitch.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! This example illustrates how to play a single-frequency sound (aka a pitch)
use bevy::prelude::*;
use bevy::{audio::PlaybackMode, prelude::*};
use std::time::Duration;

fn main() {
Expand Down Expand Up @@ -30,9 +30,9 @@ fn play_pitch(
) {
for _ in events.read() {
info!("playing pitch with frequency: {}", frequency.0);
commands.spawn((
AudioPlayer(pitch_assets.add(Pitch::new(frequency.0, Duration::new(1, 0)))),
PlaybackSettings::DESPAWN,
commands.spawn(AudioPlayer(
pitch_assets.add(Pitch::new(frequency.0, Duration::new(1, 0))),
PlaybackMode::Despawn,
));
info!("number of pitch assets: {}", pitch_assets.len());
}
Expand Down
6 changes: 2 additions & 4 deletions examples/audio/soundtrack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ fn change_track(
match game_state.as_ref() {
GameState::Peaceful => {
commands.spawn((
AudioPlayer(soundtrack_player.track_list.first().unwrap().clone()),
AudioPlayer::with_loop(soundtrack_player.track_list.first().unwrap().clone()),
PlaybackSettings {
mode: bevy::audio::PlaybackMode::Loop,
volume: bevy::audio::Volume::ZERO,
..default()
},
Expand All @@ -90,9 +89,8 @@ fn change_track(
}
GameState::Battle => {
commands.spawn((
AudioPlayer(soundtrack_player.track_list.get(1).unwrap().clone()),
AudioPlayer::with_loop(soundtrack_player.track_list.get(1).unwrap().clone()),
PlaybackSettings {
mode: bevy::audio::PlaybackMode::Loop,
volume: bevy::audio::Volume::ZERO,
..default()
},
Expand Down
4 changes: 2 additions & 2 deletions examples/audio/spatial_audio_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ fn setup(
MeshMaterial2d(materials.add(Color::from(BLUE))),
Transform::from_translation(Vec3::new(0.0, 50.0, 0.0)),
Emitter::default(),
AudioPlayer::new(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::LOOP.with_spatial(true),
AudioPlayer::with_loop(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::default().with_spatial(true),
));

let listener = SpatialListener::new(gap);
Expand Down
4 changes: 2 additions & 2 deletions examples/audio/spatial_audio_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ fn setup(
MeshMaterial3d(materials.add(Color::from(BLUE))),
Transform::from_xyz(0.0, 0.0, 0.0),
Emitter::default(),
AudioPlayer::new(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::LOOP.with_spatial(true),
AudioPlayer::with_loop(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::default().with_spatial(true),
));

let listener = SpatialListener::new(gap);
Expand Down
2 changes: 1 addition & 1 deletion examples/games/breakout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ fn play_collision_sound(
if !collision_events.is_empty() {
// This prevents events staying active on the next frame.
collision_events.clear();
commands.spawn((AudioPlayer(sound.clone()), PlaybackSettings::DESPAWN));
commands.spawn(AudioPlayer::with_despawn(sound.clone()));
}
}

Expand Down
5 changes: 2 additions & 3 deletions examples/mobile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,8 @@ fn button_handler(
}

fn setup_music(asset_server: Res<AssetServer>, mut commands: Commands) {
commands.spawn((
AudioPlayer::new(asset_server.load("sounds/Windless Slopes.ogg")),
PlaybackSettings::LOOP,
commands.spawn(AudioPlayer::with_loop(
asset_server.load("sounds/Windless Slopes.ogg"),
));
}

Expand Down

0 comments on commit 42ffd89

Please sign in to comment.