skullball/rust/src/bgm.rs

80 lines
2.2 KiB
Rust

use godot::{
classes::{AudioStream, AudioStreamPlayer},
prelude::*,
tools::get_autoload_by_name,
};
use crate::game::GameManager;
pub const MUSIC_MANAGER_GLOBAL: &str = "MusicManagerGlobal";
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
pub enum Music {
MainMenu,
Map(u8),
}
#[derive(GodotClass)]
#[class(base=Node3D, init)]
pub struct MusicManager {
#[export]
player: Option<Gd<AudioStreamPlayer>>,
#[export]
main_menu_songs: Array<Gd<AudioStream>>,
currently_playing: Option<Music>,
base: Base<Node3D>,
}
#[godot_api]
impl INode3D for MusicManager {
fn ready(&mut self) {
if let Some(player) = self.player.clone() {
player.signals().finished().connect_other(self, |s| {
if let Some(playing) = s.currently_playing {
s.play(Some(playing), true);
}
});
}
}
}
impl MusicManager {
pub fn singleton() -> Gd<MusicManager> {
get_autoload_by_name::<MusicManager>(MUSIC_MANAGER_GLOBAL)
}
pub fn play(&mut self, music: Option<Music>, force: bool) {
if self.currently_playing == music && !force {
return;
}
self.currently_playing = music;
if let Some(player) = &mut self.player {
match music {
Some(music) => {
let songs = match music {
Music::MainMenu => self.main_menu_songs.clone(),
Music::Map(idx) => {
if let Some(map) =
GameManager::singleton().bind().maps.get(idx as usize)
{
map.bind().music.clone()
} else {
Array::new()
}
}
};
if let Some(song) = songs.pick_random() {
player.set_stream(&song);
player.play();
} else {
player.stop();
}
}
None => player.stop(),
}
}
}
}