Addressed review comments and added persistence

This commit is contained in:
Syniis 2024-03-01 02:11:14 +01:00
parent 0a38c68337
commit 392599e586
4 changed files with 88 additions and 107 deletions

View File

@ -55,13 +55,11 @@ widget_ids! {
/*#[const_tweaker::tweak(min = 0.0, max = 60.0, step = 1.0)]
const X: f64 = 18.0;*/
const MAX_MESSAGES: usize = 100;
pub const MAX_MESSAGES: usize = 100;
const CHAT_ICON_WIDTH: f64 = 16.0;
const CHAT_MARGIN_THICKNESS: f64 = 2.0;
const CHAT_ICON_HEIGHT: f64 = 16.0;
pub const DEFAULT_CHAT_BOX_WIDTH: f64 = 470.0;
pub const DEFAULT_CHAT_BOX_HEIGHT: f64 = 150.0;
const MIN_DIMENSION: Vec2<f64> = Vec2::new(400.0, 150.0);
const MAX_DIMENSION: Vec2<f64> = Vec2::new(650.0, 500.0);
@ -86,8 +84,6 @@ pub struct Chat<'a> {
// TODO: add an option to adjust this
history_max: usize,
chat_size: Vec2<f64>,
chat_pos: Vec2<f64>,
scale: Scale,
localized_strings: &'a Localization,
@ -102,8 +98,6 @@ impl<'a> Chat<'a> {
imgs: &'a Imgs,
fonts: &'a Fonts,
localized_strings: &'a Localization,
chat_size: Vec2<f64>,
chat_pos: Vec2<f64>,
scale: Scale,
) -> Self {
Self {
@ -118,8 +112,6 @@ impl<'a> Chat<'a> {
global_state,
common: widget::CommonBuilder::default(),
history_max: 32,
chat_size,
chat_pos,
localized_strings,
scale,
}
@ -244,8 +236,9 @@ impl<'a> Widget for Chat<'a> {
let force_chat = !(&self.global_state.settings.interface.toggle_chat);
let chat_tabs = &chat_settings.chat_tabs;
let current_chat_tab = chat_settings.chat_tab_index.and_then(|i| chat_tabs.get(i));
let chat_box_input_width = self.chat_size.x - CHAT_ICON_WIDTH - 12.0;
let chat_size = Vec2::new(chat_settings.chat_size_x, chat_settings.chat_size_y);
let chat_pos = Vec2::new(chat_settings.chat_pos_x, chat_settings.chat_pos_y);
let chat_box_input_width = chat_size.x - CHAT_ICON_WIDTH - 12.0;
// Empty old messages
state.update(|s| {
@ -254,60 +247,46 @@ impl<'a> Widget for Chat<'a> {
}
});
let chat_in_screen_upper =
self.chat_pos.y > self.global_state.window.logical_size().y / 2.0;
let handle_chat_mouse_events = |chat_widget, ui: &mut UiCell, events: &mut Vec<Event>| {
let pos_delta: Vec2<f64> = ui
.widget_input(chat_widget)
.drags()
.left()
.map(|drag| Vec2::<f64>::from(drag.delta_xy))
.sum();
let new_pos = (self.chat_pos + pos_delta).map(|e| e.max(0.)).map2(
let chat_in_screen_upper = chat_pos.y > self.global_state.window.logical_size().y / 2.0;
let pos_delta: Vec2<f64> = ui
.widget_input(state.ids.draggable_area)
.drags()
.left()
.map(|drag| Vec2::<f64>::from(drag.delta_xy))
.sum();
let new_pos = (chat_pos + pos_delta).map(|e| e.max(0.)).map2(
self.scale
.scale_point(self.global_state.window.logical_size())
- Vec2::unit_y() * CHAT_TAB_HEIGHT
- chat_size,
|e, bounds| e.min(bounds),
);
if new_pos.abs_diff_ne(&chat_pos, f64::EPSILON) {
events.push(Event::MoveChat(new_pos));
}
let size_delta: Vec2<f64> = ui
.widget_input(state.ids.draggable_area)
.drags()
.right()
.map(|drag| Vec2::<f64>::from(drag.delta_xy))
.sum();
let new_size = (chat_size + size_delta)
.map3(
self.scale.scale_point(MIN_DIMENSION),
self.scale.scale_point(MAX_DIMENSION),
|sz, min, max| sz.clamp(min, max),
)
.map2(
self.scale
.scale_point(self.global_state.window.logical_size())
- Vec2::unit_y() * CHAT_TAB_HEIGHT
- self.chat_size,
- new_pos,
|e, bounds| e.min(bounds),
);
if new_pos.abs_diff_ne(&self.chat_pos, f64::EPSILON) {
events.push(Event::MoveChat(new_pos));
}
let size_delta: Vec2<f64> = ui
.widget_input(chat_widget)
.drags()
.right()
.map(|drag| Vec2::<f64>::from(drag.delta_xy))
.sum();
let new_size = (self.chat_size + size_delta)
.map3(
self.scale.scale_point(MIN_DIMENSION),
self.scale.scale_point(MAX_DIMENSION),
|sz, min, max| sz.clamp(min, max),
)
.map2(
self.scale
.scale_point(self.global_state.window.logical_size())
- Vec2::unit_y() * CHAT_TAB_HEIGHT
- self.chat_pos,
|e, bounds| e.min(bounds),
);
if new_size.abs_diff_ne(&self.chat_size, f64::EPSILON) {
events.push(Event::ResizeChat(new_size));
}
};
handle_chat_mouse_events(state.ids.draggable_area, ui, &mut events);
let group_members = self
.client
.group_members()
.iter()
.filter_map(|(u, r)| match r {
Role::Member => Some(u),
Role::Pet => None,
})
.collect::<HashSet<_>>();
if new_size.abs_diff_ne(&chat_size, f64::EPSILON) {
events.push(Event::ResizeChat(new_size));
}
// Maintain scrolling //
if !self.new_messages.is_empty() {
@ -474,14 +453,14 @@ impl<'a> Widget for Chat<'a> {
Dimension::Absolute(y) => y + 6.0,
_ => 0.0,
};
Rectangle::fill([self.chat_size.x, y])
.rgba(0.0, 0.0, 0.0, chat_settings.chat_opacity + 0.1)
.w(self.chat_size.x)
Rectangle::fill([chat_size.x, y])
.rgba(0.0, 0.0, 0.0, chat_settings.chat_opacity)
.w(chat_size.x)
.and(|r| {
if chat_in_screen_upper {
r.down_from(state.ids.message_box_bg, CHAT_MARGIN_THICKNESS / 2.0)
} else {
r.bottom_left_with_margins_on(ui.window, self.chat_pos.y, self.chat_pos.x)
r.bottom_left_with_margins_on(ui.window, chat_pos.y, chat_pos.x)
}
})
.set(state.ids.chat_input_bg, ui);
@ -489,13 +468,13 @@ impl<'a> Widget for Chat<'a> {
//border around focused chat window
let border_color = adjust_border_opacity(color, chat_settings.chat_opacity);
//top line
Line::centred([0.0, 0.0], [self.chat_size.x, 0.0])
Line::centred([0.0, 0.0], [chat_size.x, 0.0])
.color(border_color)
.thickness(CHAT_MARGIN_THICKNESS)
.top_left_of(state.ids.chat_input_bg)
.set(state.ids.chat_input_border_up, ui);
//bottom line
Line::centred([0.0, 0.0], [self.chat_size.x, 0.0])
Line::centred([0.0, 0.0], [chat_size.x, 0.0])
.color(border_color)
.thickness(CHAT_MARGIN_THICKNESS)
.bottom_left_of(state.ids.chat_input_bg)
@ -523,8 +502,8 @@ impl<'a> Widget for Chat<'a> {
}
// Message box
Rectangle::fill([self.chat_size.x, self.chat_size.y])
.rgba(0.0, 0.0, 0.0, chat_settings.chat_opacity + 0.1)
Rectangle::fill([chat_size.x, chat_size.y])
.rgba(0.0, 0.0, 0.0, chat_settings.chat_opacity)
.and(|r| {
if input_focused && !chat_in_screen_upper {
r.up_from(
@ -532,7 +511,7 @@ impl<'a> Widget for Chat<'a> {
0.0 + CHAT_MARGIN_THICKNESS / 2.0,
)
} else {
r.bottom_left_with_margins_on(ui.window, self.chat_pos.y, self.chat_pos.x)
r.bottom_left_with_margins_on(ui.window, chat_pos.y, chat_pos.x)
}
})
.crop_kids()
@ -544,6 +523,15 @@ impl<'a> Widget for Chat<'a> {
.resize(s.messages.len(), &mut ui.widget_id_generator())
});
}
let group_members = self
.client
.group_members()
.iter()
.filter_map(|(u, r)| match r {
Role::Member => Some(u),
Role::Pet => None,
})
.collect::<HashSet<_>>();
let show_char_name = chat_settings.chat_character_name;
let messages = &state
.messages
@ -584,13 +572,13 @@ impl<'a> Widget for Chat<'a> {
.resize(n_badges, &mut ui.widget_id_generator())
})
}
Rectangle::fill_with([CHAT_ICON_WIDTH, self.chat_size.y], color::TRANSPARENT)
Rectangle::fill_with([CHAT_ICON_WIDTH, chat_size.y], color::TRANSPARENT)
.top_left_with_margins_on(state.ids.message_box_bg, 0.0, 0.0)
.crop_kids()
.set(state.ids.chat_icon_align, ui);
let (mut items, _) = List::flow_down(messages.len() + 1)
.top_left_with_margins_on(state.ids.message_box_bg, 0.0, CHAT_ICON_WIDTH)
.w_h(self.chat_size.x - CHAT_ICON_WIDTH, self.chat_size.y)
.w_h(chat_size.x - CHAT_ICON_WIDTH, chat_size.y)
.scroll_kids_vertically()
.set(state.ids.message_box, ui);
@ -608,7 +596,7 @@ impl<'a> Widget for Chat<'a> {
let text = Text::new(text)
.font_size(self.fonts.opensans.scale(15))
.font_id(self.fonts.opensans.conrod_id)
.w(self.chat_size.x - CHAT_ICON_WIDTH - 1.0)
.w(chat_size.x - CHAT_ICON_WIDTH - 1.0)
.wrap_by_word()
.color(color)
.line_spacing(2.0);
@ -644,7 +632,7 @@ impl<'a> Widget for Chat<'a> {
Text::new("")
.font_size(self.fonts.opensans.scale(6))
.font_id(self.fonts.opensans.conrod_id)
.w(self.chat_size.x),
.w(chat_size.x),
ui,
);
};
@ -657,16 +645,17 @@ impl<'a> Widget for Chat<'a> {
{
state.update(|s| s.tabs_last_hover_pulse = Some(self.pulse));
}
if let Some(time_since_hover) = state
.tabs_last_hover_pulse
.map(|t| self.pulse - t)
.filter(|t| t <= &1.5)
{
let alpha = 1.0 - (time_since_hover / 1.5).powi(4);
let shading = color::rgba(1.0, 0.82, 0.27, (chat_settings.chat_opacity + 0.1) * alpha);
let shading = color::rgba(1.0, 0.82, 0.27, chat_settings.chat_opacity * alpha);
Rectangle::fill([self.chat_size.x, CHAT_TAB_HEIGHT])
.rgba(0.0, 0.0, 0.0, (chat_settings.chat_opacity + 0.1) * alpha)
Rectangle::fill([chat_size.x, CHAT_TAB_HEIGHT])
.rgba(0.0, 0.0, 0.0, chat_settings.chat_opacity * alpha)
.up_from(state.ids.message_box_bg, 0.0)
.set(state.ids.chat_tab_align, ui);
if ui
@ -696,7 +685,7 @@ impl<'a> Widget for Chat<'a> {
events.push(Event::ChangeChatTab(None));
}
let chat_tab_width = (self.chat_size.x - CHAT_TAB_ALL_WIDTH) / (MAX_CHAT_TABS as f64);
let chat_tab_width = (chat_size.x - CHAT_TAB_ALL_WIDTH) / (MAX_CHAT_TABS as f64);
if state.ids.chat_tabs.len() < chat_tabs.len() {
state.update(|s| {
@ -714,6 +703,7 @@ impl<'a> Widget for Chat<'a> {
.w_h(chat_tab_width, CHAT_TAB_HEIGHT)
.hover_image(self.imgs.selection_hover)
.press_image(self.imgs.selection_press)
.image_color(shading)
.label(chat_tab.label.as_str())
.label_font_size(self.fonts.cyri.scale(14))
.label_font_id(self.fonts.cyri.conrod_id)
@ -726,13 +716,6 @@ impl<'a> Widget for Chat<'a> {
},
0.0,
)
.and(|r| {
if chat_settings.chat_tab_index != Some(i) {
r.image_color(shading.complement())
} else {
r.image_color(shading)
}
})
.set(state.ids.chat_tabs[i], ui)
.was_clicked()
{
@ -808,7 +791,7 @@ impl<'a> Widget for Chat<'a> {
let pressed = matches!(key_press.key, Key::Return | Key::NumPadEnter);
if pressed {
// If chat was hidden, scroll to bottom the next time it is opened
state.update(|s| s.scroll_next = force_chat);
state.update(|s| s.scroll_next |= force_chat);
events.push(Event::DisableForceChat);
}
has_message && pressed
@ -838,12 +821,12 @@ impl<'a> Widget for Chat<'a> {
}
}
Rectangle::fill_with([self.chat_size.x, self.chat_size.y], color::TRANSPARENT)
Rectangle::fill_with([chat_size.x, chat_size.y], color::TRANSPARENT)
.and(|r| {
if input_focused {
r.up_from(state.ids.chat_input_border_up, CHAT_MARGIN_THICKNESS / 2.0)
} else {
r.bottom_left_with_margins_on(ui.window, self.chat_pos.y, self.chat_pos.x)
r.bottom_left_with_margins_on(ui.window, chat_pos.y, chat_pos.x)
}
})
.set(state.ids.draggable_area, ui);

View File

@ -140,8 +140,6 @@ use std::{
use tracing::warn;
use vek::*;
use self::chat::{DEFAULT_CHAT_BOX_HEIGHT, DEFAULT_CHAT_BOX_WIDTH};
const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
const TEXT_VELORITE: Color = Color::Rgba(0.0, 0.66, 0.66, 1.0);
const TEXT_BLUE_COLOR: Color = Color::Rgba(0.8, 0.9, 1.0, 1.0);
@ -1273,6 +1271,8 @@ pub struct Hud {
failed_entity_pickups: HashMap<EcsEntity, CollectFailedData>,
new_loot_messages: VecDeque<LootMessage>,
new_messages: VecDeque<comp::ChatMsg>,
// NOTE Used for storing messages sent while the chat is hidden. This is needed because NPC
// speech uses new_messages so we need to clear it every frame.
message_backlog: VecDeque<comp::ChatMsg>,
new_notifications: VecDeque<Notification>,
speech_bubbles: HashMap<Uid, comp::SpeechBubble>,
@ -1295,8 +1295,6 @@ pub struct Hud {
floaters: Floaters,
voxel_minimap: VoxelMinimap,
map_drag: Vec2<f64>,
chat_size: Vec2<f64>,
chat_pos: Vec2<f64>,
force_chat: bool,
}
@ -1434,8 +1432,6 @@ impl Hud {
block_floaters: Vec::new(),
},
map_drag: Vec2::zero(),
chat_size: Vec2::new(DEFAULT_CHAT_BOX_WIDTH, DEFAULT_CHAT_BOX_HEIGHT),
chat_pos: Vec2::new(10.0, 10.0),
force_chat: false,
}
}
@ -3508,8 +3504,6 @@ impl Hud {
&self.imgs,
&self.fonts,
i18n,
self.chat_size,
self.chat_pos,
scale,
)
.and_then(self.force_chat_input.take(), |c, input| c.input(input))
@ -3541,10 +3535,12 @@ impl Hud {
self.show.settings(true);
},
chat::Event::ResizeChat(size) => {
self.chat_size = size;
global_state.settings.chat.chat_size_x = size.x;
global_state.settings.chat.chat_size_y = size.y;
},
chat::Event::MoveChat(pos) => {
self.chat_pos = pos;
global_state.settings.chat.chat_pos_x = pos.x;
global_state.settings.chat.chat_pos_y = pos.y;
},
chat::Event::DisableForceChat => {
self.force_chat = false;
@ -3553,7 +3549,7 @@ impl Hud {
}
} else {
self.message_backlog.extend(self.new_messages.drain(..));
while self.message_backlog.len() > 100 {
while self.message_backlog.len() > chat::MAX_MESSAGES {
self.message_backlog.pop_front();
}
}
@ -4642,18 +4638,10 @@ impl Hud {
if show.map {
let new_zoom_lvl = (global_state.settings.interface.map_zoom * factor)
.clamped(1.25, max_zoom / 64.0);
global_state.settings.interface.map_zoom = new_zoom_lvl;
global_state
.settings
.save_to_file_warn(&global_state.config_dir);
} else if global_state.settings.interface.minimap_show {
let new_zoom_lvl = global_state.settings.interface.minimap_zoom * factor;
global_state.settings.interface.minimap_zoom = new_zoom_lvl;
global_state
.settings
.save_to_file_warn(&global_state.config_dir);
}
show.map && global_state.settings.interface.minimap_show

View File

@ -162,7 +162,7 @@ impl<'a> Widget for Chat<'a> {
if let Some(new_val) = ImageSlider::continuous(
chat_settings.chat_opacity,
0.0,
0.9,
1.0,
self.imgs.slider_indicator,
self.imgs.slider,
)

View File

@ -7,6 +7,8 @@ use serde::{Deserialize, Serialize};
use std::collections::HashSet;
pub const MAX_CHAT_TABS: usize = 5;
pub const DEFAULT_CHAT_BOX_WIDTH: f64 = 470.0;
pub const DEFAULT_CHAT_BOX_HEIGHT: f64 = 150.0;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ChatFilter {
@ -74,6 +76,10 @@ pub struct ChatSettings {
pub chat_tabs: Vec<ChatTab>,
pub chat_tab_index: Option<usize>,
pub chat_cmd_prefix: char,
pub chat_pos_x: f64,
pub chat_pos_y: f64,
pub chat_size_x: f64,
pub chat_size_y: f64,
}
impl Default for ChatSettings {
@ -84,6 +90,10 @@ impl Default for ChatSettings {
chat_tabs: vec![ChatTab::default()],
chat_tab_index: Some(0),
chat_cmd_prefix: '/',
chat_pos_x: 10.0,
chat_pos_y: 10.0,
chat_size_x: DEFAULT_CHAT_BOX_WIDTH,
chat_size_y: DEFAULT_CHAT_BOX_HEIGHT,
}
}
}