use bevy::ecs::system::Resource; use bevy::prelude::*; use bevy_kira_audio::AudioSource; use crate::music_box::MusicBox; /// This trait provides a `MusicBox` with a way of resolving a track name /// into usable audio resources that is generic over however you implement your /// asset loading /// /// # Example /// /// The canonical example is also included in the crate; using the `AssetServer` /// as a `SuppliesAudio` extension: /// /// ```rust /// # use micro_musicbox::utilities::{TrackType, SuppliesAudio}; /// # use bevy::prelude::*; /// /// impl SuppliesAudio for AssetServer { /// fn resolve_track_name<T: ToString>(&self, name: T) -> TrackType<String> { /// TrackType::Single(name.to_string()) /// } /// /// fn get_audio_track<T: ToString>(&self, name: T) -> Option<Handle<AudioSource>> { /// Some(self.load(&name.to_string())) /// } /// } /// ``` pub trait SuppliesAudio: Resource { fn resolve_track_name<T: ToString>(&self, name: T) -> TrackType<String>; fn get_audio_track<T: ToString>(&self, name: T) -> Option<Handle<AudioSource>>; } #[derive(Copy, Clone, Debug, Resource)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AudioSettings { pub master_volume: f32, pub music_volume: f32, pub ambiance_volume: f32, pub sfx_volume: f32, pub ui_volume: f32, } impl Default for AudioSettings { fn default() -> Self { Self { master_volume: 1.0, music_volume: 1.0, ambiance_volume: 1.0, sfx_volume: 1.0, ui_volume: 1.0, } } } /// Defines the type of track that a given name represents pub enum TrackType<T> { /// A single audio track that should be played as-is Single(T), /// Represents two tracks; the first is played once as the intro, and the second track will then be looped #[deprecated = "bevy_kira_audio no longer supports this functionality; the first track in the tuple will be ignored"] WithIntro(T, T), /// The requested track could not be found Missing, } impl SuppliesAudio for AssetServer { fn resolve_track_name<T: ToString>(&self, name: T) -> TrackType<String> { TrackType::Single(name.to_string()) } fn get_audio_track<T: ToString>(&self, name: T) -> Option<Handle<AudioSource>> { Some(self.load(&name.to_string())) } } /// A bevy system that triggers the MusicBox to sync its internal channels with /// the AudioSettings resource. This is automatically added when you use `MusicBoxPlugin` or /// `CombinedAudioPlugins` pub fn sync_music_volume<T: SuppliesAudio>(music: MusicBox<T>) { music.sync_settings(); }