Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::marker::PhantomData;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use bevy_kira_audio::{AudioChannel, InstanceHandle};
use crate::utilities::{AudioSettings, CrossFadeTrack, SuppliesAudio, TrackType};
use crate::{
AmbianceAudioChannelA, AmbianceAudioChannelB, AudioCrossFade, MusicAudioChannelA,
MusicAudioChannelB, SfxAudioChannel, UiSfxAudioChannel,
};
#[derive(SystemParam)]
pub struct AudioChannels<'w, 's> {
pub music_channel_a: Res<'w, AudioChannel<MusicAudioChannelA>>,
pub music_channel_b: Res<'w, AudioChannel<MusicAudioChannelB>>,
pub ambiance_channel_a: Res<'w, AudioChannel<AmbianceAudioChannelA>>,
pub ambiance_channel_b: Res<'w, AudioChannel<AmbianceAudioChannelB>>,
pub sfx_channel: Res<'w, AudioChannel<SfxAudioChannel>>,
pub ui_sfx_channel: Res<'w, AudioChannel<UiSfxAudioChannel>>,
#[system_param(ignore)]
_p: PhantomData<&'s ()>,
}
#[derive(SystemParam)]
pub struct MusicBox<'w, 's, T: SuppliesAudio> {
pub commands: Commands<'w, 's>,
pub channels: AudioChannels<'w, 's>,
pub handles: Res<'w, T>,
pub settings: Res<'w, AudioSettings>,
pub fade_state: Res<'w, AudioCrossFade>,
}
pub enum MusicTrackState {
Pending,
Playing,
FadeOut { progress: f32 },
FadeIn { progress: f32 },
CrossFade { out_progress: f32, in_progress: f32 },
}
impl Default for MusicTrackState {
fn default() -> Self {
Self::Pending
}
}
impl<'w, 's, T: SuppliesAudio> MusicBox<'w, 's, T> {
pub fn play_looped_music<Name: ToString>(&self, name: Name) -> Option<InstanceHandle> {
self.channels.music_channel_a.stop();
self.channels.music_channel_b.stop();
match self.resolve_track_name(name) {
TrackType::Single(track) => match self.fade_state.music.active {
CrossFadeTrack::A => Some(
self.channels
.music_channel_a
.play_looped(track.clone_weak()),
),
CrossFadeTrack::B => Some(
self.channels
.music_channel_b
.play_looped(track.clone_weak()),
),
},
TrackType::WithIntro(intro, looped) => match self.fade_state.music.active {
CrossFadeTrack::A => Some(
self.channels
.music_channel_a
.play_looped_with_intro(intro.clone_weak(), looped.clone_weak()),
),
CrossFadeTrack::B => Some(
self.channels
.music_channel_b
.play_looped_with_intro(intro.clone_weak(), looped.clone_weak()),
),
},
TrackType::Missing => None,
}
}
pub fn play_effect_once<Name: ToString>(&mut self, name: Name) -> Option<InstanceHandle> {
let name = name.to_string();
match self.handles.get_audio_track(&name) {
Some(track) => Some(self.channels.sfx_channel.play(track)),
None => None,
}
}
pub fn play_ambiance<Name: ToString>(&self, name: Name) -> Option<InstanceHandle> {
self.channels.ambiance_channel_a.stop();
self.channels.ambiance_channel_b.stop();
match self.resolve_track_name(name) {
TrackType::Single(track) => match self.fade_state.ambiance.active {
CrossFadeTrack::A => Some(
self.channels
.ambiance_channel_a
.play_looped(track.clone_weak()),
),
CrossFadeTrack::B => Some(
self.channels
.ambiance_channel_b
.play_looped(track.clone_weak()),
),
},
TrackType::WithIntro(intro, looped) => match self.fade_state.ambiance.active {
CrossFadeTrack::A => Some(
self.channels
.ambiance_channel_a
.play_looped_with_intro(intro.clone_weak(), looped.clone_weak()),
),
CrossFadeTrack::B => Some(
self.channels
.ambiance_channel_b
.play_looped_with_intro(intro.clone_weak(), looped.clone_weak()),
),
},
TrackType::Missing => None,
}
}
}