veloren/voxygen/src/hud/change_notification.rs
Cat Stevens 83e4cdfe76 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`.
2023-03-05 11:30:27 -05:00

87 lines
2.5 KiB
Rust

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;
}
}
}
}