concinnity_asset/
audio_cue.rs1use crate::{AssetId, AudioBus, AudioClipHandle, de_opt_asset_ref, de_opt_audio_clip_handle};
4
5#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
21#[serde(default)]
22pub struct AudioCue {
23 #[serde(skip)]
25 pub asset_id: AssetId,
26 #[serde(deserialize_with = "de_opt_asset_ref")]
28 pub screen: Option<AssetId>,
29 #[serde(deserialize_with = "de_opt_audio_clip_handle")]
31 pub clip: Option<AudioClipHandle>,
32 pub kind: CueKind,
34 pub volume: f32,
36 pub bus: Option<AudioBus>,
39 pub priority: i32,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
47#[serde(rename_all = "lowercase")]
48pub enum CueKind {
49 Music,
52 #[default]
54 Sound,
55}
56
57impl Default for AudioCue {
58 fn default() -> Self {
59 Self {
60 asset_id: AssetId::default(),
61 screen: None,
62 clip: None,
63 kind: CueKind::Sound,
64 volume: 1.0,
65 bus: None,
66 priority: 0,
67 }
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn a_blank_cue_is_a_one_shot_sound_at_unit_gain() {
77 let c = AudioCue::default();
78 assert_eq!(c.kind, CueKind::Sound);
79 assert_eq!(c.volume, 1.0);
80 assert!(c.clip.is_none());
81 assert!(c.screen.is_none());
82 assert!(c.bus.is_none());
83 assert_eq!(c.priority, 0);
84 assert_eq!(CueKind::default(), CueKind::Sound);
85 }
86
87 #[test]
88 fn a_music_cue_parses_its_clip_and_screen_by_name() {
89 crate::test_support::install_resolvers();
90 let c: AudioCue =
91 serde_json::from_str(r#"{"clip":"theme","screen":"menu","kind":"music","volume":0.4}"#)
92 .unwrap();
93 assert_eq!(c.clip, Some(AudioClipHandle(5)));
94 assert_eq!(c.screen, Some(AssetId(4)));
95 assert_eq!(c.kind, CueKind::Music);
96 assert_eq!(c.volume, 0.4);
97 assert_eq!(
98 serde_json::to_string(&CueKind::Music).unwrap(),
99 r#""music""#
100 );
101
102 let bytes = postcard::to_allocvec(&c).unwrap();
103 let back: AudioCue = postcard::from_bytes(&bytes).unwrap();
104 assert_eq!(back.clip, Some(AudioClipHandle(5)));
105 assert_eq!(back.screen, Some(AssetId(4)));
106 assert_eq!(back.kind, CueKind::Music);
107 assert_eq!(back.asset_id, AssetId::default());
108 }
109
110 #[test]
111 fn a_voice_cue_parses_its_bus_and_priority() {
112 crate::test_support::install_resolvers();
113 let c: AudioCue =
114 serde_json::from_str(r#"{"clip":"line","screen":"menu","bus":"voice","priority":5}"#)
115 .unwrap();
116 assert_eq!(c.bus, Some(AudioBus::Voice));
117 assert_eq!(c.priority, 5);
118
119 let bytes = postcard::to_allocvec(&c).unwrap();
120 let back: AudioCue = postcard::from_bytes(&bytes).unwrap();
121 assert_eq!(back.bus, Some(AudioBus::Voice));
122 assert_eq!(back.priority, 5);
123 }
124}