mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Allow locking camera zoom
Allow the camera's zoom to be locked by a keybind or a Gameplay setting. The zoom lock behavior can be changed between Toggle and Auto, where Auto only locks the camera zoom while specific movement/combat inputs are being pressed. (closes !1528) A temporary fading notification is shown at the top of the screen, informing the player of the setting change (when the keybind is used) or that the zoom is locked (when the player might have forgotten the zoom is locked, and is trying to zoom). i18n strings are added for English and German, but no other languages. To implement the simplistic fading text, the behavior was extracted into an impl called `ChangeNotification`, where reasons are quantified by `NotificationReason`.
This commit is contained in:
parent
9a025cfcc8
commit
83e4cdfe76
@ -18,6 +18,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Unlockable door blocks.
|
- Unlockable door blocks.
|
||||||
- Sprite rotation for Spots.
|
- Sprite rotation for Spots.
|
||||||
- Better entity placement options for spots.
|
- Better entity placement options for spots.
|
||||||
|
- Camera zoom can now be locked, to prevent accidental zooming while rolling in combat. It comes
|
||||||
|
with a keybind to enable/disable the setting, and an Auto/Toggle behavior setting. Auto behavior
|
||||||
|
will only lock the camera zoom while movement and combat inputs are also being pressed.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Bats move slower and use a simple proportional controller to maintain altitude
|
- Bats move slower and use a simple proportional controller to maintain altitude
|
||||||
|
@ -49,6 +49,7 @@ gameinput-togglewield = Waffe ziehen/wegstecken
|
|||||||
gameinput-interact = Interagieren
|
gameinput-interact = Interagieren
|
||||||
gameinput-freelook = Freie Sicht
|
gameinput-freelook = Freie Sicht
|
||||||
gameinput-autowalk = Automatisch Laufen/Schwimmen
|
gameinput-autowalk = Automatisch Laufen/Schwimmen
|
||||||
|
gameinput-zoomlock = Kamera-Zoomsperre
|
||||||
gameinput-cameraclamp = Kamera fixieren
|
gameinput-cameraclamp = Kamera fixieren
|
||||||
gameinput-dance = Tanzen
|
gameinput-dance = Tanzen
|
||||||
gameinput-select = Einheit auswählen
|
gameinput-select = Einheit auswählen
|
||||||
|
@ -35,6 +35,9 @@ hud-diary = Tagebuch
|
|||||||
hud-free_look_indicator = Freie Sicht aktiv. Drücke { $key } zum deaktivieren.
|
hud-free_look_indicator = Freie Sicht aktiv. Drücke { $key } zum deaktivieren.
|
||||||
hud-camera_clamp_indicator = Vertikale Kamerafixierung aktiv. Drücke { $key } zum deaktivieren.
|
hud-camera_clamp_indicator = Vertikale Kamerafixierung aktiv. Drücke { $key } zum deaktivieren.
|
||||||
hud-auto_walk_indicator = Auto Laufen/Schwimmen aktiv
|
hud-auto_walk_indicator = Auto Laufen/Schwimmen aktiv
|
||||||
|
hud-zoom_lock_indicator-remind = Zoom gesperrt
|
||||||
|
hud-zoom_lock_indicator-enable = Kamerazoom gesperrt
|
||||||
|
hud-zoom_lock_indicator-disable = Kamerazoom entsperrt
|
||||||
hud-collect = Aufsammeln
|
hud-collect = Aufsammeln
|
||||||
hud-pick_up = Aufheben
|
hud-pick_up = Aufheben
|
||||||
hud-open = Öffnen
|
hud-open = Öffnen
|
||||||
|
@ -2,6 +2,8 @@ hud-settings-general = Allgemein
|
|||||||
hud-settings-none = Keine
|
hud-settings-none = Keine
|
||||||
hud-settings-press_behavior-toggle = Umschalten
|
hud-settings-press_behavior-toggle = Umschalten
|
||||||
hud-settings-press_behavior-hold = Halten
|
hud-settings-press_behavior-hold = Halten
|
||||||
|
hud-settings-autopress_behavior-toggle = Umschalten
|
||||||
|
hud-settings-autopress_behavior-auto = Auto
|
||||||
hud-settings-help_window = Hilfe zu Fenstern
|
hud-settings-help_window = Hilfe zu Fenstern
|
||||||
hud-settings-debug_info = Debug-Informationen
|
hud-settings-debug_info = Debug-Informationen
|
||||||
hud-settings-show_hitboxes = Hitboxen anzeigen
|
hud-settings-show_hitboxes = Hitboxen anzeigen
|
||||||
@ -50,10 +52,12 @@ hud-settings-enable_mouse_smoothing = Kamera-Glättung
|
|||||||
hud-settings-free_look_behavior = Verhalten bei freiem Kameramodus
|
hud-settings-free_look_behavior = Verhalten bei freiem Kameramodus
|
||||||
hud-settings-auto_walk_behavior = Verhalten bei automatischem Gehen
|
hud-settings-auto_walk_behavior = Verhalten bei automatischem Gehen
|
||||||
hud-settings-camera_clamp_behavior = Verhalten bei starrer Kamera
|
hud-settings-camera_clamp_behavior = Verhalten bei starrer Kamera
|
||||||
|
hud-settings-zoom_lock_behavior = Verhalten bei Kamera-Zoomsperre
|
||||||
hud-settings-player_physics_behavior = Spielerphysik (experimentell)
|
hud-settings-player_physics_behavior = Spielerphysik (experimentell)
|
||||||
hud-settings-stop_auto_walk_on_input = Automatisches Gehen bei Spieleraktivität anhalten
|
hud-settings-stop_auto_walk_on_input = Automatisches Gehen bei Spieleraktivität anhalten
|
||||||
hud-settings-auto_camera = Auto Kamera
|
hud-settings-auto_camera = Auto Kamera
|
||||||
hud-settings-bow_zoom = Hinein zoomen, wenn der Bogen aufgeladen wird
|
hud-settings-bow_zoom = Hinein zoomen, wenn der Bogen aufgeladen wird
|
||||||
|
hud-settings-zoom_lock = Kamera-Zoomsperre
|
||||||
hud-settings-reset_gameplay =
|
hud-settings-reset_gameplay =
|
||||||
Einstellungen
|
Einstellungen
|
||||||
zurücksetzen
|
zurücksetzen
|
||||||
|
@ -49,6 +49,7 @@ gameinput-togglewield = Toggle Wield
|
|||||||
gameinput-interact = Interact
|
gameinput-interact = Interact
|
||||||
gameinput-freelook = Free Look
|
gameinput-freelook = Free Look
|
||||||
gameinput-autowalk = Auto Walk/Swim
|
gameinput-autowalk = Auto Walk/Swim
|
||||||
|
gameinput-zoomlock = Camera zoom lock
|
||||||
gameinput-cameraclamp = Camera Clamp
|
gameinput-cameraclamp = Camera Clamp
|
||||||
gameinput-dance = Dance
|
gameinput-dance = Dance
|
||||||
gameinput-select = Select Entity
|
gameinput-select = Select Entity
|
||||||
|
@ -35,6 +35,9 @@ hud-diary = Diary
|
|||||||
hud-free_look_indicator = Free look active. Press { $key } to disable.
|
hud-free_look_indicator = Free look active. Press { $key } to disable.
|
||||||
hud-camera_clamp_indicator = Camera vertical clamp active. Press { $key } to disable.
|
hud-camera_clamp_indicator = Camera vertical clamp active. Press { $key } to disable.
|
||||||
hud-auto_walk_indicator = Auto walk/swim active
|
hud-auto_walk_indicator = Auto walk/swim active
|
||||||
|
hud-zoom_lock_indicator-remind = Zoom locked
|
||||||
|
hud-zoom_lock_indicator-enable = Camera zoom locked
|
||||||
|
hud-zoom_lock_indicator-disable = Camera zoom unlocked
|
||||||
hud-collect = Collect
|
hud-collect = Collect
|
||||||
hud-pick_up = Pick up
|
hud-pick_up = Pick up
|
||||||
hud-open = Open
|
hud-open = Open
|
||||||
|
@ -2,6 +2,8 @@ hud-settings-general = General
|
|||||||
hud-settings-none = None
|
hud-settings-none = None
|
||||||
hud-settings-press_behavior-toggle = Toggle
|
hud-settings-press_behavior-toggle = Toggle
|
||||||
hud-settings-press_behavior-hold = Hold
|
hud-settings-press_behavior-hold = Hold
|
||||||
|
hud-settings-autopress_behavior-toggle = Toggle
|
||||||
|
hud-settings-autopress_behavior-auto = Auto
|
||||||
hud-settings-help_window = Help Window
|
hud-settings-help_window = Help Window
|
||||||
hud-settings-debug_info = Debug Info
|
hud-settings-debug_info = Debug Info
|
||||||
hud-settings-show_hitboxes = Show hitboxes
|
hud-settings-show_hitboxes = Show hitboxes
|
||||||
@ -49,10 +51,12 @@ hud-settings-enable_mouse_smoothing = Camera Smoothing
|
|||||||
hud-settings-free_look_behavior = Free look behavior
|
hud-settings-free_look_behavior = Free look behavior
|
||||||
hud-settings-auto_walk_behavior = Auto walk behavior
|
hud-settings-auto_walk_behavior = Auto walk behavior
|
||||||
hud-settings-camera_clamp_behavior = Camera clamp behavior
|
hud-settings-camera_clamp_behavior = Camera clamp behavior
|
||||||
|
hud-settings-zoom_lock_behavior = Camera zoom lock behavior
|
||||||
hud-settings-player_physics_behavior = Player physics (experimental)
|
hud-settings-player_physics_behavior = Player physics (experimental)
|
||||||
hud-settings-stop_auto_walk_on_input = Stop auto walk on movement
|
hud-settings-stop_auto_walk_on_input = Stop auto walk on movement
|
||||||
hud-settings-auto_camera = Auto camera
|
hud-settings-auto_camera = Auto camera
|
||||||
hud-settings-bow_zoom = Zoom in when charging bow
|
hud-settings-bow_zoom = Zoom in when charging bow
|
||||||
|
hud-settings-zoom_lock = Camera zoom lock
|
||||||
hud-settings-reset_gameplay = Reset to Defaults
|
hud-settings-reset_gameplay = Reset to Defaults
|
||||||
hud-settings-view_distance = View Distance
|
hud-settings-view_distance = View Distance
|
||||||
hud-settings-entity_view_distance = Entities View Distance
|
hud-settings-entity_view_distance = Entities View Distance
|
||||||
|
@ -132,6 +132,8 @@ pub enum GameInput {
|
|||||||
FreeLook,
|
FreeLook,
|
||||||
#[strum(serialize = "gameinput-autowalk")]
|
#[strum(serialize = "gameinput-autowalk")]
|
||||||
AutoWalk,
|
AutoWalk,
|
||||||
|
#[strum(serialize = "gameinput-zoomlock")]
|
||||||
|
ZoomLock,
|
||||||
#[strum(serialize = "gameinput-cameraclamp")]
|
#[strum(serialize = "gameinput-cameraclamp")]
|
||||||
CameraClamp,
|
CameraClamp,
|
||||||
#[strum(serialize = "gameinput-cyclecamera")]
|
#[strum(serialize = "gameinput-cyclecamera")]
|
||||||
|
86
voxygen/src/hud/change_notification.rs
Normal file
86
voxygen/src/hud/change_notification.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// Default initial alpha of a Notify
|
||||||
|
const NOTIF_START_ALPHA: f32 = 1.0;
|
||||||
|
|
||||||
|
/// Default time to live of a notify
|
||||||
|
const NOTIF_LIFETIME: f32 = 2.0;
|
||||||
|
/// Default fading time of a notify
|
||||||
|
const NOTIF_FADETIME: f32 = 1.5;
|
||||||
|
|
||||||
|
/// The reason this notification is being shown: the setting is being enabled or
|
||||||
|
/// disabled, or we are reminding the player of the current state.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
|
pub enum NotificationReason {
|
||||||
|
Remind = 2,
|
||||||
|
Enable = 1,
|
||||||
|
#[serde(other)]
|
||||||
|
Disable = 0,
|
||||||
|
}
|
||||||
|
/// A temporal, fading message that a setting
|
||||||
|
/// or other state was changed (probably by direct player input)
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ChangeNotification {
|
||||||
|
pub reason: Option<NotificationReason>,
|
||||||
|
pub alpha: f32,
|
||||||
|
lifetime: Duration,
|
||||||
|
fadetime: Duration,
|
||||||
|
initial_fadetime: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChangeNotification {
|
||||||
|
pub fn new(
|
||||||
|
reason: Option<NotificationReason>,
|
||||||
|
alpha: f32,
|
||||||
|
lifetime: Duration,
|
||||||
|
fadetime: Duration,
|
||||||
|
) -> Result<Self, Duration> {
|
||||||
|
if fadetime.is_zero() {
|
||||||
|
Err(fadetime)
|
||||||
|
} else {
|
||||||
|
Ok(Self {
|
||||||
|
reason,
|
||||||
|
alpha,
|
||||||
|
lifetime,
|
||||||
|
fadetime,
|
||||||
|
initial_fadetime: fadetime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_reason(reason: NotificationReason) -> Self {
|
||||||
|
ChangeNotification::new(
|
||||||
|
Some(reason),
|
||||||
|
NOTIF_START_ALPHA,
|
||||||
|
Duration::from_secs_f32(NOTIF_LIFETIME),
|
||||||
|
Duration::from_secs_f32(NOTIF_FADETIME),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_state(state: bool) -> Self {
|
||||||
|
ChangeNotification::from_reason(match state {
|
||||||
|
true => NotificationReason::Enable,
|
||||||
|
false => NotificationReason::Disable,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, dt: Duration) {
|
||||||
|
if self.reason.is_some() {
|
||||||
|
// Timer before fade
|
||||||
|
if !self.lifetime.is_zero() {
|
||||||
|
self.lifetime = self.lifetime.saturating_sub(dt);
|
||||||
|
// Lifetime expired, start to fade
|
||||||
|
} else if !self.fadetime.is_zero() {
|
||||||
|
self.fadetime = self.fadetime.saturating_sub(dt);
|
||||||
|
// alpha as elapsed duration fraction, multiply with this for nice fade curve
|
||||||
|
self.alpha = self.fadetime.as_secs_f32() / self.initial_fadetime.as_secs_f32();
|
||||||
|
// Done fading
|
||||||
|
} else {
|
||||||
|
self.reason = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ mod animation;
|
|||||||
mod bag;
|
mod bag;
|
||||||
mod buffs;
|
mod buffs;
|
||||||
mod buttons;
|
mod buttons;
|
||||||
|
mod change_notification;
|
||||||
mod chat;
|
mod chat;
|
||||||
mod crafting;
|
mod crafting;
|
||||||
mod diary;
|
mod diary;
|
||||||
@ -33,6 +34,7 @@ pub use settings_window::ScaleChange;
|
|||||||
use bag::Bag;
|
use bag::Bag;
|
||||||
use buffs::BuffsBar;
|
use buffs::BuffsBar;
|
||||||
use buttons::Buttons;
|
use buttons::Buttons;
|
||||||
|
use change_notification::{ChangeNotification, NotificationReason};
|
||||||
use chat::Chat;
|
use chat::Chat;
|
||||||
use chrono::NaiveTime;
|
use chrono::NaiveTime;
|
||||||
use crafting::Crafting;
|
use crafting::Crafting;
|
||||||
@ -329,6 +331,10 @@ widget_ids! {
|
|||||||
auto_walk_txt,
|
auto_walk_txt,
|
||||||
auto_walk_bg,
|
auto_walk_bg,
|
||||||
|
|
||||||
|
// Temporal (fading) camera zoom lock indicator
|
||||||
|
zoom_lock_txt,
|
||||||
|
zoom_lock_bg,
|
||||||
|
|
||||||
// Camera clamp indicator
|
// Camera clamp indicator
|
||||||
camera_clamp_txt,
|
camera_clamp_txt,
|
||||||
camera_clamp_bg,
|
camera_clamp_bg,
|
||||||
@ -797,6 +803,16 @@ pub enum PressBehavior {
|
|||||||
#[serde(other)]
|
#[serde(other)]
|
||||||
Toggle = 0,
|
Toggle = 0,
|
||||||
}
|
}
|
||||||
|
/// Similar to [PressBehavior], with different semantics for settings that
|
||||||
|
/// change state automatically. There is no [PressBehavior::update][update]
|
||||||
|
/// implementation because it doesn't apply to the use case; this is just a
|
||||||
|
/// sentinel.
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum AutoPressBehavior {
|
||||||
|
Auto = 1,
|
||||||
|
#[serde(other)]
|
||||||
|
Toggle = 0,
|
||||||
|
}
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct ChatTab {
|
pub struct ChatTab {
|
||||||
pub label: String,
|
pub label: String,
|
||||||
@ -889,6 +905,7 @@ pub struct Show {
|
|||||||
stats: bool,
|
stats: bool,
|
||||||
free_look: bool,
|
free_look: bool,
|
||||||
auto_walk: bool,
|
auto_walk: bool,
|
||||||
|
zoom_lock: ChangeNotification,
|
||||||
camera_clamp: bool,
|
camera_clamp: bool,
|
||||||
prompt_dialog: Option<PromptDialogSettings>,
|
prompt_dialog: Option<PromptDialogSettings>,
|
||||||
location_markers: MapMarkers,
|
location_markers: MapMarkers,
|
||||||
@ -1367,6 +1384,7 @@ impl Hud {
|
|||||||
stats: false,
|
stats: false,
|
||||||
free_look: false,
|
free_look: false,
|
||||||
auto_walk: false,
|
auto_walk: false,
|
||||||
|
zoom_lock: ChangeNotification::default(),
|
||||||
camera_clamp: false,
|
camera_clamp: false,
|
||||||
prompt_dialog: None,
|
prompt_dialog: None,
|
||||||
location_markers: MapMarkers::default(),
|
location_markers: MapMarkers::default(),
|
||||||
@ -3522,6 +3540,31 @@ impl Hud {
|
|||||||
.set(self.ids.auto_walk_txt, ui_widgets);
|
.set(self.ids.auto_walk_txt, ui_widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Camera zoom lock
|
||||||
|
self.show.zoom_lock.update(dt);
|
||||||
|
|
||||||
|
if let Some(zoom_lock) = self.show.zoom_lock.reason {
|
||||||
|
let zoom_lock_message = match zoom_lock {
|
||||||
|
NotificationReason::Remind => "hud-zoom_lock_indicator-remind",
|
||||||
|
NotificationReason::Enable => "hud-zoom_lock_indicator-enable",
|
||||||
|
NotificationReason::Disable => "hud-zoom_lock_indicator-disable",
|
||||||
|
};
|
||||||
|
|
||||||
|
Text::new(&i18n.get_msg(zoom_lock_message))
|
||||||
|
.color(TEXT_BG.alpha(self.show.zoom_lock.alpha))
|
||||||
|
.mid_top_with_margin_on(ui_widgets.window, indicator_offset)
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.font_size(self.fonts.cyri.scale(20))
|
||||||
|
.set(self.ids.zoom_lock_bg, ui_widgets);
|
||||||
|
indicator_offset += 30.0;
|
||||||
|
Text::new(&i18n.get_msg(zoom_lock_message))
|
||||||
|
.color(TEXT_COLOR.alpha(self.show.zoom_lock.alpha))
|
||||||
|
.top_left_with_margins_on(self.ids.zoom_lock_bg, -1.0, -1.0)
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.font_size(self.fonts.cyri.scale(20))
|
||||||
|
.set(self.ids.zoom_lock_txt, ui_widgets);
|
||||||
|
}
|
||||||
|
|
||||||
// Camera clamp indicator
|
// Camera clamp indicator
|
||||||
if let Some(cameraclamp_key) = global_state
|
if let Some(cameraclamp_key) = global_state
|
||||||
.settings
|
.settings
|
||||||
@ -4562,6 +4605,20 @@ impl Hud {
|
|||||||
|
|
||||||
pub fn camera_clamp(&mut self, camera_clamp: bool) { self.show.camera_clamp = camera_clamp; }
|
pub fn camera_clamp(&mut self, camera_clamp: bool) { self.show.camera_clamp = camera_clamp; }
|
||||||
|
|
||||||
|
/// Remind the player camera zoom is currently locked, for example if they
|
||||||
|
/// are trying to zoom.
|
||||||
|
pub fn zoom_lock_reminder(&mut self) {
|
||||||
|
if self.show.zoom_lock.reason.is_none() {
|
||||||
|
self.show.zoom_lock = ChangeNotification::from_reason(NotificationReason::Remind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start showing a temporary notification ([ChangeNotification]) that zoom
|
||||||
|
/// lock was toggled on/off.
|
||||||
|
pub fn zoom_lock_toggle(&mut self, state: bool) {
|
||||||
|
self.show.zoom_lock = ChangeNotification::from_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_outcome(
|
pub fn handle_outcome(
|
||||||
&mut self,
|
&mut self,
|
||||||
outcome: &Outcome,
|
outcome: &Outcome,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH};
|
use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hud::{img_ids::Imgs, PressBehavior, MENU_BG, TEXT_COLOR},
|
hud::{img_ids::Imgs, AutoPressBehavior, PressBehavior, MENU_BG, TEXT_COLOR},
|
||||||
session::settings_change::{Gameplay as GameplayChange, Gameplay::*},
|
session::settings_change::{Gameplay as GameplayChange, Gameplay::*},
|
||||||
ui::{fonts::Fonts, ImageSlider, ToggleButton},
|
ui::{fonts::Fonts, ImageSlider, ToggleButton},
|
||||||
GlobalState,
|
GlobalState,
|
||||||
@ -44,12 +44,16 @@ widget_ids! {
|
|||||||
auto_walk_behavior_list,
|
auto_walk_behavior_list,
|
||||||
camera_clamp_behavior_text,
|
camera_clamp_behavior_text,
|
||||||
camera_clamp_behavior_list,
|
camera_clamp_behavior_list,
|
||||||
|
zoom_lock_behavior_text,
|
||||||
|
zoom_lock_behavior_list,
|
||||||
stop_auto_walk_on_input_button,
|
stop_auto_walk_on_input_button,
|
||||||
stop_auto_walk_on_input_label,
|
stop_auto_walk_on_input_label,
|
||||||
auto_camera_button,
|
auto_camera_button,
|
||||||
auto_camera_label,
|
auto_camera_label,
|
||||||
bow_zoom_button,
|
bow_zoom_button,
|
||||||
bow_zoom_label,
|
bow_zoom_label,
|
||||||
|
zoom_lock_button,
|
||||||
|
zoom_lock_label,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,6 +532,68 @@ impl<'a> Widget for Gameplay<'a> {
|
|||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.bow_zoom_label, ui);
|
.set(state.ids.bow_zoom_label, ui);
|
||||||
|
|
||||||
|
let zoom_lock_label_list = [
|
||||||
|
self.localized_strings
|
||||||
|
.get_msg("hud-settings-autopress_behavior-toggle"),
|
||||||
|
self.localized_strings
|
||||||
|
.get_msg("hud-settings-autopress_behavior-auto"),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Camera zoom lock behavior
|
||||||
|
Text::new(
|
||||||
|
&self
|
||||||
|
.localized_strings
|
||||||
|
.get_msg("hud-settings-zoom_lock_behavior"),
|
||||||
|
)
|
||||||
|
.down_from(state.ids.auto_walk_behavior_list, 10.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.zoom_lock_behavior_text, ui);
|
||||||
|
|
||||||
|
let zoom_lock_selected = self.global_state.settings.gameplay.zoom_lock_behavior as usize;
|
||||||
|
|
||||||
|
if let Some(clicked) = DropDownList::new(&zoom_lock_label_list, Some(zoom_lock_selected))
|
||||||
|
.w_h(200.0, 30.0)
|
||||||
|
.color(MENU_BG)
|
||||||
|
.label_color(TEXT_COLOR)
|
||||||
|
.label_font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.down_from(state.ids.zoom_lock_behavior_text, 8.0)
|
||||||
|
.set(state.ids.zoom_lock_behavior_list, ui)
|
||||||
|
{
|
||||||
|
match clicked {
|
||||||
|
0 => events.push(ChangeZoomLockBehavior(AutoPressBehavior::Toggle)),
|
||||||
|
1 => events.push(ChangeZoomLockBehavior(AutoPressBehavior::Auto)),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Camera zoom lock toggle
|
||||||
|
let zoom_lock_toggle = ToggleButton::new(
|
||||||
|
self.global_state.settings.gameplay.zoom_lock,
|
||||||
|
self.imgs.checkbox,
|
||||||
|
self.imgs.checkbox_checked,
|
||||||
|
)
|
||||||
|
.w_h(18.0, 18.0)
|
||||||
|
.down_from(state.ids.bow_zoom_button, 8.0)
|
||||||
|
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||||
|
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||||
|
.set(state.ids.zoom_lock_button, ui);
|
||||||
|
|
||||||
|
if self.global_state.settings.gameplay.zoom_lock != zoom_lock_toggle {
|
||||||
|
events.push(ChangeZoomLock(
|
||||||
|
!self.global_state.settings.gameplay.zoom_lock,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Text::new(&self.localized_strings.get_msg("hud-settings-zoom_lock"))
|
||||||
|
.right_from(state.ids.zoom_lock_button, 10.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.graphics_for(state.ids.zoom_lock_button)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.zoom_lock_label, ui);
|
||||||
|
|
||||||
// Reset the gameplay settings to the default settings
|
// Reset the gameplay settings to the default settings
|
||||||
if Button::image(self.imgs.button)
|
if Button::image(self.imgs.button)
|
||||||
.w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
|
.w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
|
||||||
|
@ -43,8 +43,8 @@ use crate::{
|
|||||||
error::Error,
|
error::Error,
|
||||||
game_input::GameInput,
|
game_input::GameInput,
|
||||||
hud::{
|
hud::{
|
||||||
DebugInfo, Event as HudEvent, Hud, HudCollectFailedReason, HudInfo, LootMessage,
|
AutoPressBehavior, DebugInfo, Event as HudEvent, Hud, HudCollectFailedReason, HudInfo,
|
||||||
PromptDialogSettings,
|
LootMessage, PromptDialogSettings,
|
||||||
},
|
},
|
||||||
key_state::KeyState,
|
key_state::KeyState,
|
||||||
menu::char_selection::CharSelectionState,
|
menu::char_selection::CharSelectionState,
|
||||||
@ -61,6 +61,25 @@ use target::targets_under_cursor;
|
|||||||
#[cfg(feature = "egui-ui")]
|
#[cfg(feature = "egui-ui")]
|
||||||
use voxygen_egui::EguiDebugInfo;
|
use voxygen_egui::EguiDebugInfo;
|
||||||
|
|
||||||
|
/** The zoom scroll delta that is considered an "intent"
|
||||||
|
to zoom, rather than the accidental zooming that Zoom Lock
|
||||||
|
is supposed to help.
|
||||||
|
This is used for both [AutoPressBehaviors::Toggle] and [AutoPressBehaviors::Auto].
|
||||||
|
|
||||||
|
This value should likely differ between trackpad scrolling
|
||||||
|
and various mouse wheels, but we just choose a reasonable
|
||||||
|
default.
|
||||||
|
|
||||||
|
All the mice I have can only scroll at |delta|=15 no matter
|
||||||
|
how fast, I guess the default should be less than that so
|
||||||
|
it gets seen. This could possibly be a user setting changed
|
||||||
|
only in a config file; it's too minor to put in the GUI.
|
||||||
|
If a player reports that their scroll wheel is apparently not
|
||||||
|
working, this value may be to blame (i.e. their intent to scroll
|
||||||
|
is not being detected at a low enough scroll speed).
|
||||||
|
*/
|
||||||
|
const ZOOM_LOCK_SCROLL_DELTA_INTENT: f32 = 14.0;
|
||||||
|
|
||||||
/// The action to perform after a tick
|
/// The action to perform after a tick
|
||||||
enum TickAction {
|
enum TickAction {
|
||||||
// Continue executing
|
// Continue executing
|
||||||
@ -83,6 +102,7 @@ pub struct SessionState {
|
|||||||
free_look: bool,
|
free_look: bool,
|
||||||
auto_walk: bool,
|
auto_walk: bool,
|
||||||
camera_clamp: bool,
|
camera_clamp: bool,
|
||||||
|
zoom_lock: bool,
|
||||||
is_aiming: bool,
|
is_aiming: bool,
|
||||||
target_entity: Option<specs::Entity>,
|
target_entity: Option<specs::Entity>,
|
||||||
selected_entity: Option<(specs::Entity, std::time::Instant)>,
|
selected_entity: Option<(specs::Entity, std::time::Instant)>,
|
||||||
@ -152,6 +172,7 @@ impl SessionState {
|
|||||||
free_look: false,
|
free_look: false,
|
||||||
auto_walk: false,
|
auto_walk: false,
|
||||||
camera_clamp: false,
|
camera_clamp: false,
|
||||||
|
zoom_lock: false,
|
||||||
is_aiming: false,
|
is_aiming: false,
|
||||||
target_entity: None,
|
target_entity: None,
|
||||||
selected_entity: None,
|
selected_entity: None,
|
||||||
@ -171,6 +192,24 @@ impl SessionState {
|
|||||||
self.key_state.auto_walk = false;
|
self.key_state.auto_walk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Possibly lock the camera zoom depending on the current behaviour, and
|
||||||
|
/// the current inputs if in the Auto state.
|
||||||
|
fn maybe_auto_zoom_lock(
|
||||||
|
&mut self,
|
||||||
|
zoom_lock_enabled: bool,
|
||||||
|
zoom_lock_behavior: AutoPressBehavior,
|
||||||
|
) {
|
||||||
|
if let AutoPressBehavior::Auto = zoom_lock_behavior {
|
||||||
|
// to add Analog detection, update the condition rhs with a check for
|
||||||
|
// MovementX/Y event from the last tick
|
||||||
|
self.zoom_lock = zoom_lock_enabled && self.should_auto_zoom_lock();
|
||||||
|
} else {
|
||||||
|
// it's intentional that the HUD notification is not shown in this case:
|
||||||
|
// refresh session from Settings HUD checkbox change
|
||||||
|
self.zoom_lock = zoom_lock_enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the entity that is the current viewpoint, and a bool if the client
|
/// Gets the entity that is the current viewpoint, and a bool if the client
|
||||||
/// is allowed to edit it's data.
|
/// is allowed to edit it's data.
|
||||||
fn viewpoint_entity(&self) -> (specs::Entity, bool) {
|
fn viewpoint_entity(&self) -> (specs::Entity, bool) {
|
||||||
@ -406,6 +445,45 @@ impl SessionState {
|
|||||||
|
|
||||||
/// Clean up the session (and the client attached to it) after a tick.
|
/// Clean up the session (and the client attached to it) after a tick.
|
||||||
pub fn cleanup(&mut self) { self.client.borrow_mut().cleanup(); }
|
pub fn cleanup(&mut self) { self.client.borrow_mut().cleanup(); }
|
||||||
|
|
||||||
|
fn should_auto_zoom_lock(&self) -> bool {
|
||||||
|
let inputs_state = &self.inputs_state;
|
||||||
|
for input in inputs_state {
|
||||||
|
match input {
|
||||||
|
GameInput::Primary
|
||||||
|
| GameInput::Secondary
|
||||||
|
| GameInput::Block
|
||||||
|
| GameInput::MoveForward
|
||||||
|
| GameInput::MoveLeft
|
||||||
|
| GameInput::MoveRight
|
||||||
|
| GameInput::MoveBack
|
||||||
|
| GameInput::Jump
|
||||||
|
| GameInput::Roll
|
||||||
|
| GameInput::Sneak
|
||||||
|
| GameInput::AutoWalk
|
||||||
|
| GameInput::Climb
|
||||||
|
| GameInput::ClimbDown
|
||||||
|
| GameInput::SwimUp
|
||||||
|
| GameInput::SwimDown
|
||||||
|
| GameInput::SwapLoadout
|
||||||
|
| GameInput::ToggleWield
|
||||||
|
| GameInput::Slot1
|
||||||
|
| GameInput::Slot2
|
||||||
|
| GameInput::Slot3
|
||||||
|
| GameInput::Slot4
|
||||||
|
| GameInput::Slot5
|
||||||
|
| GameInput::Slot6
|
||||||
|
| GameInput::Slot7
|
||||||
|
| GameInput::Slot8
|
||||||
|
| GameInput::Slot9
|
||||||
|
| GameInput::Slot10
|
||||||
|
| GameInput::SpectateViewpoint
|
||||||
|
| GameInput::SpectateSpeedBoost => return true,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlayState for SessionState {
|
impl PlayState for SessionState {
|
||||||
@ -547,6 +625,11 @@ impl PlayState for SessionState {
|
|||||||
|
|
||||||
drop(client);
|
drop(client);
|
||||||
|
|
||||||
|
self.maybe_auto_zoom_lock(
|
||||||
|
global_state.settings.gameplay.zoom_lock,
|
||||||
|
global_state.settings.gameplay.zoom_lock_behavior,
|
||||||
|
);
|
||||||
|
|
||||||
if presence == PresenceKind::Spectator {
|
if presence == PresenceKind::Spectator {
|
||||||
let mut client = self.client.borrow_mut();
|
let mut client = self.client.borrow_mut();
|
||||||
if client.spectate_position(cam_pos) {
|
if client.spectate_position(cam_pos) {
|
||||||
@ -609,7 +692,6 @@ impl PlayState for SessionState {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Close => {
|
Event::Close => {
|
||||||
return PlayStateResult::Shutdown;
|
return PlayStateResult::Shutdown;
|
||||||
@ -950,6 +1032,14 @@ impl PlayState for SessionState {
|
|||||||
self.key_state.auto_walk =
|
self.key_state.auto_walk =
|
||||||
self.auto_walk && !self.client.borrow().is_gliding();
|
self.auto_walk && !self.client.borrow().is_gliding();
|
||||||
},
|
},
|
||||||
|
GameInput::ZoomLock => {
|
||||||
|
if state {
|
||||||
|
global_state.settings.gameplay.zoom_lock ^= true;
|
||||||
|
|
||||||
|
self.hud
|
||||||
|
.zoom_lock_toggle(global_state.settings.gameplay.zoom_lock);
|
||||||
|
}
|
||||||
|
},
|
||||||
GameInput::CameraClamp => {
|
GameInput::CameraClamp => {
|
||||||
let hud = &mut self.hud;
|
let hud = &mut self.hud;
|
||||||
global_state.settings.gameplay.camera_clamp_behavior.update(
|
global_state.settings.gameplay.camera_clamp_behavior.update(
|
||||||
@ -1032,6 +1122,13 @@ impl PlayState for SessionState {
|
|||||||
message: screenshot_message,
|
message: screenshot_message,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
Event::Zoom(delta) if self.zoom_lock => {
|
||||||
|
// only fire this Hud event when player has "intent" to zoom
|
||||||
|
if delta.abs() > ZOOM_LOCK_SCROLL_DELTA_INTENT {
|
||||||
|
self.hud.zoom_lock_reminder();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Pass all other events to the scene
|
// Pass all other events to the scene
|
||||||
event => {
|
event => {
|
||||||
self.scene.handle_input_event(event, &self.client.borrow());
|
self.scene.handle_input_event(event, &self.client.borrow());
|
||||||
|
@ -3,8 +3,8 @@ use crate::{
|
|||||||
controller::ControllerSettings,
|
controller::ControllerSettings,
|
||||||
game_input::GameInput,
|
game_input::GameInput,
|
||||||
hud::{
|
hud::{
|
||||||
BarNumbers, BuffPosition, ChatTab, CrosshairType, Intro, PressBehavior, ScaleChange,
|
AutoPressBehavior, BarNumbers, BuffPosition, ChatTab, CrosshairType, Intro, PressBehavior,
|
||||||
ShortcutNumbers, XpBar,
|
ScaleChange, ShortcutNumbers, XpBar,
|
||||||
},
|
},
|
||||||
render::RenderMode,
|
render::RenderMode,
|
||||||
settings::{
|
settings::{
|
||||||
@ -68,9 +68,11 @@ pub enum Gameplay {
|
|||||||
ChangeFreeLookBehavior(PressBehavior),
|
ChangeFreeLookBehavior(PressBehavior),
|
||||||
ChangeAutoWalkBehavior(PressBehavior),
|
ChangeAutoWalkBehavior(PressBehavior),
|
||||||
ChangeCameraClampBehavior(PressBehavior),
|
ChangeCameraClampBehavior(PressBehavior),
|
||||||
|
ChangeZoomLockBehavior(AutoPressBehavior),
|
||||||
ChangeStopAutoWalkOnInput(bool),
|
ChangeStopAutoWalkOnInput(bool),
|
||||||
ChangeAutoCamera(bool),
|
ChangeAutoCamera(bool),
|
||||||
ChangeBowZoom(bool),
|
ChangeBowZoom(bool),
|
||||||
|
ChangeZoomLock(bool),
|
||||||
|
|
||||||
ResetGameplaySettings,
|
ResetGameplaySettings,
|
||||||
}
|
}
|
||||||
@ -386,6 +388,9 @@ impl SettingsChange {
|
|||||||
Gameplay::ChangeCameraClampBehavior(behavior) => {
|
Gameplay::ChangeCameraClampBehavior(behavior) => {
|
||||||
settings.gameplay.camera_clamp_behavior = behavior;
|
settings.gameplay.camera_clamp_behavior = behavior;
|
||||||
},
|
},
|
||||||
|
Gameplay::ChangeZoomLockBehavior(state) => {
|
||||||
|
settings.gameplay.zoom_lock_behavior = state;
|
||||||
|
},
|
||||||
Gameplay::ChangeStopAutoWalkOnInput(state) => {
|
Gameplay::ChangeStopAutoWalkOnInput(state) => {
|
||||||
settings.gameplay.stop_auto_walk_on_input = state;
|
settings.gameplay.stop_auto_walk_on_input = state;
|
||||||
},
|
},
|
||||||
@ -395,6 +400,9 @@ impl SettingsChange {
|
|||||||
Gameplay::ChangeBowZoom(state) => {
|
Gameplay::ChangeBowZoom(state) => {
|
||||||
settings.gameplay.bow_zoom = state;
|
settings.gameplay.bow_zoom = state;
|
||||||
},
|
},
|
||||||
|
Gameplay::ChangeZoomLock(state) => {
|
||||||
|
settings.gameplay.zoom_lock = state;
|
||||||
|
},
|
||||||
Gameplay::ResetGameplaySettings => {
|
Gameplay::ResetGameplaySettings => {
|
||||||
// Reset Gameplay Settings
|
// Reset Gameplay Settings
|
||||||
settings.gameplay = GameplaySettings::default();
|
settings.gameplay = GameplaySettings::default();
|
||||||
|
@ -170,6 +170,7 @@ impl ControlSettings {
|
|||||||
GameInput::ToggleWield => Some(KeyMouse::Key(VirtualKeyCode::R)),
|
GameInput::ToggleWield => Some(KeyMouse::Key(VirtualKeyCode::R)),
|
||||||
GameInput::FreeLook => Some(KeyMouse::Key(VirtualKeyCode::L)),
|
GameInput::FreeLook => Some(KeyMouse::Key(VirtualKeyCode::L)),
|
||||||
GameInput::AutoWalk => Some(KeyMouse::Key(VirtualKeyCode::Period)),
|
GameInput::AutoWalk => Some(KeyMouse::Key(VirtualKeyCode::Period)),
|
||||||
|
GameInput::ZoomLock => Some(KeyMouse::Key(VirtualKeyCode::Semicolon)),
|
||||||
GameInput::CameraClamp => Some(KeyMouse::Key(VirtualKeyCode::Apostrophe)),
|
GameInput::CameraClamp => Some(KeyMouse::Key(VirtualKeyCode::Apostrophe)),
|
||||||
GameInput::CycleCamera => Some(KeyMouse::Key(VirtualKeyCode::Key0)),
|
GameInput::CycleCamera => Some(KeyMouse::Key(VirtualKeyCode::Key0)),
|
||||||
GameInput::Slot1 => Some(KeyMouse::Key(VirtualKeyCode::Key1)),
|
GameInput::Slot1 => Some(KeyMouse::Key(VirtualKeyCode::Key1)),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::hud::PressBehavior;
|
use crate::hud::{AutoPressBehavior, PressBehavior};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// `GameplaySettings` contains sensitivity and gameplay options.
|
/// `GameplaySettings` contains sensitivity and gameplay options.
|
||||||
@ -14,9 +14,11 @@ pub struct GameplaySettings {
|
|||||||
pub free_look_behavior: PressBehavior,
|
pub free_look_behavior: PressBehavior,
|
||||||
pub auto_walk_behavior: PressBehavior,
|
pub auto_walk_behavior: PressBehavior,
|
||||||
pub camera_clamp_behavior: PressBehavior,
|
pub camera_clamp_behavior: PressBehavior,
|
||||||
|
pub zoom_lock_behavior: AutoPressBehavior,
|
||||||
pub stop_auto_walk_on_input: bool,
|
pub stop_auto_walk_on_input: bool,
|
||||||
pub auto_camera: bool,
|
pub auto_camera: bool,
|
||||||
pub bow_zoom: bool,
|
pub bow_zoom: bool,
|
||||||
|
pub zoom_lock: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GameplaySettings {
|
impl Default for GameplaySettings {
|
||||||
@ -31,9 +33,11 @@ impl Default for GameplaySettings {
|
|||||||
free_look_behavior: PressBehavior::Toggle,
|
free_look_behavior: PressBehavior::Toggle,
|
||||||
auto_walk_behavior: PressBehavior::Toggle,
|
auto_walk_behavior: PressBehavior::Toggle,
|
||||||
camera_clamp_behavior: PressBehavior::Toggle,
|
camera_clamp_behavior: PressBehavior::Toggle,
|
||||||
|
zoom_lock_behavior: AutoPressBehavior::Auto,
|
||||||
stop_auto_walk_on_input: true,
|
stop_auto_walk_on_input: true,
|
||||||
auto_camera: false,
|
auto_camera: false,
|
||||||
bow_zoom: true,
|
bow_zoom: true,
|
||||||
|
zoom_lock: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user