You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			148 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Rust
		
	
			
		
		
	
	
			148 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Rust
		
	
| ///
 | |
| /// TODO: Custom Asset: FmodEventMapper
 | |
| ///
 | |
| use crate::prelude::*;
 | |
| 
 | |
| pub(crate) struct AudioPlugin;
 | |
| 
 | |
| impl Plugin for AudioPlugin {
 | |
|     fn build(&self, app: &mut App) {
 | |
|         app.add_event::<AudioEvent>();
 | |
| 
 | |
|         app.add_plugins(FmodPlugin {
 | |
|             audio_banks_paths: &[
 | |
|                 "./assets/audio/Martian Chess Audio/Build/Desktop/Master.bank",
 | |
|                 "./assets/audio/Martian Chess Audio/Build/Desktop/Master.strings.bank",
 | |
|                 "./assets/audio/Martian Chess Audio/Build/Desktop/Music.bank",
 | |
|                 "./assets/audio/Martian Chess Audio/Build/Desktop/SFX.bank",
 | |
|             ],
 | |
|         });
 | |
| 
 | |
|         app.init_resource::<AudioVolume>();
 | |
|         app.add_systems(OnEnter(GameState::Intro), play_background);
 | |
|         app.add_systems(
 | |
|             Update,
 | |
|             (
 | |
|                 play_audio.run_if(any_component_added::<AudioSource>()),
 | |
|                 audio_trigger.run_if(on_event::<AudioEvent>()),
 | |
|                 control_volume.run_if(resource_changed::<AudioVolume>),
 | |
|                 toggle_volume.run_if(just_pressed(KeyCode::KeyM)),
 | |
|             ),
 | |
|         );
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Event, Debug, PartialEq, Component, Clone)]
 | |
| pub enum AudioEvent {
 | |
|     MainMusic,
 | |
|     _StopMainMusic,
 | |
|     MenuHover,
 | |
|     MenuSelect,
 | |
|     PickUp,
 | |
|     PutDown,
 | |
|     Idle,
 | |
|     StopIdle,
 | |
|     Invalid,
 | |
| }
 | |
| 
 | |
| #[derive(Resource, Debug)]
 | |
| pub struct AudioVolume(f32);
 | |
| 
 | |
| impl Default for AudioVolume {
 | |
|     fn default() -> Self {
 | |
|         AudioVolume(1.0)
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn play_background(mut events: EventWriter<AudioEvent>) {
 | |
|     events.send(AudioEvent::MainMusic);
 | |
| }
 | |
| 
 | |
| fn play_audio(mut events: Query<&AudioSource, Added<AudioSource>>) {
 | |
|     events.iter_mut().for_each(|aud| aud.play());
 | |
| }
 | |
| 
 | |
| fn audio_trigger(
 | |
|     mut events: EventReader<AudioEvent>,
 | |
|     sources: Query<(Entity, &AudioSource, &AudioEvent)>,
 | |
|     studio: Res<FmodStudio>,
 | |
|     mut commands: Commands,
 | |
|     server: Res<AssetServer>,
 | |
|     tweaks: Res<Assets<tweak::Tweaks>>,
 | |
|     display_state: Res<State<DisplayState>>,
 | |
|     vol: Res<AudioVolume>,
 | |
| ) {
 | |
|     let tweak = tweaks
 | |
|         .get(&server.load("martian.tweak.toml"))
 | |
|         .expect("Load tweaks");
 | |
|     let state = display_state.get();
 | |
|     events.read().for_each(|event| {
 | |
|         let aud = match event {
 | |
|             AudioEvent::MainMusic | AudioEvent::_StopMainMusic => {
 | |
|                 tweak.get::<String>("audio_music_main").unwrap()
 | |
|             }
 | |
|             AudioEvent::MenuHover => tweak.get::<String>("audio_menu_hover").unwrap(),
 | |
|             AudioEvent::MenuSelect => tweak.get::<String>("audio_menu_select").unwrap(),
 | |
|             AudioEvent::PickUp => tweak.get::<String>("audio_display3d_pick_up").unwrap(),
 | |
|             AudioEvent::PutDown => tweak.get::<String>("audio_display3d_put_down").unwrap(),
 | |
|             AudioEvent::Idle | AudioEvent::StopIdle => {
 | |
|                 tweak.get::<String>("audio_display3d_idle").unwrap()
 | |
|             }
 | |
|             AudioEvent::Invalid => tweak.get::<String>("audio_display3d_invalid").unwrap(),
 | |
|         };
 | |
|         // There is an event, play an audio
 | |
|         if !aud.is_empty() {
 | |
|             let event_str = format!("event:{}", aud);
 | |
|             if let Ok(event_description) = studio.0.get_event(event_str.as_str()) {
 | |
|                 // We are stopping a playing event
 | |
|                 match event {
 | |
|                     // Find and stop playing instances of idle audio
 | |
|                     AudioEvent::StopIdle => {
 | |
|                         sources
 | |
|                             .iter()
 | |
|                             .filter(|(_, _, source_event)| **source_event == AudioEvent::Idle)
 | |
|                             .for_each(|(entity, source, _)| {
 | |
|                                 info!("Stopping audio {}", event_str);
 | |
|                                 source.stop();
 | |
|                                 commands.entity(entity).despawn_recursive();
 | |
|                             });
 | |
|                     }
 | |
|                     // Find and stop playing instances of main music
 | |
|                     AudioEvent::_StopMainMusic => {
 | |
|                         sources
 | |
|                             .iter()
 | |
|                             .filter(|(_, _, source_event)| **source_event == AudioEvent::MainMusic)
 | |
|                             .for_each(|(entity, source, _)| {
 | |
|                                 info!("Stopping audio {}", event_str);
 | |
|                                 source.stop();
 | |
|                                 commands.entity(entity).despawn_recursive();
 | |
|                             });
 | |
|                     }
 | |
|                     // we are playing a sound
 | |
|                     _ => {
 | |
|                         info!("Playing audio {}", event_str);
 | |
|                         let audio_source = AudioSource::new(event_description);
 | |
|                         audio_source.set_volume(vol.0);
 | |
|                         // TODO: Can we batch spawn all sounds at startup? Then Start/Stop/Reset at runtime?
 | |
|                         commands.spawn((audio_source, event.clone()));
 | |
|                     }
 | |
|                 }
 | |
|             } else {
 | |
|                 warn!("No music set for {:?} in {:?}", event, state);
 | |
|             }
 | |
|         }
 | |
|     });
 | |
| }
 | |
| 
 | |
| fn toggle_volume(mut vol: ResMut<AudioVolume>) {
 | |
|     if vol.0 > 0.0 {
 | |
|         vol.0 = 0.0;
 | |
|     } else {
 | |
|         vol.0 = 1.0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn control_volume(vol: Res<AudioVolume>, query: Query<&AudioSource>) {
 | |
|     query.iter().for_each(|aud_src| aud_src.set_volume(vol.0));
 | |
| }
 |