mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Impove UX of server limits on the view distance
* When client gets its view distance set by the server it stores that as the max view distance allowed by the server. * This is used to avoid skip sending requests if `set_view_distance` is called with larger values. * This is then also displayed in the UI via greying out the slider when it goes past the limit and drawing another slide at the limit. * The server clamping the client's view distance no longer leads to edits in voxygen's view distance settings (the view distance setting is instead preserved).
This commit is contained in:
parent
c36d6e873f
commit
895d6a2d8b
@ -248,6 +248,7 @@ pub struct Client {
|
||||
tick: u64,
|
||||
state: State,
|
||||
|
||||
server_view_distance_limit: Option<u32>,
|
||||
view_distance: Option<u32>,
|
||||
lod_distance: f32,
|
||||
// TODO: move into voxygen
|
||||
@ -707,6 +708,7 @@ impl Client {
|
||||
|
||||
tick: 0,
|
||||
state,
|
||||
server_view_distance_limit: None,
|
||||
view_distance: None,
|
||||
lod_distance: 4.0,
|
||||
loaded_distance: 0.0,
|
||||
@ -943,9 +945,11 @@ impl Client {
|
||||
}
|
||||
|
||||
pub fn set_view_distance(&mut self, view_distance: u32) {
|
||||
let view_distance = view_distance.max(1).min(65);
|
||||
self.view_distance = Some(view_distance);
|
||||
self.send_msg(ClientGeneral::SetViewDistance(view_distance));
|
||||
if self.server_view_distance_limit.map_or(true, |limit| view_distance >= limit) {
|
||||
let view_distance = view_distance.max(1).min(65);
|
||||
self.view_distance = Some(view_distance);
|
||||
self.send_msg(ClientGeneral::SetViewDistance(view_distance));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_lod_distance(&mut self, lod_distance: u32) {
|
||||
@ -1486,6 +1490,8 @@ impl Client {
|
||||
|
||||
pub fn view_distance(&self) -> Option<u32> { self.view_distance }
|
||||
|
||||
pub fn server_view_distance_limit(&self) -> Option<u32> { self.server_view_distance_limit }
|
||||
|
||||
pub fn loaded_distance(&self) -> f32 { self.loaded_distance }
|
||||
|
||||
pub fn position(&self) -> Option<Vec3<f32>> {
|
||||
@ -2254,6 +2260,9 @@ impl Client {
|
||||
ServerGeneral::SetViewDistance(vd) => {
|
||||
self.view_distance = Some(vd);
|
||||
frontend_events.push(Event::SetViewDistance(vd));
|
||||
// If the server is correcting client vd selection we assume this is the max
|
||||
// allowed view distance.
|
||||
self.server_view_distance_limit = Some(vd);
|
||||
},
|
||||
ServerGeneral::Outcomes(outcomes) => {
|
||||
frontend_events.extend(outcomes.into_iter().map(Event::Outcome))
|
||||
|
@ -3063,6 +3063,7 @@ impl Hud {
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
i18n,
|
||||
client.server_view_distance_limit(),
|
||||
fps as f32,
|
||||
)
|
||||
.set(self.ids.settings_window, ui_widgets)
|
||||
|
@ -93,6 +93,7 @@ pub struct SettingsWindow<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
server_view_distance_limit: Option<u32>,
|
||||
fps: f32,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
@ -105,6 +106,7 @@ impl<'a> SettingsWindow<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
server_view_distance_limit: Option<u32>,
|
||||
fps: f32,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -113,6 +115,7 @@ impl<'a> SettingsWindow<'a> {
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
server_view_distance_limit,
|
||||
fps,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
@ -299,11 +302,17 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
},
|
||||
SettingsTab::Video => {
|
||||
for change in
|
||||
video::Video::new(global_state, imgs, fonts, localized_strings, self.fps)
|
||||
.top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
|
||||
.wh_of(state.ids.settings_content_align)
|
||||
.set(state.ids.video, ui)
|
||||
for change in video::Video::new(
|
||||
global_state,
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
self.server_view_distance_limit,
|
||||
self.fps,
|
||||
)
|
||||
.top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
|
||||
.wh_of(state.ids.settings_content_align)
|
||||
.set(state.ids.video, ui)
|
||||
{
|
||||
events.push(Event::SettingsChange(change.into()));
|
||||
}
|
||||
@ -327,11 +336,16 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
},
|
||||
SettingsTab::Networking => {
|
||||
for change in
|
||||
networking::Networking::new(global_state, imgs, fonts, localized_strings)
|
||||
.top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
|
||||
.wh_of(state.ids.settings_content_align)
|
||||
.set(state.ids.networking, ui)
|
||||
for change in networking::Networking::new(
|
||||
global_state,
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
self.server_view_distance_limit,
|
||||
)
|
||||
.top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
|
||||
.wh_of(state.ids.settings_content_align)
|
||||
.set(state.ids.networking, ui)
|
||||
{
|
||||
events.push(Event::SettingsChange(change.into()));
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ pub struct Networking<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
server_view_distance_limit: Option<u32>,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
@ -43,12 +44,14 @@ impl<'a> Networking<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
server_view_distance_limit: Option<u32>,
|
||||
) -> Self {
|
||||
Self {
|
||||
global_state,
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
server_view_distance_limit,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
@ -107,6 +110,7 @@ impl<'a> Widget for Networking<'a> {
|
||||
.down_from(state.ids.vd_text, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.soft_max(self.server_view_distance_limit.unwrap_or(u32::MAX))
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.vd_slider, ui)
|
||||
{
|
||||
|
@ -131,6 +131,7 @@ pub struct Video<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
server_view_distance_limit: Option<u32>,
|
||||
fps: f32,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
@ -141,6 +142,7 @@ impl<'a> Video<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
server_view_distance_limit: Option<u32>,
|
||||
fps: f32,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -148,6 +150,7 @@ impl<'a> Video<'a> {
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
server_view_distance_limit,
|
||||
fps,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
@ -295,6 +298,7 @@ impl<'a> Widget for Video<'a> {
|
||||
.down_from(state.ids.vd_text, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.soft_max(self.server_view_distance_limit.unwrap_or(u32::MAX))
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.vd_slider, ui)
|
||||
{
|
||||
|
@ -215,12 +215,7 @@ impl PlayState for CharSelectionState {
|
||||
Ok(events) => {
|
||||
for event in events {
|
||||
match event {
|
||||
client::Event::SetViewDistance(vd) => {
|
||||
global_state.settings.graphics.view_distance = vd;
|
||||
global_state
|
||||
.settings
|
||||
.save_to_file_warn(&global_state.config_dir);
|
||||
},
|
||||
client::Event::SetViewDistance(_vd) => {},
|
||||
client::Event::Disconnect => {
|
||||
global_state.info_message = Some(
|
||||
localized_strings
|
||||
|
@ -231,12 +231,7 @@ impl PlayState for MainMenuState {
|
||||
Ok(events) => {
|
||||
for event in events {
|
||||
match event {
|
||||
client::Event::SetViewDistance(vd) => {
|
||||
global_state.settings.graphics.view_distance = vd;
|
||||
global_state
|
||||
.settings
|
||||
.save_to_file_warn(&global_state.config_dir);
|
||||
},
|
||||
client::Event::SetViewDistance(_vd) => {},
|
||||
client::Event::Disconnect => {
|
||||
global_state.info_message = Some(
|
||||
localized_strings
|
||||
|
@ -351,12 +351,7 @@ impl SessionState {
|
||||
client::Event::Notification(n) => {
|
||||
self.hud.new_notification(n);
|
||||
},
|
||||
client::Event::SetViewDistance(vd) => {
|
||||
global_state.settings.graphics.view_distance = vd;
|
||||
global_state
|
||||
.settings
|
||||
.save_to_file_warn(&global_state.config_dir);
|
||||
},
|
||||
client::Event::SetViewDistance(_vd) => {},
|
||||
client::Event::Outcome(outcome) => outcomes.push(outcome),
|
||||
client::Event::CharacterCreated(_) => {},
|
||||
client::Event::CharacterEdited(_) => {},
|
||||
|
@ -355,12 +355,7 @@ impl SettingsChange {
|
||||
SettingsChange::Graphics(graphics_change) => {
|
||||
match graphics_change {
|
||||
Graphics::AdjustViewDistance(view_distance) => {
|
||||
session_state
|
||||
.client
|
||||
.borrow_mut()
|
||||
.set_view_distance(view_distance);
|
||||
|
||||
settings.graphics.view_distance = view_distance;
|
||||
adjust_view_distance(view_distance, global_state, session_state)
|
||||
},
|
||||
Graphics::AdjustLodDistance(lod_distance) => {
|
||||
session_state
|
||||
@ -605,11 +600,7 @@ impl SettingsChange {
|
||||
},
|
||||
SettingsChange::Networking(networking_change) => match networking_change {
|
||||
Networking::AdjustViewDistance(view_distance) => {
|
||||
session_state
|
||||
.client
|
||||
.borrow_mut()
|
||||
.set_view_distance(view_distance);
|
||||
settings.graphics.view_distance = view_distance;
|
||||
adjust_view_distance(view_distance, global_state, session_state)
|
||||
},
|
||||
Networking::ChangePlayerPhysicsBehavior {
|
||||
server_authoritative,
|
||||
@ -654,6 +645,21 @@ impl SettingsChange {
|
||||
},
|
||||
},
|
||||
}
|
||||
settings.save_to_file_warn(&global_state.config_dir);
|
||||
global_state
|
||||
.settings
|
||||
.save_to_file_warn(&global_state.config_dir);
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_view_distance(
|
||||
view_distance: u32,
|
||||
global_state: &mut GlobalState,
|
||||
session_state: &mut SessionState,
|
||||
) {
|
||||
session_state
|
||||
.client
|
||||
.borrow_mut()
|
||||
.set_view_distance(view_distance);
|
||||
|
||||
global_state.settings.graphics.view_distance = view_distance;
|
||||
}
|
||||
|
@ -29,6 +29,10 @@ pub struct ImageSlider<T, K> {
|
||||
value: T,
|
||||
min: T,
|
||||
max: T,
|
||||
// If `value > soft_max` we will display the slider at `soft_max` along with a faded ghost
|
||||
// slider at `value`. The slider displayed at `soft_max` is purely a visual indicator and has
|
||||
// no effect on the values produced by this slider.
|
||||
soft_max: T,
|
||||
/// The amount in which the slider's display should be skewed.
|
||||
///
|
||||
/// Higher skew amounts (above 1.0) will weigh lower values.
|
||||
@ -65,6 +69,7 @@ widget_ids! {
|
||||
struct Ids {
|
||||
track,
|
||||
slider,
|
||||
soft_max_slider,
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,6 +81,7 @@ pub struct State {
|
||||
impl<T, K> ImageSlider<T, K> {
|
||||
builder_methods! {
|
||||
pub skew { skew = f32 }
|
||||
pub soft_max { soft_max = T }
|
||||
pub pad_track { track.padding = (f32, f32) }
|
||||
pub hover_image { slider.hover_image_id = Some(image::Id) }
|
||||
pub press_image { slider.press_image_id = Some(image::Id) }
|
||||
@ -85,18 +91,16 @@ impl<T, K> ImageSlider<T, K> {
|
||||
pub slider_color { slider.color = Some(Color) }
|
||||
}
|
||||
|
||||
fn new(
|
||||
value: T,
|
||||
min: T,
|
||||
max: T,
|
||||
slider_image_id: image::Id,
|
||||
track_image_id: image::Id,
|
||||
) -> Self {
|
||||
fn new(value: T, min: T, max: T, slider_image_id: image::Id, track_image_id: image::Id) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self {
|
||||
common: widget::CommonBuilder::default(),
|
||||
value,
|
||||
min,
|
||||
max,
|
||||
soft_max: max,
|
||||
skew: 1.0,
|
||||
track: Track {
|
||||
image_id: track_image_id,
|
||||
@ -133,7 +137,7 @@ where
|
||||
|
||||
impl<T> ImageSlider<T, Discrete>
|
||||
where
|
||||
T: Integer,
|
||||
T: Integer + Copy,
|
||||
{
|
||||
pub fn discrete(
|
||||
value: T,
|
||||
@ -266,45 +270,67 @@ where
|
||||
.unwrap_or(slider.image_id);
|
||||
|
||||
// A rectangle for positioning and sizing the slider.
|
||||
let value_perc = utils::map_range(new_value, min, max, 0.0, 1.0);
|
||||
let unskewed_perc = value_perc.powf(1.0 / skew as f64);
|
||||
let slider_rect = if is_horizontal {
|
||||
let pos = utils::map_range(
|
||||
unskewed_perc,
|
||||
0.0,
|
||||
1.0,
|
||||
rect.x.start + start_pad,
|
||||
rect.x.end - end_pad,
|
||||
);
|
||||
let w = slider.length.map_or(rect.w() / 10.0, |w| w as f64);
|
||||
Rect {
|
||||
x: Range::from_pos_and_len(pos, w),
|
||||
..rect
|
||||
}
|
||||
} else {
|
||||
let pos = utils::map_range(
|
||||
unskewed_perc,
|
||||
0.0,
|
||||
1.0,
|
||||
rect.y.start + start_pad,
|
||||
rect.y.end - end_pad,
|
||||
);
|
||||
let h = slider.length.map_or(rect.h() / 10.0, |h| h as f64);
|
||||
Rect {
|
||||
y: Range::from_pos_and_len(pos, h),
|
||||
..rect
|
||||
let slider_rect = |slider_value| {
|
||||
let value_perc = utils::map_range(slider_value, min, max, 0.0, 1.0);
|
||||
let unskewed_perc = value_perc.powf(1.0 / skew as f64);
|
||||
if is_horizontal {
|
||||
let pos = utils::map_range(
|
||||
unskewed_perc,
|
||||
0.0,
|
||||
1.0,
|
||||
rect.x.start + start_pad,
|
||||
rect.x.end - end_pad,
|
||||
);
|
||||
let w = slider.length.map_or(rect.w() / 10.0, |w| w as f64);
|
||||
Rect {
|
||||
x: Range::from_pos_and_len(pos, w),
|
||||
..rect
|
||||
}
|
||||
} else {
|
||||
let pos = utils::map_range(
|
||||
unskewed_perc,
|
||||
0.0,
|
||||
1.0,
|
||||
rect.y.start + start_pad,
|
||||
rect.y.end - end_pad,
|
||||
);
|
||||
let h = slider.length.map_or(rect.h() / 10.0, |h| h as f64);
|
||||
Rect {
|
||||
y: Range::from_pos_and_len(pos, h),
|
||||
..rect
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (x, y, w, h) = slider_rect.x_y_w_h();
|
||||
// Whether soft max slider needs to be displayed and main slider faded to look
|
||||
// like a ghost.
|
||||
let over_soft_max = new_value > self.soft_max;
|
||||
|
||||
let (x, y, w, h) = slider_rect(new_value).x_y_w_h();
|
||||
let fade = if over_soft_max { 0.5 } else { 1.0 };
|
||||
Image::new(slider_image)
|
||||
.x_y(x, y)
|
||||
.w_h(w, h)
|
||||
.parent(id)
|
||||
.graphics_for(id)
|
||||
.color(slider.color)
|
||||
.color(Some(
|
||||
slider
|
||||
.color
|
||||
.map_or(Color::Rgba(1.0, 1.0, 1.0, fade), |c: Color| c.alpha(fade)),
|
||||
))
|
||||
.set(state.ids.slider, ui);
|
||||
|
||||
if over_soft_max {
|
||||
let (x, y, w, h) = slider_rect(self.soft_max).x_y_w_h();
|
||||
Image::new(slider_image)
|
||||
.x_y(x, y)
|
||||
.w_h(w, h)
|
||||
.parent(id)
|
||||
.graphics_for(id)
|
||||
.color(slider.color)
|
||||
.set(state.ids.soft_max_slider, ui);
|
||||
}
|
||||
|
||||
// If the value has just changed, return the new value.
|
||||
if value != new_value {
|
||||
Some(new_value)
|
||||
|
Loading…
Reference in New Issue
Block a user