diff --git a/src/actor.rs b/src/actor.rs index a2db27d..6e9f897 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -98,7 +98,7 @@ pub fn handle_input( query: Query<(&Talker, &Transform)>, player: Query<&Transform, With>, mut ew_conv: EventWriter, - mut ew_click: EventWriter, + mut ew_sfx: EventWriter, ) { if keyboard_input.just_pressed(settings.key_interact) { @@ -107,7 +107,7 @@ pub fn handle_input( for (talker, transform) in &query { if transform.translation.distance_squared(player.translation) <= mindist { ew_conv.send(StartConversationEvent{conv: talker.conv.clone()}); - ew_click.send(audio::AudioClickEvent()); + ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::IncomingChatMessage)); break; } } @@ -120,7 +120,7 @@ pub fn handle_conversations( mut log: ResMut, ) { for my_event in er_conv.read() { - log.add(my_event.conv.clone()); + log.chat(my_event.conv.clone(), "Alien".to_string()); break; } } diff --git a/src/audio.rs b/src/audio.rs index be5271a..d50a579 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -4,6 +4,7 @@ use crate::settings; const ASSET_CLICK: &str = "sounds/click-button-140881-crop.ogg"; const ASSET_SWITCH: &str = "sounds/typosonic-typing-192811-crop.ogg"; +const ASSET_INCOMING_MESSAGE: &str = "tmp/multi-pop-2-188167.mp3.ogg"; const ASSET_RADIO: &str = "tmp/LP - Girls Go Wild (Official Music Video)-M7XRN0oHGIM.ogg"; const ASSET_BGM: &str = "tmp/FTL - Faster Than Light (2012) OST - 12 - Void (Explore)-edQw2yYXQJM.ogg"; @@ -14,41 +15,27 @@ impl Plugin for AudioPlugin { app.add_systems(Update, toggle_bgm); app.add_systems(PostUpdate, play_sfx); app.add_systems(PostUpdate, update_music); - app.add_event::(); - app.add_event::(); + app.add_event::(); app.add_event::(); } } -#[derive(Event)] -pub struct AudioClickEvent(); +pub enum Sfx { + IncomingChatMessage, + Click, + Switch, +} -#[derive(Event)] -pub struct AudioSwitchEvent(); - -#[derive(Event)] -pub struct ToggleMusicEvent(); - -#[derive(Component)] -pub struct ComponentBGM; - -#[derive(Component)] -pub struct ComponentRadio; - -#[derive(Component)] -pub struct ComponentThrusterSound; - -#[derive(Component)] -struct SoundBGM(Handle); - -#[derive(Component)] -pub struct SoundRadio(Handle); - -#[derive(Resource)] -pub struct SoundClick(Handle); - -#[derive(Resource)] -pub struct SoundSwitch(Handle); +#[derive(Event)] pub struct PlaySfxEvent(pub Sfx); +#[derive(Event)] pub struct ToggleMusicEvent(); +#[derive(Component)] pub struct ComponentBGM; +#[derive(Component)] pub struct ComponentRadio; +#[derive(Component)] pub struct ComponentThrusterSound; +#[derive(Component)] struct SoundBGM(Handle); +#[derive(Component)] pub struct SoundRadio(Handle); +#[derive(Resource)] pub struct SoundClick(Handle); +#[derive(Resource)] pub struct SoundSwitch(Handle); +#[derive(Resource)] pub struct SoundIncomingMessage(Handle); pub fn setup( mut commands: Commands, @@ -98,22 +85,23 @@ pub fn setup( )); commands.insert_resource(SoundClick(asset_server.load(ASSET_CLICK))); commands.insert_resource(SoundSwitch(asset_server.load(ASSET_SWITCH))); + commands.insert_resource(SoundIncomingMessage(asset_server.load(ASSET_INCOMING_MESSAGE))); } pub fn toggle_bgm( keyboard_input: Res>, mut evwriter_toggle: EventWriter, - mut evwriter_click: EventWriter, + mut evwriter_sfx: EventWriter, mut settings: ResMut, ) { if keyboard_input.just_pressed(KeyCode::KeyT) { settings.mute_music ^= true; - evwriter_click.send(AudioClickEvent()); + evwriter_sfx.send(PlaySfxEvent(Sfx::Click)); evwriter_toggle.send(ToggleMusicEvent()); } if keyboard_input.just_pressed(KeyCode::KeyM) { settings.mute_sfx ^= true; - evwriter_click.send(AudioClickEvent()); + evwriter_sfx.send(PlaySfxEvent(Sfx::Click)); evwriter_toggle.send(ToggleMusicEvent()); } } @@ -121,28 +109,23 @@ pub fn toggle_bgm( pub fn play_sfx( mut commands: Commands, settings: Res, - mut events_click: EventReader, - mut events_switch: EventReader, + mut events_sfx: EventReader, sound_click: Res, sound_switch: Res, + sound_incoming_message: Res, ) { - if !events_click.is_empty() { - events_click.clear(); - if !settings.mute_sfx { - commands.spawn(AudioBundle { - source: sound_click.0.clone(), - settings: PlaybackSettings::DESPAWN, - }); - } + if settings.mute_sfx && !events_sfx.is_empty() { + events_sfx.clear(); } - if !events_switch.is_empty() { - events_switch.clear(); - if !settings.mute_sfx { - commands.spawn(AudioBundle { - source: sound_switch.0.clone(), - settings: PlaybackSettings::DESPAWN, - }); - } + for sfx in events_sfx.read() { + commands.spawn(AudioBundle { + source: match sfx.0 { + Sfx::Switch => sound_switch.0.clone(), + Sfx::Click => sound_click.0.clone(), + Sfx::IncomingChatMessage => sound_incoming_message.0.clone(), + }, + settings: PlaybackSettings::DESPAWN, + }); } } diff --git a/src/hud.rs b/src/hud.rs index e9dcea7..8392c25 100644 --- a/src/hud.rs +++ b/src/hud.rs @@ -15,7 +15,10 @@ impl Plugin for HudPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, setup); app.add_systems(Update, (update, handle_input)); - app.insert_resource(Log { logs: VecDeque::with_capacity(LOG_MAX) }); + app.insert_resource(Log { + logs: VecDeque::with_capacity(LOG_MAX), + needs_rerendering: true, + }); app.insert_resource(FPSUpdateTimer( Timer::from_seconds(HUD_REFRESH_TIME, TimerMode::Repeating))); } @@ -27,26 +30,53 @@ impl Plugin for HudPlugin { #[derive(Resource)] struct FPSUpdateTimer(Timer); +pub enum LogLevel { + Warning, + //Error, + Info, + //Debug, + Chat, + //Ping, +} + struct Message { text: String, + sender: String, + level: LogLevel, time: u64, } #[derive(Resource)] pub struct Log { logs: VecDeque, + needs_rerendering: bool, } impl Log { - pub fn add(&mut self, message: String) { + pub fn info(&mut self, message: String) { + self.add(message, "System".to_string(), LogLevel::Info); + } + + pub fn chat(&mut self, message: String, sender: String) { + self.add(message, sender, LogLevel::Chat); + } + + pub fn warning(&mut self, message: String) { + self.add(message, "WARNING".to_string(), LogLevel::Warning); + } + + pub fn add(&mut self, message: String, sender: String, level: LogLevel) { if self.logs.len() == LOG_MAX { self.logs.pop_front(); } if let Ok(epoch) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { self.logs.push_back(Message { text: message, + sender: sender, + level: level, time: epoch.as_secs(), }); + self.needs_rerendering = true; } } @@ -67,8 +97,9 @@ fn setup( asset_server: Res, mut log: ResMut, ) { - log.add("Customer wake-up registered.".to_string()); - log.add("Systems reactivated.".to_string()); + log.info("Customer wake-up registered.".to_string()); + log.info("Systems reactivated.".to_string()); + log.warning("Oxygen Low".to_string()); let visibility = if settings.hud_active { Visibility::Inherited } else { @@ -194,26 +225,28 @@ fn setup( )); // Add Chat Box -// let bundle_chatbox = TextBundle::from_sections([ -// TextSection::new( -// "Hello :D", -// TextStyle { -// font: asset_server.load(FONT), -// font_size: settings.font_size_hud, -// color: Color::GRAY, -// ..default() -// } -// ), -// ]).with_style(Style { -// position_type: PositionType::Absolute, -// bottom: Val::VMin(40.0), -// left: Val::VMin(30.0), -// ..default() -// }); -// commands.spawn(( -// bundle_chatbox, -// ChatText, -// )); + let bundle_chatbox = TextBundle::from_sections([ + TextSection::new( + "Hello World!\nThis Is Cool, right?", + TextStyle { + font: asset_server.load(FONT), + font_size: settings.font_size_hud, + color: Color::GRAY, + ..default() + } + ), + ]).with_style(Style { + position_type: PositionType::Absolute, + top: Val::VMin(2.0), + right: Val::VMin(6.0), + //bottom: Val::VMin(40.0), + //left: Val::VMin(30.0), + ..default() + }).with_text_justify(JustifyText::Right); + commands.spawn(( + bundle_chatbox, + ChatText, + )); } fn update( @@ -223,10 +256,12 @@ fn update( player: Query<(&actor::Suit, &actor::LifeForm), With>, mut timer: ResMut, mut query: Query<&mut Text, With>, + mut query_chat: Query<&mut Text, (With, Without)>, query_all_actors: Query<&actor::Actor>, + settings: Res, ) { // TODO only when hud is actually on - if timer.0.tick(time.delta()).just_finished() { + if timer.0.tick(time.delta()).just_finished() || log.needs_rerendering { let player = player.get_single(); if player.is_ok() { let (suit, lifeform) = player.unwrap(); @@ -248,10 +283,23 @@ fn update( text.sections[9].value = format!("{all_actors:.0}"); } } - for mut text in &mut query { - let logs_vec: Vec<&str> = log.logs.iter().map(|s| s.text.as_str()).collect(); - text.sections[11].value = logs_vec.join("\n"); + + if let Ok(mut chat) = query_chat.get_single_mut() { + let logfilter = if settings.hud_active { + |_msg: &&Message| { true } + } else { + |msg: &&Message| { match msg.level { + LogLevel::Chat => true, + LogLevel::Warning => true, + _ => false + }} + }; + let logs_vec: Vec = log.logs.iter() + .filter(logfilter) + .map(|s| format!("{}: {}", s.sender, s.text)).collect(); + chat.sections[0].value = logs_vec.join("\n"); } + log.needs_rerendering = false; log.remove_old(); } } @@ -261,11 +309,11 @@ fn handle_input( mut settings: ResMut, mut query: Query<&mut Visibility, With>, mut query_bloomsettings: Query<&mut BloomSettings>, - mut evwriter: EventWriter, + mut evwriter_sfx: EventWriter, mut evwriter_togglemusic: EventWriter, ) { if keyboard_input.just_pressed(settings.key_togglehud) { - for mut vis in &mut query { + if let Ok(mut vis) = query.get_single_mut() { if let Ok(mut bloomsettings) = query_bloomsettings.get_single_mut() { if *vis == Visibility::Inherited { *vis = Visibility::Hidden; @@ -274,9 +322,10 @@ fn handle_input( } else { *vis = Visibility::Inherited; settings.hud_active = true; - bloomsettings.composite_mode = BloomCompositeMode::Additive; + bloomsettings.composite_mode = BloomCompositeMode::EnergyConserving; + //bloomsettings.composite_mode = BloomCompositeMode::Additive; } - evwriter.send(audio::AudioSwitchEvent()); + evwriter_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch)); evwriter_togglemusic.send(audio::ToggleMusicEvent()); } }