mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Popup message when setting waypoint
This commit is contained in:
parent
51eb928eb8
commit
0a723614f9
@ -72,6 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Player now starts with a lantern. Equipping/unequipping a lantern has the same effect as the `/lantern` command
|
- Player now starts with a lantern. Equipping/unequipping a lantern has the same effect as the `/lantern` command
|
||||||
- Added tab completion in chat for player names and chat commands
|
- Added tab completion in chat for player names and chat commands
|
||||||
- Added server persistence for character stats
|
- Added server persistence for character stats
|
||||||
|
- Added a popup when setting your character's waypoint
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ https://account.veloren.net."#,
|
|||||||
"hud.show_tips": "Show Tips",
|
"hud.show_tips": "Show Tips",
|
||||||
"hud.quests": "Quests",
|
"hud.quests": "Quests",
|
||||||
"hud.you_died": "You Died",
|
"hud.you_died": "You Died",
|
||||||
|
"hud.waypoint_saved": "Waypoint Saved",
|
||||||
|
|
||||||
"hud.press_key_to_show_keybindings_fmt": "Press {key} to show keybindings",
|
"hud.press_key_to_show_keybindings_fmt": "Press {key} to show keybindings",
|
||||||
"hud.press_key_to_show_debug_info_fmt": "Press {key} to show debug info",
|
"hud.press_key_to_show_debug_info_fmt": "Press {key} to show debug info",
|
||||||
|
@ -93,6 +93,7 @@ fn main() {
|
|||||||
|
|
||||||
println!("{}", message)
|
println!("{}", message)
|
||||||
},
|
},
|
||||||
|
Event::Notification(_) => {}, // TODO?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,9 @@ use common::{
|
|||||||
},
|
},
|
||||||
event::{EventBus, SfxEvent, SfxEventItem},
|
event::{EventBus, SfxEvent, SfxEventItem},
|
||||||
msg::{
|
msg::{
|
||||||
validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate,
|
validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, Notification,
|
||||||
RegisterError, RequestStateError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG,
|
PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg,
|
||||||
|
MAX_BYTES_CHAT_MSG,
|
||||||
},
|
},
|
||||||
net::PostBox,
|
net::PostBox,
|
||||||
state::State,
|
state::State,
|
||||||
@ -59,6 +60,7 @@ pub enum Event {
|
|||||||
},
|
},
|
||||||
Disconnect,
|
Disconnect,
|
||||||
DisconnectionNotification(u64),
|
DisconnectionNotification(u64),
|
||||||
|
Notification(Notification),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
@ -865,6 +867,9 @@ impl Client {
|
|||||||
warn!("CharacterActionError: {:?}.", error);
|
warn!("CharacterActionError: {:?}.", error);
|
||||||
self.character_list.error = Some(error);
|
self.character_list.error = Some(error);
|
||||||
},
|
},
|
||||||
|
ServerMsg::Notification(n) => {
|
||||||
|
frontend_events.push(Event::Notification(n));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(err) = self.postbox.error() {
|
} else if let Some(err) = self.postbox.error() {
|
||||||
|
@ -6,7 +6,9 @@ pub mod server;
|
|||||||
pub use self::{
|
pub use self::{
|
||||||
client::ClientMsg,
|
client::ClientMsg,
|
||||||
ecs_packet::EcsCompPacket,
|
ecs_packet::EcsCompPacket,
|
||||||
server::{PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg},
|
server::{
|
||||||
|
Notification, PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
|
@ -26,6 +26,11 @@ pub enum PlayerListUpdate {
|
|||||||
Alias(u64, String),
|
Alias(u64, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum Notification {
|
||||||
|
WaypointSaved,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum ServerMsg {
|
pub enum ServerMsg {
|
||||||
InitialSync {
|
InitialSync {
|
||||||
@ -64,6 +69,8 @@ pub enum ServerMsg {
|
|||||||
Disconnect,
|
Disconnect,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
TooManyPlayers,
|
TooManyPlayers,
|
||||||
|
/// Send a popup notification such as "Waypoint Saved"
|
||||||
|
Notification(Notification),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
|
@ -9,7 +9,7 @@ use common::{
|
|||||||
cmd::{ChatCommand, CHAT_COMMANDS},
|
cmd::{ChatCommand, CHAT_COMMANDS},
|
||||||
comp,
|
comp,
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
msg::{PlayerListUpdate, ServerMsg},
|
msg::{Notification, PlayerListUpdate, ServerMsg},
|
||||||
npc::{self, get_npc_name},
|
npc::{self, get_npc_name},
|
||||||
state::TimeOfDay,
|
state::TimeOfDay,
|
||||||
sync::{Uid, WorldSyncExt},
|
sync::{Uid, WorldSyncExt},
|
||||||
@ -838,7 +838,8 @@ fn handle_waypoint(
|
|||||||
.ecs()
|
.ecs()
|
||||||
.write_storage::<comp::Waypoint>()
|
.write_storage::<comp::Waypoint>()
|
||||||
.insert(target, comp::Waypoint::new(pos.0));
|
.insert(target, comp::Waypoint::new(pos.0));
|
||||||
server.notify_client(client, ServerMsg::private(String::from("Waypoint set!")));
|
server.notify_client(client, ServerMsg::private(String::from("Waypoint saved!")));
|
||||||
|
server.notify_client(client, ServerMsg::Notification(Notification::WaypointSaved));
|
||||||
},
|
},
|
||||||
None => server.notify_client(
|
None => server.notify_client(
|
||||||
client,
|
client,
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
use super::SysTimer;
|
use super::SysTimer;
|
||||||
use common::comp::{Player, Pos, Waypoint, WaypointArea};
|
use crate::client::Client;
|
||||||
|
use common::{
|
||||||
|
comp::{Player, Pos, Waypoint, WaypointArea},
|
||||||
|
msg::{Notification, ServerMsg},
|
||||||
|
};
|
||||||
use specs::{Entities, Join, ReadStorage, System, Write, WriteStorage};
|
use specs::{Entities, Join, ReadStorage, System, Write, WriteStorage};
|
||||||
|
|
||||||
|
const NOTIFY_DISTANCE: f32 = 10.0;
|
||||||
|
|
||||||
/// This system updates player waypoints
|
/// This system updates player waypoints
|
||||||
/// TODO: Make this faster by only considering local waypoints
|
/// TODO: Make this faster by only considering local waypoints
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
@ -12,19 +18,28 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadStorage<'a, Player>,
|
ReadStorage<'a, Player>,
|
||||||
ReadStorage<'a, WaypointArea>,
|
ReadStorage<'a, WaypointArea>,
|
||||||
WriteStorage<'a, Waypoint>,
|
WriteStorage<'a, Waypoint>,
|
||||||
|
WriteStorage<'a, Client>,
|
||||||
Write<'a, SysTimer<Self>>,
|
Write<'a, SysTimer<Self>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
(entities, positions, players, waypoint_areas, mut waypoints, mut timer): Self::SystemData,
|
(entities, positions, players, waypoint_areas, mut waypoints, mut clients, mut timer): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
for (entity, player_pos, _) in (&entities, &positions, &players).join() {
|
for (entity, player_pos, _, client) in
|
||||||
for (waypoint_pos, waypoint_area) in (&positions, &waypoint_areas).join() {
|
(&entities, &positions, &players, &mut clients).join()
|
||||||
if player_pos.0.distance_squared(waypoint_pos.0) < waypoint_area.radius().powf(2.0)
|
|
||||||
{
|
{
|
||||||
|
for (waypoint_pos, waypoint_area) in (&positions, &waypoint_areas).join() {
|
||||||
|
if player_pos.0.distance_squared(waypoint_pos.0) < waypoint_area.radius().powi(2) {
|
||||||
|
if let Some(wp) = waypoints.get(entity) {
|
||||||
|
if player_pos.0.distance_squared(wp.get_pos()) > NOTIFY_DISTANCE.powi(2) {
|
||||||
|
client
|
||||||
|
.postbox
|
||||||
|
.send_message(ServerMsg::Notification(Notification::WaypointSaved));
|
||||||
|
}
|
||||||
|
}
|
||||||
let _ = waypoints.insert(entity, Waypoint::new(player_pos.0));
|
let _ = waypoints.insert(entity, Waypoint::new(player_pos.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{
|
use super::{
|
||||||
img_ids::{Imgs, ImgsRot},
|
img_ids::{Imgs, ImgsRot},
|
||||||
Show, HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
Show, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||||
};
|
};
|
||||||
use crate::ui::{fonts::ConrodVoxygenFonts, img_ids};
|
use crate::ui::{fonts::ConrodVoxygenFonts, img_ids};
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
@ -8,10 +8,9 @@ use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
|
|||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color, position,
|
color, position,
|
||||||
widget::{self, Button, Image, Rectangle, Text},
|
widget::{self, Button, Image, Rectangle, Text},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
use specs::WorldExt;
|
use specs::WorldExt;
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
widget_ids! {
|
widget_ids! {
|
||||||
@ -68,8 +67,6 @@ impl<'a> MiniMap<'a> {
|
|||||||
pub struct State {
|
pub struct State {
|
||||||
ids: Ids,
|
ids: Ids,
|
||||||
|
|
||||||
last_region_name: Option<String>,
|
|
||||||
last_update: Instant,
|
|
||||||
zoom: f64,
|
zoom: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +83,6 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
State {
|
State {
|
||||||
ids: Ids::new(id_gen),
|
ids: Ids::new(id_gen),
|
||||||
|
|
||||||
last_region_name: None,
|
|
||||||
last_update: Instant::now(),
|
|
||||||
zoom: {
|
zoom: {
|
||||||
let min_world_dim = self.world_map.1.reduce_partial_min() as f64;
|
let min_world_dim = self.world_map.1.reduce_partial_min() as f64;
|
||||||
min_world_dim.min(
|
min_world_dim.min(
|
||||||
@ -250,57 +245,6 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
return Some(Event::Toggle);
|
return Some(Event::Toggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display zone name on entry
|
|
||||||
|
|
||||||
const FADE_IN: f32 = 0.5;
|
|
||||||
const FADE_HOLD: f32 = 1.0;
|
|
||||||
const FADE_OUT: f32 = 3.0;
|
|
||||||
match self.client.current_chunk() {
|
|
||||||
Some(chunk) => {
|
|
||||||
let current = chunk.meta().name();
|
|
||||||
// Check if no other popup is displayed and a new one is needed
|
|
||||||
if state.last_update.elapsed()
|
|
||||||
> Duration::from_secs_f32(FADE_IN + FADE_HOLD + FADE_OUT)
|
|
||||||
&& state
|
|
||||||
.last_region_name
|
|
||||||
.as_ref()
|
|
||||||
.map(|l| l != current)
|
|
||||||
.unwrap_or(true)
|
|
||||||
{
|
|
||||||
// Update last_region
|
|
||||||
state.update(|s| s.last_region_name = Some(current.to_owned()));
|
|
||||||
state.update(|s| s.last_update = Instant::now());
|
|
||||||
}
|
|
||||||
|
|
||||||
let seconds = state.last_update.elapsed().as_secs_f32();
|
|
||||||
let fade = if seconds < FADE_IN {
|
|
||||||
seconds / FADE_IN
|
|
||||||
} else if seconds < FADE_IN + FADE_HOLD {
|
|
||||||
1.0
|
|
||||||
} else {
|
|
||||||
(1.0 - (seconds - FADE_IN - FADE_HOLD) / FADE_OUT).max(0.0)
|
|
||||||
};
|
|
||||||
// Region Name
|
|
||||||
Text::new(state.last_region_name.as_ref().unwrap_or(&"".to_owned()))
|
|
||||||
.mid_top_with_margin_on(ui.window, 200.0)
|
|
||||||
.font_size(self.fonts.alkhemi.scale(70))
|
|
||||||
.font_id(self.fonts.alkhemi.conrod_id)
|
|
||||||
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
|
|
||||||
.set(state.ids.zone_display_bg, ui);
|
|
||||||
Text::new(state.last_region_name.as_ref().unwrap_or(&"".to_owned()))
|
|
||||||
.top_left_with_margins_on(state.ids.zone_display_bg, -2.5, -2.5)
|
|
||||||
.font_size(self.fonts.alkhemi.scale(70))
|
|
||||||
.font_id(self.fonts.alkhemi.conrod_id)
|
|
||||||
.color(Color::Rgba(1.0, 1.0, 1.0, fade))
|
|
||||||
.set(state.ids.zone_display, ui);
|
|
||||||
},
|
|
||||||
None => Text::new(" ")
|
|
||||||
.middle_of(ui.window)
|
|
||||||
.font_size(self.fonts.alkhemi.scale(14))
|
|
||||||
.color(HP_COLOR)
|
|
||||||
.set(state.ids.zone_display, ui),
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Subregion name display
|
// TODO: Subregion name display
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
|
@ -7,6 +7,7 @@ mod img_ids;
|
|||||||
mod item_imgs;
|
mod item_imgs;
|
||||||
mod map;
|
mod map;
|
||||||
mod minimap;
|
mod minimap;
|
||||||
|
mod popup;
|
||||||
mod settings_window;
|
mod settings_window;
|
||||||
mod skillbar;
|
mod skillbar;
|
||||||
mod slots;
|
mod slots;
|
||||||
@ -26,6 +27,7 @@ use img_ids::Imgs;
|
|||||||
use item_imgs::ItemImgs;
|
use item_imgs::ItemImgs;
|
||||||
use map::Map;
|
use map::Map;
|
||||||
use minimap::MiniMap;
|
use minimap::MiniMap;
|
||||||
|
use popup::Popup;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings_window::{SettingsTab, SettingsWindow};
|
use settings_window::{SettingsTab, SettingsWindow};
|
||||||
use skillbar::Skillbar;
|
use skillbar::Skillbar;
|
||||||
@ -174,6 +176,7 @@ widget_ids! {
|
|||||||
map,
|
map,
|
||||||
world_map,
|
world_map,
|
||||||
character_window,
|
character_window,
|
||||||
|
popup,
|
||||||
minimap,
|
minimap,
|
||||||
bag,
|
bag,
|
||||||
social,
|
social,
|
||||||
@ -1641,6 +1644,10 @@ impl Hud {
|
|||||||
None => {},
|
None => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
Popup::new(&self.voxygen_i18n, client, &self.new_messages, &self.fonts)
|
||||||
|
.set(self.ids.popup, ui_widgets);
|
||||||
|
|
||||||
// MiniMap
|
// MiniMap
|
||||||
match MiniMap::new(
|
match MiniMap::new(
|
||||||
&self.show,
|
&self.show,
|
||||||
@ -1734,6 +1741,16 @@ impl Hud {
|
|||||||
.set(self.ids.skillbar, ui_widgets);
|
.set(self.ids.skillbar, ui_widgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The chat box breaks if it has non-chat messages left in the queue, so take
|
||||||
|
// them out.
|
||||||
|
self.new_messages.retain(|msg| {
|
||||||
|
if let ClientEvent::Chat { .. } = &msg {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Chat box
|
// Chat box
|
||||||
match Chat::new(
|
match Chat::new(
|
||||||
&mut self.new_messages,
|
&mut self.new_messages,
|
||||||
|
233
voxygen/src/hud/popup.rs
Normal file
233
voxygen/src/hud/popup.rs
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
use crate::{i18n::VoxygenLocalization, ui::fonts::ConrodVoxygenFonts};
|
||||||
|
use client::{self, Client, Event as ClientEvent};
|
||||||
|
use common::msg::Notification;
|
||||||
|
use conrod_core::{
|
||||||
|
widget::{self, Text},
|
||||||
|
widget_ids, Color, Colorable, Positionable, Widget, WidgetCommon,
|
||||||
|
};
|
||||||
|
use std::{collections::VecDeque, time::Instant};
|
||||||
|
|
||||||
|
widget_ids! {
|
||||||
|
struct Ids {
|
||||||
|
error_bg,
|
||||||
|
error_text,
|
||||||
|
info_bg,
|
||||||
|
info_text,
|
||||||
|
message_bg,
|
||||||
|
message_text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(WidgetCommon)]
|
||||||
|
pub struct Popup<'a> {
|
||||||
|
voxygen_i18n: &'a std::sync::Arc<VoxygenLocalization>,
|
||||||
|
client: &'a Client,
|
||||||
|
new_messages: &'a VecDeque<ClientEvent>,
|
||||||
|
fonts: &'a ConrodVoxygenFonts,
|
||||||
|
#[conrod(common_builder)]
|
||||||
|
common: widget::CommonBuilder,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Popup notifications for messages such as <Chunk Name>, Waypoint Saved,
|
||||||
|
/// Dungeon Cleared (TODO), and Quest Completed (TODO)
|
||||||
|
impl<'a> Popup<'a> {
|
||||||
|
pub fn new(
|
||||||
|
voxygen_i18n: &'a std::sync::Arc<VoxygenLocalization>,
|
||||||
|
client: &'a Client,
|
||||||
|
new_messages: &'a VecDeque<ClientEvent>,
|
||||||
|
fonts: &'a ConrodVoxygenFonts,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
voxygen_i18n,
|
||||||
|
client,
|
||||||
|
new_messages,
|
||||||
|
fonts,
|
||||||
|
common: widget::CommonBuilder::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
ids: Ids,
|
||||||
|
errors: VecDeque<String>,
|
||||||
|
infos: VecDeque<String>,
|
||||||
|
messages: VecDeque<String>,
|
||||||
|
last_error_update: Instant,
|
||||||
|
last_info_update: Instant,
|
||||||
|
last_message_update: Instant,
|
||||||
|
last_region_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Widget for Popup<'a> {
|
||||||
|
type Event = ();
|
||||||
|
type State = State;
|
||||||
|
type Style = ();
|
||||||
|
|
||||||
|
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
|
||||||
|
State {
|
||||||
|
ids: Ids::new(id_gen),
|
||||||
|
errors: VecDeque::new(),
|
||||||
|
infos: VecDeque::new(),
|
||||||
|
messages: VecDeque::new(),
|
||||||
|
last_error_update: Instant::now(),
|
||||||
|
last_info_update: Instant::now(),
|
||||||
|
last_message_update: Instant::now(),
|
||||||
|
last_region_name: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self) -> Self::Style { () }
|
||||||
|
|
||||||
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
|
let widget::UpdateArgs { state, ui, .. } = args;
|
||||||
|
|
||||||
|
const FADE_IN: f32 = 0.5;
|
||||||
|
const FADE_HOLD: f32 = 1.0;
|
||||||
|
const FADE_OUT: f32 = 3.0;
|
||||||
|
|
||||||
|
let bg_color = |fade| Color::Rgba(0.0, 0.0, 0.0, fade);
|
||||||
|
let error_color = |fade| Color::Rgba(1.0, 0.0, 0.0, fade);
|
||||||
|
let info_color = |fade| Color::Rgba(1.0, 1.0, 0.0, fade);
|
||||||
|
let message_color = |fade| Color::Rgba(1.0, 1.0, 1.0, fade);
|
||||||
|
|
||||||
|
// Push chunk name to message queue
|
||||||
|
if let Some(chunk) = self.client.current_chunk() {
|
||||||
|
let current = chunk.meta().name();
|
||||||
|
// Check if no other popup is displayed and a new one is needed
|
||||||
|
if state.messages.is_empty()
|
||||||
|
&& state
|
||||||
|
.last_region_name
|
||||||
|
.as_ref()
|
||||||
|
.map(|l| l != current)
|
||||||
|
.unwrap_or(true)
|
||||||
|
{
|
||||||
|
// Update last_region
|
||||||
|
state.update(|s| {
|
||||||
|
if s.messages.is_empty() {
|
||||||
|
s.last_message_update = Instant::now();
|
||||||
|
}
|
||||||
|
s.last_region_name = Some(current.to_owned());
|
||||||
|
s.messages.push_back(current.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push waypoint to message queue
|
||||||
|
for notification in self.new_messages {
|
||||||
|
match notification {
|
||||||
|
ClientEvent::Notification(Notification::WaypointSaved) => {
|
||||||
|
state.update(|s| {
|
||||||
|
if s.infos.is_empty() {
|
||||||
|
s.last_info_update = Instant::now();
|
||||||
|
}
|
||||||
|
let text = self.voxygen_i18n.get("hud.waypoint_saved");
|
||||||
|
s.infos.push_back(text.to_string());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next error from queue
|
||||||
|
if !state.errors.is_empty()
|
||||||
|
&& state.last_error_update.elapsed().as_secs_f32() > FADE_IN + FADE_HOLD + FADE_OUT
|
||||||
|
{
|
||||||
|
state.update(|s| {
|
||||||
|
s.errors.pop_front();
|
||||||
|
s.last_error_update = Instant::now();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display error as popup
|
||||||
|
if let Some(error) = state.errors.front() {
|
||||||
|
let seconds = state.last_error_update.elapsed().as_secs_f32();
|
||||||
|
let fade = if seconds < FADE_IN {
|
||||||
|
seconds / FADE_IN
|
||||||
|
} else if seconds < FADE_IN + FADE_HOLD {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
(1.0 - (seconds - FADE_IN - FADE_HOLD) / FADE_OUT).max(0.0)
|
||||||
|
};
|
||||||
|
Text::new(error)
|
||||||
|
.mid_top_with_margin_on(ui.window, 50.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(20))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(bg_color(fade))
|
||||||
|
.set(state.ids.error_bg, ui);
|
||||||
|
Text::new(error)
|
||||||
|
.top_left_with_margins_on(state.ids.error_bg, -1.0, -1.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(20))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(error_color(fade))
|
||||||
|
.set(state.ids.error_text, ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next info from queue
|
||||||
|
if !state.infos.is_empty()
|
||||||
|
&& state.last_info_update.elapsed().as_secs_f32() > FADE_IN + FADE_HOLD + FADE_OUT
|
||||||
|
{
|
||||||
|
state.update(|s| {
|
||||||
|
s.infos.pop_front();
|
||||||
|
s.last_info_update = Instant::now();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display info as popup
|
||||||
|
if let Some(info) = state.infos.front() {
|
||||||
|
let seconds = state.last_info_update.elapsed().as_secs_f32();
|
||||||
|
let fade = if seconds < FADE_IN {
|
||||||
|
seconds / FADE_IN
|
||||||
|
} else if seconds < FADE_IN + FADE_HOLD {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
(1.0 - (seconds - FADE_IN - FADE_HOLD) / FADE_OUT).max(0.0)
|
||||||
|
};
|
||||||
|
Text::new(info)
|
||||||
|
.mid_top_with_margin_on(ui.window, 100.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(20))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(bg_color(fade))
|
||||||
|
.set(state.ids.info_bg, ui);
|
||||||
|
Text::new(info)
|
||||||
|
.top_left_with_margins_on(state.ids.info_bg, -1.0, -1.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(20))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.color(info_color(fade))
|
||||||
|
.set(state.ids.info_text, ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next message from queue
|
||||||
|
if !state.messages.is_empty()
|
||||||
|
&& state.last_message_update.elapsed().as_secs_f32() > FADE_IN + FADE_HOLD + FADE_OUT
|
||||||
|
{
|
||||||
|
state.update(|s| {
|
||||||
|
s.messages.pop_front();
|
||||||
|
s.last_message_update = Instant::now();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display message as popup
|
||||||
|
if let Some(message) = state.messages.front() {
|
||||||
|
let seconds = state.last_message_update.elapsed().as_secs_f32();
|
||||||
|
let fade = if seconds < FADE_IN {
|
||||||
|
seconds / FADE_IN
|
||||||
|
} else if seconds < FADE_IN + FADE_HOLD {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
(1.0 - (seconds - FADE_IN - FADE_HOLD) / FADE_OUT).max(0.0)
|
||||||
|
};
|
||||||
|
Text::new(message)
|
||||||
|
.mid_top_with_margin_on(ui.window, 200.0)
|
||||||
|
.font_size(self.fonts.alkhemi.scale(70))
|
||||||
|
.font_id(self.fonts.alkhemi.conrod_id)
|
||||||
|
.color(bg_color(fade))
|
||||||
|
.set(state.ids.message_bg, ui);
|
||||||
|
Text::new(message)
|
||||||
|
.top_left_with_margins_on(state.ids.message_bg, -2.5, -2.5)
|
||||||
|
.font_size(self.fonts.alkhemi.scale(70))
|
||||||
|
.font_id(self.fonts.alkhemi.conrod_id)
|
||||||
|
.color(message_color(fade))
|
||||||
|
.set(state.ids.message_text, ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
clock::Clock,
|
clock::Clock,
|
||||||
comp,
|
comp,
|
||||||
comp::{Pos, Vel, MAX_PICKUP_RANGE_SQR},
|
comp::{Pos, Vel, MAX_PICKUP_RANGE_SQR},
|
||||||
msg::ClientState,
|
msg::{ClientState, Notification},
|
||||||
terrain::{Block, BlockKind},
|
terrain::{Block, BlockKind},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
@ -102,6 +102,10 @@ impl SessionState {
|
|||||||
message,
|
message,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
client::Event::Notification(Notification::WaypointSaved) => {
|
||||||
|
self.hud
|
||||||
|
.new_message(client::Event::Notification(Notification::WaypointSaved));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user