mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'audio-devices' into 'master'
Audio device selection Closes #105, #95, and #100 See merge request veloren/veloren!156 Former-commit-id: 59c6cb0bc5eab295985853a3945874d96db9e894
This commit is contained in:
commit
5636a5ac73
BIN
assets/voxygen/audio/soundtrack/field_grazing.ogg
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/soundtrack/field_grazing.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -1,3 +1,4 @@
|
|||||||
|
use crate::settings::AudioSettings;
|
||||||
use common::assets;
|
use common::assets;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rodio::{Decoder, Device, Source, SpatialSink};
|
use rodio::{Decoder, Device, Source, SpatialSink};
|
||||||
@ -5,6 +6,7 @@ use std::{
|
|||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::BufReader,
|
io::BufReader,
|
||||||
|
iter::{Filter, Iterator},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::mpsc::{channel, Receiver, Sender, TryRecvError},
|
sync::mpsc::{channel, Receiver, Sender, TryRecvError},
|
||||||
thread,
|
thread,
|
||||||
@ -15,30 +17,31 @@ use vek::*;
|
|||||||
|
|
||||||
pub struct AudioFrontend {
|
pub struct AudioFrontend {
|
||||||
device: Device,
|
device: Device,
|
||||||
|
// Performance optimisation, iterating through available audio devices takes time
|
||||||
|
devices: Vec<Device>,
|
||||||
// streams: HashMap<String, SpatialSink>, //always use SpatialSink even if no possition is used for now
|
// streams: HashMap<String, SpatialSink>, //always use SpatialSink even if no possition is used for now
|
||||||
stream: SpatialSink,
|
stream: SpatialSink,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioFrontend {
|
impl AudioFrontend {
|
||||||
pub fn new() -> Self {
|
pub fn new(settings: &AudioSettings) -> Self {
|
||||||
let mut device = rodio::default_output_device().unwrap();
|
let mut device = match &settings.audio_device {
|
||||||
|
Some(dev) => rodio::output_devices()
|
||||||
for d in rodio::devices() {
|
.find(|x| &x.name() == dev)
|
||||||
if d.name().contains("jack") {
|
.or_else(rodio::default_output_device)
|
||||||
continue;
|
.expect("No Audio devices found"),
|
||||||
}
|
None => rodio::default_output_device().expect("No audio devices found"),
|
||||||
|
};
|
||||||
device = d;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut sink =
|
let mut sink =
|
||||||
rodio::SpatialSink::new(&device, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]);
|
rodio::SpatialSink::new(&device, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]);
|
||||||
|
sink.set_volume(settings.music_volume);
|
||||||
|
|
||||||
AudioFrontend {
|
AudioFrontend {
|
||||||
device,
|
device,
|
||||||
// streams: HashMap::<String, SpatialSink>::new(),
|
// streams: HashMap::<String, SpatialSink>::new(),
|
||||||
stream: sink,
|
stream: sink,
|
||||||
|
devices: AudioFrontend::list_devices_raw(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,27 +49,20 @@ impl AudioFrontend {
|
|||||||
let bufreader = assets::load_from_path(path).unwrap();
|
let bufreader = assets::load_from_path(path).unwrap();
|
||||||
let src = Decoder::new(bufreader).unwrap();
|
let src = Decoder::new(bufreader).unwrap();
|
||||||
|
|
||||||
let mut sink = rodio::SpatialSink::new(
|
// TODO: stop previous audio from playing. Sink has this ability, but
|
||||||
&self.device,
|
// SpatialSink does not for some reason. This means that we will
|
||||||
[0.0, 0.0, 0.0],
|
// probably want to use sinks for music, and SpatialSink for sfx.
|
||||||
[1.0, 0.0, 0.0],
|
self.stream.append(src);
|
||||||
[-1.0, 0.0, 0.0],
|
|
||||||
);
|
|
||||||
|
|
||||||
sink.append(src);
|
|
||||||
|
|
||||||
// self.streams.insert(path.to_string(), sink);
|
|
||||||
self.stream = sink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maintain(&mut self) {
|
pub fn maintain(&mut self) {
|
||||||
let music = [
|
let music = [
|
||||||
"voxygen/audio/soundtrack/Ethereal_Bonds.ogg",
|
"voxygen/audio/soundtrack/Ethereal_Bonds.ogg",
|
||||||
"voxygen/audio/soundtrack/Field_Grazing.mp3",
|
"voxygen/audio/soundtrack/field_grazing.ogg",
|
||||||
"voxygen/audio/soundtrack/fiesta_del_pueblo.ogg",
|
"voxygen/audio/soundtrack/fiesta_del_pueblo.ogg",
|
||||||
"voxygen/audio/soundtrack/library_theme_with_harpsichord.ogg",
|
"voxygen/audio/soundtrack/library_theme_with_harpsichord.ogg",
|
||||||
"voxygen/audio/soundtrack/Mineral_Deposits.ogg",
|
"voxygen/audio/soundtrack/Mineral_Deposits.ogg",
|
||||||
"voxygen/audio/soundtrack/Ruination.ogg",
|
//"voxygen/audio/soundtrack/Ruination.ogg",
|
||||||
"voxygen/audio/soundtrack/sacred_temple.ogg",
|
"voxygen/audio/soundtrack/sacred_temple.ogg",
|
||||||
"voxygen/audio/soundtrack/Snowtop.ogg",
|
"voxygen/audio/soundtrack/Snowtop.ogg",
|
||||||
"voxygen/audio/soundtrack/veloren_title_tune-3.ogg",
|
"voxygen/audio/soundtrack/veloren_title_tune-3.ogg",
|
||||||
@ -80,4 +76,49 @@ impl AudioFrontend {
|
|||||||
pub fn set_volume(&mut self, volume: f32) {
|
pub fn set_volume(&mut self, volume: f32) {
|
||||||
self.stream.set_volume(volume.min(1.0).max(0.0))
|
self.stream.set_volume(volume.min(1.0).max(0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a vec of the audio devices available.
|
||||||
|
/// Does not return rodio Device struct in case our audio backend changes.
|
||||||
|
pub fn list_device_names(&self) -> Vec<String> {
|
||||||
|
self.devices.iter().map(|x| x.name()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns vec of devices
|
||||||
|
fn list_devices_raw() -> Vec<Device> {
|
||||||
|
rodio::output_devices().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Caches vec of devices for later reference
|
||||||
|
fn maintain_devices(&mut self) {
|
||||||
|
self.devices = AudioFrontend::list_devices_raw()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the default audio device.
|
||||||
|
/// Does not return rodio Device struct in case our audio backend changes.
|
||||||
|
pub fn get_default_device() -> String {
|
||||||
|
rodio::default_output_device()
|
||||||
|
.expect("No audio output devices detected.")
|
||||||
|
.name()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the name of the current audio device.
|
||||||
|
/// Does not return rodio Device struct in case our audio backend changes.
|
||||||
|
pub fn get_device_name(&self) -> String {
|
||||||
|
self.device.name()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the current audio device from a string.
|
||||||
|
/// Does not use the rodio Device struct in case that detail changes.
|
||||||
|
/// If the string is an invalid audio device, then no change is made.
|
||||||
|
pub fn set_device(&mut self, name: String) {
|
||||||
|
if let Some(dev) = rodio::output_devices().find(|x| x.name() == name) {
|
||||||
|
self.device = dev;
|
||||||
|
self.stream = rodio::SpatialSink::new(
|
||||||
|
&self.device,
|
||||||
|
[0.0, 0.0, 0.0],
|
||||||
|
[1.0, 0.0, 0.0],
|
||||||
|
[-1.0, 0.0, 0.0],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ pub enum Event {
|
|||||||
SendMessage(String),
|
SendMessage(String),
|
||||||
AdjustViewDistance(u32),
|
AdjustViewDistance(u32),
|
||||||
AdjustVolume(f32),
|
AdjustVolume(f32),
|
||||||
|
ChangeAudioDevice(String),
|
||||||
Logout,
|
Logout,
|
||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
@ -207,15 +208,11 @@ pub struct Hud {
|
|||||||
inventory_space: u32,
|
inventory_space: u32,
|
||||||
show: Show,
|
show: Show,
|
||||||
to_focus: Option<Option<widget::Id>>,
|
to_focus: Option<Option<widget::Id>>,
|
||||||
settings: Settings,
|
|
||||||
force_ungrab: bool,
|
force_ungrab: bool,
|
||||||
// TODO: move to settings
|
|
||||||
current_vd: u32,
|
|
||||||
current_volume: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hud {
|
impl Hud {
|
||||||
pub fn new(window: &mut Window, settings: Settings) -> Self {
|
pub fn new(window: &mut Window) -> Self {
|
||||||
let mut ui = Ui::new(window).unwrap();
|
let mut ui = Ui::new(window).unwrap();
|
||||||
// TODO: Adjust/remove this, right now it is used to demonstrate window scaling functionality.
|
// TODO: Adjust/remove this, right now it is used to demonstrate window scaling functionality.
|
||||||
ui.scaling_mode(ScaleMode::RelativeToWindow([1920.0, 1080.0].into()));
|
ui.scaling_mode(ScaleMode::RelativeToWindow([1920.0, 1080.0].into()));
|
||||||
@ -246,14 +243,11 @@ impl Hud {
|
|||||||
want_grab: true,
|
want_grab: true,
|
||||||
},
|
},
|
||||||
to_focus: None,
|
to_focus: None,
|
||||||
settings,
|
|
||||||
force_ungrab: false,
|
force_ungrab: false,
|
||||||
current_vd: 5,
|
|
||||||
current_volume: 0.5,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_layout(&mut self, tps: f64) -> Vec<Event> {
|
fn update_layout(&mut self, tps: f64, global_state: &GlobalState) -> Vec<Event> {
|
||||||
let mut events = Vec::new();
|
let mut events = Vec::new();
|
||||||
let ref mut ui_widgets = self.ui.set_widgets();
|
let ref mut ui_widgets = self.ui.set_widgets();
|
||||||
let version = env!("CARGO_PKG_VERSION");
|
let version = env!("CARGO_PKG_VERSION");
|
||||||
@ -302,7 +296,7 @@ impl Hud {
|
|||||||
.top_left_with_margins_on(ui_widgets.window, 3.0, 3.0)
|
.top_left_with_margins_on(ui_widgets.window, 3.0, 3.0)
|
||||||
.w_h(300.0, 190.0)
|
.w_h(300.0, 190.0)
|
||||||
.set(self.ids.help_bg, ui_widgets);
|
.set(self.ids.help_bg, ui_widgets);
|
||||||
Text::new(get_help_text(&self.settings.controls).as_str())
|
Text::new(get_help_text(&global_state.settings.controls).as_str())
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.top_left_with_margins_on(self.ids.help_bg, 20.0, 20.0)
|
.top_left_with_margins_on(self.ids.help_bg, 20.0, 20.0)
|
||||||
.font_id(self.fonts.opensans)
|
.font_id(self.fonts.opensans)
|
||||||
@ -379,14 +373,8 @@ impl Hud {
|
|||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
if let Windows::Settings = self.show.open_windows {
|
if let Windows::Settings = self.show.open_windows {
|
||||||
for event in SettingsWindow::new(
|
for event in SettingsWindow::new(&self.show, &self.imgs, &self.fonts, &global_state)
|
||||||
&self.show,
|
.set(self.ids.settings_window, ui_widgets)
|
||||||
&self.imgs,
|
|
||||||
&self.fonts,
|
|
||||||
self.current_vd,
|
|
||||||
self.current_volume,
|
|
||||||
)
|
|
||||||
.set(self.ids.settings_window, ui_widgets)
|
|
||||||
{
|
{
|
||||||
match event {
|
match event {
|
||||||
settings_window::Event::ToggleHelp => self.show.toggle_help(),
|
settings_window::Event::ToggleHelp => self.show.toggle_help(),
|
||||||
@ -396,13 +384,14 @@ impl Hud {
|
|||||||
settings_window::Event::ToggleDebug => self.show.debug = !self.show.debug,
|
settings_window::Event::ToggleDebug => self.show.debug = !self.show.debug,
|
||||||
settings_window::Event::Close => self.show.open_windows = Windows::None,
|
settings_window::Event::Close => self.show.open_windows = Windows::None,
|
||||||
settings_window::Event::AdjustViewDistance(view_distance) => {
|
settings_window::Event::AdjustViewDistance(view_distance) => {
|
||||||
self.current_vd = view_distance;
|
|
||||||
events.push(Event::AdjustViewDistance(view_distance));
|
events.push(Event::AdjustViewDistance(view_distance));
|
||||||
}
|
}
|
||||||
settings_window::Event::AdjustVolume(volume) => {
|
settings_window::Event::AdjustVolume(volume) => {
|
||||||
self.current_volume = volume;
|
|
||||||
events.push(Event::AdjustVolume(volume));
|
events.push(Event::AdjustVolume(volume));
|
||||||
}
|
}
|
||||||
|
settings_window::Event::ChangeAudioDevice(name) => {
|
||||||
|
events.push(Event::ChangeAudioDevice(name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,10 +472,6 @@ impl Hud {
|
|||||||
pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool {
|
pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool {
|
||||||
let cursor_grabbed = global_state.window.is_cursor_grabbed();
|
let cursor_grabbed = global_state.window.is_cursor_grabbed();
|
||||||
let handled = match event {
|
let handled = match event {
|
||||||
WinEvent::SettingsChanged => {
|
|
||||||
self.settings = global_state.settings.clone();
|
|
||||||
false
|
|
||||||
}
|
|
||||||
WinEvent::Ui(event) => {
|
WinEvent::Ui(event) => {
|
||||||
if (self.typing() && event.is_keyboard() && self.show.ui)
|
if (self.typing() && event.is_keyboard() && self.show.ui)
|
||||||
|| !(cursor_grabbed && event.is_keyboard_or_mouse())
|
|| !(cursor_grabbed && event.is_keyboard_or_mouse())
|
||||||
@ -581,12 +566,12 @@ impl Hud {
|
|||||||
handled
|
handled
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maintain(&mut self, renderer: &mut Renderer, tps: f64) -> Vec<Event> {
|
pub fn maintain(&mut self, global_state: &mut GlobalState, tps: f64) -> Vec<Event> {
|
||||||
if let Some(maybe_id) = self.to_focus.take() {
|
if let Some(maybe_id) = self.to_focus.take() {
|
||||||
self.ui.focus_widget(maybe_id);
|
self.ui.focus_widget(maybe_id);
|
||||||
}
|
}
|
||||||
let events = self.update_layout(tps);
|
let events = self.update_layout(tps, &global_state);
|
||||||
self.ui.maintain(renderer);
|
self.ui.maintain(&mut global_state.window.renderer_mut());
|
||||||
events
|
events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,11 @@ use crate::{
|
|||||||
ImageSlider, ScaleMode, ToggleButton, Ui,
|
ImageSlider, ScaleMode, ToggleButton, Ui,
|
||||||
},
|
},
|
||||||
window::Window,
|
window::Window,
|
||||||
|
AudioFrontend, GlobalState,
|
||||||
};
|
};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color,
|
color,
|
||||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
widget::{self, Button, DropDownList, Image, List, Rectangle, Scrollbar, Text},
|
||||||
widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
widget_ids! {
|
widget_ids! {
|
||||||
@ -45,6 +46,8 @@ widget_ids! {
|
|||||||
vd_slider_text,
|
vd_slider_text,
|
||||||
audio_volume_slider,
|
audio_volume_slider,
|
||||||
audio_volume_text,
|
audio_volume_text,
|
||||||
|
audio_device_list,
|
||||||
|
audio_device_text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +66,7 @@ pub struct SettingsWindow<'a> {
|
|||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
|
|
||||||
current_vd: u32,
|
global_state: &'a GlobalState,
|
||||||
current_volume: f32,
|
|
||||||
|
|
||||||
#[conrod(common_builder)]
|
#[conrod(common_builder)]
|
||||||
common: widget::CommonBuilder,
|
common: widget::CommonBuilder,
|
||||||
@ -75,15 +77,13 @@ impl<'a> SettingsWindow<'a> {
|
|||||||
show: &'a Show,
|
show: &'a Show,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
current_vd: u32,
|
global_state: &'a GlobalState,
|
||||||
current_volume: f32,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
show,
|
show,
|
||||||
imgs,
|
imgs,
|
||||||
fonts,
|
fonts,
|
||||||
current_vd,
|
global_state,
|
||||||
current_volume,
|
|
||||||
common: widget::CommonBuilder::default(),
|
common: widget::CommonBuilder::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,6 +102,7 @@ pub enum Event {
|
|||||||
Close,
|
Close,
|
||||||
AdjustViewDistance(u32),
|
AdjustViewDistance(u32),
|
||||||
AdjustVolume(f32),
|
AdjustVolume(f32),
|
||||||
|
ChangeAudioDevice(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Widget for SettingsWindow<'a> {
|
impl<'a> Widget for SettingsWindow<'a> {
|
||||||
@ -490,7 +491,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
.set(state.ids.vd_slider_text, ui);
|
.set(state.ids.vd_slider_text, ui);
|
||||||
|
|
||||||
if let Some(new_val) = ImageSlider::discrete(
|
if let Some(new_val) = ImageSlider::discrete(
|
||||||
self.current_vd,
|
self.global_state.settings.graphics.view_distance,
|
||||||
1,
|
1,
|
||||||
25,
|
25,
|
||||||
self.imgs.slider_indicator,
|
self.imgs.slider_indicator,
|
||||||
@ -535,6 +536,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
}
|
}
|
||||||
// Contents
|
// Contents
|
||||||
if let SettingsTab::Sound = state.settings_tab {
|
if let SettingsTab::Sound = state.settings_tab {
|
||||||
|
// Volume Slider ----------------------------------------------------
|
||||||
Text::new("Volume")
|
Text::new("Volume")
|
||||||
.top_left_with_margins_on(state.ids.settings_content, 10.0, 10.0)
|
.top_left_with_margins_on(state.ids.settings_content, 10.0, 10.0)
|
||||||
.font_size(14)
|
.font_size(14)
|
||||||
@ -543,7 +545,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
.set(state.ids.audio_volume_text, ui);
|
.set(state.ids.audio_volume_text, ui);
|
||||||
|
|
||||||
if let Some(new_val) = ImageSlider::continuous(
|
if let Some(new_val) = ImageSlider::continuous(
|
||||||
self.current_volume,
|
self.global_state.settings.audio.music_volume,
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0,
|
||||||
self.imgs.slider_indicator,
|
self.imgs.slider_indicator,
|
||||||
@ -558,6 +560,29 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
{
|
{
|
||||||
events.push(Event::AdjustVolume(new_val));
|
events.push(Event::AdjustVolume(new_val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Audio Device Selector --------------------------------------------
|
||||||
|
let device = self.global_state.audio.get_device_name();
|
||||||
|
let device_list = self.global_state.audio.list_device_names();
|
||||||
|
Text::new("Volume")
|
||||||
|
.down_from(state.ids.audio_volume_slider, 10.0)
|
||||||
|
.font_size(14)
|
||||||
|
.font_id(self.fonts.opensans)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.audio_device_text, ui);
|
||||||
|
|
||||||
|
// Get which device is currently selected
|
||||||
|
let selected = device_list.iter().position(|x| x.contains(&device));
|
||||||
|
|
||||||
|
if let Some(clicked) = DropDownList::new(&device_list, selected)
|
||||||
|
.w_h(400.0, 22.0)
|
||||||
|
.down_from(state.ids.audio_device_text, 10.0)
|
||||||
|
.label_font_id(self.fonts.opensans)
|
||||||
|
.set(state.ids.audio_device_list, ui)
|
||||||
|
{
|
||||||
|
let new_val = device_list[clicked].clone();
|
||||||
|
events.push(Event::ChangeAudioDevice(new_val));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
events
|
events
|
||||||
|
@ -79,7 +79,7 @@ pub trait PlayState {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Set up the global state.
|
// Set up the global state.
|
||||||
let settings = Settings::load();
|
let mut settings = Settings::load();
|
||||||
let window = Window::new(&settings).expect("Failed to create window!");
|
let window = Window::new(&settings).expect("Failed to create window!");
|
||||||
|
|
||||||
// Initialize logging.
|
// Initialize logging.
|
||||||
@ -159,15 +159,15 @@ fn main() {
|
|||||||
default_hook(panic_info);
|
default_hook(panic_info);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut global_state = GlobalState {
|
if settings.audio.audio_device == None {
|
||||||
settings,
|
settings.audio.audio_device = Some(AudioFrontend::get_default_device());
|
||||||
window,
|
}
|
||||||
audio: AudioFrontend::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Remove this when the volume setting can be saved
|
let mut global_state = GlobalState {
|
||||||
// Lower the volume to 50%
|
audio: AudioFrontend::new(&settings.audio),
|
||||||
global_state.audio.set_volume(0.5);
|
window,
|
||||||
|
settings,
|
||||||
|
};
|
||||||
|
|
||||||
// Set up the initial play state.
|
// Set up the initial play state.
|
||||||
let mut states: Vec<Box<dyn PlayState>> = vec![Box::new(MainMenuState::new(&mut global_state))];
|
let mut states: Vec<Box<dyn PlayState>> = vec![Box::new(MainMenuState::new(&mut global_state))];
|
||||||
|
@ -32,7 +32,7 @@ impl SessionState {
|
|||||||
scene,
|
scene,
|
||||||
client,
|
client,
|
||||||
key_state: KeyState::new(),
|
key_state: KeyState::new(),
|
||||||
hud: Hud::new(window, settings),
|
hud: Hud::new(window),
|
||||||
input_events: Vec::new(),
|
input_events: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,14 +173,11 @@ impl PlayState for SessionState {
|
|||||||
// Maintain the scene.
|
// Maintain the scene.
|
||||||
self.scene.maintain(
|
self.scene.maintain(
|
||||||
global_state.window.renderer_mut(),
|
global_state.window.renderer_mut(),
|
||||||
&mut self.client.borrow_mut(),
|
&self.client.borrow_mut(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Maintain the UI.
|
// Maintain the UI.
|
||||||
for event in self
|
for event in self.hud.maintain(global_state, clock.get_tps()) {
|
||||||
.hud
|
|
||||||
.maintain(global_state.window.renderer_mut(), clock.get_tps())
|
|
||||||
{
|
|
||||||
match event {
|
match event {
|
||||||
HudEvent::SendMessage(msg) => {
|
HudEvent::SendMessage(msg) => {
|
||||||
// TODO: Handle result
|
// TODO: Handle result
|
||||||
@ -191,10 +188,22 @@ impl PlayState for SessionState {
|
|||||||
return PlayStateResult::Shutdown;
|
return PlayStateResult::Shutdown;
|
||||||
}
|
}
|
||||||
HudEvent::AdjustViewDistance(view_distance) => {
|
HudEvent::AdjustViewDistance(view_distance) => {
|
||||||
self.client.borrow_mut().set_view_distance(view_distance)
|
self.client.borrow_mut().set_view_distance(view_distance);
|
||||||
|
|
||||||
|
global_state.settings.graphics.view_distance = view_distance;
|
||||||
|
global_state.settings.save_to_file();
|
||||||
}
|
}
|
||||||
HudEvent::AdjustVolume(volume) => {
|
HudEvent::AdjustVolume(volume) => {
|
||||||
global_state.audio.set_volume(volume);
|
global_state.audio.set_volume(volume);
|
||||||
|
|
||||||
|
global_state.settings.audio.music_volume = volume;
|
||||||
|
global_state.settings.save_to_file();
|
||||||
|
}
|
||||||
|
HudEvent::ChangeAudioDevice(name) => {
|
||||||
|
global_state.audio.set_device(name.clone());
|
||||||
|
|
||||||
|
global_state.settings.audio.audio_device = Some(name);
|
||||||
|
global_state.settings.save_to_file();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ pub struct Settings {
|
|||||||
pub controls: ControlSettings,
|
pub controls: ControlSettings,
|
||||||
pub networking: NetworkingSettings,
|
pub networking: NetworkingSettings,
|
||||||
pub log: Log,
|
pub log: Log,
|
||||||
|
pub graphics: GraphicsSettings,
|
||||||
|
pub audio: AudioSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ControlSettings` contains keybindings.
|
/// `ControlSettings` contains keybindings.
|
||||||
@ -52,6 +54,22 @@ pub struct Log {
|
|||||||
pub file: PathBuf,
|
pub file: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct GraphicsSettings {
|
||||||
|
pub view_distance: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// AudioSettings controls the volume of different audio subsystems and which
|
||||||
|
/// device is used.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct AudioSettings {
|
||||||
|
pub music_volume: f32,
|
||||||
|
pub sfx_volume: f32,
|
||||||
|
|
||||||
|
/// Audio Device that Voxygen will use to play audio.
|
||||||
|
pub audio_device: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Settings {
|
Settings {
|
||||||
@ -86,6 +104,12 @@ impl Default for Settings {
|
|||||||
log: Log {
|
log: Log {
|
||||||
file: "voxygen.log".into(),
|
file: "voxygen.log".into(),
|
||||||
},
|
},
|
||||||
|
graphics: GraphicsSettings { view_distance: 5 },
|
||||||
|
audio: AudioSettings {
|
||||||
|
music_volume: 0.5,
|
||||||
|
sfx_volume: 0.5,
|
||||||
|
audio_device: None,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user