mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Completely redoing ambient sound again.
This commit is contained in:
parent
16ca1410be
commit
aafd13508d
@ -111,7 +111,9 @@ impl Outcome {
|
|||||||
| Outcome::Utterance { pos, .. }
|
| Outcome::Utterance { pos, .. }
|
||||||
| Outcome::Glider { pos, .. } => Some(*pos),
|
| Outcome::Glider { pos, .. } => Some(*pos),
|
||||||
Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)),
|
Outcome::BreakBlock { pos, .. } => Some(pos.map(|e| e as f32 + 0.5)),
|
||||||
Outcome::ExpChange { .. } | Outcome::ComboChange { .. } | Outcome::SkillPointGain { .. } => None,
|
Outcome::ExpChange { .. }
|
||||||
|
| Outcome::ComboChange { .. }
|
||||||
|
| Outcome::SkillPointGain { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
//! Handles ambient non-positional sounds
|
//! Handles ambient non-positional sounds
|
||||||
use crate::{
|
use crate::{
|
||||||
audio::{channel::AmbientChannelTag, AudioFrontend},
|
audio::{
|
||||||
|
channel::{AmbientChannel, AmbientChannelTag},
|
||||||
|
AudioFrontend,
|
||||||
|
},
|
||||||
scene::Camera,
|
scene::Camera,
|
||||||
};
|
};
|
||||||
use client::Client;
|
use client::Client;
|
||||||
@ -10,12 +13,13 @@ use common::{
|
|||||||
};
|
};
|
||||||
use common_state::State;
|
use common_state::State;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize)]
|
#[derive(Debug, Default, Deserialize)]
|
||||||
struct AmbientCollection {
|
pub struct AmbientCollection {
|
||||||
tracks: Vec<AmbientItem>,
|
tracks: Vec<AmbientItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,49 +33,11 @@ pub struct AmbientItem {
|
|||||||
tag: AmbientChannelTag,
|
tag: AmbientChannelTag,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AmbientWindMgr {
|
pub struct AmbientMgr {
|
||||||
ambience: AssetHandle<AmbientCollection>,
|
pub ambience: AssetHandle<AmbientCollection>,
|
||||||
began_playing: Instant,
|
|
||||||
next_track_change: f32,
|
|
||||||
volume: f32,
|
|
||||||
tree_multiplier: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AmbientRainMgr {
|
impl AmbientMgr {
|
||||||
ambience: AssetHandle<AmbientCollection>,
|
|
||||||
began_playing: Instant,
|
|
||||||
next_track_change: f32,
|
|
||||||
volume: f32,
|
|
||||||
rain_intensity: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for AmbientWindMgr {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
ambience: load_ambience_items(),
|
|
||||||
began_playing: Instant::now(),
|
|
||||||
next_track_change: 0.0,
|
|
||||||
volume: 0.0,
|
|
||||||
tree_multiplier: 0.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for AmbientRainMgr {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
ambience: load_ambience_items(),
|
|
||||||
began_playing: Instant::now(),
|
|
||||||
next_track_change: 0.0,
|
|
||||||
volume: 0.0,
|
|
||||||
rain_intensity: 0.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AmbientWindMgr {
|
|
||||||
/// Checks whether the previous track has completed. If so, sends a
|
|
||||||
/// request to play the next (random) track
|
|
||||||
pub fn maintain(
|
pub fn maintain(
|
||||||
&mut self,
|
&mut self,
|
||||||
audio: &mut AudioFrontend,
|
audio: &mut AudioFrontend,
|
||||||
@ -79,157 +45,156 @@ impl AmbientWindMgr {
|
|||||||
client: &Client,
|
client: &Client,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
) {
|
) {
|
||||||
if audio.sfx_enabled() && !self.ambience.read().tracks.is_empty() {
|
let sfx_volume = audio.get_sfx_volume();
|
||||||
let focus_off = camera.get_focus_pos().map(f32::trunc);
|
// iterate through each tag
|
||||||
let cam_pos = camera.dependents().cam_pos + focus_off;
|
for tag in AmbientChannelTag::iter() {
|
||||||
|
// iterate through the supposed number of channels - one for each tag
|
||||||
let (terrain_alt, tree_density) = if let Some(chunk) = client.current_chunk() {
|
for index in 0..AmbientChannelTag::iter().len() {
|
||||||
(chunk.meta().alt(), chunk.meta().tree_density())
|
// if index would exceed current number of channels, create a new one with
|
||||||
} else {
|
// current tag
|
||||||
(0.0, 0.0)
|
if index >= audio.ambient_channels.len() {
|
||||||
};
|
audio.new_ambient_channel(tag);
|
||||||
|
|
||||||
// The following code is specifically for wind, as it is the only
|
|
||||||
// non-positional ambient sound in the game. Others can be added
|
|
||||||
// as seen fit.
|
|
||||||
|
|
||||||
let target_volume = {
|
|
||||||
// Wind volume increases with altitude
|
|
||||||
let alt_multiplier = (cam_pos.z / 1200.0).abs();
|
|
||||||
|
|
||||||
// Tree density factors into wind volume. The more trees,
|
|
||||||
// the lower wind volume. The trees make more of an impact
|
|
||||||
// the closer the camera is to the ground.
|
|
||||||
self.tree_multiplier = ((1.0 - tree_density)
|
|
||||||
+ ((cam_pos.z - terrain_alt).abs() / 150.0).powi(2))
|
|
||||||
.min(1.0);
|
|
||||||
|
|
||||||
let mut volume_multiplier = alt_multiplier * self.tree_multiplier;
|
|
||||||
|
|
||||||
// Checks if the camera is underwater to stop ambient sounds
|
|
||||||
if state
|
|
||||||
.terrain()
|
|
||||||
.get((cam_pos).map(|e| e.floor() as i32))
|
|
||||||
.map(|b| b.is_liquid())
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
volume_multiplier *= 0.1;
|
|
||||||
}
|
|
||||||
// Is the camera roughly under the terrain?
|
|
||||||
if cam_pos.z < terrain_alt - 10.0 {
|
|
||||||
volume_multiplier = 0.0;
|
|
||||||
}
|
}
|
||||||
|
// update with sfx volume
|
||||||
|
audio.ambient_channels[index].set_volume(sfx_volume);
|
||||||
|
// if current channel's tag is not the current tag, move on to next channel
|
||||||
|
if audio.ambient_channels[index].get_tag() == tag {
|
||||||
|
// maintain: get the correct multiplier of whatever the tag of the current
|
||||||
|
// channel is
|
||||||
|
let target_volume =
|
||||||
|
audio.ambient_channels[index].maintain(state, client, camera);
|
||||||
|
// get multiplier of the current channel
|
||||||
|
let initial_volume = audio.ambient_channels[index].get_multiplier();
|
||||||
|
|
||||||
volume_multiplier.clamped(0.0, 1.0)
|
// lerp multiplier of current channel
|
||||||
};
|
audio.ambient_channels[index].set_multiplier(Lerp::lerp(
|
||||||
|
initial_volume,
|
||||||
|
target_volume,
|
||||||
|
0.01,
|
||||||
|
));
|
||||||
|
|
||||||
// Transitions the ambient sounds (more) smoothly
|
// set the duration of the loop to whatever the current value is (0.0 by
|
||||||
if audio.get_ambient_channel(AmbientChannelTag::Wind).is_none() {
|
// default)
|
||||||
audio.new_ambient_channel(AmbientChannelTag::Wind);
|
let next_track_change = audio.ambient_channels[index].get_next_track_change();
|
||||||
} else {
|
|
||||||
self.volume = audio.get_ambient_volume(AmbientChannelTag::Wind);
|
|
||||||
audio.set_ambient_volume(
|
|
||||||
AmbientChannelTag::Wind,
|
|
||||||
Lerp::lerp(self.volume, target_volume, 0.01),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.began_playing.elapsed().as_secs_f32() > self.next_track_change {
|
// if the sound should loop at this point:
|
||||||
let ambience = self.ambience.read();
|
if audio.ambient_channels[index]
|
||||||
let wind_track = &ambience
|
.get_began_playing()
|
||||||
.tracks
|
.elapsed()
|
||||||
.iter()
|
.as_secs_f32()
|
||||||
.find(|track| track.tag == AmbientChannelTag::Wind);
|
> next_track_change
|
||||||
self.began_playing = Instant::now();
|
{
|
||||||
if let Some(wind_track) = wind_track {
|
let ambience = self.ambience.read();
|
||||||
self.next_track_change = wind_track.length;
|
let track = ambience.tracks.iter().find(|track| track.tag == tag);
|
||||||
audio.play_ambient(AmbientChannelTag::Wind, &wind_track.path, target_volume);
|
// set the track's start point at this instant
|
||||||
}
|
audio.ambient_channels[index].set_began_playing(Instant::now());
|
||||||
}
|
if let Some(track) = track {
|
||||||
}
|
// set loop duration to the one specified in the ron
|
||||||
}
|
audio.ambient_channels[index].set_next_track_change(track.length);
|
||||||
}
|
// play the file of the current tag at the current multiplier
|
||||||
|
let current_multiplier = audio.ambient_channels[index].get_multiplier();
|
||||||
|
audio.play_ambient(tag, &track.path, current_multiplier);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
impl AmbientRainMgr {
|
// remove channel if not playing
|
||||||
/// Checks whether the previous track has completed. If so, sends a
|
if audio.ambient_channels[index].get_multiplier() == 0.0 {
|
||||||
/// request to play the next (random) track
|
audio.ambient_channels[index].stop();
|
||||||
pub fn maintain(
|
audio.ambient_channels.remove(index);
|
||||||
&mut self,
|
};
|
||||||
audio: &mut AudioFrontend,
|
// move on to next tag
|
||||||
state: &State,
|
break;
|
||||||
client: &Client,
|
|
||||||
camera: &Camera,
|
|
||||||
) {
|
|
||||||
if audio.sfx_enabled() && !self.ambience.read().tracks.is_empty() {
|
|
||||||
let focus_off = camera.get_focus_pos().map(f32::trunc);
|
|
||||||
let cam_pos = camera.dependents().cam_pos + focus_off;
|
|
||||||
|
|
||||||
let terrain_alt = if let Some(chunk) = client.current_chunk() {
|
|
||||||
chunk.meta().alt()
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
};
|
|
||||||
|
|
||||||
// multipler at end will have to change depending on how intense rain normally
|
|
||||||
// is
|
|
||||||
self.rain_intensity = client.current_weather().rain * 5.0;
|
|
||||||
|
|
||||||
let mut volume_multiplier = self.rain_intensity;
|
|
||||||
|
|
||||||
// TODO: make rain diminish with distance above terrain
|
|
||||||
let target_volume = {
|
|
||||||
// Checks if the camera is underwater to stop ambient sounds
|
|
||||||
if state
|
|
||||||
.terrain()
|
|
||||||
.get((cam_pos).map(|e| e.floor() as i32))
|
|
||||||
.map(|b| b.is_liquid())
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
volume_multiplier *= 0.1;
|
|
||||||
}
|
|
||||||
// Is the camera roughly under the terrain?
|
|
||||||
if cam_pos.z < terrain_alt - 10.0 {
|
|
||||||
volume_multiplier = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_multiplier = volume_multiplier.clamped(0.0, 1.0);
|
|
||||||
|
|
||||||
// possibly remove noise
|
|
||||||
if volume_multiplier < 0.05 {
|
|
||||||
0.0
|
|
||||||
} else {
|
} else {
|
||||||
volume_multiplier
|
// channel tag and current tag don't match, move on to next channel
|
||||||
}
|
continue;
|
||||||
};
|
|
||||||
|
|
||||||
// Transitions the ambient sounds (more) smoothly
|
|
||||||
if audio.get_ambient_channel(AmbientChannelTag::Rain).is_none() {
|
|
||||||
audio.new_ambient_channel(AmbientChannelTag::Rain);
|
|
||||||
} else {
|
|
||||||
self.volume = audio.get_ambient_volume(AmbientChannelTag::Rain);
|
|
||||||
audio.set_ambient_volume(
|
|
||||||
AmbientChannelTag::Rain,
|
|
||||||
Lerp::lerp(self.volume, target_volume, 0.01),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.began_playing.elapsed().as_secs_f32() > self.next_track_change {
|
|
||||||
let ambience = self.ambience.read();
|
|
||||||
let rain_track = &ambience
|
|
||||||
.tracks
|
|
||||||
.iter()
|
|
||||||
.find(|track| track.tag == AmbientChannelTag::Rain);
|
|
||||||
self.began_playing = Instant::now();
|
|
||||||
if let Some(rain_track) = rain_track {
|
|
||||||
self.next_track_change = rain_track.length;
|
|
||||||
audio.play_ambient(AmbientChannelTag::Rain, &rain_track.path, target_volume);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_ambience_items() -> AssetHandle<AmbientCollection> {
|
impl AmbientChannel {
|
||||||
|
pub fn maintain(&mut self, state: &State, client: &Client, camera: &Camera) -> f32 {
|
||||||
|
let tag = self.get_tag();
|
||||||
|
|
||||||
|
let focus_off = camera.get_focus_pos().map(f32::trunc);
|
||||||
|
let cam_pos = camera.dependents().cam_pos + focus_off;
|
||||||
|
|
||||||
|
let mut target_volume: f32 = match tag {
|
||||||
|
// Get target volume of wind
|
||||||
|
AmbientChannelTag::Wind => self.get_wind_volume(client, camera),
|
||||||
|
// get target volume of rain
|
||||||
|
AmbientChannelTag::Rain => self.get_rain_volume(client),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: make rain diminish with distance above terrain
|
||||||
|
target_volume = self.check_camera(state, client, cam_pos, target_volume);
|
||||||
|
|
||||||
|
return target_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_camera(
|
||||||
|
&mut self,
|
||||||
|
state: &State,
|
||||||
|
client: &Client,
|
||||||
|
cam_pos: Vec3<f32>,
|
||||||
|
initial_volume: f32,
|
||||||
|
) -> f32 {
|
||||||
|
let mut volume_multiplier = initial_volume;
|
||||||
|
let terrain_alt = if let Some(chunk) = client.current_chunk() {
|
||||||
|
chunk.meta().alt()
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
// Checks if the camera is underwater to stop ambient sounds
|
||||||
|
if state
|
||||||
|
.terrain()
|
||||||
|
.get((cam_pos).map(|e| e.floor() as i32))
|
||||||
|
.map(|b| b.is_liquid())
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
volume_multiplier *= 0.1;
|
||||||
|
}
|
||||||
|
// Is the camera roughly under the terrain?
|
||||||
|
if cam_pos.z < terrain_alt - 10.0 {
|
||||||
|
volume_multiplier = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_multiplier.clamped(0.0, 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_wind_volume(&mut self, client: &Client, camera: &Camera) -> f32 {
|
||||||
|
let focus_off = camera.get_focus_pos().map(f32::trunc);
|
||||||
|
let cam_pos = camera.dependents().cam_pos + focus_off;
|
||||||
|
|
||||||
|
let (terrain_alt, tree_density) = if let Some(chunk) = client.current_chunk() {
|
||||||
|
(chunk.meta().alt(), chunk.meta().tree_density())
|
||||||
|
} else {
|
||||||
|
(0.0, 0.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wind volume increases with altitude
|
||||||
|
let alt_multiplier = (cam_pos.z / 1200.0).abs();
|
||||||
|
|
||||||
|
// Tree density factors into wind volume. The more trees,
|
||||||
|
// the lower wind volume. The trees make more of an impact
|
||||||
|
// the closer the camera is to the ground.
|
||||||
|
let tree_multiplier =
|
||||||
|
((1.0 - tree_density) + ((cam_pos.z - terrain_alt).abs() / 150.0).powi(2)).min(1.0);
|
||||||
|
|
||||||
|
return alt_multiplier * tree_multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rain_volume(&mut self, client: &Client) -> f32 {
|
||||||
|
// multipler at end will have to change depending on how intense rain normally
|
||||||
|
// is
|
||||||
|
let rain_intensity = client.current_weather().rain * 5.0;
|
||||||
|
|
||||||
|
return rain_intensity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_ambience_items() -> AssetHandle<AmbientCollection> {
|
||||||
AmbientCollection::load_or_insert_with("voxygen.audio.ambient", |error| {
|
AmbientCollection::load_or_insert_with("voxygen.audio.ambient", |error| {
|
||||||
warn!(
|
warn!(
|
||||||
"Error reading ambience config file, ambience will not be available: {:#?}",
|
"Error reading ambience config file, ambience will not be available: {:#?}",
|
||||||
|
@ -22,6 +22,8 @@ use crate::audio::{
|
|||||||
};
|
};
|
||||||
use rodio::{OutputStreamHandle, Sample, Sink, Source, SpatialSink};
|
use rodio::{OutputStreamHandle, Sample, Sink, Source, SpatialSink};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use strum::EnumIter;
|
||||||
|
use std::time::Instant;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -157,7 +159,7 @@ impl MusicChannel {
|
|||||||
|
|
||||||
/// AmbientChannelTags are used for non-positional sfx. Currently the only use
|
/// AmbientChannelTags are used for non-positional sfx. Currently the only use
|
||||||
/// is for wind.
|
/// is for wind.
|
||||||
#[derive(Debug, PartialEq, Clone, Copy, Deserialize)]
|
#[derive(Debug, PartialEq, Clone, Copy, Deserialize, EnumIter)]
|
||||||
pub enum AmbientChannelTag {
|
pub enum AmbientChannelTag {
|
||||||
Wind,
|
Wind,
|
||||||
Rain,
|
Rain,
|
||||||
@ -168,6 +170,8 @@ pub struct AmbientChannel {
|
|||||||
tag: AmbientChannelTag,
|
tag: AmbientChannelTag,
|
||||||
multiplier: f32,
|
multiplier: f32,
|
||||||
sink: Sink,
|
sink: Sink,
|
||||||
|
began_playing: Instant,
|
||||||
|
next_track_change: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AmbientChannel {
|
impl AmbientChannel {
|
||||||
@ -178,6 +182,8 @@ impl AmbientChannel {
|
|||||||
tag,
|
tag,
|
||||||
multiplier,
|
multiplier,
|
||||||
sink,
|
sink,
|
||||||
|
began_playing: Instant::now(),
|
||||||
|
next_track_change: 0.0,
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("Failed to create rodio sink. May not play ambient sounds.");
|
warn!("Failed to create rodio sink. May not play ambient sounds.");
|
||||||
@ -185,6 +191,8 @@ impl AmbientChannel {
|
|||||||
tag,
|
tag,
|
||||||
multiplier,
|
multiplier,
|
||||||
sink: Sink::new_idle().0,
|
sink: Sink::new_idle().0,
|
||||||
|
began_playing: Instant::now(),
|
||||||
|
next_track_change: 0.0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -211,6 +219,20 @@ impl AmbientChannel {
|
|||||||
pub fn get_multiplier(&mut self) -> f32 { self.multiplier }
|
pub fn get_multiplier(&mut self) -> f32 { self.multiplier }
|
||||||
|
|
||||||
pub fn get_tag(&self) -> AmbientChannelTag { self.tag }
|
pub fn get_tag(&self) -> AmbientChannelTag { self.tag }
|
||||||
|
|
||||||
|
pub fn set_tag(&mut self, tag: AmbientChannelTag) { self.tag = tag }
|
||||||
|
|
||||||
|
pub fn get_began_playing(&self) -> Instant { self.began_playing }
|
||||||
|
|
||||||
|
pub fn get_next_track_change(&self) -> f32 { self.next_track_change }
|
||||||
|
|
||||||
|
pub fn set_began_playing(&mut self, began_playing: Instant) {
|
||||||
|
self.began_playing = began_playing
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_next_track_change(&mut self, next_track_change: f32) {
|
||||||
|
self.next_track_change = next_track_change
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An SfxChannel uses a positional audio sink, and is designed for short-lived
|
/// An SfxChannel uses a positional audio sink, and is designed for short-lived
|
||||||
@ -264,9 +286,8 @@ impl SfxChannel {
|
|||||||
pub fn update(&mut self, listener: &Listener) {
|
pub fn update(&mut self, listener: &Listener) {
|
||||||
const FALLOFF: f32 = 0.13;
|
const FALLOFF: f32 = 0.13;
|
||||||
|
|
||||||
self.sink.set_emitter_position(
|
self.sink
|
||||||
((self.pos - listener.pos) * FALLOFF).into_array(),
|
.set_emitter_position(((self.pos - listener.pos) * FALLOFF).into_array());
|
||||||
);
|
|
||||||
self.sink
|
self.sink
|
||||||
.set_left_ear_position(listener.ear_left_rpos.into_array());
|
.set_left_ear_position(listener.ear_left_rpos.into_array());
|
||||||
self.sink
|
self.sink
|
||||||
@ -281,7 +302,7 @@ pub struct UIChannel {
|
|||||||
impl UIChannel {
|
impl UIChannel {
|
||||||
pub fn new(stream: &OutputStreamHandle) -> Self {
|
pub fn new(stream: &OutputStreamHandle) -> Self {
|
||||||
Self {
|
Self {
|
||||||
sink: Sink::try_new(stream).unwrap()
|
sink: Sink::try_new(stream).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,9 @@ pub mod music;
|
|||||||
pub mod sfx;
|
pub mod sfx;
|
||||||
pub mod soundcache;
|
pub mod soundcache;
|
||||||
|
|
||||||
use channel::{AmbientChannel, AmbientChannelTag, MusicChannel, MusicChannelTag, SfxChannel, UIChannel};
|
use channel::{
|
||||||
|
AmbientChannel, AmbientChannelTag, MusicChannel, MusicChannelTag, SfxChannel, UIChannel,
|
||||||
|
};
|
||||||
use fader::Fader;
|
use fader::Fader;
|
||||||
use music::MusicTransitionManifest;
|
use music::MusicTransitionManifest;
|
||||||
use sfx::{SfxEvent, SfxTriggerItem};
|
use sfx::{SfxEvent, SfxTriggerItem};
|
||||||
@ -38,16 +40,16 @@ pub struct AudioFrontend {
|
|||||||
//pub device_list: Vec<String>,
|
//pub device_list: Vec<String>,
|
||||||
//pub audio_device: Option<Device>,
|
//pub audio_device: Option<Device>,
|
||||||
pub stream: Option<rodio::OutputStream>,
|
pub stream: Option<rodio::OutputStream>,
|
||||||
audio_stream: Option<rodio::OutputStreamHandle>,
|
pub audio_stream: Option<rodio::OutputStreamHandle>,
|
||||||
|
|
||||||
music_channels: Vec<MusicChannel>,
|
pub music_channels: Vec<MusicChannel>,
|
||||||
ambient_channels: Vec<AmbientChannel>,
|
pub ambient_channels: Vec<AmbientChannel>,
|
||||||
sfx_channels: Vec<SfxChannel>,
|
pub sfx_channels: Vec<SfxChannel>,
|
||||||
ui_channels: Vec<UIChannel>,
|
pub ui_channels: Vec<UIChannel>,
|
||||||
sfx_volume: f32,
|
pub sfx_volume: f32,
|
||||||
music_volume: f32,
|
pub music_volume: f32,
|
||||||
master_volume: f32,
|
pub master_volume: f32,
|
||||||
listener: Listener,
|
pub listener: Listener,
|
||||||
|
|
||||||
mtm: AssetHandle<MusicTransitionManifest>,
|
mtm: AssetHandle<MusicTransitionManifest>,
|
||||||
}
|
}
|
||||||
@ -216,7 +218,11 @@ impl AudioFrontend {
|
|||||||
|
|
||||||
/// Function to play sfx from external places. Useful for UI and
|
/// Function to play sfx from external places. Useful for UI and
|
||||||
/// inventory events
|
/// inventory events
|
||||||
pub fn emit_sfx_item(&mut self, trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>, vol: Option<f32>) {
|
pub fn emit_sfx_item(
|
||||||
|
&mut self,
|
||||||
|
trigger_item: Option<(&SfxEvent, &SfxTriggerItem)>,
|
||||||
|
vol: Option<f32>,
|
||||||
|
) {
|
||||||
if let Some((event, item)) = trigger_item {
|
if let Some((event, item)) = trigger_item {
|
||||||
let sfx_file = match item.files.len() {
|
let sfx_file = match item.files.len() {
|
||||||
0 => {
|
0 => {
|
||||||
@ -371,29 +377,29 @@ impl AudioFrontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sets the volume of the channel with the given tag to the given volume
|
// sets the volume of the channel with the given tag to the given volume
|
||||||
fn set_ambient_volume(&mut self, channel_tag: AmbientChannelTag, volume_multiplier: f32) {
|
// fn set_ambient_volume(&mut self, channel_tag: AmbientChannelTag,
|
||||||
if self.audio_stream.is_some() {
|
// volume_multiplier: f32) { if self.audio_stream.is_some() {
|
||||||
let sfx_volume = self.get_sfx_volume();
|
// let sfx_volume = self.get_sfx_volume();
|
||||||
if let Some(channel) = self.get_ambient_channel(channel_tag) {
|
// if let Some(channel) = self.get_ambient_channel(channel_tag) {
|
||||||
channel.set_multiplier(volume_multiplier);
|
// channel.set_multiplier(volume_multiplier);
|
||||||
channel.set_volume(sfx_volume);
|
// channel.set_volume(sfx_volume);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// retrieves volume (pre-sfx-setting) of the channel with a given tag
|
// retrieves volume (pre-sfx-setting) of the channel with a given tag
|
||||||
fn get_ambient_volume(&mut self, channel_tag: AmbientChannelTag) -> f32 {
|
// fn get_ambient_volume(&mut self, channel_tag: AmbientChannelTag) -> f32 {
|
||||||
if self.audio_stream.is_some() {
|
// if self.audio_stream.is_some() {
|
||||||
if let Some(channel) = self.get_ambient_channel(channel_tag) {
|
// if let Some(channel) = self.get_ambient_channel(channel_tag) {
|
||||||
let channel_multiplier = channel.get_multiplier();
|
// let channel_multiplier = channel.get_multiplier();
|
||||||
channel_multiplier
|
// channel_multiplier
|
||||||
} else {
|
// } else {
|
||||||
0.0
|
// 0.0
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
0.0
|
// 0.0
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn play_music(&mut self, sound: &str, channel_tag: MusicChannelTag) {
|
fn play_music(&mut self, sound: &str, channel_tag: MusicChannelTag) {
|
||||||
if self.music_enabled() {
|
if self.music_enabled() {
|
||||||
|
@ -82,7 +82,7 @@
|
|||||||
|
|
||||||
mod event_mapper;
|
mod event_mapper;
|
||||||
|
|
||||||
use specs::{WorldExt};
|
use specs::WorldExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
audio::AudioFrontend,
|
audio::AudioFrontend,
|
||||||
|
@ -223,7 +223,10 @@ fn main() {
|
|||||||
// Setup audio
|
// Setup audio
|
||||||
let mut audio = match settings.audio.output {
|
let mut audio = match settings.audio.output {
|
||||||
AudioOutput::Off => AudioFrontend::no_audio(),
|
AudioOutput::Off => AudioFrontend::no_audio(),
|
||||||
AudioOutput::Automatic => AudioFrontend::new(settings.audio.num_sfx_channels, settings.audio.num_ui_channels),
|
AudioOutput::Automatic => AudioFrontend::new(
|
||||||
|
settings.audio.num_sfx_channels,
|
||||||
|
settings.audio.num_ui_channels,
|
||||||
|
),
|
||||||
// AudioOutput::Device(ref dev) => Some(dev.clone()),
|
// AudioOutput::Device(ref dev) => Some(dev.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,12 +19,7 @@ pub use self::{
|
|||||||
trail::TrailMgr,
|
trail::TrailMgr,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
audio::{
|
audio::{ambient, ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend},
|
||||||
ambient::{AmbientRainMgr, AmbientWindMgr},
|
|
||||||
music::MusicMgr,
|
|
||||||
sfx::SfxMgr,
|
|
||||||
AudioFrontend,
|
|
||||||
},
|
|
||||||
render::{
|
render::{
|
||||||
create_skybox_mesh, CloudsLocals, Consts, Drawer, GlobalModel, Globals, GlobalsBindGroup,
|
create_skybox_mesh, CloudsLocals, Consts, Drawer, GlobalModel, Globals, GlobalsBindGroup,
|
||||||
Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow, ShadowLocals,
|
Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow, ShadowLocals,
|
||||||
@ -107,8 +102,9 @@ pub struct Scene {
|
|||||||
figure_mgr: FigureMgr,
|
figure_mgr: FigureMgr,
|
||||||
pub sfx_mgr: SfxMgr,
|
pub sfx_mgr: SfxMgr,
|
||||||
music_mgr: MusicMgr,
|
music_mgr: MusicMgr,
|
||||||
ambient_wind_mgr: AmbientWindMgr,
|
ambient_mgr: AmbientMgr,
|
||||||
ambient_rain_mgr: AmbientRainMgr,
|
// ambient_wind_mgr: AmbientWindMgr,
|
||||||
|
// ambient_rain_mgr: AmbientRainMgr,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SceneData<'a> {
|
pub struct SceneData<'a> {
|
||||||
@ -320,8 +316,11 @@ impl Scene {
|
|||||||
figure_mgr: FigureMgr::new(renderer),
|
figure_mgr: FigureMgr::new(renderer),
|
||||||
sfx_mgr: SfxMgr::default(),
|
sfx_mgr: SfxMgr::default(),
|
||||||
music_mgr: MusicMgr::default(),
|
music_mgr: MusicMgr::default(),
|
||||||
ambient_wind_mgr: AmbientWindMgr::default(),
|
ambient_mgr: AmbientMgr {
|
||||||
ambient_rain_mgr: AmbientRainMgr::default(),
|
ambience: ambient::load_ambience_items(),
|
||||||
|
},
|
||||||
|
// ambient_wind_mgr: AmbientWindMgr::default(),
|
||||||
|
// ambient_rain_mgr: AmbientRainMgr::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,10 +413,10 @@ impl Scene {
|
|||||||
) {
|
) {
|
||||||
span!(_guard, "handle_outcome", "Scene::handle_outcome");
|
span!(_guard, "handle_outcome", "Scene::handle_outcome");
|
||||||
let underwater = state
|
let underwater = state
|
||||||
.terrain()
|
.terrain()
|
||||||
.get(cam_pos.map(|e| e.floor() as i32))
|
.get(cam_pos.map(|e| e.floor() as i32))
|
||||||
.map(|b| b.is_liquid())
|
.map(|b| b.is_liquid())
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
self.particle_mgr.handle_outcome(outcome, scene_data);
|
self.particle_mgr.handle_outcome(outcome, scene_data);
|
||||||
self.sfx_mgr
|
self.sfx_mgr
|
||||||
.handle_outcome(outcome, audio, scene_data.client, state, underwater);
|
.handle_outcome(outcome, audio, scene_data.client, state, underwater);
|
||||||
@ -1080,10 +1079,12 @@ impl Scene {
|
|||||||
client,
|
client,
|
||||||
);
|
);
|
||||||
self.music_mgr.maintain(audio, scene_data.state, client);
|
self.music_mgr.maintain(audio, scene_data.state, client);
|
||||||
self.ambient_wind_mgr
|
self.ambient_mgr
|
||||||
.maintain(audio, scene_data.state, client, &self.camera);
|
|
||||||
self.ambient_rain_mgr
|
|
||||||
.maintain(audio, scene_data.state, client, &self.camera);
|
.maintain(audio, scene_data.state, client, &self.camera);
|
||||||
|
// self.ambient_wind_mgr
|
||||||
|
// .maintain(audio, scene_data.state, client, &self.camera);
|
||||||
|
// self.ambient_rain_mgr
|
||||||
|
// .maintain(audio, scene_data.state, client, &self.camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
|
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
|
||||||
|
@ -245,7 +245,9 @@ impl SessionState {
|
|||||||
let sfx_triggers = self.scene.sfx_mgr.triggers.read();
|
let sfx_triggers = self.scene.sfx_mgr.triggers.read();
|
||||||
|
|
||||||
let sfx_trigger_item = sfx_triggers.get_key_value(&SfxEvent::from(&inv_event));
|
let sfx_trigger_item = sfx_triggers.get_key_value(&SfxEvent::from(&inv_event));
|
||||||
global_state.audio.emit_sfx_item(sfx_trigger_item, Some(1.0));
|
global_state
|
||||||
|
.audio
|
||||||
|
.emit_sfx_item(sfx_trigger_item, Some(1.0));
|
||||||
|
|
||||||
match inv_event {
|
match inv_event {
|
||||||
InventoryUpdateEvent::BlockCollectFailed { pos, reason } => {
|
InventoryUpdateEvent::BlockCollectFailed { pos, reason } => {
|
||||||
@ -1578,11 +1580,15 @@ impl PlayState for SessionState {
|
|||||||
&client,
|
&client,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Process outcomes from client
|
// Process outcomes from client
|
||||||
for outcome in outcomes {
|
for outcome in outcomes {
|
||||||
self.scene
|
self.scene.handle_outcome(
|
||||||
.handle_outcome(&outcome, &scene_data, &mut global_state.audio, &client.state(), cam_pos);
|
&outcome,
|
||||||
|
&scene_data,
|
||||||
|
&mut global_state.audio,
|
||||||
|
&client.state(),
|
||||||
|
cam_pos,
|
||||||
|
);
|
||||||
self.hud
|
self.hud
|
||||||
.handle_outcome(&outcome, scene_data.client, global_state);
|
.handle_outcome(&outcome, scene_data.client, global_state);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user