Merge branch 'imbirs/hud-map-tweaks' into 'master'

A few tweaks to the Hud map

See merge request veloren/veloren!2901
This commit is contained in:
Imbris 2021-10-06 20:04:39 +00:00
commit fd181d008a
5 changed files with 86 additions and 70 deletions

View File

@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Tweaked CR and exp calculation formula
- Sprite spawn rates
- The Interact button can be used on campfires to sit
- Made map icons fade out when near the edge of the map display
### Removed

View File

@ -103,6 +103,7 @@ pub struct Map<'a> {
rot_imgs: &'a ImgsRot,
tooltip_manager: &'a mut TooltipManager,
location_marker: Option<Vec2<f32>>,
map_drag: Vec2<f64>,
}
impl<'a> Map<'a> {
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
@ -118,6 +119,7 @@ impl<'a> Map<'a> {
global_state: &'a GlobalState,
tooltip_manager: &'a mut TooltipManager,
location_marker: Option<Vec2<f32>>,
map_drag: Vec2<f64>,
) -> Self {
Self {
show,
@ -132,6 +134,7 @@ impl<'a> Map<'a> {
global_state,
tooltip_manager,
location_marker,
map_drag,
}
}
}
@ -145,6 +148,7 @@ pub enum Event {
Close,
RequestSiteInfo(SiteId),
SetLocationMarker(Vec2<f32>),
MapDrag(Vec2<f64>),
ToggleMarker,
}
@ -197,7 +201,6 @@ impl<'a> Widget for Map<'a> {
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
common_base::prof_span!("Map::update");
let widget::UpdateArgs { state, ui, .. } = args;
let drag = self.global_state.settings.interface.map_drag;
let zoom = self.global_state.settings.interface.map_zoom;
let show_difficulty = self.global_state.settings.interface.map_show_difficulty;
let show_towns = self.global_state.settings.interface.map_show_towns;
@ -318,7 +321,7 @@ impl<'a> Widget for Map<'a> {
player_pos.xy().map(|x| x as f64) / TerrainChunkSize::RECT_SIZE.map(|x| x as f64);
let min_drag = player_pos_chunks - worldsize.map(|x| x as f64);
let max_drag = player_pos_chunks;
let drag = drag.clamped(min_drag, max_drag);
let drag = self.map_drag.clamped(min_drag, max_drag);
let handle_widget_mouse_events = |widget,
wpos: Option<Vec2<f32>>,
@ -360,7 +363,7 @@ impl<'a> Widget for Map<'a> {
let mouse_pos = Vec2::from_slice(&cursor_pos);
let drag_new = drag + mouse_pos * (1.0 / new_zoom_lvl - 1.0 / zoom);
if drag_new != drag {
events.push(Event::SettingsChange(MapDrag(drag_new)));
events.push(Event::MapDrag(drag_new));
}
}
}
@ -375,7 +378,7 @@ impl<'a> Widget for Map<'a> {
// Drag represents offset of view from the player_pos in chunk coords
let drag_new = drag + dragged / zoom;
if drag_new != drag {
events.push(Event::SettingsChange(MapDrag(drag_new)));
events.push(Event::MapDrag(drag_new));
}
};
@ -748,37 +751,46 @@ impl<'a> Widget for Map<'a> {
});
}
let wpos_to_rpos = |wpos: Vec2<f32>| {
// Site pos in world coordinates relative to the player
let rwpos = wpos - player_pos;
// Convert to chunk coordinates
let rcpos = rwpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e / sz as f32)
let wpos_to_rpos_fade =
|wpos: Vec2<f32>, bounding_rect_size: Vec2<f32>, fade_start: f32| {
// Site pos in world coordinates relative to the player
let rwpos = wpos - player_pos;
// Convert to chunk coordinates
let rcpos = rwpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e / sz as f32)
// Add map dragging
+ drag.map(|e| e as f32);
// Convert to relative pixel coordinates from the center of the map
// Accounting for zooming
let rpos = rcpos.map(|e| e * zoom as f32);
// Convert to relative pixel coordinates from the center of the map
// Accounting for zooming
let rpos = rcpos.map(|e| e * zoom as f32);
if rpos
.map2(map_size, |e, sz| e.abs() > sz as f32 / 2.0)
.reduce_or()
{
None
} else {
Some(rpos)
}
};
let dist_to_closest_map_edge =
(rpos.map2(map_size, |e, sz| sz as f32 / 2.0 - e.abs()) - bounding_rect_size)
.reduce_partial_min();
match dist_to_closest_map_edge {
x if x <= 0.0 => None,
x if x < fade_start => Some((
rpos,
// Easing function
1.0 - 2.0_f32.powf(-10.0 * x / fade_start),
)),
_ => Some((rpos, 1.0)),
}
};
for (i, site_rich) in self.client.sites().values().enumerate() {
let site = &site_rich.site;
let rpos = match wpos_to_rpos(site.wpos.map(|e| e as f32)) {
let rside = zoom as f32 * 8.0 * 1.2;
let (rpos, fade) = match wpos_to_rpos_fade(
site.wpos.map(|e| e as f32),
Vec2::from(rside / 2.0),
rside / 2.0,
) {
Some(rpos) => rpos,
None => continue,
};
let rside = zoom * 8.0;
let title = site.name.as_deref().unwrap_or_else(|| match &site.kind {
SiteKind::Town => i18n.get("hud.map.town"),
SiteKind::Dungeon { .. } => i18n.get("hud.map.dungeon"),
@ -810,7 +822,7 @@ impl<'a> Widget for Map<'a> {
position::Relative::Scalar(rpos.x as f64),
position::Relative::Scalar(rpos.y as f64),
)
.w_h(rside * 1.2, rside * 1.2)
.w_h(rside as f64, rside as f64)
.hover_image(match &site.kind {
SiteKind::Town => self.imgs.mmap_site_town_hover,
SiteKind::Dungeon { .. } => self.imgs.mmap_site_dungeon_hover,
@ -818,7 +830,7 @@ impl<'a> Widget for Map<'a> {
SiteKind::Cave => self.imgs.mmap_site_cave_hover,
SiteKind::Tree => self.imgs.mmap_site_tree_hover,
})
.image_color(UI_HIGHLIGHT_0)
.image_color(UI_HIGHLIGHT_0.alpha(fade))
.with_tooltip(
self.tooltip_manager,
title,
@ -942,7 +954,13 @@ impl<'a> Widget for Map<'a> {
}
}
for (i, poi) in self.client.pois().iter().enumerate() {
let rpos = match wpos_to_rpos(poi.wpos.map(|e| e as f32)) {
// TODO: computation of text size to pass to wpos_to_rpos_fade, so it can
// determine when it's going past the edge of the map screen
let (rpos, fade) = match wpos_to_rpos_fade(
poi.wpos.map(|e| e as f32),
Vec2::from(zoom as f32 * 3.0),
zoom as f32 * 5.0,
) {
Some(rpos) => rpos,
None => continue,
};
@ -960,14 +978,14 @@ impl<'a> Widget for Map<'a> {
.font_size(self.fonts.cyri.scale((zoom * 3.0) as u32))
.font_id(self.fonts.cyri.conrod_id)
.graphics_for(state.ids.map_layers[0])
.color(TEXT_BG)
.color(TEXT_BG.alpha(fade))
.set(state.ids.mmap_poi_title_bgs[i], ui);
Text::new(title)
.bottom_left_with_margins_on(state.ids.mmap_poi_title_bgs[i], 1.0, 1.0)
.font_size(self.fonts.cyri.scale((zoom * 3.0) as u32))
.font_id(self.fonts.cyri.conrod_id)
//.graphics_for(state.ids.map_layers[0])
.color(TEXT_COLOR)
.color(TEXT_COLOR.alpha(fade))
.set(state.ids.mmap_poi_titles[i], ui);
handle_widget_mouse_events(
@ -992,14 +1010,14 @@ impl<'a> Widget for Map<'a> {
.font_size(self.fonts.cyri.scale((zoom * 3.0) as u32))
.font_id(self.fonts.cyri.conrod_id)
.graphics_for(state.ids.map_layers[0])
.color(TEXT_BG)
.color(TEXT_BG.alpha(fade))
.set(state.ids.peaks_txt_bg, ui);
Text::new(&height)
.bottom_left_with_margins_on(state.ids.peaks_txt_bg, 1.0, 1.0)
.font_size(self.fonts.cyri.scale((zoom * 3.0) as u32))
.font_id(self.fonts.cyri.conrod_id)
.graphics_for(state.ids.map_layers[0])
.color(TEXT_COLOR)
.color(TEXT_COLOR.alpha(fade))
.set(state.ids.peaks_txt, ui);
}
}
@ -1028,7 +1046,7 @@ impl<'a> Widget for Map<'a> {
)
.font_id(self.fonts.cyri.conrod_id)
.graphics_for(state.ids.map_layers[0])
.color(TEXT_BLUE_COLOR)
.color(TEXT_BLUE_COLOR.alpha(fade))
.set(state.ids.mmap_poi_icons[i], ui);
}
},
@ -1070,12 +1088,18 @@ impl<'a> Widget for Map<'a> {
};
if let Some(member_pos) = member_pos {
let rpos = match wpos_to_rpos(member_pos.0.xy().map(|e| e as f32)) {
Some(rpos) => rpos,
let factor = 1.2;
let side_length = 20.0 * factor;
let (rpos, fade) = match wpos_to_rpos_fade(
member_pos.0.xy().map(|e| e as f32),
Vec2::from(side_length / 2.0),
side_length / 2.0,
) {
Some(x) => x,
None => continue,
};
let factor = 1.2;
let z_comparison = (member_pos.0.z - player_pos.z) as i32;
Button::image(match z_comparison {
@ -1088,7 +1112,8 @@ impl<'a> Widget for Map<'a> {
position::Relative::Scalar(rpos.x as f64),
position::Relative::Scalar(rpos.y as f64),
)
.w_h(20.0 * factor, 20.0 * factor)
.w_h(side_length as f64, side_length as f64)
.image_color(Color::Rgba(1.0, 1.0, 1.0, fade))
.floating(true)
.with_tooltip(self.tooltip_manager, &name, "", &site_tooltip, TEXT_COLOR)
.set(state.ids.member_indicators[i], ui);
@ -1105,19 +1130,23 @@ impl<'a> Widget for Map<'a> {
// Location marker
if self.show.map_marker {
if let Some((lm, rpos)) = self
.location_marker
.and_then(|lm| Some(lm).zip(wpos_to_rpos(lm)))
{
let factor = 1.4;
let factor = 1.4;
let side_length = 20.0 * factor;
if let Some((lm, (rpos, fade))) = self.location_marker.and_then(|lm| {
Some(lm).zip(wpos_to_rpos_fade(
lm,
Vec2::from(side_length / 2.0),
side_length / 2.0,
))
}) {
if Button::image(self.imgs.location_marker)
.x_y_position_relative_to(
state.ids.map_layers[0],
position::Relative::Scalar(rpos.x as f64),
position::Relative::Scalar(rpos.y as f64 + 10.0 * factor),
position::Relative::Scalar(rpos.y as f64 + 10.0 * factor as f64),
)
.w_h(20.0 * factor, 20.0 * factor)
.w_h(side_length as f64, side_length as f64)
.image_color(Color::Rgba(1.0, 1.0, 1.0, fade))
.floating(true)
.with_tooltip(
self.tooltip_manager,
@ -1151,21 +1180,14 @@ impl<'a> Widget for Map<'a> {
// Cursor stops moving on an axis as soon as it's position exceeds the maximum
// // size of the widget
// Offset from map center due to dragging
let rcpos = drag.map(|e| e as f32);
// Convert to relative pixel coordinates from the center of the map
// Accounting for zooming
let rpos = rcpos.map(|e| e * zoom as f32);
// Don't show if outside or near the edge of the map
let arrow_sz = {
let scale = 0.5;
Vec2::new(36.0, 37.0) * scale
};
// Hide if icon could go off of the edge of the map
let arrow_mag = arrow_sz.map(|e| e as f32 / 2.0).magnitude();
if !rpos
.map2(map_size, |e, sz| e.abs() + arrow_mag > sz as f32 / 2.0)
.reduce_or()
if let Some((rpos, fade)) =
wpos_to_rpos_fade(player_pos.xy(), arrow_sz, arrow_sz.reduce_partial_min())
{
Image::new(self.rot_imgs.indicator_mmap_small.target_north)
.x_y_position_relative_to(
@ -1173,8 +1195,8 @@ impl<'a> Widget for Map<'a> {
position::Relative::Scalar(rpos.x as f64),
position::Relative::Scalar(rpos.y as f64),
)
.w_h(arrow_sz.x, arrow_sz.y)
.color(Some(UI_HIGHLIGHT_0))
.w_h(arrow_sz.x as f64, arrow_sz.y as f64)
.color(Some(UI_HIGHLIGHT_0.alpha(fade)))
.set(state.ids.indicator, ui);
handle_widget_mouse_events(
@ -1219,7 +1241,7 @@ impl<'a> Widget for Map<'a> {
.set(state.ids.recenter_button, ui)
.was_clicked()
{
events.push(Event::SettingsChange(MapDrag(Vec2::zero())));
events.push(Event::MapDrag(Vec2::zero()));
};
Image::new(self.imgs.m_move_ico)

View File

@ -930,6 +930,7 @@ pub struct Hud {
crosshair_opacity: f32,
floaters: Floaters,
voxel_minimap: VoxelMinimap,
map_drag: Vec2<f64>,
}
impl Hud {
@ -1052,6 +1053,7 @@ impl Hud {
combo_floaters: VecDeque::new(),
block_floaters: Vec::new(),
},
map_drag: Vec2::zero(),
}
}
@ -3064,6 +3066,7 @@ impl Hud {
global_state,
tooltip_manager,
self.show.location_marker,
self.map_drag,
)
.set(self.ids.map, ui_widgets)
{
@ -3082,6 +3085,9 @@ impl Hud {
map::Event::SetLocationMarker(pos) => {
self.show.location_marker = Some(pos);
},
map::Event::MapDrag(new_drag) => {
self.map_drag = new_drag;
},
map::Event::ToggleMarker => {
self.show.map_marker = !self.show.map_marker;
},
@ -3089,12 +3095,7 @@ impl Hud {
}
} else {
// Reset the map position when it's not showing
let drag = &global_state.settings.interface.map_drag;
if drag.x != 0.0 || drag.y != 0.0 {
events.push(Event::SettingsChange(
InterfaceChange::MapDrag(Vec2::zero()).into(),
))
}
self.map_drag = Vec2::zero();
}
if self.show.esc_menu {

View File

@ -15,7 +15,6 @@ use crate::{
GlobalState,
};
use i18n::{LanguageMetadata, LocalizationHandle};
use vek::*;
#[derive(Clone)]
pub enum Audio {
@ -118,7 +117,6 @@ pub enum Interface {
MinimapZoom(f64),
//Map settings
MapZoom(f64),
MapDrag(Vec2<f64>),
MapShowTopoMap(bool),
MapShowDifficulty(bool),
MapShowTowns(bool),
@ -497,9 +495,6 @@ impl SettingsChange {
Interface::MapZoom(map_zoom) => {
settings.interface.map_zoom = map_zoom;
},
Interface::MapDrag(map_drag) => {
settings.interface.map_drag = map_drag;
},
Interface::MapShowTopoMap(map_show_topo_map) => {
settings.interface.map_show_topo_map = map_show_topo_map;
},

View File

@ -3,7 +3,6 @@ use crate::{
ui::ScaleMode,
};
use serde::{Deserialize, Serialize};
use vek::*;
/// `InterfaceSettings` contains UI, HUD and Map options.
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -29,7 +28,6 @@ pub struct InterfaceSettings {
pub always_show_bars: bool,
pub ui_scale: ScaleMode,
pub map_zoom: f64,
pub map_drag: Vec2<f64>,
pub map_show_topo_map: bool,
pub map_show_difficulty: bool,
pub map_show_towns: bool,
@ -68,7 +66,6 @@ impl Default for InterfaceSettings {
always_show_bars: false,
ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()),
map_zoom: 10.0,
map_drag: Vec2 { x: 0.0, y: 0.0 },
map_show_topo_map: true,
map_show_difficulty: true,
map_show_towns: true,