mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added chat tabs
This commit is contained in:
parent
e66a2079ce
commit
95a6e35a3a
@ -59,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- /skill_preset command which allows you to apply skill presets
|
||||
- Added timed bans and ban history.
|
||||
- Added non-admin moderators with limit privileges and updated the security model to reflect this.
|
||||
- Chat tabs
|
||||
|
||||
### Changed
|
||||
|
||||
|
BIN
assets/voxygen/element/ui/settings/buttons/settings_button_plus.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/settings/buttons/settings_button_plus.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/ui/settings/buttons/settings_button_plus_hover.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/settings/buttons/settings_button_plus_hover.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/ui/settings/buttons/settings_button_plus_press.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/settings/buttons/settings_button_plus_press.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/ui/settings/chat_tab_settings_bg.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/settings/chat_tab_settings_bg.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/ui/settings/chat_tab_settings_frame.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/settings/chat_tab_settings_frame.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -16,6 +16,7 @@
|
||||
"common.controls": "Controls",
|
||||
"common.video": "Graphics",
|
||||
"common.sound": "Sound",
|
||||
"common.chat": "Chat",
|
||||
"common.resume": "Resume",
|
||||
"common.characters": "Characters",
|
||||
"common.close": "Close",
|
||||
@ -44,6 +45,7 @@
|
||||
"common.video_settings": "Graphics Settings",
|
||||
"common.sound_settings": "Sound Settings",
|
||||
"common.language_settings": "Language Settings",
|
||||
"common.chat_settings": "Chat Settings",
|
||||
|
||||
// Message when connection to the server is lost
|
||||
"common.connection_lost": r#"Connection lost!
|
||||
|
@ -3,6 +3,9 @@
|
||||
/// Localization for "global" English
|
||||
(
|
||||
string_map: {
|
||||
"hud.chat.all": "All",
|
||||
"hud.chat.chat_tab_hover_tooltip": "Right click for settings",
|
||||
|
||||
// Debuff outcomes
|
||||
"hud.outcome.burning": "died of: burning",
|
||||
"hud.outcome.curse": "died of: curse",
|
||||
|
@ -107,6 +107,23 @@
|
||||
"hud.settings.awaitingkey": "Press a key...",
|
||||
"hud.settings.unbound": "None",
|
||||
"hud.settings.reset_keybinds": "Reset to Defaults",
|
||||
|
||||
"hud.settings.chat_tabs": "Chat Tabs",
|
||||
"hud.settings.label": "Label:",
|
||||
"hud.settings.delete": "Delete",
|
||||
"hud.settings.show_all": "Show all",
|
||||
"hud.settings.messages": "Messages",
|
||||
"hud.settings.activity": "Activity",
|
||||
"hud.settings.death": "Death",
|
||||
"hud.settings.group": "Group",
|
||||
"hud.settings.faction": "Faction",
|
||||
"hud.settings.world": "World",
|
||||
"hud.settings.region": "Region",
|
||||
"hud.settings.say": "Say",
|
||||
"hud.settings.none": "None",
|
||||
"hud.settings.all": "All",
|
||||
"hud.settings.group_only": "Group only",
|
||||
"hud.settings.reset_chat" : "Reset to Defaults",
|
||||
},
|
||||
|
||||
|
||||
|
@ -1,15 +1,18 @@
|
||||
use super::{
|
||||
img_ids::Imgs, ERROR_COLOR, FACTION_COLOR, GROUP_COLOR, INFO_COLOR, KILL_COLOR, LOOT_COLOR,
|
||||
OFFLINE_COLOR, ONLINE_COLOR, REGION_COLOR, SAY_COLOR, TELL_COLOR, WORLD_COLOR,
|
||||
img_ids::Imgs, ChatTab, ERROR_COLOR, FACTION_COLOR, GROUP_COLOR, INFO_COLOR, KILL_COLOR,
|
||||
LOOT_COLOR, OFFLINE_COLOR, ONLINE_COLOR, REGION_COLOR, SAY_COLOR, TELL_COLOR, TEXT_COLOR,
|
||||
WORLD_COLOR,
|
||||
};
|
||||
use crate::{i18n::Localization, ui::fonts::Fonts, GlobalState};
|
||||
use crate::{i18n::Localization, settings::chat::MAX_CHAT_TABS, ui::fonts::Fonts, GlobalState};
|
||||
use client::{cmd, Client};
|
||||
use common::comp::{
|
||||
chat::{KillSource, KillType},
|
||||
group::Role,
|
||||
BuffKind, ChatMode, ChatMsg, ChatType,
|
||||
};
|
||||
use common_net::msg::validate_chat_msg;
|
||||
use conrod_core::{
|
||||
color,
|
||||
input::Key,
|
||||
position::Dimension,
|
||||
text::{
|
||||
@ -17,9 +20,10 @@ use conrod_core::{
|
||||
cursor::{self, Index},
|
||||
},
|
||||
widget::{self, Button, Id, Image, List, Rectangle, Text, TextEdit},
|
||||
widget_ids, Color, Colorable, Positionable, Sizeable, Ui, UiCell, Widget, WidgetCommon,
|
||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Ui, UiCell, Widget,
|
||||
WidgetCommon,
|
||||
};
|
||||
use std::collections::VecDeque;
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
@ -29,7 +33,15 @@ widget_ids! {
|
||||
chat_input_bg,
|
||||
chat_input_icon,
|
||||
chat_arrow,
|
||||
chat_icon_align,
|
||||
chat_icons[],
|
||||
|
||||
chat_tab_align,
|
||||
chat_tab_all,
|
||||
chat_tab_selected,
|
||||
chat_tabs[],
|
||||
chat_tab_tooltip_bg,
|
||||
chat_tab_tooltip_text,
|
||||
}
|
||||
}
|
||||
/*#[const_tweaker::tweak(min = 0.0, max = 60.0, step = 1.0)]
|
||||
@ -41,10 +53,14 @@ const CHAT_ICON_WIDTH: f64 = 16.0;
|
||||
const CHAT_ICON_HEIGHT: f64 = 16.0;
|
||||
const CHAT_BOX_WIDTH: f64 = 470.0;
|
||||
const CHAT_BOX_INPUT_WIDTH: f64 = 460.0 - CHAT_ICON_WIDTH - 1.0;
|
||||
const CHAT_BOX_HEIGHT: f64 = 174.0;
|
||||
const CHAT_BOX_HEIGHT: f64 = 154.0;
|
||||
|
||||
const CHAT_TAB_HEIGHT: f64 = 20.0;
|
||||
const CHAT_TAB_ALL_WIDTH: f64 = 40.0;
|
||||
|
||||
#[derive(WidgetCommon)]
|
||||
pub struct Chat<'a> {
|
||||
pulse: f32,
|
||||
new_messages: &'a mut VecDeque<ChatMsg>,
|
||||
client: &'a Client,
|
||||
force_input: Option<String>,
|
||||
@ -69,11 +85,13 @@ impl<'a> Chat<'a> {
|
||||
new_messages: &'a mut VecDeque<ChatMsg>,
|
||||
client: &'a Client,
|
||||
global_state: &'a GlobalState,
|
||||
pulse: f32,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
) -> Self {
|
||||
Self {
|
||||
pulse,
|
||||
new_messages,
|
||||
client,
|
||||
force_input: None,
|
||||
@ -142,16 +160,22 @@ pub struct State {
|
||||
completions_index: Option<usize>,
|
||||
// At which character is tab completion happening
|
||||
completion_cursor: Option<usize>,
|
||||
// last time mouse has been hovered
|
||||
tabs_last_hover_pulse: Option<f32>,
|
||||
// last chat_tab (used to see if chat tab has been changed)
|
||||
prev_chat_tab: Option<ChatTab>,
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
TabCompletionStart(String),
|
||||
SendMessage(String),
|
||||
Focus(Id),
|
||||
ChangeChatTab(Option<usize>),
|
||||
ShowChatTabSettings(usize),
|
||||
}
|
||||
|
||||
impl<'a> Widget for Chat<'a> {
|
||||
type Event = Option<Event>;
|
||||
type Event = Vec<Event>;
|
||||
type State = State;
|
||||
type Style = ();
|
||||
|
||||
@ -168,6 +192,8 @@ impl<'a> Widget for Chat<'a> {
|
||||
completions_index: None,
|
||||
completion_cursor: None,
|
||||
ids: Ids::new(id_gen),
|
||||
tabs_last_hover_pulse: None,
|
||||
prev_chat_tab: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,12 +204,23 @@ impl<'a> Widget for Chat<'a> {
|
||||
#[allow(clippy::single_match)] // TODO: Pending review in #587
|
||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||
let widget::UpdateArgs { id, state, ui, .. } = args;
|
||||
let transp = self.global_state.settings.interface.chat_transp;
|
||||
|
||||
let mut events = Vec::new();
|
||||
|
||||
let chat_settings = &self.global_state.settings.chat;
|
||||
|
||||
let chat_tabs = &chat_settings.chat_tabs;
|
||||
let current_chat_tab = chat_settings.chat_tab_index.and_then(|i| chat_tabs.get(i));
|
||||
|
||||
// Maintain scrolling.
|
||||
if !self.new_messages.is_empty() {
|
||||
state.update(|s| s.messages.extend(self.new_messages.drain(..)));
|
||||
ui.scroll_widget(state.ids.message_box, [0.0, std::f64::MAX]);
|
||||
}
|
||||
if current_chat_tab != state.prev_chat_tab.as_ref() {
|
||||
state.update(|s| s.prev_chat_tab = current_chat_tab.cloned());
|
||||
ui.scroll_widget(state.ids.message_box, [0.0, std::f64::MAX]);
|
||||
}
|
||||
|
||||
// Empty old messages
|
||||
state.update(|s| {
|
||||
@ -322,7 +359,7 @@ impl<'a> Widget for Chat<'a> {
|
||||
_ => 0.0,
|
||||
};
|
||||
Rectangle::fill([CHAT_BOX_WIDTH, y])
|
||||
.rgba(0.0, 0.0, 0.0, transp + 0.1)
|
||||
.rgba(0.0, 0.0, 0.0, chat_settings.chat_transp + 0.1)
|
||||
.bottom_left_with_margins_on(ui.window, 10.0, 10.0)
|
||||
.w(CHAT_BOX_WIDTH)
|
||||
.set(state.ids.chat_input_bg, ui);
|
||||
@ -341,7 +378,7 @@ impl<'a> Widget for Chat<'a> {
|
||||
|
||||
// Message box
|
||||
Rectangle::fill([CHAT_BOX_WIDTH, CHAT_BOX_HEIGHT])
|
||||
.rgba(0.0, 0.0, 0.0, transp)
|
||||
.rgba(0.0, 0.0, 0.0, chat_settings.chat_transp)
|
||||
.and(|r| {
|
||||
if input_focused {
|
||||
r.up_from(state.ids.chat_input_bg, 0.0)
|
||||
@ -351,11 +388,6 @@ impl<'a> Widget for Chat<'a> {
|
||||
})
|
||||
.crop_kids()
|
||||
.set(state.ids.message_box_bg, ui);
|
||||
let (mut items, _) = List::flow_down(state.messages.len() + 1)
|
||||
.top_left_with_margins_on(state.ids.message_box_bg, 0.0, 16.0)
|
||||
.w_h(CHAT_BOX_WIDTH - 16.0, CHAT_BOX_HEIGHT)
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.message_box, ui);
|
||||
if state.ids.chat_icons.len() < state.messages.len() {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
@ -363,105 +395,70 @@ 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
|
||||
.iter()
|
||||
.map(|m| {
|
||||
let mut message = m.clone();
|
||||
if let Some(template_key) = get_chat_template_key(&message.chat_type) {
|
||||
message.message = self.localized_strings.get(template_key).to_string();
|
||||
if let ChatType::Kill(kill_source, _) = &message.chat_type {
|
||||
match kill_source {
|
||||
KillSource::Player(_, KillType::Buff(buffkind))
|
||||
| KillSource::NonExistent(KillType::Buff(buffkind))
|
||||
| KillSource::NonPlayer(_, KillType::Buff(buffkind)) => {
|
||||
message.message = insert_killing_buff(
|
||||
*buffkind,
|
||||
self.localized_strings,
|
||||
&message.message,
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
message.message = self.client.format_message(&message, show_char_name);
|
||||
message
|
||||
})
|
||||
.filter(|m| {
|
||||
if let Some(chat_tab) = current_chat_tab {
|
||||
chat_tab.filter.satisfies(&m, &group_members)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Rectangle::fill_with([CHAT_ICON_WIDTH, CHAT_BOX_HEIGHT], 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(CHAT_BOX_WIDTH - CHAT_ICON_WIDTH, CHAT_BOX_HEIGHT)
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.message_box, ui);
|
||||
|
||||
let show_char_name = self.global_state.settings.interface.chat_character_name;
|
||||
while let Some(item) = items.next(ui) {
|
||||
// This would be easier if conrod used the v-metrics from rusttype.
|
||||
if item.i < state.messages.len() {
|
||||
let mut message = state.messages[item.i].clone();
|
||||
if item.i < messages.len() {
|
||||
let message = &messages[item.i];
|
||||
let (color, icon) = render_chat_line(&message.chat_type, &self.imgs);
|
||||
let ChatMsg { chat_type, .. } = &message;
|
||||
// For each ChatType needing localization get/set matching pre-formatted
|
||||
// localized string. This string will be formatted with the data
|
||||
// provided in ChatType in the client/src/mod.rs
|
||||
// fn format_message called below
|
||||
message.message = match chat_type {
|
||||
ChatType::Online(_) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.online_msg")
|
||||
.to_string(),
|
||||
ChatType::Offline(_) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.offline_msg")
|
||||
.to_string(),
|
||||
ChatType::Kill(kill_source, _) => match kill_source {
|
||||
KillSource::Player(_, KillType::Buff(buffkind)) => insert_killing_buff(
|
||||
*buffkind,
|
||||
self.localized_strings,
|
||||
self.localized_strings.get("hud.chat.died_of_pvp_buff_msg"),
|
||||
),
|
||||
KillSource::Player(_, KillType::Melee) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.pvp_melee_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::Player(_, KillType::Projectile) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.pvp_ranged_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::Player(_, KillType::Explosion) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.pvp_explosion_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::Player(_, KillType::Energy) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.pvp_energy_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::Player(_, KillType::Other) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.pvp_other_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::NonExistent(KillType::Buff(buffkind)) => insert_killing_buff(
|
||||
*buffkind,
|
||||
self.localized_strings,
|
||||
self.localized_strings
|
||||
.get("hud.chat.died_of_buff_nonexistent_msg"),
|
||||
),
|
||||
KillSource::NonPlayer(_, KillType::Buff(buffkind)) => insert_killing_buff(
|
||||
*buffkind,
|
||||
self.localized_strings,
|
||||
self.localized_strings.get("hud.chat.died_of_npc_buff_msg"),
|
||||
),
|
||||
KillSource::NonPlayer(_, KillType::Melee) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.npc_melee_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::NonPlayer(_, KillType::Projectile) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.npc_ranged_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::NonPlayer(_, KillType::Explosion) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.npc_explosion_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::NonPlayer(_, KillType::Energy) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.npc_energy_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::NonPlayer(_, KillType::Other) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.npc_other_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::Environment(_) => self
|
||||
.localized_strings
|
||||
.get("hud.chat.environmental_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::FallDamage => self
|
||||
.localized_strings
|
||||
.get("hud.chat.fall_kill_msg")
|
||||
.to_string(),
|
||||
KillSource::Suicide => self
|
||||
.localized_strings
|
||||
.get("hud.chat.suicide_msg")
|
||||
.to_string(),
|
||||
KillSource::NonExistent(_) | KillSource::Other => self
|
||||
.localized_strings
|
||||
.get("hud.chat.default_death_msg")
|
||||
.to_string(),
|
||||
},
|
||||
_ => message.message,
|
||||
};
|
||||
let msg = self.client.format_message(&message, show_char_name);
|
||||
let text = Text::new(&msg)
|
||||
|
||||
let text = Text::new(&message.message)
|
||||
.font_size(self.fonts.opensans.scale(15))
|
||||
.font_id(self.fonts.opensans.conrod_id)
|
||||
.w(CHAT_BOX_WIDTH - 17.0)
|
||||
@ -477,7 +474,7 @@ impl<'a> Widget for Chat<'a> {
|
||||
Image::new(icon)
|
||||
.w_h(CHAT_ICON_WIDTH, CHAT_ICON_HEIGHT)
|
||||
.top_left_with_margins_on(item.widget_id, 2.0, -CHAT_ICON_WIDTH)
|
||||
.parent(state.ids.message_box_bg)
|
||||
.parent(state.ids.chat_icon_align)
|
||||
.set(icon_id, ui);
|
||||
} else {
|
||||
// Spacer at bottom of the last message so that it is not cut off.
|
||||
@ -492,6 +489,125 @@ impl<'a> Widget for Chat<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
//Chat tabs
|
||||
if ui
|
||||
.rect_of(state.ids.message_box_bg)
|
||||
.map_or(false, |r| r.is_over(ui.global_input().current.mouse.xy))
|
||||
{
|
||||
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, 1.0, 1.0, (chat_settings.chat_transp + 0.1) * alpha);
|
||||
|
||||
Rectangle::fill([CHAT_BOX_WIDTH, CHAT_TAB_HEIGHT])
|
||||
.rgba(0.0, 0.0, 0.0, (chat_settings.chat_transp + 0.1) * alpha)
|
||||
.up_from(state.ids.message_box_bg, 0.0)
|
||||
.set(state.ids.chat_tab_align, ui);
|
||||
if ui
|
||||
.rect_of(state.ids.chat_tab_align)
|
||||
.map_or(false, |r| r.is_over(ui.global_input().current.mouse.xy))
|
||||
{
|
||||
state.update(|s| s.tabs_last_hover_pulse = Some(self.pulse));
|
||||
}
|
||||
|
||||
if Button::image(if chat_settings.chat_tab_index.is_none() {
|
||||
self.imgs.selection
|
||||
} else {
|
||||
self.imgs.nothing
|
||||
})
|
||||
.top_left_with_margins_on(state.ids.chat_tab_align, 0.0, 0.0)
|
||||
.w_h(CHAT_TAB_ALL_WIDTH, CHAT_TAB_HEIGHT)
|
||||
.hover_image(self.imgs.selection_hover)
|
||||
.hover_image(self.imgs.selection_press)
|
||||
.image_color(shading)
|
||||
.label(&self.localized_strings.get("hud.chat.all"))
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR.alpha(alpha))
|
||||
.set(state.ids.chat_tab_all, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChangeChatTab(None));
|
||||
}
|
||||
|
||||
let chat_tab_width = (CHAT_BOX_WIDTH - CHAT_TAB_ALL_WIDTH) / (MAX_CHAT_TABS as f64);
|
||||
|
||||
if state.ids.chat_tabs.len() < chat_tabs.len() {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.chat_tabs
|
||||
.resize(chat_tabs.len(), &mut ui.widget_id_generator())
|
||||
});
|
||||
}
|
||||
for (i, chat_tab) in chat_tabs.iter().enumerate() {
|
||||
if Button::image(if chat_settings.chat_tab_index == Some(i) {
|
||||
self.imgs.selection
|
||||
} else {
|
||||
self.imgs.nothing
|
||||
})
|
||||
.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)
|
||||
.label_color(TEXT_COLOR.alpha(alpha))
|
||||
.right_from(
|
||||
if i == 0 {
|
||||
state.ids.chat_tab_all
|
||||
} else {
|
||||
state.ids.chat_tabs[i - 1]
|
||||
},
|
||||
0.0,
|
||||
)
|
||||
.set(state.ids.chat_tabs[i], ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChangeChatTab(Some(i)));
|
||||
}
|
||||
|
||||
if ui
|
||||
.widget_input(state.ids.chat_tabs[i])
|
||||
.mouse()
|
||||
.map_or(false, |m| m.is_over())
|
||||
{
|
||||
Rectangle::fill([120.0, 20.0])
|
||||
.rgba(0.0, 0.0, 0.0, 0.9)
|
||||
.top_left_with_margins_on(state.ids.chat_tabs[i], -20.0, 5.0)
|
||||
.parent(id)
|
||||
.set(state.ids.chat_tab_tooltip_bg, ui);
|
||||
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.chat.chat_tab_hover_tooltip"),
|
||||
)
|
||||
.mid_top_with_margin_on(state.ids.chat_tab_tooltip_bg, 3.0)
|
||||
.font_size(self.fonts.cyri.scale(10))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.chat_tab_tooltip_text, ui);
|
||||
}
|
||||
|
||||
if ui
|
||||
.widget_input(state.ids.chat_tabs[i])
|
||||
.clicks()
|
||||
.right()
|
||||
.next()
|
||||
.is_some()
|
||||
{
|
||||
events.push(Event::ShowChatTabSettings(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Chat Arrow
|
||||
// Check if already at bottom.
|
||||
if !Self::scrolled_to_bottom(state, ui)
|
||||
@ -509,11 +625,11 @@ impl<'a> Widget for Chat<'a> {
|
||||
|
||||
// We've started a new tab completion. Populate tab completion suggestions.
|
||||
if request_tab_completions {
|
||||
Some(Event::TabCompletionStart(state.input.message.to_string()))
|
||||
events.push(Event::TabCompletionStart(state.input.message.to_string()));
|
||||
// If the chat widget is focused, return a focus event to pass the focus
|
||||
// to the input box.
|
||||
} else if keyboard_capturer == Some(id) {
|
||||
Some(Event::Focus(state.ids.chat_input))
|
||||
events.push(Event::Focus(state.ids.chat_input));
|
||||
}
|
||||
// If enter is pressed and the input box is not empty, send the current message.
|
||||
else if ui.widget_input(state.ids.chat_input).presses().key().any(
|
||||
@ -530,10 +646,9 @@ impl<'a> Widget for Chat<'a> {
|
||||
s.history.truncate(self.history_max);
|
||||
}
|
||||
});
|
||||
Some(Event::SendMessage(msg))
|
||||
} else {
|
||||
None
|
||||
events.push(Event::SendMessage(msg));
|
||||
}
|
||||
events
|
||||
}
|
||||
}
|
||||
|
||||
@ -646,3 +761,30 @@ fn insert_killing_buff(buff: BuffKind, localized_strings: &Localization, templat
|
||||
|
||||
template.replace("{died_of_buff}", buff_outcome)
|
||||
}
|
||||
|
||||
fn get_chat_template_key(chat_type: &ChatType<String>) -> Option<&str> {
|
||||
Some(match chat_type {
|
||||
ChatType::Online(_) => "hud.chat.online_msg",
|
||||
ChatType::Offline(_) => "hud.chat.offline_msg",
|
||||
ChatType::Kill(kill_source, _) => match kill_source {
|
||||
KillSource::Player(_, KillType::Buff(_)) => "hud.chat.died_of_pvp_buff_msg",
|
||||
KillSource::Player(_, KillType::Melee) => "hud.chat.pvp_melee_kill_msg",
|
||||
KillSource::Player(_, KillType::Projectile) => "hud.chat.pvp_ranged_kill_msg",
|
||||
KillSource::Player(_, KillType::Explosion) => "hud.chat.pvp_explosion_kill_msg",
|
||||
KillSource::Player(_, KillType::Energy) => "hud.chat.pvp_energy_kill_msg",
|
||||
KillSource::Player(_, KillType::Other) => "hud.chat.pvp_other_kill_msg",
|
||||
KillSource::NonExistent(KillType::Buff(_)) => "hud.chat.died_of_buff_nonexistent_msg",
|
||||
KillSource::NonPlayer(_, KillType::Buff(_)) => "hud.chat.died_of_npc_buff_msg",
|
||||
KillSource::NonPlayer(_, KillType::Melee) => "hud.chat.npc_melee_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Projectile) => "hud.chat.npc_ranged_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Explosion) => "hud.chat.npc_explosion_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Energy) => "hud.chat.npc_energy_kill_msg",
|
||||
KillSource::NonPlayer(_, KillType::Other) => "hud.chat.npc_other_kill_msg",
|
||||
KillSource::Environment(_) => "hud.chat.environmental_kill_msg",
|
||||
KillSource::FallDamage => "hud.chat.fall_kill_msg",
|
||||
KillSource::Suicide => "hud.chat.suicide_msg",
|
||||
KillSource::NonExistent(_) | KillSource::Other => "hud.chat.default_death_msg",
|
||||
},
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
@ -122,6 +122,13 @@ image_ids! {
|
||||
settings_button_hover: "voxygen.element.ui.settings.buttons.settings_button_hover",
|
||||
settings_button_press: "voxygen.element.ui.settings.buttons.settings_button_press",
|
||||
|
||||
settings_plus: "voxygen.element.ui.settings.buttons.settings_button_plus",
|
||||
settings_plus_hover: "voxygen.element.ui.settings.buttons.settings_button_plus_hover",
|
||||
settings_plus_press: "voxygen.element.ui.settings.buttons.settings_button_plus_press",
|
||||
|
||||
chat_tab_settings_bg: "voxygen.element.ui.settings.chat_tab_settings_bg",
|
||||
chat_tab_settings_frame: "voxygen.element.ui.settings.chat_tab_settings_frame",
|
||||
|
||||
quest_bg: "voxygen.element.ui.quests.temp_quest_bg",
|
||||
|
||||
// Slider
|
||||
|
@ -55,9 +55,10 @@ use crate::{
|
||||
render::{Consts, Globals, Renderer},
|
||||
scene::camera::{self, Camera},
|
||||
session::{
|
||||
settings_change::{Interface as InterfaceChange, SettingsChange},
|
||||
settings_change::{Chat as ChatChange, Interface as InterfaceChange, SettingsChange},
|
||||
Interactable,
|
||||
},
|
||||
settings::chat::ChatFilter,
|
||||
ui::{
|
||||
fonts::Fonts, img_ids::Rotations, slot, slot::SlotKey, Graphic, Ingameable, ScaleMode, Ui,
|
||||
},
|
||||
@ -466,6 +467,19 @@ pub enum PressBehavior {
|
||||
#[serde(other)]
|
||||
Toggle = 0,
|
||||
}
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct ChatTab {
|
||||
pub label: String,
|
||||
pub filter: ChatFilter,
|
||||
}
|
||||
impl Default for ChatTab {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
label: String::from("Chat"),
|
||||
filter: ChatFilter::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PressBehavior {
|
||||
pub fn update(&self, keystate: bool, setting: &mut bool, f: impl FnOnce(bool)) {
|
||||
@ -503,6 +517,7 @@ pub struct Show {
|
||||
open_windows: Windows,
|
||||
map: bool,
|
||||
ingame: bool,
|
||||
chat_tab_settings_index: Option<usize>,
|
||||
settings_tab: SettingsTab,
|
||||
skilltreetab: SelectedSkillTree,
|
||||
crafting_tab: CraftingTab,
|
||||
@ -869,6 +884,7 @@ impl Hud {
|
||||
diary: false,
|
||||
group: false,
|
||||
group_menu: false,
|
||||
chat_tab_settings_index: None,
|
||||
settings_tab: SettingsTab::Interface,
|
||||
skilltreetab: SelectedSkillTree::General,
|
||||
crafting_tab: CraftingTab::All,
|
||||
@ -2585,10 +2601,11 @@ impl Hud {
|
||||
.retain(|m| !matches!(m.chat_type, comp::ChatType::Npc(_, _)));
|
||||
|
||||
// Chat box
|
||||
match Chat::new(
|
||||
for event in Chat::new(
|
||||
&mut self.new_messages,
|
||||
&client,
|
||||
global_state,
|
||||
self.pulse,
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
i18n,
|
||||
@ -2600,16 +2617,25 @@ impl Hud {
|
||||
.and_then(self.force_chat_cursor.take(), |c, pos| c.cursor_pos(pos))
|
||||
.set(self.ids.chat, ui_widgets)
|
||||
{
|
||||
Some(chat::Event::TabCompletionStart(input)) => {
|
||||
self.tab_complete = Some(input);
|
||||
},
|
||||
Some(chat::Event::SendMessage(message)) => {
|
||||
events.push(Event::SendMessage(message));
|
||||
},
|
||||
Some(chat::Event::Focus(focus_id)) => {
|
||||
self.to_focus = Some(Some(focus_id));
|
||||
},
|
||||
None => {},
|
||||
match event {
|
||||
chat::Event::TabCompletionStart(input) => {
|
||||
self.tab_complete = Some(input);
|
||||
},
|
||||
chat::Event::SendMessage(message) => {
|
||||
events.push(Event::SendMessage(message));
|
||||
},
|
||||
chat::Event::Focus(focus_id) => {
|
||||
self.to_focus = Some(Some(focus_id));
|
||||
},
|
||||
chat::Event::ChangeChatTab(tab) => {
|
||||
events.push(Event::SettingsChange(ChatChange::ChangeChatTab(tab).into()));
|
||||
},
|
||||
chat::Event::ShowChatTabSettings(tab) => {
|
||||
self.show.chat_tab_settings_index = Some(tab);
|
||||
self.show.settings_tab = SettingsTab::Chat;
|
||||
self.show.settings(true);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
self.new_messages = VecDeque::new();
|
||||
@ -2644,6 +2670,9 @@ impl Hud {
|
||||
|
||||
self.show.settings(false)
|
||||
},
|
||||
settings_window::Event::ChangeChatSettingsTab(tab) => {
|
||||
self.show.chat_tab_settings_index = tab;
|
||||
},
|
||||
settings_window::Event::SettingsChange(settings_change) => {
|
||||
match &settings_change {
|
||||
SettingsChange::Interface(interface_change) => match interface_change {
|
||||
|
658
voxygen/src/hud/settings_window/chat.rs
Normal file
658
voxygen/src/hud/settings_window/chat.rs
Normal file
@ -0,0 +1,658 @@
|
||||
use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH};
|
||||
|
||||
use crate::{
|
||||
hud::{img_ids::Imgs, ChatTab, Show, TEXT_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN},
|
||||
i18n::Localization,
|
||||
session::settings_change::{Chat as ChatChange, Chat::*},
|
||||
settings::chat::MAX_CHAT_TABS,
|
||||
ui::{fonts::Fonts, ImageSlider, ToggleButton},
|
||||
GlobalState,
|
||||
};
|
||||
use conrod_core::{
|
||||
color,
|
||||
position::Relative,
|
||||
widget::{self, Button, DropDownList, Image, Rectangle, Text, TextEdit},
|
||||
widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
window,
|
||||
window_r,
|
||||
general_txt,
|
||||
transp_text,
|
||||
transp_slider,
|
||||
char_name_text,
|
||||
char_name_button,
|
||||
reset_chat_button,
|
||||
|
||||
//Tabs
|
||||
tabs_frame,
|
||||
tabs_bg,
|
||||
tabs_text,
|
||||
tab_align,
|
||||
tab_add,
|
||||
tabs[],
|
||||
|
||||
//tab content
|
||||
tab_content_align,
|
||||
tab_content_align_r,
|
||||
tab_label_text,
|
||||
tab_label_input,
|
||||
tab_label_bg,
|
||||
btn_tab_delete,
|
||||
|
||||
text_messages,
|
||||
btn_messages_all,
|
||||
text_messages_all,
|
||||
btn_messages_world,
|
||||
text_messages_world,
|
||||
icon_messages_world,
|
||||
btn_messages_region,
|
||||
text_messages_region,
|
||||
icon_messages_region,
|
||||
btn_messages_faction,
|
||||
text_messages_faction,
|
||||
icon_messages_faction,
|
||||
btn_messages_group,
|
||||
text_messages_group,
|
||||
icon_messages_group,
|
||||
btn_messages_say,
|
||||
text_messages_say,
|
||||
icon_messages_say,
|
||||
|
||||
text_activity,
|
||||
list_activity,
|
||||
|
||||
text_death,
|
||||
list_death,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(WidgetCommon)]
|
||||
pub struct Chat<'a> {
|
||||
global_state: &'a GlobalState,
|
||||
show: &'a Show,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
impl<'a> Chat<'a> {
|
||||
pub fn new(
|
||||
global_state: &'a GlobalState,
|
||||
show: &'a Show,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a Localization,
|
||||
) -> Self {
|
||||
Self {
|
||||
global_state,
|
||||
show,
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
ids: Ids,
|
||||
}
|
||||
pub enum Event {
|
||||
ChangeChatSettingsTab(Option<usize>),
|
||||
ChatChange(ChatChange),
|
||||
}
|
||||
|
||||
impl<'a> Widget for Chat<'a> {
|
||||
type Event = Vec<Event>;
|
||||
type State = State;
|
||||
type Style = ();
|
||||
|
||||
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
|
||||
State {
|
||||
ids: Ids::new(id_gen),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_unit)] // TODO: Pending review in #587
|
||||
fn style(&self) -> Self::Style { () }
|
||||
|
||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||
let widget::UpdateArgs { state, ui, .. } = args;
|
||||
|
||||
let mut events = Vec::new();
|
||||
let chat_settings = &self.global_state.settings.chat;
|
||||
// Alignment
|
||||
// Settings Window
|
||||
Rectangle::fill_with(args.rect.dim(), color::TRANSPARENT)
|
||||
.xy(args.rect.xy())
|
||||
.graphics_for(args.id)
|
||||
.scroll_kids()
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.window, ui);
|
||||
// Right Side
|
||||
Rectangle::fill_with([args.rect.w() / 2.0, args.rect.h()], color::TRANSPARENT)
|
||||
.top_right_of(state.ids.window)
|
||||
.set(state.ids.window_r, ui);
|
||||
|
||||
// General Title
|
||||
Text::new(&self.localized_strings.get("hud.settings.general"))
|
||||
.top_left_with_margins_on(state.ids.window, 5.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.general_txt, ui);
|
||||
|
||||
// Chat Transp
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.background_transparency"),
|
||||
)
|
||||
.down_from(state.ids.general_txt, 20.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.transp_text, ui);
|
||||
if let Some(new_val) = ImageSlider::continuous(
|
||||
chat_settings.chat_transp,
|
||||
0.0,
|
||||
0.9,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.down_from(state.ids.transp_text, 10.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.transp_slider, ui)
|
||||
{
|
||||
events.push(Event::ChatChange(Transp(new_val)));
|
||||
}
|
||||
|
||||
// "Show character names in chat" toggle button
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.chat_character_name"),
|
||||
)
|
||||
.down_from(state.ids.transp_slider, 10.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.char_name_text, ui);
|
||||
|
||||
if chat_settings.chat_character_name
|
||||
!= ToggleButton::new(
|
||||
chat_settings.chat_character_name,
|
||||
self.imgs.checkbox,
|
||||
self.imgs.checkbox_checked,
|
||||
)
|
||||
.w_h(18.0, 18.0)
|
||||
.right_from(state.ids.char_name_text, 10.0)
|
||||
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
.set(state.ids.char_name_button, ui)
|
||||
{
|
||||
events.push(Event::ChatChange(CharName(
|
||||
!chat_settings.chat_character_name,
|
||||
)));
|
||||
}
|
||||
|
||||
// Reset the chat settings to the default settings
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.down_from(state.ids.char_name_text, 20.0)
|
||||
.label(&self.localized_strings.get("hud.settings.reset_chat"))
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.set(state.ids.reset_chat_button, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChatChange(ResetChatSettings));
|
||||
}
|
||||
|
||||
// Tabs Title
|
||||
Text::new(&self.localized_strings.get("hud.settings.chat_tabs"))
|
||||
.top_left_with_margins_on(state.ids.window_r, 5.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.tabs_text, ui);
|
||||
|
||||
// bg and frame
|
||||
Image::new(self.imgs.chat_tab_settings_bg)
|
||||
.w_h(390.0, 270.0)
|
||||
.color(Some(UI_MAIN))
|
||||
.down_from(state.ids.tabs_text, 20.0)
|
||||
.set(state.ids.tabs_bg, ui);
|
||||
|
||||
Image::new(self.imgs.chat_tab_settings_frame)
|
||||
.w_h(390.0, 270.0)
|
||||
.color(Some(UI_HIGHLIGHT_0))
|
||||
.down_from(state.ids.tabs_text, 20.0)
|
||||
.set(state.ids.tabs_frame, ui);
|
||||
|
||||
// Tabs Alignment
|
||||
Rectangle::fill_with([390.0, 20.0], color::TRANSPARENT)
|
||||
.down_from(state.ids.tabs_text, 20.0)
|
||||
.set(state.ids.tab_align, ui);
|
||||
|
||||
// Tabs Settings Alignment
|
||||
Rectangle::fill_with([390.0, 250.0], color::TRANSPARENT)
|
||||
.down_from(state.ids.tab_align, 0.0)
|
||||
.set(state.ids.tab_content_align, ui);
|
||||
Rectangle::fill_with([195.0, 250.0], color::TRANSPARENT)
|
||||
.top_right_of(state.ids.tab_content_align)
|
||||
.set(state.ids.tab_content_align_r, ui);
|
||||
|
||||
let chat_tabs = &chat_settings.chat_tabs;
|
||||
if state.ids.tabs.len() < chat_tabs.len() {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.tabs
|
||||
.resize(chat_tabs.len(), &mut ui.widget_id_generator())
|
||||
});
|
||||
}
|
||||
for (i, chat_tab) in chat_tabs.iter().enumerate() {
|
||||
let is_selected = self
|
||||
.show
|
||||
.chat_tab_settings_index
|
||||
.map(|index| index == i)
|
||||
.unwrap_or(false);
|
||||
|
||||
let button = Button::image(if is_selected {
|
||||
self.imgs.selection
|
||||
} else {
|
||||
self.imgs.nothing
|
||||
})
|
||||
.w_h(390.0 / (MAX_CHAT_TABS as f64), 19.0)
|
||||
.hover_image(self.imgs.selection_hover)
|
||||
.press_image(self.imgs.selection_press)
|
||||
.label(chat_tab.label.as_str())
|
||||
.label_font_size(self.fonts.cyri.scale(12))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_y(Relative::Scalar(1.0));
|
||||
|
||||
let button = if i == 0 {
|
||||
button.top_left_with_margins_on(state.ids.tab_align, 1.0, 1.0)
|
||||
} else {
|
||||
button.right_from(state.ids.tabs[i - 1], 0.0)
|
||||
};
|
||||
if button.set(state.ids.tabs[i], ui).was_clicked() {
|
||||
events.push(Event::ChangeChatSettingsTab(if is_selected {
|
||||
None
|
||||
} else {
|
||||
Some(i)
|
||||
}));
|
||||
}
|
||||
}
|
||||
//Add button
|
||||
if chat_tabs.len() < MAX_CHAT_TABS {
|
||||
let add_tab_button = Button::image(self.imgs.settings_plus)
|
||||
.hover_image(self.imgs.settings_plus_hover)
|
||||
.press_image(self.imgs.settings_plus_press)
|
||||
.w_h(19.0, 19.0);
|
||||
|
||||
let add_tab_button = if chat_tabs.is_empty() {
|
||||
add_tab_button.top_left_with_margins_on(state.ids.tab_align, 1.0, 1.0)
|
||||
} else {
|
||||
add_tab_button.right_from(state.ids.tabs[chat_tabs.len() - 1], 0.0)
|
||||
};
|
||||
|
||||
if add_tab_button.set(state.ids.tab_add, ui).was_clicked() {
|
||||
let index = chat_tabs.len();
|
||||
events.push(Event::ChatChange(ChatTabInsert(index, ChatTab::default())));
|
||||
events.push(Event::ChangeChatSettingsTab(Some(index)));
|
||||
}
|
||||
}
|
||||
|
||||
//Content
|
||||
if let Some((index, chat_tab)) = self
|
||||
.show
|
||||
.chat_tab_settings_index
|
||||
.and_then(|i| chat_tabs.get(i).map(|ct| (i, ct)))
|
||||
{
|
||||
let mut updated_chat_tab = chat_tab.clone();
|
||||
|
||||
Text::new(&self.localized_strings.get("hud.settings.label"))
|
||||
.top_left_with_margins_on(state.ids.tab_content_align, 5.0, 25.0)
|
||||
.font_size(self.fonts.cyri.scale(16))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.tab_label_text, ui);
|
||||
|
||||
Rectangle::fill([90.0, 20.0])
|
||||
.right_from(state.ids.tab_label_text, 5.0)
|
||||
.color(color::rgba(0.0, 0.0, 0.0, 0.7))
|
||||
.set(state.ids.tab_label_bg, ui);
|
||||
|
||||
if let Some(label) = TextEdit::new(chat_tab.label.as_str())
|
||||
.right_from(state.ids.tab_label_text, 10.0)
|
||||
.y_relative_to(state.ids.tab_label_text, -3.0)
|
||||
.w_h(75.0, 20.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.tab_label_input, ui)
|
||||
{
|
||||
updated_chat_tab.label = label;
|
||||
}
|
||||
|
||||
if Button::image(self.imgs.button)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.w_h(100.0, 30.0)
|
||||
.label(&self.localized_strings.get("hud.settings.delete"))
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_y(Relative::Scalar(1.0))
|
||||
.bottom_right_with_margins_on(state.ids.tab_content_align, 10.0, 10.0)
|
||||
.set(state.ids.btn_tab_delete, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
events.push(Event::ChatChange(ChatTabRemove(index)));
|
||||
events.push(Event::ChangeChatSettingsTab(None));
|
||||
|
||||
if let Some(chat_tab_index) = chat_settings.chat_tab_index {
|
||||
match chat_tab_index.cmp(&index) {
|
||||
Ordering::Equal => {
|
||||
events.push(Event::ChatChange(ChangeChatTab(None)));
|
||||
},
|
||||
Ordering::Greater => {
|
||||
events.push(Event::ChatChange(ChangeChatTab(Some(index - 1))));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//helper methods to reduce on repeated code
|
||||
//(TODO: perhaps introduce a checkbox with label widget)
|
||||
let create_toggle = |selected, enabled| {
|
||||
ToggleButton::new(selected, self.imgs.checkbox, self.imgs.checkbox_checked)
|
||||
.and(|button| {
|
||||
if enabled {
|
||||
button
|
||||
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
} else {
|
||||
button.image_colors(TEXT_GRAY_COLOR, TEXT_GRAY_COLOR)
|
||||
}
|
||||
})
|
||||
.w_h(16.0, 16.0)
|
||||
};
|
||||
|
||||
let create_toggle_text = |text, enabled| {
|
||||
Text::new(text)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(if enabled { TEXT_COLOR } else { TEXT_GRAY_COLOR })
|
||||
};
|
||||
|
||||
let create_toggle_icon = |img, enabled: bool| {
|
||||
Image::new(img)
|
||||
.and_if(!enabled, |image| image.color(Some(TEXT_GRAY_COLOR)))
|
||||
.w_h(18.0, 18.0)
|
||||
};
|
||||
|
||||
//Messages
|
||||
Text::new(&self.localized_strings.get("hud.settings.messages"))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(16))
|
||||
.color(TEXT_COLOR)
|
||||
.top_left_with_margins_on(state.ids.tab_content_align, 35.0, 15.0)
|
||||
.set(state.ids.text_messages, ui);
|
||||
|
||||
// Toggle all options
|
||||
if chat_tab.filter.message_all
|
||||
!= ToggleButton::new(
|
||||
chat_tab.filter.message_all,
|
||||
self.imgs.checkbox,
|
||||
self.imgs.checkbox_checked,
|
||||
)
|
||||
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
.w_h(18.0, 18.0)
|
||||
.down_from(state.ids.text_messages, 10.0)
|
||||
.set(state.ids.btn_messages_all, ui)
|
||||
{
|
||||
updated_chat_tab.filter.message_all = !chat_tab.filter.message_all;
|
||||
};
|
||||
|
||||
Text::new(&self.localized_strings.get("hud.settings.show_all"))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(16))
|
||||
.color(TEXT_COLOR)
|
||||
.right_from(state.ids.btn_messages_all, 5.0)
|
||||
.set(state.ids.text_messages_all, ui);
|
||||
|
||||
//Messages - group
|
||||
if chat_tab.filter.message_group
|
||||
!= create_toggle(chat_tab.filter.message_group, !chat_tab.filter.message_all)
|
||||
.down_from(state.ids.btn_messages_all, 10.0)
|
||||
.set(state.ids.btn_messages_group, ui)
|
||||
&& !chat_tab.filter.message_all
|
||||
{
|
||||
updated_chat_tab.filter.message_group = !chat_tab.filter.message_group;
|
||||
}
|
||||
|
||||
create_toggle_text(
|
||||
&self.localized_strings.get("hud.settings.group"),
|
||||
!chat_tab.filter.message_all,
|
||||
)
|
||||
.right_from(state.ids.btn_messages_group, 5.0)
|
||||
.set(state.ids.text_messages_group, ui);
|
||||
|
||||
create_toggle_icon(self.imgs.chat_group_small, !chat_tab.filter.message_all)
|
||||
.right_from(state.ids.text_messages_group, 5.0)
|
||||
.set(state.ids.icon_messages_group, ui);
|
||||
|
||||
//Messages - faction
|
||||
if chat_tab.filter.message_faction
|
||||
!= create_toggle(
|
||||
chat_tab.filter.message_faction,
|
||||
!chat_tab.filter.message_all,
|
||||
)
|
||||
.down_from(state.ids.btn_messages_group, 10.0)
|
||||
.set(state.ids.btn_messages_faction, ui)
|
||||
&& !chat_tab.filter.message_all
|
||||
{
|
||||
updated_chat_tab.filter.message_faction = !chat_tab.filter.message_faction;
|
||||
}
|
||||
|
||||
create_toggle_text(
|
||||
&self.localized_strings.get("hud.settings.faction"),
|
||||
!chat_tab.filter.message_all,
|
||||
)
|
||||
.right_from(state.ids.btn_messages_faction, 5.0)
|
||||
.set(state.ids.text_messages_faction, ui);
|
||||
|
||||
create_toggle_icon(self.imgs.chat_faction_small, !chat_tab.filter.message_all)
|
||||
.right_from(state.ids.text_messages_faction, 5.0)
|
||||
.set(state.ids.icon_messages_faction, ui);
|
||||
|
||||
//Messages - world
|
||||
if chat_tab.filter.message_world
|
||||
!= create_toggle(chat_tab.filter.message_world, !chat_tab.filter.message_all)
|
||||
.down_from(state.ids.btn_messages_faction, 10.0)
|
||||
.set(state.ids.btn_messages_world, ui)
|
||||
&& !chat_tab.filter.message_all
|
||||
{
|
||||
updated_chat_tab.filter.message_world = !chat_tab.filter.message_world;
|
||||
}
|
||||
|
||||
create_toggle_text(
|
||||
&self.localized_strings.get("hud.settings.world"),
|
||||
!chat_tab.filter.message_all,
|
||||
)
|
||||
.right_from(state.ids.btn_messages_world, 5.0)
|
||||
.set(state.ids.text_messages_world, ui);
|
||||
|
||||
create_toggle_icon(self.imgs.chat_world_small, !chat_tab.filter.message_all)
|
||||
.right_from(state.ids.text_messages_world, 5.0)
|
||||
.set(state.ids.icon_messages_world, ui);
|
||||
|
||||
//Messages - region
|
||||
if chat_tab.filter.message_region
|
||||
!= create_toggle(chat_tab.filter.message_region, !chat_tab.filter.message_all)
|
||||
.down_from(state.ids.btn_messages_world, 10.0)
|
||||
.set(state.ids.btn_messages_region, ui)
|
||||
&& !chat_tab.filter.message_all
|
||||
{
|
||||
updated_chat_tab.filter.message_region = !chat_tab.filter.message_region;
|
||||
}
|
||||
|
||||
create_toggle_text(
|
||||
&self.localized_strings.get("hud.settings.region"),
|
||||
!chat_tab.filter.message_all,
|
||||
)
|
||||
.right_from(state.ids.btn_messages_region, 5.0)
|
||||
.set(state.ids.text_messages_region, ui);
|
||||
|
||||
create_toggle_icon(self.imgs.chat_region_small, !chat_tab.filter.message_all)
|
||||
.right_from(state.ids.text_messages_region, 5.0)
|
||||
.set(state.ids.icon_messages_region, ui);
|
||||
|
||||
//Messages - say
|
||||
if chat_tab.filter.message_say
|
||||
!= create_toggle(chat_tab.filter.message_say, !chat_tab.filter.message_all)
|
||||
.down_from(state.ids.btn_messages_region, 10.0)
|
||||
.set(state.ids.btn_messages_say, ui)
|
||||
&& !chat_tab.filter.message_all
|
||||
{
|
||||
updated_chat_tab.filter.message_say = !chat_tab.filter.message_say;
|
||||
}
|
||||
|
||||
create_toggle_text(
|
||||
&self.localized_strings.get("hud.settings.say"),
|
||||
!chat_tab.filter.message_all,
|
||||
)
|
||||
.right_from(state.ids.btn_messages_say, 5.0)
|
||||
.set(state.ids.text_messages_say, ui);
|
||||
|
||||
create_toggle_icon(self.imgs.chat_say_small, !chat_tab.filter.message_all)
|
||||
.right_from(state.ids.text_messages_say, 5.0)
|
||||
.set(state.ids.icon_messages_say, ui);
|
||||
|
||||
//Activity
|
||||
Text::new(&self.localized_strings.get("hud.settings.activity"))
|
||||
.top_left_with_margins_on(state.ids.tab_content_align_r, 0.0, 5.0)
|
||||
.align_middle_y_of(state.ids.text_messages)
|
||||
.font_size(self.fonts.cyri.scale(16))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.text_activity, ui);
|
||||
|
||||
if let Some(clicked) = DropDownList::new(
|
||||
&[
|
||||
&self.localized_strings.get("hud.settings.none"),
|
||||
&self.localized_strings.get("hud.settings.all"),
|
||||
&self.localized_strings.get("hud.settings.group_only"),
|
||||
],
|
||||
Some(if chat_tab.filter.activity_all {
|
||||
//all
|
||||
1
|
||||
} else if chat_tab.filter.activity_group {
|
||||
//group only
|
||||
2
|
||||
} else {
|
||||
//none
|
||||
0
|
||||
}),
|
||||
)
|
||||
.w_h(100.0, 20.0)
|
||||
.color(color::hsl(0.0, 0.0, 0.1))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_y(Relative::Scalar(1.0))
|
||||
.down_from(state.ids.text_activity, 10.0)
|
||||
.set(state.ids.list_activity, ui)
|
||||
{
|
||||
match clicked {
|
||||
0 => {
|
||||
updated_chat_tab.filter.activity_all = false;
|
||||
updated_chat_tab.filter.activity_group = false;
|
||||
},
|
||||
1 => {
|
||||
updated_chat_tab.filter.activity_all = true;
|
||||
},
|
||||
2 => {
|
||||
updated_chat_tab.filter.activity_all = false;
|
||||
updated_chat_tab.filter.activity_group = true;
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
//Death
|
||||
Text::new(&self.localized_strings.get("hud.settings.death"))
|
||||
.down_from(state.ids.list_activity, 20.0)
|
||||
.font_size(self.fonts.cyri.scale(16))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.text_death, ui);
|
||||
|
||||
if let Some(clicked) = DropDownList::new(
|
||||
&[
|
||||
&self.localized_strings.get("hud.settings.none"),
|
||||
&self.localized_strings.get("hud.settings.all"),
|
||||
&self.localized_strings.get("hud.settings.group_only"),
|
||||
],
|
||||
Some(if chat_tab.filter.death_all {
|
||||
//all
|
||||
1
|
||||
} else if chat_tab.filter.death_group {
|
||||
//group only
|
||||
2
|
||||
} else {
|
||||
//none
|
||||
0
|
||||
}),
|
||||
)
|
||||
.w_h(100.0, 20.0)
|
||||
.color(color::hsl(0.0, 0.0, 0.1))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_font_size(self.fonts.cyri.scale(14))
|
||||
.label_y(Relative::Scalar(1.0))
|
||||
.down_from(state.ids.text_death, 10.0)
|
||||
.set(state.ids.list_death, ui)
|
||||
{
|
||||
match clicked {
|
||||
0 => {
|
||||
updated_chat_tab.filter.death_all = false;
|
||||
updated_chat_tab.filter.death_group = false;
|
||||
},
|
||||
1 => {
|
||||
updated_chat_tab.filter.death_all = true;
|
||||
},
|
||||
2 => {
|
||||
updated_chat_tab.filter.death_all = false;
|
||||
updated_chat_tab.filter.death_group = true;
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
if chat_tab != &updated_chat_tab {
|
||||
//insert to front to avoid errors where the tab is moved or removed
|
||||
events.insert(0, Event::ChatChange(ChatTabUpdate(index, updated_chat_tab)));
|
||||
}
|
||||
}
|
||||
|
||||
events
|
||||
}
|
||||
}
|
@ -66,12 +66,6 @@ widget_ids! {
|
||||
buff_pos_map_button,
|
||||
buff_pos_map_text,
|
||||
//
|
||||
chat_transp_title,
|
||||
chat_transp_text,
|
||||
chat_transp_slider,
|
||||
chat_char_name_text,
|
||||
chat_char_name_button,
|
||||
//
|
||||
sct_title,
|
||||
sct_show_text,
|
||||
sct_show_radio,
|
||||
@ -164,7 +158,6 @@ impl<'a> Widget for Interface<'a> {
|
||||
let crosshair_transp = self.global_state.settings.interface.crosshair_transp;
|
||||
let crosshair_type = self.global_state.settings.interface.crosshair_type;
|
||||
let ui_scale = self.global_state.settings.interface.ui_scale;
|
||||
let chat_transp = self.global_state.settings.interface.chat_transp;
|
||||
|
||||
Text::new(&self.localized_strings.get("hud.settings.general"))
|
||||
.top_left_with_margins_on(state.ids.window, 5.0, 5.0)
|
||||
@ -942,70 +935,6 @@ impl<'a> Widget for Interface<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.show_bar_numbers_percentage_text, ui);
|
||||
|
||||
// Chat Transp
|
||||
Text::new(&self.localized_strings.get("hud.settings.chat"))
|
||||
.down_from(state.ids.show_bar_numbers_percentage_button, 20.0)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.chat_transp_title, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.background_transparency"),
|
||||
)
|
||||
.right_from(state.ids.chat_transp_slider, 20.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.chat_transp_text, ui);
|
||||
|
||||
if let Some(new_val) = ImageSlider::continuous(
|
||||
chat_transp,
|
||||
0.0,
|
||||
0.9,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider,
|
||||
)
|
||||
.w_h(104.0, 22.0)
|
||||
.down_from(state.ids.chat_transp_title, 8.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(state.ids.chat_transp_slider, ui)
|
||||
{
|
||||
events.push(ChatTransp(new_val));
|
||||
}
|
||||
|
||||
// "Show character names in chat" toggle button
|
||||
let chat_char_name = ToggleButton::new(
|
||||
self.global_state.settings.interface.chat_character_name,
|
||||
self.imgs.checkbox,
|
||||
self.imgs.checkbox_checked,
|
||||
)
|
||||
.w_h(18.0, 18.0)
|
||||
.down_from(state.ids.chat_transp_slider, 20.0)
|
||||
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
.set(state.ids.chat_char_name_button, ui);
|
||||
if self.global_state.settings.interface.chat_character_name != chat_char_name {
|
||||
events.push(ChatCharName(
|
||||
!self.global_state.settings.interface.chat_character_name,
|
||||
));
|
||||
}
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.chat_character_name"),
|
||||
)
|
||||
.right_from(state.ids.chat_char_name_button, 20.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.chat_char_name_text, ui);
|
||||
|
||||
// TODO Show account name in chat
|
||||
|
||||
// Reset the interface settings to the default settings
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
|
||||
|
@ -1,3 +1,4 @@
|
||||
mod chat;
|
||||
mod controls;
|
||||
mod gameplay;
|
||||
mod interface;
|
||||
@ -38,6 +39,7 @@ widget_ids! {
|
||||
video,
|
||||
sound,
|
||||
language,
|
||||
chat,
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,6 +49,7 @@ const RESET_BUTTONS_WIDTH: f64 = 155.0;
|
||||
#[derive(Debug, EnumIter, PartialEq)]
|
||||
pub enum SettingsTab {
|
||||
Interface,
|
||||
Chat,
|
||||
Video,
|
||||
Sound,
|
||||
Gameplay,
|
||||
@ -57,6 +60,7 @@ impl SettingsTab {
|
||||
fn name_key(&self) -> &str {
|
||||
match self {
|
||||
SettingsTab::Interface => "common.interface",
|
||||
SettingsTab::Chat => "common.chat",
|
||||
SettingsTab::Gameplay => "common.gameplay",
|
||||
SettingsTab::Controls => "common.controls",
|
||||
SettingsTab::Video => "common.video",
|
||||
@ -68,6 +72,7 @@ impl SettingsTab {
|
||||
fn title_key(&self) -> &str {
|
||||
match self {
|
||||
SettingsTab::Interface => "common.interface_settings",
|
||||
SettingsTab::Chat => "common.chat_settings",
|
||||
SettingsTab::Gameplay => "common.gameplay_settings",
|
||||
SettingsTab::Controls => "common.controls_settings",
|
||||
SettingsTab::Video => "common.video_settings",
|
||||
@ -118,6 +123,7 @@ pub enum Event {
|
||||
ChangeTab(SettingsTab),
|
||||
Close,
|
||||
SettingsChange(SettingsChange),
|
||||
ChangeChatSettingsTab(Option<usize>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -250,6 +256,23 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
events.push(Event::SettingsChange(change.into()));
|
||||
}
|
||||
},
|
||||
SettingsTab::Chat => {
|
||||
for event in
|
||||
chat::Chat::new(global_state, self.show, 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.chat, ui)
|
||||
{
|
||||
match event {
|
||||
chat::Event::ChatChange(change) => {
|
||||
events.push(Event::SettingsChange(change.into()));
|
||||
},
|
||||
chat::Event::ChangeChatSettingsTab(index) => {
|
||||
events.push(Event::ChangeChatSettingsTab(index));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
SettingsTab::Gameplay => {
|
||||
for change in gameplay::Gameplay::new(global_state, imgs, fonts, localized_strings)
|
||||
.top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
|
||||
|
@ -2,14 +2,14 @@ use super::SessionState;
|
||||
use crate::{
|
||||
controller::ControllerSettings,
|
||||
hud::{
|
||||
BarNumbers, BuffPosition, CrosshairType, Intro, PressBehavior, ScaleChange,
|
||||
BarNumbers, BuffPosition, ChatTab, CrosshairType, Intro, PressBehavior, ScaleChange,
|
||||
ShortcutNumbers, XpBar,
|
||||
},
|
||||
i18n::{LanguageMetadata, LocalizationHandle},
|
||||
render::RenderMode,
|
||||
settings::{
|
||||
AudioSettings, ControlSettings, Fps, GamepadSettings, GameplaySettings, GraphicsSettings,
|
||||
InterfaceSettings,
|
||||
AudioSettings, ChatSettings, ControlSettings, Fps, GamepadSettings, GameplaySettings,
|
||||
GraphicsSettings, InterfaceSettings,
|
||||
},
|
||||
window::{FullScreenSettings, GameInput},
|
||||
GlobalState,
|
||||
@ -26,6 +26,17 @@ pub enum Audio {
|
||||
ResetAudioSettings,
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub enum Chat {
|
||||
Transp(f32),
|
||||
CharName(bool),
|
||||
ChangeChatTab(Option<usize>),
|
||||
ChatTabUpdate(usize, ChatTab),
|
||||
ChatTabInsert(usize, ChatTab),
|
||||
ChatTabMove(usize, usize), //(i, j) move item from position i, and insert into position j
|
||||
ChatTabRemove(usize),
|
||||
ResetChatSettings,
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub enum Control {
|
||||
ChangeBinding(GameInput),
|
||||
ResetKeyBindings,
|
||||
@ -88,8 +99,6 @@ pub enum Interface {
|
||||
ToggleTips(bool),
|
||||
|
||||
CrosshairTransp(f32),
|
||||
ChatTransp(f32),
|
||||
ChatCharName(bool),
|
||||
CrosshairType(CrosshairType),
|
||||
Intro(Intro),
|
||||
ToggleXpBar(XpBar),
|
||||
@ -127,6 +136,7 @@ pub enum Networking {}
|
||||
#[derive(Clone)]
|
||||
pub enum SettingsChange {
|
||||
Audio(Audio),
|
||||
Chat(Chat),
|
||||
Control(Control),
|
||||
Gamepad(Gamepad),
|
||||
Gameplay(Gameplay),
|
||||
@ -144,6 +154,7 @@ macro_rules! settings_change_from {
|
||||
};
|
||||
}
|
||||
settings_change_from!(Audio);
|
||||
settings_change_from!(Chat);
|
||||
settings_change_from!(Control);
|
||||
settings_change_from!(Gamepad);
|
||||
settings_change_from!(Gameplay);
|
||||
@ -190,6 +201,46 @@ impl SettingsChange {
|
||||
}
|
||||
settings.save_to_file_warn();
|
||||
},
|
||||
SettingsChange::Chat(chat_change) => {
|
||||
let chat_tabs = &mut settings.chat.chat_tabs;
|
||||
match chat_change {
|
||||
Chat::Transp(chat_transp) => {
|
||||
settings.chat.chat_transp = chat_transp;
|
||||
},
|
||||
Chat::CharName(chat_char_name) => {
|
||||
settings.chat.chat_character_name = chat_char_name;
|
||||
},
|
||||
Chat::ChangeChatTab(chat_tab_index) => {
|
||||
settings.chat.chat_tab_index =
|
||||
chat_tab_index.filter(|i| *i < chat_tabs.len());
|
||||
},
|
||||
Chat::ChatTabUpdate(i, chat_tab) => {
|
||||
if i < chat_tabs.len() {
|
||||
chat_tabs[i] = chat_tab;
|
||||
}
|
||||
},
|
||||
Chat::ChatTabInsert(i, chat_tab) => {
|
||||
if i <= chat_tabs.len() {
|
||||
settings.chat.chat_tabs.insert(i, chat_tab);
|
||||
}
|
||||
},
|
||||
Chat::ChatTabMove(i, j) => {
|
||||
if i < chat_tabs.len() && j < chat_tabs.len() {
|
||||
let chat_tab = settings.chat.chat_tabs.remove(i);
|
||||
settings.chat.chat_tabs.insert(j, chat_tab);
|
||||
}
|
||||
},
|
||||
Chat::ChatTabRemove(i) => {
|
||||
if i < chat_tabs.len() {
|
||||
settings.chat.chat_tabs.remove(i);
|
||||
}
|
||||
},
|
||||
Chat::ResetChatSettings => {
|
||||
settings.chat = ChatSettings::default();
|
||||
},
|
||||
}
|
||||
settings.save_to_file_warn();
|
||||
},
|
||||
SettingsChange::Control(control_change) => match control_change {
|
||||
Control::ChangeBinding(game_input) => {
|
||||
global_state.window.set_keybinding_mode(game_input);
|
||||
@ -400,12 +451,6 @@ impl SettingsChange {
|
||||
Interface::CrosshairTransp(crosshair_transp) => {
|
||||
settings.interface.crosshair_transp = crosshair_transp;
|
||||
},
|
||||
Interface::ChatTransp(chat_transp) => {
|
||||
settings.interface.chat_transp = chat_transp;
|
||||
},
|
||||
Interface::ChatCharName(chat_char_name) => {
|
||||
settings.interface.chat_character_name = chat_char_name;
|
||||
},
|
||||
Interface::CrosshairType(crosshair_type) => {
|
||||
settings.interface.crosshair_type = crosshair_type;
|
||||
},
|
||||
|
88
voxygen/src/settings/chat.rs
Normal file
88
voxygen/src/settings/chat.rs
Normal file
@ -0,0 +1,88 @@
|
||||
use crate::hud::ChatTab;
|
||||
use common::{
|
||||
comp::{ChatMsg, ChatType},
|
||||
uid::Uid,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub const MAX_CHAT_TABS: usize = 5;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct ChatFilter {
|
||||
//messages
|
||||
pub message_all: bool,
|
||||
pub message_world: bool,
|
||||
pub message_region: bool,
|
||||
pub message_say: bool,
|
||||
pub message_group: bool,
|
||||
pub message_faction: bool,
|
||||
//activity (login/logout)
|
||||
pub activity_all: bool,
|
||||
pub activity_group: bool,
|
||||
//deaths
|
||||
pub death_all: bool,
|
||||
pub death_group: bool,
|
||||
}
|
||||
impl ChatFilter {
|
||||
pub fn satisfies(&self, chat_msg: &ChatMsg, group_members: &HashSet<&Uid>) -> bool {
|
||||
match &chat_msg.chat_type {
|
||||
ChatType::Online(u) | ChatType::Offline(u) => {
|
||||
self.activity_all || (self.activity_group && group_members.contains(u))
|
||||
},
|
||||
ChatType::CommandInfo | ChatType::CommandError => true,
|
||||
ChatType::Kill(_, u) => self.death_all || self.death_group && group_members.contains(u),
|
||||
ChatType::GroupMeta(_) => true, //todo
|
||||
ChatType::FactionMeta(_) => true, //todo
|
||||
ChatType::Tell(..) => true,
|
||||
ChatType::Say(_) => self.message_all || self.message_say,
|
||||
ChatType::Group(..) => self.message_all || self.message_group,
|
||||
ChatType::Faction(..) => self.message_all || self.message_faction,
|
||||
ChatType::Region(_) => self.message_all || self.message_region,
|
||||
ChatType::World(_) => self.message_all || self.message_world,
|
||||
ChatType::Npc(..) => true,
|
||||
ChatType::NpcSay(..) => true,
|
||||
ChatType::NpcTell(..) => true,
|
||||
ChatType::Meta => true,
|
||||
ChatType::Loot => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Default for ChatFilter {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
message_all: true,
|
||||
message_world: true,
|
||||
message_region: true,
|
||||
message_say: true,
|
||||
message_group: true,
|
||||
message_faction: true,
|
||||
|
||||
activity_all: false,
|
||||
activity_group: true,
|
||||
|
||||
death_all: false,
|
||||
death_group: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct ChatSettings {
|
||||
pub chat_transp: f32,
|
||||
pub chat_character_name: bool,
|
||||
pub chat_tabs: Vec<ChatTab>,
|
||||
pub chat_tab_index: Option<usize>,
|
||||
}
|
||||
|
||||
impl Default for ChatSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
chat_transp: 0.4,
|
||||
chat_character_name: true,
|
||||
chat_tabs: vec![ChatTab::default()],
|
||||
chat_tab_index: Some(0),
|
||||
}
|
||||
}
|
||||
}
|
@ -16,8 +16,6 @@ pub struct InterfaceSettings {
|
||||
pub speech_bubble_dark_mode: bool,
|
||||
pub speech_bubble_icon: bool,
|
||||
pub crosshair_transp: f32,
|
||||
pub chat_transp: f32,
|
||||
pub chat_character_name: bool,
|
||||
pub crosshair_type: CrosshairType,
|
||||
pub intro_show: Intro,
|
||||
pub xp_bar: XpBar,
|
||||
@ -51,8 +49,6 @@ impl Default for InterfaceSettings {
|
||||
speech_bubble_dark_mode: false,
|
||||
speech_bubble_icon: true,
|
||||
crosshair_transp: 0.6,
|
||||
chat_transp: 0.4,
|
||||
chat_character_name: true,
|
||||
crosshair_type: CrosshairType::Round,
|
||||
intro_show: Intro::Show,
|
||||
xp_bar: XpBar::Always,
|
||||
|
@ -3,16 +3,18 @@ use serde::{Deserialize, Serialize};
|
||||
use std::{fs, path::PathBuf};
|
||||
use tracing::warn;
|
||||
|
||||
mod audio;
|
||||
mod control;
|
||||
mod gamepad;
|
||||
mod gameplay;
|
||||
mod graphics;
|
||||
mod interface;
|
||||
mod language;
|
||||
mod networking;
|
||||
pub mod audio;
|
||||
pub mod chat;
|
||||
pub mod control;
|
||||
pub mod gamepad;
|
||||
pub mod gameplay;
|
||||
pub mod graphics;
|
||||
pub mod interface;
|
||||
pub mod language;
|
||||
pub mod networking;
|
||||
|
||||
pub use audio::{AudioOutput, AudioSettings};
|
||||
pub use chat::ChatSettings;
|
||||
pub use control::ControlSettings;
|
||||
pub use gamepad::GamepadSettings;
|
||||
pub use gameplay::GameplaySettings;
|
||||
@ -60,6 +62,7 @@ impl Default for Log {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Settings {
|
||||
pub chat: ChatSettings,
|
||||
pub controls: ControlSettings,
|
||||
pub interface: InterfaceSettings,
|
||||
pub gameplay: GameplaySettings,
|
||||
@ -96,6 +99,7 @@ impl Default for Settings {
|
||||
.expect("Couldn't choose a place to store the screenshots");
|
||||
|
||||
Settings {
|
||||
chat: ChatSettings::default(),
|
||||
controls: ControlSettings::default(),
|
||||
interface: InterfaceSettings::default(),
|
||||
gameplay: GameplaySettings::default(),
|
||||
|
Loading…
Reference in New Issue
Block a user