mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'midge/mouse-sensitivity' into 'master'
Better Settings Closes #142 and #132 See merge request veloren/veloren!216
This commit is contained in:
commit
9783ff56e8
@ -3,7 +3,7 @@ use common::{clock::Clock, comp};
|
||||
use log::{error, info};
|
||||
use std::time::Duration;
|
||||
|
||||
const FPS: u64 = 60;
|
||||
const TPS: u64 = 10; // Low value is okay, just reading messages.
|
||||
|
||||
fn main() {
|
||||
// Initialize logging.
|
||||
@ -48,6 +48,6 @@ fn main() {
|
||||
client.cleanup();
|
||||
|
||||
// Wait for the next tick.
|
||||
clock.tick(Duration::from_millis(1000 / FPS));
|
||||
clock.tick(Duration::from_millis(1000 / TPS));
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,25 @@
|
||||
use std::{
|
||||
thread,
|
||||
time::{Duration, SystemTime},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
const CLOCK_SMOOTHING: f64 = 0.9;
|
||||
|
||||
pub struct Clock {
|
||||
last_sys_time: SystemTime,
|
||||
last_sys_time: Instant,
|
||||
last_delta: Option<Duration>,
|
||||
running_tps_average: f64,
|
||||
compensation: f64,
|
||||
}
|
||||
|
||||
impl Clock {
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
last_sys_time: SystemTime::now(),
|
||||
last_sys_time: Instant::now(),
|
||||
last_delta: None,
|
||||
running_tps_average: 0.0,
|
||||
compensation: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,27 +40,25 @@ impl Clock {
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn tick(&mut self, tgt: Duration) {
|
||||
let delta = SystemTime::now()
|
||||
.duration_since(self.last_sys_time)
|
||||
.expect("Time went backwards!");
|
||||
let delta = Instant::now().duration_since(self.last_sys_time);
|
||||
|
||||
// Attempt to sleep to fill the gap.
|
||||
if let Some(sleep_dur) = tgt.checked_sub(delta) {
|
||||
let adjustment = if self.running_tps_average == 0.0 {
|
||||
1.0
|
||||
} else {
|
||||
tgt.as_secs_f64() / self.running_tps_average
|
||||
};
|
||||
thread::sleep(Duration::from_secs_f64(
|
||||
sleep_dur.as_secs_f64() * adjustment,
|
||||
));
|
||||
if self.running_tps_average != 0.0 {
|
||||
self.compensation =
|
||||
(self.compensation + (tgt.as_secs_f64() / self.running_tps_average) - 1.0)
|
||||
.max(0.0)
|
||||
}
|
||||
|
||||
let sleep_secs = sleep_dur.as_secs_f64() * self.compensation;
|
||||
if sleep_secs > 0.0 {
|
||||
thread::sleep(Duration::from_secs_f64(sleep_secs));
|
||||
}
|
||||
}
|
||||
|
||||
let delta = SystemTime::now()
|
||||
.duration_since(self.last_sys_time)
|
||||
.expect("Time went backwards!");
|
||||
let delta = Instant::now().duration_since(self.last_sys_time);
|
||||
|
||||
self.last_sys_time = SystemTime::now();
|
||||
self.last_sys_time = Instant::now();
|
||||
self.last_delta = Some(delta);
|
||||
self.running_tps_average = if self.running_tps_average == 0.0 {
|
||||
delta.as_secs_f64()
|
||||
|
@ -108,9 +108,12 @@ pub struct DebugInfo {
|
||||
|
||||
pub enum Event {
|
||||
SendMessage(String),
|
||||
AdjustMousePan(u32),
|
||||
AdjustMouseZoom(u32),
|
||||
AdjustViewDistance(u32),
|
||||
AdjustVolume(f32),
|
||||
ChangeAudioDevice(String),
|
||||
ChangeMaxFPS(u32),
|
||||
CharacterSelection,
|
||||
Logout,
|
||||
Quit,
|
||||
@ -567,12 +570,21 @@ impl Hud {
|
||||
settings_window::Event::ToggleDebug => self.show.debug = !self.show.debug,
|
||||
settings_window::Event::ChangeTab(tab) => self.show.open_setting_tab(tab),
|
||||
settings_window::Event::Close => self.show.settings(false),
|
||||
settings_window::Event::AdjustMousePan(sensitivity) => {
|
||||
events.push(Event::AdjustMousePan(sensitivity));
|
||||
}
|
||||
settings_window::Event::AdjustMouseZoom(sensitivity) => {
|
||||
events.push(Event::AdjustMouseZoom(sensitivity));
|
||||
}
|
||||
settings_window::Event::AdjustViewDistance(view_distance) => {
|
||||
events.push(Event::AdjustViewDistance(view_distance));
|
||||
}
|
||||
settings_window::Event::AdjustVolume(volume) => {
|
||||
events.push(Event::AdjustVolume(volume));
|
||||
}
|
||||
settings_window::Event::MaximumFPS(max_fps) => {
|
||||
events.push(Event::ChangeMaxFPS(max_fps));
|
||||
}
|
||||
settings_window::Event::ChangeAudioDevice(name) => {
|
||||
events.push(Event::ChangeAudioDevice(name));
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ use conrod_core::{
|
||||
widget::{self, Button, DropDownList, Image, Rectangle, Scrollbar, Text},
|
||||
widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
|
||||
const FPS_CHOICES: [u32; 11] = [15, 30, 40, 50, 60, 90, 120, 144, 240, 300, 500];
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
settings_content,
|
||||
@ -31,12 +34,22 @@ widget_ids! {
|
||||
interface,
|
||||
inventory_test_button,
|
||||
inventory_test_button_label,
|
||||
mouse_pan_slider,
|
||||
mouse_pan_label,
|
||||
mouse_pan_value,
|
||||
mouse_zoom_slider,
|
||||
mouse_zoom_label,
|
||||
mouse_zoom_value,
|
||||
settings_bg,
|
||||
sound,
|
||||
test,
|
||||
video,
|
||||
vd_slider,
|
||||
vd_slider_text,
|
||||
vd_text,
|
||||
vd_value,
|
||||
max_fps_slider,
|
||||
max_fps_text,
|
||||
max_fps_value,
|
||||
audio_volume_slider,
|
||||
audio_volume_text,
|
||||
audio_device_list,
|
||||
@ -92,9 +105,12 @@ pub enum Event {
|
||||
ToggleDebug,
|
||||
ChangeTab(SettingsTab),
|
||||
Close,
|
||||
AdjustMousePan(u32),
|
||||
AdjustMouseZoom(u32),
|
||||
AdjustViewDistance(u32),
|
||||
AdjustVolume(f32),
|
||||
ChangeAudioDevice(String),
|
||||
MaximumFPS(u32),
|
||||
}
|
||||
|
||||
impl<'a> Widget for SettingsWindow<'a> {
|
||||
@ -160,7 +176,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.settings_title, ui);
|
||||
|
||||
// Interface
|
||||
// 1) Interface Tab -------------------------------
|
||||
if Button::image(if let SettingsTab::Interface = self.show.settings_tab {
|
||||
self.imgs.settings_button_pressed
|
||||
} else {
|
||||
@ -187,6 +203,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
events.push(Event::ChangeTab(SettingsTab::Interface));
|
||||
}
|
||||
|
||||
// Contents
|
||||
if let SettingsTab::Interface = self.show.settings_tab {
|
||||
// Help
|
||||
let show_help =
|
||||
@ -255,7 +272,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.set(state.ids.debug_button_label, ui);
|
||||
}
|
||||
|
||||
// 2 Gameplay
|
||||
// 2) Gameplay Tab --------------------------------
|
||||
if Button::image(if let SettingsTab::Gameplay = self.show.settings_tab {
|
||||
self.imgs.settings_button_pressed
|
||||
} else {
|
||||
@ -282,7 +299,77 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
events.push(Event::ChangeTab(SettingsTab::Gameplay));
|
||||
}
|
||||
|
||||
// 3 Controls
|
||||
// Contents
|
||||
if let SettingsTab::Gameplay = self.show.settings_tab {
|
||||
let display_pan = self.global_state.settings.gameplay.pan_sensitivity;
|
||||
let display_zoom = self.global_state.settings.gameplay.zoom_sensitivity;
|
||||
|
||||
// Mouse Pan Sensitivity
|
||||
Text::new("Pan Sensitivity")
|
||||
.top_left_with_margins_on(state.ids.settings_content, 10.0, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_pan_label, ui);
|
||||
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
display_pan,
|
||||
1,
|
||||
200,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(550.0, 22.0)
|
||||
.down_from(state.ids.mouse_pan_label, 10.0)
|
||||
.track_breadth(30.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.mouse_pan_slider, ui)
|
||||
{
|
||||
events.push(Event::AdjustMousePan(new_val));
|
||||
}
|
||||
|
||||
Text::new(&format!("{}", display_pan))
|
||||
.right_from(state.ids.mouse_pan_slider, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_pan_value, ui);
|
||||
|
||||
// Mouse Zoom Sensitivity
|
||||
Text::new("Zoom Sensitivity")
|
||||
.down_from(state.ids.mouse_pan_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_zoom_label, ui);
|
||||
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
display_zoom,
|
||||
1,
|
||||
200,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(550.0, 22.0)
|
||||
.down_from(state.ids.mouse_zoom_label, 10.0)
|
||||
.track_breadth(30.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.mouse_zoom_slider, ui)
|
||||
{
|
||||
events.push(Event::AdjustMouseZoom(new_val));
|
||||
}
|
||||
|
||||
Text::new(&format!("{}", display_zoom))
|
||||
.right_from(state.ids.mouse_zoom_slider, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_zoom_value, ui);
|
||||
}
|
||||
|
||||
// 3) Controls Tab --------------------------------
|
||||
if Button::image(if let SettingsTab::Controls = self.show.settings_tab {
|
||||
self.imgs.settings_button_pressed
|
||||
} else {
|
||||
@ -308,6 +395,8 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::ChangeTab(SettingsTab::Controls));
|
||||
}
|
||||
|
||||
// Contents
|
||||
if let SettingsTab::Controls = self.show.settings_tab {
|
||||
Text::new(
|
||||
"Free Cursor\n\
|
||||
@ -376,7 +465,6 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
/tp [Name] - Teleports you to another player \n\
|
||||
/jump <dx> <dy> <dz> - Offset your position \n\
|
||||
/goto <x> <y> <z> - Teleport to a position \n\
|
||||
/tp <name> - Teleport to another player \n\
|
||||
/kill - Kill yourself \n\
|
||||
/pig - Spawn pig NPC \n\
|
||||
/wolf - Spawn wolf NPC \n\
|
||||
@ -462,7 +550,8 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.font_size(18)
|
||||
.set(state.ids.controls_controls, ui);
|
||||
}
|
||||
// 4 Video
|
||||
|
||||
// 4) Video Tab -----------------------------------
|
||||
if Button::image(if let SettingsTab::Video = self.show.settings_tab {
|
||||
self.imgs.settings_button_pressed
|
||||
} else {
|
||||
@ -489,14 +578,16 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::ChangeTab(SettingsTab::Video));
|
||||
}
|
||||
|
||||
// Contents
|
||||
if let SettingsTab::Video = self.show.settings_tab {
|
||||
// View Distance
|
||||
Text::new("View Distance")
|
||||
.top_left_with_margins_on(state.ids.settings_content, 10.0, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.vd_slider_text, ui);
|
||||
.set(state.ids.vd_text, ui);
|
||||
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
self.global_state.settings.graphics.view_distance,
|
||||
@ -506,7 +597,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.down_from(state.ids.vd_slider_text, 10.0)
|
||||
.down_from(state.ids.vd_text, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
@ -514,8 +605,54 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::AdjustViewDistance(new_val));
|
||||
}
|
||||
|
||||
Text::new(&format!(
|
||||
"{}",
|
||||
self.global_state.settings.graphics.view_distance
|
||||
))
|
||||
.right_from(state.ids.vd_slider, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.vd_value, ui);
|
||||
|
||||
// Max FPS
|
||||
Text::new("Maximum FPS")
|
||||
.down_from(state.ids.vd_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.max_fps_text, ui);
|
||||
|
||||
if let Some(which) = ImageSlider::discrete(
|
||||
FPS_CHOICES
|
||||
.iter()
|
||||
.position(|&x| x == self.global_state.settings.graphics.max_fps)
|
||||
.unwrap_or(5),
|
||||
0,
|
||||
10,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.down_from(state.ids.max_fps_text, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.max_fps_slider, ui)
|
||||
{
|
||||
events.push(Event::MaximumFPS(FPS_CHOICES[which]));
|
||||
}
|
||||
|
||||
Text::new(&format!("{}", self.global_state.settings.graphics.max_fps))
|
||||
.right_from(state.ids.max_fps_slider, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.max_fps_value, ui);
|
||||
}
|
||||
// 5 Sound
|
||||
|
||||
// 5) Sound Tab -----------------------------------
|
||||
if Button::image(if let SettingsTab::Sound = self.show.settings_tab {
|
||||
self.imgs.settings_button_pressed
|
||||
} else {
|
||||
@ -542,6 +679,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::ChangeTab(SettingsTab::Sound));
|
||||
}
|
||||
|
||||
// Contents
|
||||
if let SettingsTab::Sound = self.show.settings_tab {
|
||||
Text::new("Volume")
|
||||
|
@ -14,8 +14,6 @@ use std::{cell::RefCell, rc::Rc, time::Duration};
|
||||
use ui::CharSelectionUi;
|
||||
use vek::*;
|
||||
|
||||
const FPS: u64 = 60;
|
||||
|
||||
pub struct CharSelectionState {
|
||||
char_selection_ui: CharSelectionUi,
|
||||
client: Rc<RefCell<Client>>,
|
||||
@ -125,7 +123,9 @@ impl PlayState for CharSelectionState {
|
||||
.expect("Failed to swap window buffers");
|
||||
|
||||
// Wait for the next tick.
|
||||
clock.tick(Duration::from_millis(1000 / FPS));
|
||||
clock.tick(Duration::from_millis(
|
||||
1000 / (global_state.settings.graphics.max_fps as u64),
|
||||
));
|
||||
|
||||
current_client_state = self.client.borrow().get_client_state();
|
||||
}
|
||||
|
@ -12,8 +12,6 @@ use std::time::Duration;
|
||||
use ui::{Event as MainMenuEvent, MainMenuUi};
|
||||
use vek::*;
|
||||
|
||||
const FPS: u64 = 60;
|
||||
|
||||
pub struct MainMenuState {
|
||||
main_menu_ui: MainMenuUi,
|
||||
}
|
||||
@ -134,7 +132,9 @@ impl PlayState for MainMenuState {
|
||||
.expect("Failed to swap window buffers!");
|
||||
|
||||
// Wait for the next tick
|
||||
clock.tick(Duration::from_millis(1000 / FPS));
|
||||
clock.tick(Duration::from_millis(
|
||||
1000 / (global_state.settings.graphics.max_fps as u64),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,6 @@ use log::{error, warn};
|
||||
use std::{cell::RefCell, rc::Rc, time::Duration};
|
||||
use vek::*;
|
||||
|
||||
const FPS: u64 = 60;
|
||||
|
||||
pub struct SessionState {
|
||||
scene: Scene,
|
||||
client: Rc<RefCell<Client>>,
|
||||
@ -149,10 +147,10 @@ impl PlayState for SessionState {
|
||||
return PlayStateResult::Pop;
|
||||
}
|
||||
|
||||
// Maintain global state
|
||||
// Maintain global state.
|
||||
global_state.maintain();
|
||||
|
||||
// extract HUD events ensuring the client borrow gets dropped
|
||||
// Extract HUD events ensuring the client borrow gets dropped.
|
||||
let hud_events = self.hud.maintain(
|
||||
&self.client.borrow(),
|
||||
global_state,
|
||||
@ -170,6 +168,7 @@ impl PlayState for SessionState {
|
||||
},
|
||||
&self.scene.camera(),
|
||||
);
|
||||
|
||||
// Maintain the UI.
|
||||
for event in hud_events {
|
||||
match event {
|
||||
@ -184,6 +183,20 @@ impl PlayState for SessionState {
|
||||
HudEvent::Quit => {
|
||||
return PlayStateResult::Shutdown;
|
||||
}
|
||||
HudEvent::AdjustMousePan(sensitivity) => {
|
||||
global_state.window.pan_sensitivity = sensitivity;
|
||||
global_state.settings.gameplay.pan_sensitivity = sensitivity;
|
||||
if let Err(err) = global_state.settings.save_to_file() {
|
||||
warn!("Failed to save settings: {:?}", err);
|
||||
}
|
||||
}
|
||||
HudEvent::AdjustMouseZoom(sensitivity) => {
|
||||
global_state.window.zoom_sensitivity = sensitivity;
|
||||
global_state.settings.gameplay.zoom_sensitivity = sensitivity;
|
||||
if let Err(err) = global_state.settings.save_to_file() {
|
||||
warn!("Failed to save settings: {:?}", err);
|
||||
}
|
||||
}
|
||||
HudEvent::AdjustViewDistance(view_distance) => {
|
||||
self.client.borrow_mut().set_view_distance(view_distance);
|
||||
|
||||
@ -208,6 +221,12 @@ impl PlayState for SessionState {
|
||||
warn!("Failed to save settings!\n{:?}", err);
|
||||
}
|
||||
}
|
||||
HudEvent::ChangeMaxFPS(fps) => {
|
||||
global_state.settings.graphics.max_fps = fps;
|
||||
if let Err(err) = global_state.settings.save_to_file() {
|
||||
warn!("Failed to save settings!\n{:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +244,9 @@ impl PlayState for SessionState {
|
||||
.expect("Failed to swap window buffers!");
|
||||
|
||||
// Wait for the next tick.
|
||||
clock.tick(Duration::from_millis(1000 / FPS));
|
||||
clock.tick(Duration::from_millis(
|
||||
1000 / global_state.settings.graphics.max_fps as u64,
|
||||
));
|
||||
|
||||
// Clean things up after the tick.
|
||||
self.cleanup();
|
||||
|
@ -4,20 +4,9 @@ use glutin::{MouseButton, VirtualKeyCode};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fs, io::prelude::*, path::PathBuf};
|
||||
|
||||
/// `Settings` contains everything that can be configured in the Settings.toml file.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Settings {
|
||||
pub controls: ControlSettings,
|
||||
pub networking: NetworkingSettings,
|
||||
pub log: Log,
|
||||
pub graphics: GraphicsSettings,
|
||||
pub audio: AudioSettings,
|
||||
pub show_disclaimer: bool,
|
||||
}
|
||||
|
||||
/// `ControlSettings` contains keybindings.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct ControlSettings {
|
||||
pub toggle_cursor: KeyMouse,
|
||||
pub escape: KeyMouse,
|
||||
@ -41,31 +30,111 @@ pub struct ControlSettings {
|
||||
pub fullscreen: KeyMouse,
|
||||
pub screenshot: KeyMouse,
|
||||
pub toggle_ingame_ui: KeyMouse,
|
||||
pub pan_sensitivity: f32,
|
||||
pub zoom_sensitivity: f32,
|
||||
pub attack: KeyMouse,
|
||||
}
|
||||
|
||||
impl Default for ControlSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
toggle_cursor: KeyMouse::Key(VirtualKeyCode::Tab),
|
||||
escape: KeyMouse::Key(VirtualKeyCode::Escape),
|
||||
enter: KeyMouse::Key(VirtualKeyCode::Return),
|
||||
move_forward: KeyMouse::Key(VirtualKeyCode::W),
|
||||
move_left: KeyMouse::Key(VirtualKeyCode::A),
|
||||
move_back: KeyMouse::Key(VirtualKeyCode::S),
|
||||
move_right: KeyMouse::Key(VirtualKeyCode::D),
|
||||
jump: KeyMouse::Key(VirtualKeyCode::Space),
|
||||
glide: KeyMouse::Key(VirtualKeyCode::LShift),
|
||||
map: KeyMouse::Key(VirtualKeyCode::M),
|
||||
bag: KeyMouse::Key(VirtualKeyCode::B),
|
||||
quest_log: KeyMouse::Key(VirtualKeyCode::L),
|
||||
character_window: KeyMouse::Key(VirtualKeyCode::C),
|
||||
social: KeyMouse::Key(VirtualKeyCode::O),
|
||||
spellbook: KeyMouse::Key(VirtualKeyCode::P),
|
||||
settings: KeyMouse::Key(VirtualKeyCode::N),
|
||||
help: KeyMouse::Key(VirtualKeyCode::F1),
|
||||
toggle_interface: KeyMouse::Key(VirtualKeyCode::F2),
|
||||
toggle_debug: KeyMouse::Key(VirtualKeyCode::F3),
|
||||
fullscreen: KeyMouse::Key(VirtualKeyCode::F11),
|
||||
screenshot: KeyMouse::Key(VirtualKeyCode::F4),
|
||||
toggle_ingame_ui: KeyMouse::Key(VirtualKeyCode::F6),
|
||||
attack: KeyMouse::Mouse(MouseButton::Left),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `GameplaySettings` contains sensitivity and gameplay options.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct GameplaySettings {
|
||||
pub pan_sensitivity: u32,
|
||||
pub zoom_sensitivity: u32,
|
||||
}
|
||||
|
||||
impl Default for GameplaySettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
pan_sensitivity: 100,
|
||||
zoom_sensitivity: 100,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `NetworkingSettings` stores server and networking settings.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct NetworkingSettings {
|
||||
pub username: String,
|
||||
pub servers: Vec<String>,
|
||||
pub default_server: usize,
|
||||
}
|
||||
|
||||
impl Default for NetworkingSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
username: "Username".to_string(),
|
||||
servers: vec!["server.veloren.net".to_string()],
|
||||
default_server: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `Log` stores the name to the log file.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Log {
|
||||
pub file: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct GraphicsSettings {
|
||||
pub view_distance: u32,
|
||||
impl Default for Log {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
file: "voxygen.log".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// AudioSettings controls the volume of different audio subsystems and which
|
||||
/// `GraphicsSettings` contains settings related to framerate and in-game visuals.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct GraphicsSettings {
|
||||
pub view_distance: u32,
|
||||
pub max_fps: u32,
|
||||
}
|
||||
|
||||
impl Default for GraphicsSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
view_distance: 5,
|
||||
max_fps: 60,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `AudioSettings` controls the volume of different audio subsystems and which
|
||||
/// device is used.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct AudioSettings {
|
||||
pub music_volume: f32,
|
||||
pub sfx_volume: f32,
|
||||
@ -74,50 +143,38 @@ pub struct AudioSettings {
|
||||
pub audio_device: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for AudioSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
music_volume: 0.5,
|
||||
sfx_volume: 0.5,
|
||||
audio_device: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `Settings` contains everything that can be configured in the settings.ron file.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Settings {
|
||||
pub controls: ControlSettings,
|
||||
pub gameplay: GameplaySettings,
|
||||
pub networking: NetworkingSettings,
|
||||
pub log: Log,
|
||||
pub graphics: GraphicsSettings,
|
||||
pub audio: AudioSettings,
|
||||
pub show_disclaimer: bool,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
fn default() -> Self {
|
||||
Settings {
|
||||
controls: ControlSettings {
|
||||
toggle_cursor: KeyMouse::Key(VirtualKeyCode::Tab),
|
||||
escape: KeyMouse::Key(VirtualKeyCode::Escape),
|
||||
enter: KeyMouse::Key(VirtualKeyCode::Return),
|
||||
move_forward: KeyMouse::Key(VirtualKeyCode::W),
|
||||
move_left: KeyMouse::Key(VirtualKeyCode::A),
|
||||
move_back: KeyMouse::Key(VirtualKeyCode::S),
|
||||
move_right: KeyMouse::Key(VirtualKeyCode::D),
|
||||
jump: KeyMouse::Key(VirtualKeyCode::Space),
|
||||
glide: KeyMouse::Key(VirtualKeyCode::LShift),
|
||||
map: KeyMouse::Key(VirtualKeyCode::M),
|
||||
bag: KeyMouse::Key(VirtualKeyCode::B),
|
||||
quest_log: KeyMouse::Key(VirtualKeyCode::L),
|
||||
character_window: KeyMouse::Key(VirtualKeyCode::C),
|
||||
social: KeyMouse::Key(VirtualKeyCode::O),
|
||||
spellbook: KeyMouse::Key(VirtualKeyCode::P),
|
||||
settings: KeyMouse::Key(VirtualKeyCode::N),
|
||||
help: KeyMouse::Key(VirtualKeyCode::F1),
|
||||
toggle_interface: KeyMouse::Key(VirtualKeyCode::F2),
|
||||
toggle_debug: KeyMouse::Key(VirtualKeyCode::F3),
|
||||
fullscreen: KeyMouse::Key(VirtualKeyCode::F11),
|
||||
screenshot: KeyMouse::Key(VirtualKeyCode::F4),
|
||||
toggle_ingame_ui: KeyMouse::Key(VirtualKeyCode::F6),
|
||||
pan_sensitivity: 1.0,
|
||||
zoom_sensitivity: 1.0,
|
||||
attack: KeyMouse::Mouse(MouseButton::Left),
|
||||
},
|
||||
networking: NetworkingSettings {
|
||||
username: "Username".to_string(),
|
||||
servers: vec!["server.veloren.net".to_string()],
|
||||
default_server: 0,
|
||||
},
|
||||
log: Log {
|
||||
file: "voxygen.log".into(),
|
||||
},
|
||||
graphics: GraphicsSettings { view_distance: 5 },
|
||||
audio: AudioSettings {
|
||||
music_volume: 0.5,
|
||||
sfx_volume: 0.5,
|
||||
audio_device: None,
|
||||
},
|
||||
controls: ControlSettings::default(),
|
||||
gameplay: GameplaySettings::default(),
|
||||
networking: NetworkingSettings::default(),
|
||||
log: Log::default(),
|
||||
graphics: GraphicsSettings::default(),
|
||||
audio: AudioSettings::default(),
|
||||
show_disclaimer: true,
|
||||
}
|
||||
}
|
||||
@ -137,23 +194,22 @@ impl Settings {
|
||||
|
||||
pub fn save_to_file(&self) -> std::io::Result<()> {
|
||||
let path = Settings::get_settings_path();
|
||||
|
||||
if let Some(dir) = path.parent() {
|
||||
fs::create_dir_all(dir)?;
|
||||
}
|
||||
|
||||
let mut config_file = fs::File::create(path)?;
|
||||
|
||||
let s: &str = &ron::ser::to_string_pretty(self, ron::ser::PrettyConfig::default()).unwrap();
|
||||
config_file.write_all(s.as_bytes()).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_settings_path() -> PathBuf {
|
||||
let proj_dirs =
|
||||
ProjectDirs::from("net", "veloren", "voxygen").expect("No home directory defined!");
|
||||
let path = proj_dirs.config_dir();
|
||||
path.join("settings");
|
||||
let path = path.with_extension("ron");
|
||||
path
|
||||
let proj_dirs = ProjectDirs::from("net", "veloren", "voxygen")
|
||||
.expect("System's $HOME directory path not found!");
|
||||
proj_dirs
|
||||
.config_dir()
|
||||
.join("settings")
|
||||
.with_extension("ron")
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ pub enum Event {
|
||||
InputUpdate(GameInput, bool),
|
||||
/// Event that the ui uses.
|
||||
Ui(ui::Event),
|
||||
// The view distance has been changed
|
||||
/// The view distance has changed.
|
||||
ViewDistanceChanged(u32),
|
||||
/// Game settings have changed.
|
||||
SettingsChanged,
|
||||
@ -71,8 +71,8 @@ pub struct Window {
|
||||
renderer: Renderer,
|
||||
window: glutin::GlWindow,
|
||||
cursor_grabbed: bool,
|
||||
pub pan_sensitivity: f32,
|
||||
pub zoom_sensitivity: f32,
|
||||
pub pan_sensitivity: u32,
|
||||
pub zoom_sensitivity: u32,
|
||||
fullscreen: bool,
|
||||
needs_refresh_resize: bool,
|
||||
key_map: HashMap<KeyMouse, GameInput>,
|
||||
@ -140,8 +140,8 @@ impl Window {
|
||||
renderer: Renderer::new(device, factory, win_color_view, win_depth_view)?,
|
||||
window,
|
||||
cursor_grabbed: false,
|
||||
pan_sensitivity: settings.controls.pan_sensitivity,
|
||||
zoom_sensitivity: settings.controls.zoom_sensitivity,
|
||||
pan_sensitivity: settings.gameplay.pan_sensitivity,
|
||||
zoom_sensitivity: settings.gameplay.zoom_sensitivity,
|
||||
fullscreen: false,
|
||||
needs_refresh_resize: false,
|
||||
key_map,
|
||||
@ -230,14 +230,14 @@ impl Window {
|
||||
glutin::DeviceEvent::MouseMotion {
|
||||
delta: (dx, dy), ..
|
||||
} if cursor_grabbed && *focused => events.push(Event::CursorPan(Vec2::new(
|
||||
dx as f32 * pan_sensitivity,
|
||||
dy as f32 * pan_sensitivity,
|
||||
dx as f32 * (pan_sensitivity as f32 / 100.0),
|
||||
dy as f32 * (pan_sensitivity as f32 / 100.0),
|
||||
))),
|
||||
glutin::DeviceEvent::MouseWheel {
|
||||
delta: glutin::MouseScrollDelta::LineDelta(_x, y),
|
||||
..
|
||||
} if cursor_grabbed && *focused => {
|
||||
events.push(Event::Zoom(y as f32 * zoom_sensitivity))
|
||||
events.push(Event::Zoom(y * (zoom_sensitivity as f32 / 100.0)))
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user